@neriros/ralphy 3.10.17 → 3.10.18
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 +1370 -1124
- package/package.json +2 -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.18")
|
|
18932
|
+
return "3.10.18";
|
|
18933
18933
|
} catch {}
|
|
18934
18934
|
const dirsToTry = [];
|
|
18935
18935
|
try {
|
|
@@ -19655,8 +19655,8 @@ var init_fields = __esm(() => {
|
|
|
19655
19655
|
},
|
|
19656
19656
|
{
|
|
19657
19657
|
id: "setupScript",
|
|
19658
|
-
label: "Worktree setup script (runs
|
|
19659
|
-
description: "Part of the worktree flow: a shell script run once
|
|
19658
|
+
label: "Worktree setup script (runs once per worktree)",
|
|
19659
|
+
description: "Part of the worktree flow: a shell script run once when a task's worktree is first created \u2014 e.g. to install dependencies in the new working copy. It does NOT re-run on resume, conflict-fix, ci-fix, or review re-runs that reuse an existing worktree.",
|
|
19660
19660
|
spec: { kind: "text" },
|
|
19661
19661
|
when: worktreeEnabled
|
|
19662
19662
|
},
|
|
@@ -19699,6 +19699,13 @@ var init_fields = __esm(() => {
|
|
|
19699
19699
|
spec: { kind: "text", placeholder: "main" },
|
|
19700
19700
|
when: isOn("createPrOnSuccess")
|
|
19701
19701
|
},
|
|
19702
|
+
{
|
|
19703
|
+
id: "prLabels",
|
|
19704
|
+
label: "PR labels",
|
|
19705
|
+
description: "GitHub labels attached to every pull request Ralph opens. The labels must already exist in the repo; a missing one is skipped, never fatal. One label per entry.",
|
|
19706
|
+
spec: { kind: "list", placeholder: "ralph" },
|
|
19707
|
+
when: isOn("createPrOnSuccess")
|
|
19708
|
+
},
|
|
19702
19709
|
{
|
|
19703
19710
|
id: "stackPrsOnDependencies",
|
|
19704
19711
|
label: "Stack dependent issues' PRs onto their blocker's PR?",
|
|
@@ -81315,7 +81322,7 @@ function foldLegacyAssignee(v) {
|
|
|
81315
81322
|
}
|
|
81316
81323
|
return rest2;
|
|
81317
81324
|
}
|
|
81318
|
-
var CURRENT_WORKFLOW_VERSION =
|
|
81325
|
+
var CURRENT_WORKFLOW_VERSION = 8, MarkerSchema, FilterMarkerSchema, LinearFilterSchema, SET_INDICATOR_KEYS, GetIndicatorSchema, SetIndicatorSchema, IndicatorsSchema, ProjectSchema, CommandsSchema, DEFAULT_META_ONLY_FILES, BoundariesSchema, WorkflowConfigSchema;
|
|
81319
81326
|
var init_schema = __esm(() => {
|
|
81320
81327
|
init_zod();
|
|
81321
81328
|
MarkerSchema = exports_external.discriminatedUnion("type", [
|
|
@@ -81455,6 +81462,7 @@ var init_schema = __esm(() => {
|
|
|
81455
81462
|
createPrOnSuccess: exports_external.boolean().default(false),
|
|
81456
81463
|
prDraft: exports_external.boolean().default(false),
|
|
81457
81464
|
prBaseBranch: exports_external.string().default("main"),
|
|
81465
|
+
prLabels: exports_external.array(exports_external.string()).default([]),
|
|
81458
81466
|
stackPrsOnDependencies: exports_external.boolean().default(false),
|
|
81459
81467
|
autoMergeStrategy: exports_external.enum(["squash", "merge", "rebase"]).default("squash"),
|
|
81460
81468
|
manualMergeWhenAutoMergeDisabled: exports_external.boolean().default(true),
|
|
@@ -81509,6 +81517,7 @@ var init_schema = __esm(() => {
|
|
|
81509
81517
|
github: exports_external.object({
|
|
81510
81518
|
base_branch: exports_external.string().optional(),
|
|
81511
81519
|
auto_merge_strategy: exports_external.enum(["squash", "merge", "rebase"]).optional(),
|
|
81520
|
+
pr_labels: exports_external.array(exports_external.string()).optional(),
|
|
81512
81521
|
issues: exports_external.object({
|
|
81513
81522
|
repo: exports_external.string().optional(),
|
|
81514
81523
|
label: exports_external.string().optional(),
|
|
@@ -81591,7 +81600,7 @@ var init_schema = __esm(() => {
|
|
|
81591
81600
|
var FRONTMATTER_RE, DEFAULT_WORKFLOW_MD = `---
|
|
81592
81601
|
# WORKFLOW.md schema version \u2014 managed by \`ralphy init\`. When a newer version
|
|
81593
81602
|
# ships, re-running init migrates this file and fills in the new settings.
|
|
81594
|
-
version:
|
|
81603
|
+
version: 8
|
|
81595
81604
|
|
|
81596
81605
|
project:
|
|
81597
81606
|
name: ralphy
|
|
@@ -81643,6 +81652,11 @@ prDraft: true
|
|
|
81643
81652
|
prBaseBranch: main
|
|
81644
81653
|
stackPrsOnDependencies: false
|
|
81645
81654
|
autoMergeStrategy: squash
|
|
81655
|
+
# Labels attached to every PR Ralph opens (best-effort \u2014 a missing label is
|
|
81656
|
+
# logged, never fatal). The labels must already exist in the repo.
|
|
81657
|
+
# prLabels:
|
|
81658
|
+
# - ralph
|
|
81659
|
+
# - automated
|
|
81646
81660
|
|
|
81647
81661
|
prRecovery:
|
|
81648
81662
|
enabled: true
|
|
@@ -82375,6 +82389,9 @@ function applyAliases(cfg) {
|
|
|
82375
82389
|
if (cfg.github.auto_merge_strategy !== undefined && cfg.autoMergeStrategy === "squash") {
|
|
82376
82390
|
cfg.autoMergeStrategy = cfg.github.auto_merge_strategy;
|
|
82377
82391
|
}
|
|
82392
|
+
if (cfg.github.pr_labels !== undefined && cfg.prLabels.length === 0) {
|
|
82393
|
+
cfg.prLabels = cfg.github.pr_labels;
|
|
82394
|
+
}
|
|
82378
82395
|
}
|
|
82379
82396
|
if (cfg.agent) {
|
|
82380
82397
|
if (cfg.agent.engine !== undefined)
|
|
@@ -84691,6 +84708,11 @@ var init_migrations = __esm(() => {
|
|
|
84691
84708
|
"github.issues.statusLabels.done",
|
|
84692
84709
|
"github.issues.statusLabels.error"
|
|
84693
84710
|
]
|
|
84711
|
+
},
|
|
84712
|
+
{
|
|
84713
|
+
version: 8,
|
|
84714
|
+
description: "Pull requests Ralph opens can now carry GitHub labels via `prLabels`. " + "List the labels to attach to every PR (they must already exist in the " + "repo; a missing label is skipped, never fatal). Only asked when " + "PR-creation is enabled \u2014 leave empty to attach no labels.",
|
|
84715
|
+
fields: ["prLabels"]
|
|
84694
84716
|
}
|
|
84695
84717
|
];
|
|
84696
84718
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max2, migration) => Math.max(max2, migration.version), 0);
|
|
@@ -85262,7 +85284,7 @@ function projectLayout(root) {
|
|
|
85262
85284
|
stateFile: (name) => join7(statesDir, name, STATE_FILE)
|
|
85263
85285
|
};
|
|
85264
85286
|
}
|
|
85265
|
-
var STATE_FILE = ".ralph-state.json"
|
|
85287
|
+
var STATE_FILE = ".ralph-state.json";
|
|
85266
85288
|
var init_layout = __esm(() => {
|
|
85267
85289
|
init_context();
|
|
85268
85290
|
});
|
|
@@ -99729,6 +99751,39 @@ var init_example_machine = __esm(() => {
|
|
|
99729
99751
|
});
|
|
99730
99752
|
|
|
99731
99753
|
// packages/core/src/machines/flow.machine.ts
|
|
99754
|
+
function recordDetection(reason) {
|
|
99755
|
+
return ({
|
|
99756
|
+
context,
|
|
99757
|
+
event
|
|
99758
|
+
}) => {
|
|
99759
|
+
const previous = context.data.recovery;
|
|
99760
|
+
return {
|
|
99761
|
+
data: {
|
|
99762
|
+
...context.data,
|
|
99763
|
+
recovery: {
|
|
99764
|
+
attempts: (previous?.attempts ?? 0) + 1,
|
|
99765
|
+
lastReason: reason,
|
|
99766
|
+
firstFailedAt: previous?.firstFailedAt ?? event.at ?? ""
|
|
99767
|
+
}
|
|
99768
|
+
}
|
|
99769
|
+
};
|
|
99770
|
+
};
|
|
99771
|
+
}
|
|
99772
|
+
function reachesQuarantine({ context }) {
|
|
99773
|
+
const max2 = context.data.maxRecoveryAttempts;
|
|
99774
|
+
return max2 > 0 && (context.data.recovery?.attempts ?? 0) + 1 >= max2;
|
|
99775
|
+
}
|
|
99776
|
+
function refreshReason(reason) {
|
|
99777
|
+
return ({ context }) => ({
|
|
99778
|
+
data: {
|
|
99779
|
+
...context.data,
|
|
99780
|
+
recovery: context.data.recovery ? { ...context.data.recovery, lastReason: reason } : { attempts: 0, lastReason: reason, firstFailedAt: "" }
|
|
99781
|
+
}
|
|
99782
|
+
});
|
|
99783
|
+
}
|
|
99784
|
+
function clearRecovery({ context }) {
|
|
99785
|
+
return { data: { ...context.data, recovery: undefined } };
|
|
99786
|
+
}
|
|
99732
99787
|
var preemptionActorLogic, flowMachine;
|
|
99733
99788
|
var init_flow_machine = __esm(() => {
|
|
99734
99789
|
init_xstate_development_cjs();
|
|
@@ -99775,14 +99830,20 @@ var init_flow_machine = __esm(() => {
|
|
|
99775
99830
|
}).createMachine({
|
|
99776
99831
|
id: "flow",
|
|
99777
99832
|
context: ({ input }) => ({
|
|
99778
|
-
|
|
99779
|
-
|
|
99780
|
-
|
|
99781
|
-
|
|
99782
|
-
|
|
99783
|
-
|
|
99784
|
-
|
|
99785
|
-
|
|
99833
|
+
data: {
|
|
99834
|
+
issueId: input?.issueId ?? "",
|
|
99835
|
+
graceMs: input?.graceMs ?? 5000,
|
|
99836
|
+
maxRecoveryAttempts: input?.maxRecoveryAttempts ?? 0,
|
|
99837
|
+
currentAssignment: undefined,
|
|
99838
|
+
pendingAssignment: undefined,
|
|
99839
|
+
recovery: undefined
|
|
99840
|
+
},
|
|
99841
|
+
runtime: {
|
|
99842
|
+
bus: input?.bus ?? createNoopBus(),
|
|
99843
|
+
persist: input?.persist ?? (() => {}),
|
|
99844
|
+
worker: undefined,
|
|
99845
|
+
teardown: undefined
|
|
99846
|
+
}
|
|
99786
99847
|
}),
|
|
99787
99848
|
initial: "idle",
|
|
99788
99849
|
states: {
|
|
@@ -99791,29 +99852,63 @@ var init_flow_machine = __esm(() => {
|
|
|
99791
99852
|
FRESH_PICKED_UP: "working",
|
|
99792
99853
|
RESUME_DETECTED: "working",
|
|
99793
99854
|
REVIEW_TRIGGERED: "review",
|
|
99794
|
-
CONFLICT_DETECTED:
|
|
99795
|
-
|
|
99855
|
+
CONFLICT_DETECTED: [
|
|
99856
|
+
{
|
|
99857
|
+
guard: reachesQuarantine,
|
|
99858
|
+
target: "quarantined",
|
|
99859
|
+
actions: import_xstate_development_cjs.assign(recordDetection("conflicting"))
|
|
99860
|
+
},
|
|
99861
|
+
{ target: "conflict-fix", actions: import_xstate_development_cjs.assign(recordDetection("conflicting")) }
|
|
99862
|
+
],
|
|
99863
|
+
CI_FAILED_DETECTED: [
|
|
99864
|
+
{
|
|
99865
|
+
guard: reachesQuarantine,
|
|
99866
|
+
target: "quarantined",
|
|
99867
|
+
actions: import_xstate_development_cjs.assign(recordDetection("ci_failed"))
|
|
99868
|
+
},
|
|
99869
|
+
{ target: "ci-fix", actions: import_xstate_development_cjs.assign(recordDetection("ci_failed")) }
|
|
99870
|
+
]
|
|
99796
99871
|
}
|
|
99797
99872
|
},
|
|
99798
99873
|
working: {
|
|
99799
99874
|
on: {
|
|
99800
99875
|
AWAITING_DETECTED: "awaiting",
|
|
99801
|
-
CONFLICT_DETECTED:
|
|
99802
|
-
|
|
99876
|
+
CONFLICT_DETECTED: [
|
|
99877
|
+
{
|
|
99878
|
+
guard: reachesQuarantine,
|
|
99879
|
+
target: "quarantined",
|
|
99880
|
+
actions: import_xstate_development_cjs.assign(recordDetection("conflicting"))
|
|
99881
|
+
},
|
|
99882
|
+
{ target: "conflict-fix", actions: import_xstate_development_cjs.assign(recordDetection("conflicting")) }
|
|
99883
|
+
],
|
|
99884
|
+
CI_FAILED_DETECTED: [
|
|
99885
|
+
{
|
|
99886
|
+
guard: reachesQuarantine,
|
|
99887
|
+
target: "quarantined",
|
|
99888
|
+
actions: import_xstate_development_cjs.assign(recordDetection("ci_failed"))
|
|
99889
|
+
},
|
|
99890
|
+
{ target: "ci-fix", actions: import_xstate_development_cjs.assign(recordDetection("ci_failed")) }
|
|
99891
|
+
],
|
|
99803
99892
|
PR_OPENED: "awaiting-ci",
|
|
99804
99893
|
WORKER_SUCCEEDED: "done",
|
|
99805
99894
|
WORKER_FAILED: "error",
|
|
99806
99895
|
PREEMPT: {
|
|
99807
99896
|
target: "preempting",
|
|
99808
99897
|
actions: import_xstate_development_cjs.assign({
|
|
99809
|
-
|
|
99898
|
+
data: ({ context, event }) => ({
|
|
99899
|
+
...context.data,
|
|
99900
|
+
pendingAssignment: event.newAssignment
|
|
99901
|
+
})
|
|
99810
99902
|
})
|
|
99811
99903
|
},
|
|
99812
99904
|
WORKER_SPAWNED: {
|
|
99813
|
-
actions: import_xstate_development_cjs.assign(({ event }) => ({
|
|
99814
|
-
|
|
99815
|
-
|
|
99816
|
-
|
|
99905
|
+
actions: import_xstate_development_cjs.assign(({ context, event }) => ({
|
|
99906
|
+
data: { ...context.data, currentAssignment: event.assignment },
|
|
99907
|
+
runtime: {
|
|
99908
|
+
...context.runtime,
|
|
99909
|
+
worker: event.worker,
|
|
99910
|
+
teardown: event.teardown ?? undefined
|
|
99911
|
+
}
|
|
99817
99912
|
}))
|
|
99818
99913
|
}
|
|
99819
99914
|
}
|
|
@@ -99825,14 +99920,20 @@ var init_flow_machine = __esm(() => {
|
|
|
99825
99920
|
PREEMPT: {
|
|
99826
99921
|
target: "preempting",
|
|
99827
99922
|
actions: import_xstate_development_cjs.assign({
|
|
99828
|
-
|
|
99923
|
+
data: ({ context, event }) => ({
|
|
99924
|
+
...context.data,
|
|
99925
|
+
pendingAssignment: event.newAssignment
|
|
99926
|
+
})
|
|
99829
99927
|
})
|
|
99830
99928
|
},
|
|
99831
99929
|
WORKER_SPAWNED: {
|
|
99832
|
-
actions: import_xstate_development_cjs.assign(({ event }) => ({
|
|
99833
|
-
|
|
99834
|
-
|
|
99835
|
-
|
|
99930
|
+
actions: import_xstate_development_cjs.assign(({ context, event }) => ({
|
|
99931
|
+
data: { ...context.data, currentAssignment: event.assignment },
|
|
99932
|
+
runtime: {
|
|
99933
|
+
...context.runtime,
|
|
99934
|
+
worker: event.worker,
|
|
99935
|
+
teardown: event.teardown ?? undefined
|
|
99936
|
+
}
|
|
99836
99937
|
}))
|
|
99837
99938
|
}
|
|
99838
99939
|
}
|
|
@@ -99844,14 +99945,20 @@ var init_flow_machine = __esm(() => {
|
|
|
99844
99945
|
PREEMPT: {
|
|
99845
99946
|
target: "preempting",
|
|
99846
99947
|
actions: import_xstate_development_cjs.assign({
|
|
99847
|
-
|
|
99948
|
+
data: ({ context, event }) => ({
|
|
99949
|
+
...context.data,
|
|
99950
|
+
pendingAssignment: event.newAssignment
|
|
99951
|
+
})
|
|
99848
99952
|
})
|
|
99849
99953
|
},
|
|
99850
99954
|
WORKER_SPAWNED: {
|
|
99851
|
-
actions: import_xstate_development_cjs.assign(({ event }) => ({
|
|
99852
|
-
|
|
99853
|
-
|
|
99854
|
-
|
|
99955
|
+
actions: import_xstate_development_cjs.assign(({ context, event }) => ({
|
|
99956
|
+
data: { ...context.data, currentAssignment: event.assignment },
|
|
99957
|
+
runtime: {
|
|
99958
|
+
...context.runtime,
|
|
99959
|
+
worker: event.worker,
|
|
99960
|
+
teardown: event.teardown ?? undefined
|
|
99961
|
+
}
|
|
99855
99962
|
}))
|
|
99856
99963
|
}
|
|
99857
99964
|
}
|
|
@@ -99862,7 +99969,10 @@ var init_flow_machine = __esm(() => {
|
|
|
99862
99969
|
PREEMPT: {
|
|
99863
99970
|
target: "preempting",
|
|
99864
99971
|
actions: import_xstate_development_cjs.assign({
|
|
99865
|
-
|
|
99972
|
+
data: ({ context, event }) => ({
|
|
99973
|
+
...context.data,
|
|
99974
|
+
pendingAssignment: event.newAssignment
|
|
99975
|
+
})
|
|
99866
99976
|
})
|
|
99867
99977
|
}
|
|
99868
99978
|
}
|
|
@@ -99870,20 +99980,41 @@ var init_flow_machine = __esm(() => {
|
|
|
99870
99980
|
"awaiting-ci": {
|
|
99871
99981
|
on: {
|
|
99872
99982
|
PR_PASSED: "done",
|
|
99873
|
-
|
|
99874
|
-
|
|
99983
|
+
RECOVERY_CLEARED: { actions: import_xstate_development_cjs.assign(clearRecovery) },
|
|
99984
|
+
CONFLICT_DETECTED: [
|
|
99985
|
+
{
|
|
99986
|
+
guard: reachesQuarantine,
|
|
99987
|
+
target: "quarantined",
|
|
99988
|
+
actions: import_xstate_development_cjs.assign(recordDetection("conflicting"))
|
|
99989
|
+
},
|
|
99990
|
+
{ target: "conflict-fix", actions: import_xstate_development_cjs.assign(recordDetection("conflicting")) }
|
|
99991
|
+
],
|
|
99992
|
+
CI_FAILED_DETECTED: [
|
|
99993
|
+
{
|
|
99994
|
+
guard: reachesQuarantine,
|
|
99995
|
+
target: "quarantined",
|
|
99996
|
+
actions: import_xstate_development_cjs.assign(recordDetection("ci_failed"))
|
|
99997
|
+
},
|
|
99998
|
+
{ target: "ci-fix", actions: import_xstate_development_cjs.assign(recordDetection("ci_failed")) }
|
|
99999
|
+
],
|
|
99875
100000
|
REVIEW_TRIGGERED: "review",
|
|
99876
100001
|
PREEMPT: {
|
|
99877
100002
|
target: "preempting",
|
|
99878
100003
|
actions: import_xstate_development_cjs.assign({
|
|
99879
|
-
|
|
100004
|
+
data: ({ context, event }) => ({
|
|
100005
|
+
...context.data,
|
|
100006
|
+
pendingAssignment: event.newAssignment
|
|
100007
|
+
})
|
|
99880
100008
|
})
|
|
99881
100009
|
},
|
|
99882
100010
|
WORKER_SPAWNED: {
|
|
99883
|
-
actions: import_xstate_development_cjs.assign(({ event }) => ({
|
|
99884
|
-
|
|
99885
|
-
|
|
99886
|
-
|
|
100011
|
+
actions: import_xstate_development_cjs.assign(({ context, event }) => ({
|
|
100012
|
+
data: { ...context.data, currentAssignment: event.assignment },
|
|
100013
|
+
runtime: {
|
|
100014
|
+
...context.runtime,
|
|
100015
|
+
worker: event.worker,
|
|
100016
|
+
teardown: event.teardown ?? undefined
|
|
100017
|
+
}
|
|
99887
100018
|
}))
|
|
99888
100019
|
}
|
|
99889
100020
|
}
|
|
@@ -99894,10 +100025,13 @@ var init_flow_machine = __esm(() => {
|
|
|
99894
100025
|
PR_OPENED: "awaiting-ci",
|
|
99895
100026
|
WORKER_FAILED: "error",
|
|
99896
100027
|
WORKER_SPAWNED: {
|
|
99897
|
-
actions: import_xstate_development_cjs.assign(({ event }) => ({
|
|
99898
|
-
|
|
99899
|
-
|
|
99900
|
-
|
|
100028
|
+
actions: import_xstate_development_cjs.assign(({ context, event }) => ({
|
|
100029
|
+
data: { ...context.data, currentAssignment: event.assignment },
|
|
100030
|
+
runtime: {
|
|
100031
|
+
...context.runtime,
|
|
100032
|
+
worker: event.worker,
|
|
100033
|
+
teardown: event.teardown ?? undefined
|
|
100034
|
+
}
|
|
99901
100035
|
}))
|
|
99902
100036
|
}
|
|
99903
100037
|
}
|
|
@@ -99906,20 +100040,19 @@ var init_flow_machine = __esm(() => {
|
|
|
99906
100040
|
invoke: {
|
|
99907
100041
|
src: "preemption",
|
|
99908
100042
|
input: ({ context }) => ({
|
|
99909
|
-
graceMs: context.graceMs,
|
|
99910
|
-
bus: context.bus,
|
|
99911
|
-
persist: context.persist,
|
|
99912
|
-
issueId: context.issueId,
|
|
99913
|
-
newAssignment: context.pendingAssignment,
|
|
99914
|
-
...context.currentAssignment !== undefined ? { from: context.currentAssignment.flowId } : {},
|
|
99915
|
-
...context.worker !== undefined ? { worker: context.worker } : {},
|
|
99916
|
-
...context.teardown !== undefined ? { teardown: context.teardown } : {}
|
|
100043
|
+
graceMs: context.data.graceMs,
|
|
100044
|
+
bus: context.runtime.bus,
|
|
100045
|
+
persist: context.runtime.persist,
|
|
100046
|
+
issueId: context.data.issueId,
|
|
100047
|
+
newAssignment: context.data.pendingAssignment,
|
|
100048
|
+
...context.data.currentAssignment !== undefined ? { from: context.data.currentAssignment.flowId } : {},
|
|
100049
|
+
...context.runtime.worker !== undefined ? { worker: context.runtime.worker } : {},
|
|
100050
|
+
...context.runtime.teardown !== undefined ? { teardown: context.runtime.teardown } : {}
|
|
99917
100051
|
}),
|
|
99918
100052
|
onDone: {
|
|
99919
100053
|
actions: import_xstate_development_cjs.assign(({ context }) => ({
|
|
99920
|
-
|
|
99921
|
-
teardown: undefined
|
|
99922
|
-
currentAssignment: context.pendingAssignment
|
|
100054
|
+
data: { ...context.data, currentAssignment: context.data.pendingAssignment },
|
|
100055
|
+
runtime: { ...context.runtime, worker: undefined, teardown: undefined }
|
|
99923
100056
|
})),
|
|
99924
100057
|
target: "routing-after-preempt"
|
|
99925
100058
|
},
|
|
@@ -99929,32 +100062,40 @@ var init_flow_machine = __esm(() => {
|
|
|
99929
100062
|
"routing-after-preempt": {
|
|
99930
100063
|
always: [
|
|
99931
100064
|
{
|
|
99932
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "conflict-fix",
|
|
100065
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "conflict-fix",
|
|
99933
100066
|
target: "conflict-fix"
|
|
99934
100067
|
},
|
|
99935
100068
|
{
|
|
99936
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "ci-fix",
|
|
100069
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "ci-fix",
|
|
99937
100070
|
target: "ci-fix"
|
|
99938
100071
|
},
|
|
99939
100072
|
{
|
|
99940
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "awaiting-ci",
|
|
100073
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "awaiting-ci",
|
|
99941
100074
|
target: "awaiting-ci"
|
|
99942
100075
|
},
|
|
99943
100076
|
{
|
|
99944
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "confirmation",
|
|
100077
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "confirmation",
|
|
99945
100078
|
target: "awaiting"
|
|
99946
100079
|
},
|
|
99947
100080
|
{
|
|
99948
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "review-followup",
|
|
100081
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "review-followup",
|
|
99949
100082
|
target: "review"
|
|
99950
100083
|
},
|
|
99951
100084
|
{
|
|
99952
|
-
guard: ({ context }) => context.pendingAssignment?.flowId === "idle",
|
|
100085
|
+
guard: ({ context }) => context.data.pendingAssignment?.flowId === "idle",
|
|
99953
100086
|
target: "idle"
|
|
99954
100087
|
},
|
|
99955
100088
|
{ target: "working" }
|
|
99956
100089
|
]
|
|
99957
100090
|
},
|
|
100091
|
+
quarantined: {
|
|
100092
|
+
on: {
|
|
100093
|
+
PR_PASSED: "done",
|
|
100094
|
+
QUARANTINE_CLEARED: { target: "idle", actions: import_xstate_development_cjs.assign(clearRecovery) },
|
|
100095
|
+
CONFLICT_DETECTED: { actions: import_xstate_development_cjs.assign(refreshReason("conflicting")) },
|
|
100096
|
+
CI_FAILED_DETECTED: { actions: import_xstate_development_cjs.assign(refreshReason("ci_failed")) }
|
|
100097
|
+
}
|
|
100098
|
+
},
|
|
99958
100099
|
done: {
|
|
99959
100100
|
type: "final"
|
|
99960
100101
|
},
|
|
@@ -99983,17 +100124,22 @@ class FlowActorStore {
|
|
|
99983
100124
|
...this.deps ? {
|
|
99984
100125
|
bus: this.deps.bus,
|
|
99985
100126
|
persist: this.deps.persist,
|
|
99986
|
-
...this.deps.graceMs !== undefined ? { graceMs: this.deps.graceMs } : {}
|
|
100127
|
+
...this.deps.graceMs !== undefined ? { graceMs: this.deps.graceMs } : {},
|
|
100128
|
+
...this.deps.maxRecoveryAttempts !== undefined ? { maxRecoveryAttempts: this.deps.maxRecoveryAttempts } : {}
|
|
99987
100129
|
} : {}
|
|
99988
100130
|
};
|
|
100131
|
+
const inspector = this.deps?.onTransition ? this.makeInspect(key, changeDir) : null;
|
|
99989
100132
|
if (changeDir) {
|
|
99990
100133
|
const snapshot = await this.loadSnapshot(changeDir);
|
|
99991
100134
|
if (snapshot !== null && this.isValidSnapshot(snapshot)) {
|
|
99992
100135
|
try {
|
|
100136
|
+
const restored = this.withRestoredRuntime(snapshot);
|
|
99993
100137
|
const a2 = import_xstate_development_cjs.createActor(this.machine, {
|
|
99994
|
-
snapshot,
|
|
99995
|
-
input
|
|
100138
|
+
snapshot: restored,
|
|
100139
|
+
input,
|
|
100140
|
+
...inspector ? { inspect: inspector.inspect } : {}
|
|
99996
100141
|
});
|
|
100142
|
+
inspector?.setRoot(a2);
|
|
99997
100143
|
a2.start();
|
|
99998
100144
|
if (a2.getSnapshot().value !== undefined) {
|
|
99999
100145
|
this.actors.set(key, a2);
|
|
@@ -100005,11 +100151,61 @@ class FlowActorStore {
|
|
|
100005
100151
|
} catch {}
|
|
100006
100152
|
}
|
|
100007
100153
|
}
|
|
100008
|
-
const a = import_xstate_development_cjs.createActor(this.machine, {
|
|
100154
|
+
const a = import_xstate_development_cjs.createActor(this.machine, {
|
|
100155
|
+
input,
|
|
100156
|
+
...inspector ? { inspect: inspector.inspect } : {}
|
|
100157
|
+
});
|
|
100158
|
+
inspector?.setRoot(a);
|
|
100009
100159
|
a.start();
|
|
100010
100160
|
this.actors.set(key, a);
|
|
100011
100161
|
return a;
|
|
100012
100162
|
}
|
|
100163
|
+
buildRuntime() {
|
|
100164
|
+
return {
|
|
100165
|
+
bus: this.deps?.bus ?? createNoopBus(),
|
|
100166
|
+
persist: this.deps?.persist ?? (() => {}),
|
|
100167
|
+
worker: undefined,
|
|
100168
|
+
teardown: undefined
|
|
100169
|
+
};
|
|
100170
|
+
}
|
|
100171
|
+
withRestoredRuntime(snapshot) {
|
|
100172
|
+
if (!snapshot || typeof snapshot !== "object")
|
|
100173
|
+
return snapshot;
|
|
100174
|
+
const snap = snapshot;
|
|
100175
|
+
const context = snap.context ?? {};
|
|
100176
|
+
const data = context.data && typeof context.data === "object" ? context.data : {
|
|
100177
|
+
issueId: context.issueId,
|
|
100178
|
+
graceMs: context.graceMs ?? 5000,
|
|
100179
|
+
maxRecoveryAttempts: this.deps?.maxRecoveryAttempts ?? 0,
|
|
100180
|
+
currentAssignment: context.currentAssignment,
|
|
100181
|
+
pendingAssignment: context.pendingAssignment,
|
|
100182
|
+
recovery: undefined
|
|
100183
|
+
};
|
|
100184
|
+
return { ...snap, context: { data, runtime: this.buildRuntime() } };
|
|
100185
|
+
}
|
|
100186
|
+
makeInspect(issueId, changeDir) {
|
|
100187
|
+
let root;
|
|
100188
|
+
let previous;
|
|
100189
|
+
const inspect = (event) => {
|
|
100190
|
+
if (event.type !== "@xstate.snapshot" || event.actorRef !== root)
|
|
100191
|
+
return;
|
|
100192
|
+
const value = event.snapshot.value;
|
|
100193
|
+
const to = typeof value === "string" ? value : JSON.stringify(value);
|
|
100194
|
+
const eventType = event.event.type ?? "?";
|
|
100195
|
+
if (previous !== undefined && previous !== to) {
|
|
100196
|
+
try {
|
|
100197
|
+
this.deps?.onTransition?.(issueId, changeDir, { from: previous, event: eventType, to });
|
|
100198
|
+
} catch {}
|
|
100199
|
+
}
|
|
100200
|
+
previous = to;
|
|
100201
|
+
};
|
|
100202
|
+
return {
|
|
100203
|
+
inspect,
|
|
100204
|
+
setRoot: (actor) => {
|
|
100205
|
+
root = actor;
|
|
100206
|
+
}
|
|
100207
|
+
};
|
|
100208
|
+
}
|
|
100013
100209
|
peekActor(key) {
|
|
100014
100210
|
return this.actors.get(key) ?? null;
|
|
100015
100211
|
}
|
|
@@ -100065,6 +100261,7 @@ var init_flow_actor_store = __esm(() => {
|
|
|
100065
100261
|
init_xstate_development_cjs();
|
|
100066
100262
|
init_flow_machine();
|
|
100067
100263
|
init_store();
|
|
100264
|
+
init_src2();
|
|
100068
100265
|
});
|
|
100069
100266
|
|
|
100070
100267
|
// packages/core/src/machines/loop.machine.ts
|
|
@@ -102921,6 +103118,9 @@ function formatTicketError(err) {
|
|
|
102921
103118
|
parts.push(`configured team: ${e.team}`);
|
|
102922
103119
|
return parts.length > 0 ? `${e.message} (${parts.join(", ")})` : e.message;
|
|
102923
103120
|
}
|
|
103121
|
+
function openBlockersFromInverse(nodes) {
|
|
103122
|
+
return (nodes ?? []).filter((r) => r.type === "blocks" && !DONE_BLOCKER_STATE_TYPES.has(r.issue.state.type)).map((r) => ({ id: r.issue.id, identifier: r.issue.identifier }));
|
|
103123
|
+
}
|
|
102924
103124
|
function partition2(markers) {
|
|
102925
103125
|
const statuses = [];
|
|
102926
103126
|
const labels = [];
|
|
@@ -103140,8 +103340,8 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
103140
103340
|
project { id name priority }
|
|
103141
103341
|
projectMilestone { id name sortOrder targetDate }
|
|
103142
103342
|
labels { nodes { name } }
|
|
103143
|
-
|
|
103144
|
-
nodes { type
|
|
103343
|
+
inverseRelations(first: 50) {
|
|
103344
|
+
nodes { type issue { id identifier state { type } } }
|
|
103145
103345
|
}
|
|
103146
103346
|
comments(first: 50) {
|
|
103147
103347
|
nodes { id body createdAt user { name email } }
|
|
@@ -103152,24 +103352,26 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
103152
103352
|
const data = await linearRequest(apiKey, query, {
|
|
103153
103353
|
filter: where
|
|
103154
103354
|
});
|
|
103155
|
-
|
|
103156
|
-
|
|
103157
|
-
|
|
103158
|
-
|
|
103159
|
-
|
|
103160
|
-
|
|
103161
|
-
|
|
103162
|
-
|
|
103163
|
-
|
|
103164
|
-
|
|
103165
|
-
|
|
103166
|
-
|
|
103167
|
-
|
|
103168
|
-
|
|
103169
|
-
|
|
103170
|
-
|
|
103171
|
-
|
|
103172
|
-
|
|
103355
|
+
return data.issues.nodes.map((n) => {
|
|
103356
|
+
const blockers = openBlockersFromInverse(n.inverseRelations?.nodes);
|
|
103357
|
+
return {
|
|
103358
|
+
id: n.id,
|
|
103359
|
+
identifier: n.identifier,
|
|
103360
|
+
title: n.title,
|
|
103361
|
+
description: n.description,
|
|
103362
|
+
url: n.url,
|
|
103363
|
+
state: n.state,
|
|
103364
|
+
assignee: n.assignee,
|
|
103365
|
+
project: mapNodeProject(n),
|
|
103366
|
+
...milestoneSpread(n),
|
|
103367
|
+
labels: n.labels.nodes.map((l) => l.name),
|
|
103368
|
+
priority: n.priority,
|
|
103369
|
+
createdAt: n.createdAt ?? "",
|
|
103370
|
+
blockedByIds: blockers.map((b) => b.id),
|
|
103371
|
+
blockedByIdentifiers: blockers.map((b) => b.identifier),
|
|
103372
|
+
comments: n.comments?.nodes ?? []
|
|
103373
|
+
};
|
|
103374
|
+
});
|
|
103173
103375
|
}
|
|
103174
103376
|
async function fetchOpenIssues(apiKey, spec, options) {
|
|
103175
103377
|
const where = buildIssueFilter(spec);
|
|
@@ -103186,10 +103388,10 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
103186
103388
|
project { id name priority }
|
|
103187
103389
|
projectMilestone { id name sortOrder targetDate }
|
|
103188
103390
|
labels { nodes { name } }
|
|
103189
|
-
|
|
103391
|
+
inverseRelations(first: 50) {
|
|
103190
103392
|
nodes {
|
|
103191
103393
|
type
|
|
103192
|
-
|
|
103394
|
+
issue { id identifier state { type } }
|
|
103193
103395
|
}
|
|
103194
103396
|
}
|
|
103195
103397
|
${commentsSlice}
|
|
@@ -103199,24 +103401,26 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
103199
103401
|
const data = await linearRequest(apiKey, query, {
|
|
103200
103402
|
filter: where
|
|
103201
103403
|
});
|
|
103202
|
-
|
|
103203
|
-
|
|
103204
|
-
|
|
103205
|
-
|
|
103206
|
-
|
|
103207
|
-
|
|
103208
|
-
|
|
103209
|
-
|
|
103210
|
-
|
|
103211
|
-
|
|
103212
|
-
|
|
103213
|
-
|
|
103214
|
-
|
|
103215
|
-
|
|
103216
|
-
|
|
103217
|
-
|
|
103218
|
-
|
|
103219
|
-
|
|
103404
|
+
return data.issues.nodes.map((n) => {
|
|
103405
|
+
const blockers = openBlockersFromInverse(n.inverseRelations?.nodes);
|
|
103406
|
+
return {
|
|
103407
|
+
id: n.id,
|
|
103408
|
+
identifier: n.identifier,
|
|
103409
|
+
title: n.title,
|
|
103410
|
+
description: n.description,
|
|
103411
|
+
url: n.url,
|
|
103412
|
+
state: n.state,
|
|
103413
|
+
assignee: n.assignee,
|
|
103414
|
+
project: mapNodeProject(n),
|
|
103415
|
+
...milestoneSpread(n),
|
|
103416
|
+
labels: n.labels.nodes.map((l) => l.name),
|
|
103417
|
+
priority: n.priority,
|
|
103418
|
+
createdAt: n.createdAt ?? "",
|
|
103419
|
+
blockedByIds: blockers.map((b) => b.id),
|
|
103420
|
+
blockedByIdentifiers: blockers.map((b) => b.identifier),
|
|
103421
|
+
...includeComments ? { comments: n.comments?.nodes ?? [] } : {}
|
|
103422
|
+
};
|
|
103423
|
+
});
|
|
103220
103424
|
}
|
|
103221
103425
|
function isRetryableStatus(status) {
|
|
103222
103426
|
return status >= 500 && status <= 599;
|
|
@@ -103530,17 +103734,15 @@ async function fetchBlockedByForIssues(apiKey, issueIds) {
|
|
|
103530
103734
|
issues(filter: { id: { in: $ids } }, first: 250) {
|
|
103531
103735
|
nodes {
|
|
103532
103736
|
id
|
|
103533
|
-
|
|
103534
|
-
nodes { type
|
|
103737
|
+
inverseRelations(first: 50) {
|
|
103738
|
+
nodes { type issue { id identifier state { type } } }
|
|
103535
103739
|
}
|
|
103536
103740
|
}
|
|
103537
103741
|
}
|
|
103538
103742
|
}`;
|
|
103539
103743
|
const data = await linearRequest(apiKey, query, { ids: issueIds });
|
|
103540
|
-
const DONE_STATE_TYPES = new Set(["completed", "cancelled"]);
|
|
103541
103744
|
for (const node2 of data.issues.nodes) {
|
|
103542
|
-
|
|
103543
|
-
out.set(node2.id, blockers);
|
|
103745
|
+
out.set(node2.id, openBlockersFromInverse(node2.inverseRelations?.nodes));
|
|
103544
103746
|
}
|
|
103545
103747
|
return out;
|
|
103546
103748
|
}
|
|
@@ -103754,12 +103956,13 @@ async function removeLabelFromIssue(apiKey, issueId, labelId) {
|
|
|
103754
103956
|
labelId
|
|
103755
103957
|
});
|
|
103756
103958
|
}
|
|
103757
|
-
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:";
|
|
103959
|
+
var LINEAR_API = "https://api.linear.app/graphql", TICKET_IDENTIFIER_RE, TICKET_BARE_NUMBER_RE, DONE_BLOCKER_STATE_TYPES, 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:";
|
|
103758
103960
|
var init_linear_client = __esm(() => {
|
|
103759
103961
|
init_types2();
|
|
103760
103962
|
init_ralph_comment();
|
|
103761
103963
|
TICKET_IDENTIFIER_RE = /^([A-Za-z]+)-(\d+)(?:-.*)?$/;
|
|
103762
103964
|
TICKET_BARE_NUMBER_RE = /^(\d+)$/;
|
|
103965
|
+
DONE_BLOCKER_STATE_TYPES = new Set(["completed", "cancelled"]);
|
|
103763
103966
|
linearRequestInternals = {
|
|
103764
103967
|
sleep: (ms) => Bun.sleep(ms)
|
|
103765
103968
|
};
|
|
@@ -103866,7 +104069,7 @@ async function provisionWorktree(projectRoot, changeName, baseBranch, runner) {
|
|
|
103866
104069
|
if (list.stdout.includes(`worktree ${cwd2}
|
|
103867
104070
|
`)) {
|
|
103868
104071
|
await installPrePushHook(cwd2, runner);
|
|
103869
|
-
return { cwd: cwd2, branch };
|
|
104072
|
+
return { cwd: cwd2, branch, created: false };
|
|
103870
104073
|
}
|
|
103871
104074
|
let branchExists = true;
|
|
103872
104075
|
try {
|
|
@@ -103877,12 +104080,12 @@ async function provisionWorktree(projectRoot, changeName, baseBranch, runner) {
|
|
|
103877
104080
|
if (branchExists) {
|
|
103878
104081
|
await runner.run(["worktree", "add", cwd2, branch], projectRoot);
|
|
103879
104082
|
await installPrePushHook(cwd2, runner);
|
|
103880
|
-
return { cwd: cwd2, branch };
|
|
104083
|
+
return { cwd: cwd2, branch, created: true };
|
|
103881
104084
|
}
|
|
103882
104085
|
await runner.run(["fetch", "origin", baseBranch], projectRoot);
|
|
103883
104086
|
await runner.run(["worktree", "add", "-b", branch, cwd2, `origin/${baseBranch}`], projectRoot);
|
|
103884
104087
|
await installPrePushHook(cwd2, runner);
|
|
103885
|
-
return { cwd: cwd2, branch };
|
|
104088
|
+
return { cwd: cwd2, branch, created: true };
|
|
103886
104089
|
}
|
|
103887
104090
|
async function installPrePushHook(cwd2, runner) {
|
|
103888
104091
|
const hookPath = join22(cwd2, ".ralph-hooks", "pre-push");
|
|
@@ -104188,6 +104391,14 @@ async function branchAlreadyMerged(runner, cwd2, branch, base2) {
|
|
|
104188
104391
|
} catch {}
|
|
104189
104392
|
return false;
|
|
104190
104393
|
}
|
|
104394
|
+
async function applyPrLabels(runner, cwd2, prRef, labels) {
|
|
104395
|
+
const clean = labels.map((l) => l.trim()).filter(Boolean);
|
|
104396
|
+
if (clean.length === 0 || !prRef)
|
|
104397
|
+
return;
|
|
104398
|
+
try {
|
|
104399
|
+
await runner.run(["gh", "pr", "edit", prRef, "--add-label", clean.join(",")], cwd2);
|
|
104400
|
+
} catch {}
|
|
104401
|
+
}
|
|
104191
104402
|
async function createPullRequest(input, runner) {
|
|
104192
104403
|
const base2 = input.base ?? "main";
|
|
104193
104404
|
const log3 = await runner.run(["git", "log", "--oneline", `${base2}..HEAD`, "--no-merges"], input.cwd);
|
|
@@ -104224,8 +104435,10 @@ async function createPullRequest(input, runner) {
|
|
|
104224
104435
|
".[0].url // empty"
|
|
104225
104436
|
], input.cwd);
|
|
104226
104437
|
const existingUrl = existing.stdout.trim();
|
|
104227
|
-
if (existingUrl)
|
|
104438
|
+
if (existingUrl) {
|
|
104439
|
+
await applyPrLabels(runner, input.cwd, existingUrl, input.labels ?? []);
|
|
104228
104440
|
return { url: existingUrl, created: false };
|
|
104441
|
+
}
|
|
104229
104442
|
const title = defaultTitle(input.issue);
|
|
104230
104443
|
const body = defaultBody(input.issue, input.branch, input.stackedOn);
|
|
104231
104444
|
const createArgs = ["gh", "pr", "create", "--base", base2, "--title", title, "--body", body];
|
|
@@ -104234,6 +104447,7 @@ async function createPullRequest(input, runner) {
|
|
|
104234
104447
|
const created = await runner.run(createArgs, input.cwd);
|
|
104235
104448
|
const url2 = created.stdout.trim().split(`
|
|
104236
104449
|
`).pop() ?? "";
|
|
104450
|
+
await applyPrLabels(runner, input.cwd, url2, input.labels ?? []);
|
|
104237
104451
|
return { url: url2, created: true };
|
|
104238
104452
|
}
|
|
104239
104453
|
var init_pr = __esm(() => {
|
|
@@ -104787,7 +105001,7 @@ function emitFeatureSkipped(bus, id, reason) {
|
|
|
104787
105001
|
var init_run_feature = () => {};
|
|
104788
105002
|
|
|
104789
105003
|
// apps/agent/src/agent/post-task.ts
|
|
104790
|
-
import { join as join23
|
|
105004
|
+
import { join as join23 } from "path";
|
|
104791
105005
|
function summarizeUncommittedStatus(stdout) {
|
|
104792
105006
|
const lines = stdout.split(`
|
|
104793
105007
|
`).filter((line) => line.length > 0);
|
|
@@ -104914,6 +105128,7 @@ async function createPrWithRetry(ctx, issue2) {
|
|
|
104914
105128
|
base: base2,
|
|
104915
105129
|
metaOnlyFiles: ctx.cfg.metaOnlyFiles ?? [],
|
|
104916
105130
|
draft: ctx.cfg.prDraft ?? false,
|
|
105131
|
+
labels: ctx.cfg.prLabels ?? [],
|
|
104917
105132
|
...ctx.stackedOn ? {
|
|
104918
105133
|
stackedOn: {
|
|
104919
105134
|
prUrl: ctx.stackedOn.prUrl,
|
|
@@ -105285,17 +105500,6 @@ async function runValidateOnlyPhase(input, deps) {
|
|
|
105285
105500
|
await reactivateState(stateFilePath, log3, changeName);
|
|
105286
105501
|
return respawnWorker();
|
|
105287
105502
|
}
|
|
105288
|
-
async function recordGaveUp(stateFilePath, log3, changeName) {
|
|
105289
|
-
const path = join23(dirname9(stateFilePath), GAVEUP_COUNT_FILE);
|
|
105290
|
-
try {
|
|
105291
|
-
const file2 = Bun.file(path);
|
|
105292
|
-
const current = await file2.exists() ? Number.parseInt(await file2.text(), 10) || 0 : 0;
|
|
105293
|
-
await Bun.write(path, String(current + 1) + `
|
|
105294
|
-
`);
|
|
105295
|
-
} catch (err) {
|
|
105296
|
-
log3(`! could not record gave-up for ${changeName}: ${err.message}`, "yellow");
|
|
105297
|
-
}
|
|
105298
|
-
}
|
|
105299
105503
|
async function runPostTask(input, deps) {
|
|
105300
105504
|
const { log: log3, cmd, git: git2, runScript } = deps;
|
|
105301
105505
|
const emit3 = (phase, detail) => deps.onPhase?.(phase, detail);
|
|
@@ -105338,8 +105542,6 @@ async function runPostTask(input, deps) {
|
|
|
105338
105542
|
respawnWorker
|
|
105339
105543
|
});
|
|
105340
105544
|
emit3(effectiveCode === 0 ? "done" : "gave-up", effectiveCode !== 0 ? `exit ${effectiveCode}` : undefined);
|
|
105341
|
-
if (effectiveCode !== 0)
|
|
105342
|
-
await recordGaveUp(stateFilePath, log3, changeName);
|
|
105343
105545
|
await runWorktreeCleanupPhase({ changeName, cwd: cwd2, projectRoot, useWorktree, effectiveCode, cfg }, { git: git2, log: log3, emit: emit3 });
|
|
105344
105546
|
await runTeardownPhase({ cwd: cwd2, teardownScript: cfg.teardownScript }, { runScript, log: log3, emit: emit3 });
|
|
105345
105547
|
return effectiveCode;
|
|
@@ -105362,7 +105564,6 @@ async function runPostTask(input, deps) {
|
|
|
105362
105564
|
if (checked && aheadCount > 0) {
|
|
105363
105565
|
log3(`! ${identifier}: conflict-fix worker left ${aheadCount} unpushed commit(s) ahead of ` + `origin/${branch} \u2014 the resolution never reached the PR. Failing the iteration so it ` + `is retried instead of reported as resolved.`, "red");
|
|
105364
105566
|
emit3("gave-up", "unpushed conflict resolution");
|
|
105365
|
-
await recordGaveUp(stateFilePath, log3, changeName);
|
|
105366
105567
|
await runWorktreeCleanupPhase({ changeName, cwd: cwd2, projectRoot, useWorktree, effectiveCode: PR_FAILED_EXIT, cfg }, { git: git2, log: log3, emit: emit3 });
|
|
105367
105568
|
await runTeardownPhase({ cwd: cwd2, teardownScript: cfg.teardownScript }, { runScript, log: log3, emit: emit3 });
|
|
105368
105569
|
return PR_FAILED_EXIT;
|
|
@@ -105432,8 +105633,6 @@ async function runPostTask(input, deps) {
|
|
|
105432
105633
|
}
|
|
105433
105634
|
const succeeded = effectiveCode === 0 || effectiveCode === NO_CHANGES_EXIT;
|
|
105434
105635
|
emit3(succeeded ? "done" : "gave-up", succeeded ? undefined : `exit ${effectiveCode}`);
|
|
105435
|
-
if (!succeeded)
|
|
105436
|
-
await recordGaveUp(stateFilePath, log3, changeName);
|
|
105437
105636
|
await deps.runRetrospective?.({
|
|
105438
105637
|
changeName,
|
|
105439
105638
|
cwd: cwd2,
|
|
@@ -105460,7 +105659,6 @@ var PR_FAILED_EXIT = 71, MAX_PR_CREATE_ATTEMPTS = 5, NO_CHANGES_EXIT = 72, repoA
|
|
|
105460
105659
|
return { exitCode: proc.exitCode ?? 1, output };
|
|
105461
105660
|
};
|
|
105462
105661
|
var init_post_task = __esm(() => {
|
|
105463
|
-
init_layout();
|
|
105464
105662
|
init_tasks_md();
|
|
105465
105663
|
init_fs_change();
|
|
105466
105664
|
init_git2();
|
|
@@ -105474,6 +105672,300 @@ var init_post_task = __esm(() => {
|
|
|
105474
105672
|
repoAutoMergeCache = new Map;
|
|
105475
105673
|
});
|
|
105476
105674
|
|
|
105675
|
+
// apps/agent/src/shared/capabilities/gh-client.ts
|
|
105676
|
+
var init_gh_client = () => {};
|
|
105677
|
+
|
|
105678
|
+
// apps/agent/src/shared/capabilities/github/github-client.ts
|
|
105679
|
+
var STARTED_LABEL_NAMES, ISSUE_FIELDS = "id,number,title,body,state,stateReason,labels,assignees,author,createdAt,url", ISSUE_FIELDS_WITH_COMMENTS;
|
|
105680
|
+
var init_github_client = __esm(() => {
|
|
105681
|
+
init_worktree();
|
|
105682
|
+
init_gh_client();
|
|
105683
|
+
STARTED_LABEL_NAMES = new Set(["in progress", "in-progress", "started"]);
|
|
105684
|
+
ISSUE_FIELDS_WITH_COMMENTS = `${ISSUE_FIELDS},comments`;
|
|
105685
|
+
});
|
|
105686
|
+
|
|
105687
|
+
// apps/agent/src/shared/capabilities/github/identifier-strategy.ts
|
|
105688
|
+
function linearChangeName(issue2) {
|
|
105689
|
+
const slug = issue2.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40).replace(/^-+|-+$/g, "");
|
|
105690
|
+
return slug ? `${issue2.identifier.toLowerCase()}-${slug}` : issue2.identifier.toLowerCase();
|
|
105691
|
+
}
|
|
105692
|
+
var linearIdentifierStrategy;
|
|
105693
|
+
var init_identifier_strategy = __esm(() => {
|
|
105694
|
+
init_worktree();
|
|
105695
|
+
init_github_client();
|
|
105696
|
+
linearIdentifierStrategy = {
|
|
105697
|
+
scopeKey: (issue2) => issue2.identifier.split("-")[0],
|
|
105698
|
+
changeName: linearChangeName,
|
|
105699
|
+
branchName: (issue2) => branchForChange(linearChangeName(issue2))
|
|
105700
|
+
};
|
|
105701
|
+
});
|
|
105702
|
+
|
|
105703
|
+
// apps/agent/src/agent/scaffold.ts
|
|
105704
|
+
import { join as join24 } from "path";
|
|
105705
|
+
function changeNameForIssue(issue2) {
|
|
105706
|
+
return linearIdentifierStrategy.changeName(issue2);
|
|
105707
|
+
}
|
|
105708
|
+
async function scaffoldChangeForIssue(tasksDir, statesDir, issue2, comments = [], appendPrompt = "", attachments = []) {
|
|
105709
|
+
const name = changeNameForIssue(issue2);
|
|
105710
|
+
const changeDir = join24(tasksDir, name);
|
|
105711
|
+
const stateDir = join24(statesDir, name);
|
|
105712
|
+
const commentsBlock = comments.length > 0 ? [
|
|
105713
|
+
"",
|
|
105714
|
+
"## Linear comments",
|
|
105715
|
+
"",
|
|
105716
|
+
...comments.flatMap((c) => [
|
|
105717
|
+
`**${c.user?.name ?? "unknown"}** \u2014 ${c.createdAt}`,
|
|
105718
|
+
"",
|
|
105719
|
+
c.body.trim(),
|
|
105720
|
+
""
|
|
105721
|
+
])
|
|
105722
|
+
] : [];
|
|
105723
|
+
const attachmentsBlock = attachments.length > 0 ? [
|
|
105724
|
+
"",
|
|
105725
|
+
"## Ticket Attachments",
|
|
105726
|
+
"",
|
|
105727
|
+
...attachments.map((a) => `- [${a.title ?? "Attachment"}](${a.url})`)
|
|
105728
|
+
] : [];
|
|
105729
|
+
const descriptionBody = issue2.description?.trim() || "_No description provided in Linear._";
|
|
105730
|
+
const proposal = [
|
|
105731
|
+
`# ${issue2.identifier}: ${issue2.title}`,
|
|
105732
|
+
"",
|
|
105733
|
+
`Source: [${issue2.identifier}](${issue2.url})`,
|
|
105734
|
+
`Status: ${issue2.state.name}`,
|
|
105735
|
+
issue2.assignee ? `Assignee: ${issue2.assignee.name}` : "",
|
|
105736
|
+
issue2.labels.length ? `Labels: ${issue2.labels.join(", ")}` : "",
|
|
105737
|
+
"",
|
|
105738
|
+
"## Why",
|
|
105739
|
+
"",
|
|
105740
|
+
descriptionBody,
|
|
105741
|
+
"",
|
|
105742
|
+
"## What Changes",
|
|
105743
|
+
"",
|
|
105744
|
+
"_Describe the concrete changes this proposal introduces (one bullet per change)._",
|
|
105745
|
+
...commentsBlock,
|
|
105746
|
+
...attachmentsBlock,
|
|
105747
|
+
...appendPrompt.trim() ? ["", "## Additional instructions", "", appendPrompt.trim()] : [],
|
|
105748
|
+
"",
|
|
105749
|
+
"## Steering",
|
|
105750
|
+
"",
|
|
105751
|
+
"_Add steering notes here as the loop runs._",
|
|
105752
|
+
""
|
|
105753
|
+
].filter((l) => l !== "").join(`
|
|
105754
|
+
`);
|
|
105755
|
+
const tasks = [
|
|
105756
|
+
`# Tasks for ${issue2.identifier}`,
|
|
105757
|
+
"",
|
|
105758
|
+
"## Planning",
|
|
105759
|
+
"",
|
|
105760
|
+
`- [ ] Read the Linear issue at ${issue2.url} and research the codebase to understand the mission and its scope`,
|
|
105761
|
+
`- [ ] Refine proposal.md with the problem statement, approach, and acceptance criteria derived from the research`,
|
|
105762
|
+
`- [ ] Fill in \`## Why\` and \`## What Changes\` in proposal.md so \`openspec validate\` passes (these sections are required by the validator)`,
|
|
105763
|
+
`- [ ] Add at least one spec delta under \`specs/<capability>/spec.md\` describing the behavior added/modified/removed by this change`,
|
|
105764
|
+
`- [ ] Fill in design.md with the technical design (files to touch, data flow, edge cases). design.md holds prose and tables ONLY \u2014 never a task checklist; the implementation tasks belong in this tasks.md file (next item).`,
|
|
105765
|
+
`- [ ] Append an \`## Implementation\` section to **this tasks.md file** (below the \`## Planning\` section above \u2014 NOT in design.md) with concrete mission-specific tasks derived from the plan, including tests and \`bun run lint\` / \`bun run test\`. Every item in the new section MUST start as \`- [ ]\` (unchecked) \u2014 do not pre-check items even if you already did the work during planning. The loop ticks them off in later iterations after each one is verified.`,
|
|
105766
|
+
`- [ ] Is there anything else to add? Review the complete change context and document any additional edge cases, constraints, or open questions not captured above.`,
|
|
105767
|
+
""
|
|
105768
|
+
].join(`
|
|
105769
|
+
`);
|
|
105770
|
+
const design = [
|
|
105771
|
+
`# Design for ${issue2.identifier}`,
|
|
105772
|
+
"",
|
|
105773
|
+
"_Fill in the technical design as you work through the issue._",
|
|
105774
|
+
""
|
|
105775
|
+
].join(`
|
|
105776
|
+
`);
|
|
105777
|
+
await runCapability(fsChange.scaffold, {
|
|
105778
|
+
changeDir,
|
|
105779
|
+
stateDir,
|
|
105780
|
+
proposal,
|
|
105781
|
+
tasks,
|
|
105782
|
+
design
|
|
105783
|
+
});
|
|
105784
|
+
return name;
|
|
105785
|
+
}
|
|
105786
|
+
var init_scaffold = __esm(() => {
|
|
105787
|
+
init_fs_change();
|
|
105788
|
+
init_identifier_strategy();
|
|
105789
|
+
});
|
|
105790
|
+
|
|
105791
|
+
// apps/agent/src/components/task-pipeline.ts
|
|
105792
|
+
function stages(todo, confirmation, work, pr, ci, done) {
|
|
105793
|
+
return [
|
|
105794
|
+
{ node: "todo", status: todo },
|
|
105795
|
+
{ node: "confirmation", status: confirmation },
|
|
105796
|
+
{ node: "work", status: work },
|
|
105797
|
+
{ node: "PR", status: pr },
|
|
105798
|
+
{ node: "CI", status: ci },
|
|
105799
|
+
{ node: "done", status: done }
|
|
105800
|
+
];
|
|
105801
|
+
}
|
|
105802
|
+
function pipelineStages(row) {
|
|
105803
|
+
const state = row.state;
|
|
105804
|
+
switch (state) {
|
|
105805
|
+
case "todo":
|
|
105806
|
+
return stages("current", "pending", "pending", "pending", "pending", "pending");
|
|
105807
|
+
case "awaiting":
|
|
105808
|
+
return stages("done", "current", "pending", "pending", "pending", "pending");
|
|
105809
|
+
case "queued":
|
|
105810
|
+
case "working":
|
|
105811
|
+
case "in-progress":
|
|
105812
|
+
return stages("done", "done", "current", "pending", "pending", "pending");
|
|
105813
|
+
case "awaiting-ci":
|
|
105814
|
+
return stages("done", "done", "done", "done", "current", "pending");
|
|
105815
|
+
case "conflict-fix":
|
|
105816
|
+
return stages("done", "done", "done", "failed", "pending", "pending");
|
|
105817
|
+
case "ci-fix":
|
|
105818
|
+
return stages("done", "done", "done", "done", "failed", "pending");
|
|
105819
|
+
case "review":
|
|
105820
|
+
return stages("done", "done", "current", "done", "done", "pending");
|
|
105821
|
+
case "quarantined":
|
|
105822
|
+
return row.recovery?.lastReason === "conflicting" ? stages("done", "done", "done", "bailed", "pending", "pending") : stages("done", "done", "done", "done", "bailed", "pending");
|
|
105823
|
+
case "done":
|
|
105824
|
+
return stages("done", "done", "done", "done", "done", "done");
|
|
105825
|
+
case "error":
|
|
105826
|
+
return stages("done", "done", "failed", "pending", "pending", "pending");
|
|
105827
|
+
default: {
|
|
105828
|
+
const exhaustive = state;
|
|
105829
|
+
return exhaustive;
|
|
105830
|
+
}
|
|
105831
|
+
}
|
|
105832
|
+
}
|
|
105833
|
+
function attemptCount(plural) {
|
|
105834
|
+
return `${plural} fix attempt${plural === 1 ? "" : "s"}`;
|
|
105835
|
+
}
|
|
105836
|
+
function statusLabel(row) {
|
|
105837
|
+
const state = row.state;
|
|
105838
|
+
switch (state) {
|
|
105839
|
+
case "todo":
|
|
105840
|
+
return "todo";
|
|
105841
|
+
case "queued":
|
|
105842
|
+
return "queued";
|
|
105843
|
+
case "working":
|
|
105844
|
+
return "working";
|
|
105845
|
+
case "in-progress":
|
|
105846
|
+
return "in progress";
|
|
105847
|
+
case "awaiting":
|
|
105848
|
+
return "awaiting confirmation";
|
|
105849
|
+
case "awaiting-ci":
|
|
105850
|
+
return "awaiting CI";
|
|
105851
|
+
case "conflict-fix":
|
|
105852
|
+
return `conflict \xB7 ${attemptCount(row.recovery?.attempts ?? 0)}`;
|
|
105853
|
+
case "ci-fix":
|
|
105854
|
+
return `CI red \xB7 ${attemptCount(row.recovery?.attempts ?? 0)}`;
|
|
105855
|
+
case "review":
|
|
105856
|
+
return "addressing review";
|
|
105857
|
+
case "quarantined": {
|
|
105858
|
+
const tries = row.recovery?.attempts ?? 0;
|
|
105859
|
+
const reason = row.recovery?.lastReason === "conflicting" ? "conflict" : "CI";
|
|
105860
|
+
return `quarantined \xB7 ${tries} tries (${reason}), bailed`;
|
|
105861
|
+
}
|
|
105862
|
+
case "done":
|
|
105863
|
+
return "done";
|
|
105864
|
+
case "error":
|
|
105865
|
+
return "error";
|
|
105866
|
+
default: {
|
|
105867
|
+
const exhaustive = state;
|
|
105868
|
+
return exhaustive;
|
|
105869
|
+
}
|
|
105870
|
+
}
|
|
105871
|
+
}
|
|
105872
|
+
function buildBoardTree(rows) {
|
|
105873
|
+
const byId = new Map(rows.map((r) => [r.id, r]));
|
|
105874
|
+
const orderIndex = new Map(rows.map((r, i) => [r.id, i]));
|
|
105875
|
+
const blockersOf = (r) => (r.blockedByIds ?? []).filter((id) => id !== r.id && byId.has(id));
|
|
105876
|
+
const childrenOf = new Map;
|
|
105877
|
+
for (const r of rows) {
|
|
105878
|
+
for (const blockerId of blockersOf(r)) {
|
|
105879
|
+
const list = childrenOf.get(blockerId);
|
|
105880
|
+
if (list)
|
|
105881
|
+
list.push(r);
|
|
105882
|
+
else
|
|
105883
|
+
childrenOf.set(blockerId, [r]);
|
|
105884
|
+
}
|
|
105885
|
+
}
|
|
105886
|
+
for (const list of childrenOf.values()) {
|
|
105887
|
+
list.sort((a, b) => orderIndex.get(a.id) - orderIndex.get(b.id));
|
|
105888
|
+
}
|
|
105889
|
+
const emitted = new Set;
|
|
105890
|
+
const depthById = new Map;
|
|
105891
|
+
const result2 = [];
|
|
105892
|
+
const blockerIdentifiersOf = (r) => blockersOf(r).map((id) => byId.get(id).identifier);
|
|
105893
|
+
const tryEmit = (r) => {
|
|
105894
|
+
if (emitted.has(r.id))
|
|
105895
|
+
return;
|
|
105896
|
+
const blockers = blockersOf(r);
|
|
105897
|
+
if (!blockers.every((id) => emitted.has(id)))
|
|
105898
|
+
return;
|
|
105899
|
+
const depth = blockers.length === 0 ? 0 : Math.max(...blockers.map((id) => depthById.get(id))) + 1;
|
|
105900
|
+
depthById.set(r.id, depth);
|
|
105901
|
+
emitted.add(r.id);
|
|
105902
|
+
result2.push({ row: r, depth, blockerIdentifiers: blockerIdentifiersOf(r) });
|
|
105903
|
+
for (const child of childrenOf.get(r.id) ?? [])
|
|
105904
|
+
tryEmit(child);
|
|
105905
|
+
};
|
|
105906
|
+
for (const r of rows) {
|
|
105907
|
+
if (blockersOf(r).length === 0)
|
|
105908
|
+
tryEmit(r);
|
|
105909
|
+
}
|
|
105910
|
+
for (const r of rows) {
|
|
105911
|
+
if (emitted.has(r.id))
|
|
105912
|
+
continue;
|
|
105913
|
+
depthById.set(r.id, 0);
|
|
105914
|
+
emitted.add(r.id);
|
|
105915
|
+
result2.push({ row: r, depth: 0, blockerIdentifiers: blockerIdentifiersOf(r) });
|
|
105916
|
+
for (const child of childrenOf.get(r.id) ?? [])
|
|
105917
|
+
tryEmit(child);
|
|
105918
|
+
}
|
|
105919
|
+
return result2;
|
|
105920
|
+
}
|
|
105921
|
+
function machineStateToTicketState(value) {
|
|
105922
|
+
switch (value) {
|
|
105923
|
+
case "idle":
|
|
105924
|
+
return "in-progress";
|
|
105925
|
+
case "working":
|
|
105926
|
+
return "working";
|
|
105927
|
+
case "conflict-fix":
|
|
105928
|
+
return "conflict-fix";
|
|
105929
|
+
case "ci-fix":
|
|
105930
|
+
return "ci-fix";
|
|
105931
|
+
case "awaiting":
|
|
105932
|
+
return "awaiting";
|
|
105933
|
+
case "awaiting-ci":
|
|
105934
|
+
return "awaiting-ci";
|
|
105935
|
+
case "review":
|
|
105936
|
+
return "review";
|
|
105937
|
+
case "quarantined":
|
|
105938
|
+
return "quarantined";
|
|
105939
|
+
case "preempting":
|
|
105940
|
+
case "routing-after-preempt":
|
|
105941
|
+
return "working";
|
|
105942
|
+
case "done":
|
|
105943
|
+
return "done";
|
|
105944
|
+
case "error":
|
|
105945
|
+
return "error";
|
|
105946
|
+
default:
|
|
105947
|
+
return "working";
|
|
105948
|
+
}
|
|
105949
|
+
}
|
|
105950
|
+
var STATUS_GLYPH, PIPELINE_NODES;
|
|
105951
|
+
var init_task_pipeline = __esm(() => {
|
|
105952
|
+
STATUS_GLYPH = {
|
|
105953
|
+
done: "\u2713",
|
|
105954
|
+
current: "\u25CF",
|
|
105955
|
+
pending: "\u25CB",
|
|
105956
|
+
failed: "\u2717",
|
|
105957
|
+
bailed: "\u26D4"
|
|
105958
|
+
};
|
|
105959
|
+
PIPELINE_NODES = [
|
|
105960
|
+
"todo",
|
|
105961
|
+
"confirmation",
|
|
105962
|
+
"work",
|
|
105963
|
+
"PR",
|
|
105964
|
+
"CI",
|
|
105965
|
+
"done"
|
|
105966
|
+
];
|
|
105967
|
+
});
|
|
105968
|
+
|
|
105477
105969
|
// packages/core/src/ordering/hierarchical-order.ts
|
|
105478
105970
|
function rank(priority) {
|
|
105479
105971
|
return !priority ? Number.POSITIVE_INFINITY : priority;
|
|
@@ -105735,12 +106227,13 @@ var init_queue_order = __esm(() => {
|
|
|
105735
106227
|
});
|
|
105736
106228
|
|
|
105737
106229
|
// apps/agent/src/runtime/coordinator.ts
|
|
106230
|
+
import { appendFile as appendFile2 } from "fs/promises";
|
|
105738
106231
|
function emitCapture(bus, event, properties) {
|
|
105739
106232
|
capture(event, properties);
|
|
105740
106233
|
bus.emit({ type: event, ...properties });
|
|
105741
106234
|
}
|
|
105742
106235
|
function completionCommentBody(args) {
|
|
105743
|
-
const { noChanges, ok, trigger, changeName, code } = args;
|
|
106236
|
+
const { noChanges, ok, trigger, changeName, code, reachedDone } = args;
|
|
105744
106237
|
if (noChanges) {
|
|
105745
106238
|
return buildRalphyComment({
|
|
105746
106239
|
type: "completed-noop",
|
|
@@ -105767,6 +106260,23 @@ function completionCommentBody(args) {
|
|
|
105767
106260
|
fields: { change: changeName }
|
|
105768
106261
|
});
|
|
105769
106262
|
}
|
|
106263
|
+
if (trigger === "ci-fix") {
|
|
106264
|
+
return buildRalphyComment({
|
|
106265
|
+
type: "ci-fix-pushed",
|
|
106266
|
+
action: "pushed a CI fix",
|
|
106267
|
+
body: `Pushed a fix for the failing CI on this PR \u2014 re-checking the checks on the ` + `next poll before marking this done. Change: \`${changeName}\``,
|
|
106268
|
+
fields: { change: changeName }
|
|
106269
|
+
});
|
|
106270
|
+
}
|
|
106271
|
+
if (!reachedDone) {
|
|
106272
|
+
const isReview = trigger === "review";
|
|
106273
|
+
return buildRalphyComment({
|
|
106274
|
+
type: "awaiting-ci",
|
|
106275
|
+
action: isReview ? "addressed review feedback" : "opened a PR",
|
|
106276
|
+
body: (isReview ? `Pushed changes for the review feedback to this PR. ` : `Finished the work and opened a PR. `) + `Awaiting CI, review, and a clean merge state before marking this done. ` + `Change: \`${changeName}\``,
|
|
106277
|
+
fields: { change: changeName }
|
|
106278
|
+
});
|
|
106279
|
+
}
|
|
105770
106280
|
return buildRalphyComment({
|
|
105771
106281
|
type: "completed",
|
|
105772
106282
|
action: "completed work",
|
|
@@ -105799,7 +106309,19 @@ class AgentCoordinator {
|
|
|
105799
106309
|
this.opts = opts;
|
|
105800
106310
|
this.bus = deps.bus ?? createNoopBus();
|
|
105801
106311
|
const providedMachine = flowMachine.provide({ actors: { preemption: preemptionActorLogic } });
|
|
105802
|
-
this.flowStore = new FlowActorStore({
|
|
106312
|
+
this.flowStore = new FlowActorStore({
|
|
106313
|
+
bus: this.bus,
|
|
106314
|
+
persist: () => {},
|
|
106315
|
+
maxRecoveryAttempts: this.opts.prRecovery?.maxRecoverySessions ?? 0,
|
|
106316
|
+
onTransition: (_issueId, changeDir, transition2) => {
|
|
106317
|
+
if (!changeDir)
|
|
106318
|
+
return;
|
|
106319
|
+
const path = `${changeDir}/.ralph-state.flow-history.jsonl`;
|
|
106320
|
+
const line = `${JSON.stringify({ ts: new Date().toISOString(), ...transition2 })}
|
|
106321
|
+
`;
|
|
106322
|
+
appendFile2(path, line).catch(() => {});
|
|
106323
|
+
}
|
|
106324
|
+
}, providedMachine);
|
|
105803
106325
|
}
|
|
105804
106326
|
get activeCount() {
|
|
105805
106327
|
return this.workers.length;
|
|
@@ -105871,7 +106393,15 @@ class AgentCoordinator {
|
|
|
105871
106393
|
awaiting: awaitingCount
|
|
105872
106394
|
};
|
|
105873
106395
|
const found2 = buckets2.todo + buckets2.inProgress + buckets2.mentions + buckets2.awaiting;
|
|
105874
|
-
return {
|
|
106396
|
+
return {
|
|
106397
|
+
found: found2,
|
|
106398
|
+
added: 0,
|
|
106399
|
+
buckets: buckets2,
|
|
106400
|
+
prStatus: emptyPrStatus(),
|
|
106401
|
+
phase: {},
|
|
106402
|
+
flow: {},
|
|
106403
|
+
board: []
|
|
106404
|
+
};
|
|
105875
106405
|
}
|
|
105876
106406
|
const maxT = this.opts.maxTickets ?? 0;
|
|
105877
106407
|
const atTicketLimit = () => {
|
|
@@ -105950,7 +106480,7 @@ class AgentCoordinator {
|
|
|
105950
106480
|
added += 1;
|
|
105951
106481
|
this.deps.onLog(` \u21B3 ${issue2.identifier} queued (fresh)`, "gray");
|
|
105952
106482
|
}
|
|
105953
|
-
const prStatus = await this.scanPrMergeStates();
|
|
106483
|
+
const { counts: prStatus, prByIssue } = await this.scanPrMergeStates();
|
|
105954
106484
|
if (this.queue.length > 0) {
|
|
105955
106485
|
this.queue = orderQueueEntries(this.queue, this.opts.getAutoMerge);
|
|
105956
106486
|
}
|
|
@@ -105980,7 +106510,103 @@ class AgentCoordinator {
|
|
|
105980
106510
|
flow2[w.changeName] = "working";
|
|
105981
106511
|
}
|
|
105982
106512
|
}
|
|
105983
|
-
|
|
106513
|
+
const board = await this.buildBoard({
|
|
106514
|
+
todo,
|
|
106515
|
+
inProgress,
|
|
106516
|
+
mentions,
|
|
106517
|
+
prByIssue,
|
|
106518
|
+
awaitingIds: awaitingClaimed
|
|
106519
|
+
});
|
|
106520
|
+
return { found, added, buckets, prStatus, phase: {}, flow: flow2, board };
|
|
106521
|
+
}
|
|
106522
|
+
async buildBoard(args) {
|
|
106523
|
+
const { todo, inProgress, mentions, prByIssue, awaitingIds } = args;
|
|
106524
|
+
const order = [
|
|
106525
|
+
...this.workers.map((w) => ({
|
|
106526
|
+
issue: w.issue,
|
|
106527
|
+
kind: "worker",
|
|
106528
|
+
changeName: w.changeName
|
|
106529
|
+
})),
|
|
106530
|
+
...this.queue.map((q) => ({
|
|
106531
|
+
issue: q.issue,
|
|
106532
|
+
kind: "queued",
|
|
106533
|
+
changeName: changeNameForIssue(q.issue)
|
|
106534
|
+
})),
|
|
106535
|
+
...inProgress.map((issue2) => ({
|
|
106536
|
+
issue: issue2,
|
|
106537
|
+
kind: awaitingIds.has(issue2.id) ? "awaiting" : "in-progress",
|
|
106538
|
+
changeName: changeNameForIssue(issue2)
|
|
106539
|
+
})),
|
|
106540
|
+
...todo.map((issue2) => ({
|
|
106541
|
+
issue: issue2,
|
|
106542
|
+
kind: "todo",
|
|
106543
|
+
changeName: changeNameForIssue(issue2)
|
|
106544
|
+
})),
|
|
106545
|
+
...mentions.map((m) => ({
|
|
106546
|
+
issue: m.issue,
|
|
106547
|
+
kind: "mention",
|
|
106548
|
+
changeName: changeNameForIssue(m.issue)
|
|
106549
|
+
}))
|
|
106550
|
+
];
|
|
106551
|
+
const seen = new Set;
|
|
106552
|
+
const rows = [];
|
|
106553
|
+
for (const src of order) {
|
|
106554
|
+
if (seen.has(src.issue.id))
|
|
106555
|
+
continue;
|
|
106556
|
+
seen.add(src.issue.id);
|
|
106557
|
+
const row = await this.resolveBoardRow(src.issue, src.kind, src.changeName, prByIssue);
|
|
106558
|
+
if (row)
|
|
106559
|
+
rows.push(row);
|
|
106560
|
+
}
|
|
106561
|
+
return rows;
|
|
106562
|
+
}
|
|
106563
|
+
async resolveBoardRow(issue2, kind, changeName, prByIssue) {
|
|
106564
|
+
let state;
|
|
106565
|
+
let recovery;
|
|
106566
|
+
if (kind === "todo") {
|
|
106567
|
+
state = "todo";
|
|
106568
|
+
} else if (kind === "mention") {
|
|
106569
|
+
state = "review";
|
|
106570
|
+
} else if (kind === "awaiting") {
|
|
106571
|
+
state = "awaiting";
|
|
106572
|
+
} else if (kind !== "worker" && issue2.blockedByIds.length > 0) {
|
|
106573
|
+
state = "todo";
|
|
106574
|
+
} else {
|
|
106575
|
+
const changeDir = this.deps.getChangeDir?.(issue2) ?? undefined;
|
|
106576
|
+
const actor = await this.flowStore.getActor(issue2.id, changeDir);
|
|
106577
|
+
const snapshot = actor.getSnapshot();
|
|
106578
|
+
state = machineStateToTicketState(snapshot.value);
|
|
106579
|
+
if (state === "done")
|
|
106580
|
+
return null;
|
|
106581
|
+
if (kind === "queued" && state === "in-progress")
|
|
106582
|
+
state = "queued";
|
|
106583
|
+
const flowRecovery = snapshot.context.data.recovery;
|
|
106584
|
+
if (flowRecovery) {
|
|
106585
|
+
recovery = {
|
|
106586
|
+
attempts: flowRecovery.attempts,
|
|
106587
|
+
bailed: state === "quarantined",
|
|
106588
|
+
firstFailedAt: flowRecovery.firstFailedAt,
|
|
106589
|
+
lastReason: flowRecovery.lastReason
|
|
106590
|
+
};
|
|
106591
|
+
if (state === "awaiting-ci" || state === "in-progress" || state === "working") {
|
|
106592
|
+
state = flowRecovery.lastReason === "conflicting" ? "conflict-fix" : "ci-fix";
|
|
106593
|
+
}
|
|
106594
|
+
}
|
|
106595
|
+
}
|
|
106596
|
+
const prUrl = prByIssue.get(issue2.id)?.url;
|
|
106597
|
+
return {
|
|
106598
|
+
changeName,
|
|
106599
|
+
id: issue2.id,
|
|
106600
|
+
identifier: issue2.identifier,
|
|
106601
|
+
title: issue2.title,
|
|
106602
|
+
url: issue2.url,
|
|
106603
|
+
priority: issue2.priority,
|
|
106604
|
+
state,
|
|
106605
|
+
blockedByIds: issue2.blockedByIds,
|
|
106606
|
+
blockedByIdentifiers: issue2.blockedByIdentifiers ?? [],
|
|
106607
|
+
...recovery ? { recovery } : {},
|
|
106608
|
+
...prUrl ? { prUrl } : {}
|
|
106609
|
+
};
|
|
105984
106610
|
}
|
|
105985
106611
|
async walkRegistryForInProgress(inProgress) {
|
|
105986
106612
|
const claimed = new Map;
|
|
@@ -106191,20 +106817,20 @@ class AgentCoordinator {
|
|
|
106191
106817
|
}
|
|
106192
106818
|
async scanPrMergeStates() {
|
|
106193
106819
|
const counts = emptyPrStatus();
|
|
106820
|
+
const prByIssue = new Map;
|
|
106194
106821
|
if (!this.opts.prRecovery?.enabled)
|
|
106195
|
-
return counts;
|
|
106822
|
+
return { counts, prByIssue };
|
|
106196
106823
|
let candidates = [];
|
|
106197
106824
|
try {
|
|
106198
106825
|
candidates = await this.deps.fetchDoneCandidates();
|
|
106199
106826
|
} catch (err) {
|
|
106200
106827
|
this.deps.onLog(`! PR merge-state scan fetch failed: ${err.message}`, "yellow");
|
|
106201
|
-
return counts;
|
|
106828
|
+
return { counts, prByIssue };
|
|
106202
106829
|
}
|
|
106203
106830
|
if (candidates.length === 0)
|
|
106204
|
-
return counts;
|
|
106831
|
+
return { counts, prByIssue };
|
|
106205
106832
|
const preQueue = this.queue.map((q) => ({ id: q.issue.id, trigger: q.trigger }));
|
|
106206
106833
|
const preWorkers = this.workers.map((w) => ({ id: w.issueId, trigger: w.trigger }));
|
|
106207
|
-
const tracker = this.opts.prTracker;
|
|
106208
106834
|
for (const issue2 of candidates) {
|
|
106209
106835
|
if (this.workers.some((w) => w.issueId === issue2.id))
|
|
106210
106836
|
continue;
|
|
@@ -106212,12 +106838,17 @@ class AgentCoordinator {
|
|
|
106212
106838
|
continue;
|
|
106213
106839
|
if (this.queue.some((q) => q.issue.id === issue2.id))
|
|
106214
106840
|
continue;
|
|
106215
|
-
|
|
106216
|
-
|
|
106841
|
+
const changeDir = this.deps.getChangeDir?.(issue2) ?? undefined;
|
|
106842
|
+
const actor = await this.flowStore.getActor(issue2.id, changeDir);
|
|
106843
|
+
const stateValue = () => actor.getSnapshot().value;
|
|
106844
|
+
if (stateValue() === "quarantined" && this.errorMarkerCleared(issue2)) {
|
|
106845
|
+
actor.send({ type: "QUARANTINE_CLEARED" });
|
|
106846
|
+
if (changeDir)
|
|
106847
|
+
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106217
106848
|
this.conflictNotified.delete(issue2.id);
|
|
106218
106849
|
this.ciFailedNotified.delete(issue2.id);
|
|
106219
106850
|
this.conflictPromoted.delete(issue2.id);
|
|
106220
|
-
this.deps.onLog(` ${issue2.identifier}:
|
|
106851
|
+
this.deps.onLog(` ${issue2.identifier}: quarantine cleared (ralph:error removed) \u2014 retrying recovery`, "cyan");
|
|
106221
106852
|
}
|
|
106222
106853
|
let pr;
|
|
106223
106854
|
try {
|
|
@@ -106228,45 +106859,47 @@ class AgentCoordinator {
|
|
|
106228
106859
|
}
|
|
106229
106860
|
if (!pr)
|
|
106230
106861
|
continue;
|
|
106862
|
+
prByIssue.set(issue2.id, pr);
|
|
106231
106863
|
if (pr.status === "mergeable")
|
|
106232
106864
|
counts.mergeable += 1;
|
|
106233
|
-
if (pr.status === "mergeable" && this.opts.prTracker) {
|
|
106234
|
-
try {
|
|
106235
|
-
await this.opts.prTracker.clear(issue2.identifier);
|
|
106236
|
-
} catch (err) {
|
|
106237
|
-
this.deps.onLog(`! pr-tracker clear failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106238
|
-
}
|
|
106239
|
-
}
|
|
106240
106865
|
if (pr.status === "mergeable") {
|
|
106241
|
-
const
|
|
106242
|
-
|
|
106243
|
-
if (actor.getSnapshot().value === "awaiting-ci") {
|
|
106866
|
+
const value = stateValue();
|
|
106867
|
+
if (value === "awaiting-ci" || value === "quarantined") {
|
|
106244
106868
|
if (this.issueInSetDoneState(issue2)) {
|
|
106869
|
+
actor.send({ type: "RECOVERY_CLEARED" });
|
|
106245
106870
|
actor.send({ type: "PR_PASSED" });
|
|
106246
106871
|
if (changeDir)
|
|
106247
106872
|
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106248
|
-
if (
|
|
106873
|
+
if (stateValue() === "done")
|
|
106249
106874
|
this.flowStore.disposeActor(issue2.id);
|
|
106250
|
-
}
|
|
106251
106875
|
} else {
|
|
106252
106876
|
await this.advancePrToDone(issue2, pr.url, actor, changeDir);
|
|
106253
106877
|
}
|
|
106878
|
+
} else {
|
|
106879
|
+
actor.send({ type: "RECOVERY_CLEARED" });
|
|
106880
|
+
if (changeDir)
|
|
106881
|
+
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106254
106882
|
}
|
|
106255
106883
|
continue;
|
|
106256
106884
|
}
|
|
106257
106885
|
if (pr.status === "conflicted") {
|
|
106258
106886
|
if (!this.opts.prRecovery?.fixConflicts)
|
|
106259
106887
|
continue;
|
|
106260
|
-
if (
|
|
106888
|
+
if (stateValue() === "quarantined") {
|
|
106261
106889
|
counts.quarantined += 1;
|
|
106262
106890
|
continue;
|
|
106263
106891
|
}
|
|
106264
106892
|
counts.conflicted += 1;
|
|
106265
106893
|
if (this.conflictNotified.has(issue2.id))
|
|
106266
106894
|
continue;
|
|
106267
|
-
|
|
106895
|
+
actor.send({ type: "RESUME_DETECTED" });
|
|
106896
|
+
actor.send({ type: "CONFLICT_DETECTED", at: new Date().toISOString() });
|
|
106897
|
+
if (changeDir)
|
|
106898
|
+
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106899
|
+
if (stateValue() === "quarantined") {
|
|
106268
106900
|
counts.conflicted -= 1;
|
|
106269
106901
|
counts.quarantined += 1;
|
|
106902
|
+
await this.quarantineBail(issue2, pr.url, "conflicting", actor);
|
|
106270
106903
|
continue;
|
|
106271
106904
|
}
|
|
106272
106905
|
emitCapture(this.bus, "agent_conflict_detected", { issue_identifier: issue2.identifier });
|
|
@@ -106284,9 +106917,6 @@ class AgentCoordinator {
|
|
|
106284
106917
|
this.deps.onLog(`! Linear conflict comment failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106285
106918
|
}
|
|
106286
106919
|
}
|
|
106287
|
-
const conflictActor = await this.flowStore.getActor(issue2.id, this.deps.getChangeDir?.(issue2) ?? undefined);
|
|
106288
|
-
conflictActor.send({ type: "RESUME_DETECTED" });
|
|
106289
|
-
conflictActor.send({ type: "CONFLICT_DETECTED" });
|
|
106290
106920
|
this.queue.push({
|
|
106291
106921
|
issue: issue2,
|
|
106292
106922
|
trigger: "conflict-fix",
|
|
@@ -106297,16 +106927,21 @@ class AgentCoordinator {
|
|
|
106297
106927
|
if (pr.status === "ci_failed") {
|
|
106298
106928
|
if (!this.opts.prRecovery?.fixCi)
|
|
106299
106929
|
continue;
|
|
106300
|
-
if (
|
|
106930
|
+
if (stateValue() === "quarantined") {
|
|
106301
106931
|
counts.quarantined += 1;
|
|
106302
106932
|
continue;
|
|
106303
106933
|
}
|
|
106304
106934
|
counts.ciFailed += 1;
|
|
106305
106935
|
if (this.ciFailedNotified.has(issue2.id))
|
|
106306
106936
|
continue;
|
|
106307
|
-
|
|
106937
|
+
actor.send({ type: "RESUME_DETECTED" });
|
|
106938
|
+
actor.send({ type: "CI_FAILED_DETECTED", at: new Date().toISOString() });
|
|
106939
|
+
if (changeDir)
|
|
106940
|
+
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106941
|
+
if (stateValue() === "quarantined") {
|
|
106308
106942
|
counts.ciFailed -= 1;
|
|
106309
106943
|
counts.quarantined += 1;
|
|
106944
|
+
await this.quarantineBail(issue2, pr.url, "ci_failed", actor);
|
|
106310
106945
|
continue;
|
|
106311
106946
|
}
|
|
106312
106947
|
emitCapture(this.bus, "agent_ci_failed_detected", { issue_identifier: issue2.identifier });
|
|
@@ -106324,9 +106959,6 @@ class AgentCoordinator {
|
|
|
106324
106959
|
this.deps.onLog(`! Linear ci-failed comment failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106325
106960
|
}
|
|
106326
106961
|
}
|
|
106327
|
-
const ciActor = await this.flowStore.getActor(issue2.id, this.deps.getChangeDir?.(issue2) ?? undefined);
|
|
106328
|
-
ciActor.send({ type: "RESUME_DETECTED" });
|
|
106329
|
-
ciActor.send({ type: "CI_FAILED_DETECTED" });
|
|
106330
106962
|
this.queue.push({
|
|
106331
106963
|
issue: issue2,
|
|
106332
106964
|
trigger: "ci-fix",
|
|
@@ -106346,7 +106978,7 @@ class AgentCoordinator {
|
|
|
106346
106978
|
else if (w.trigger === "ci-fix")
|
|
106347
106979
|
counts.ciFailed += 1;
|
|
106348
106980
|
}
|
|
106349
|
-
return counts;
|
|
106981
|
+
return { counts, prByIssue };
|
|
106350
106982
|
}
|
|
106351
106983
|
issueInSetDoneState(issue2) {
|
|
106352
106984
|
const sd = this.opts.setDone;
|
|
@@ -106356,6 +106988,7 @@ class AgentCoordinator {
|
|
|
106356
106988
|
}
|
|
106357
106989
|
async advancePrToDone(issue2, prUrl, actor, changeDir) {
|
|
106358
106990
|
this.deps.onLog(` ${issue2.identifier}: PR ${prUrl} mergeable \u2014 moving to done`, "green");
|
|
106991
|
+
actor.send({ type: "RECOVERY_CLEARED" });
|
|
106359
106992
|
if (this.opts.setDone) {
|
|
106360
106993
|
try {
|
|
106361
106994
|
await this.deps.applyIndicator(issue2, this.opts.setDone);
|
|
@@ -106367,6 +107000,8 @@ class AgentCoordinator {
|
|
|
106367
107000
|
issue_identifier: issue2.identifier,
|
|
106368
107001
|
error: err.message
|
|
106369
107002
|
});
|
|
107003
|
+
if (changeDir)
|
|
107004
|
+
await this.flowStore.persistActor(issue2.id, changeDir).catch(() => {});
|
|
106370
107005
|
return;
|
|
106371
107006
|
}
|
|
106372
107007
|
if (this.opts.setInProgress) {
|
|
@@ -106406,48 +107041,34 @@ class AgentCoordinator {
|
|
|
106406
107041
|
const have = new Set(issue2.labels.map((l) => l.toLowerCase()));
|
|
106407
107042
|
return !wantLabels.some((v) => have.has(v));
|
|
106408
107043
|
}
|
|
106409
|
-
async
|
|
106410
|
-
const
|
|
106411
|
-
|
|
106412
|
-
|
|
106413
|
-
|
|
106414
|
-
|
|
106415
|
-
|
|
106416
|
-
}
|
|
106417
|
-
|
|
106418
|
-
|
|
106419
|
-
|
|
106420
|
-
|
|
106421
|
-
|
|
106422
|
-
if (decision.firstBail) {
|
|
106423
|
-
this.deps.onLog(` ${issue2.identifier}: pr-tracker bailing after ${decision.attempts} recovery attempts (${reason}) \u2014 applying setError`, "red");
|
|
106424
|
-
emitCapture(this.bus, "agent_pr_tracker_bailed", {
|
|
106425
|
-
issue_identifier: issue2.identifier,
|
|
106426
|
-
reason,
|
|
106427
|
-
attempts: decision.attempts
|
|
106428
|
-
});
|
|
106429
|
-
if (this.opts.setError) {
|
|
106430
|
-
try {
|
|
106431
|
-
await this.deps.applyIndicator(issue2, this.opts.setError);
|
|
106432
|
-
} catch (err) {
|
|
106433
|
-
this.deps.onLog(`! Linear setError failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106434
|
-
}
|
|
107044
|
+
async quarantineBail(issue2, prUrl, reason, actor) {
|
|
107045
|
+
const attempts = actor.getSnapshot().context.data.recovery?.attempts ?? 0;
|
|
107046
|
+
this.deps.onLog(` ${issue2.identifier}: quarantined after ${attempts} recovery attempts (${reason}) \u2014 applying setError`, "red");
|
|
107047
|
+
emitCapture(this.bus, "agent_pr_tracker_bailed", {
|
|
107048
|
+
issue_identifier: issue2.identifier,
|
|
107049
|
+
reason,
|
|
107050
|
+
attempts
|
|
107051
|
+
});
|
|
107052
|
+
if (this.opts.setError) {
|
|
107053
|
+
try {
|
|
107054
|
+
await this.deps.applyIndicator(issue2, this.opts.setError);
|
|
107055
|
+
} catch (err) {
|
|
107056
|
+
this.deps.onLog(`! Linear setError failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106435
107057
|
}
|
|
106436
|
-
|
|
106437
|
-
|
|
106438
|
-
|
|
106439
|
-
|
|
106440
|
-
|
|
106441
|
-
|
|
106442
|
-
|
|
106443
|
-
|
|
106444
|
-
}
|
|
106445
|
-
}
|
|
106446
|
-
|
|
106447
|
-
}
|
|
107058
|
+
}
|
|
107059
|
+
if (this.opts.postComments !== false) {
|
|
107060
|
+
const human = reason === "conflicting" ? "merge conflicts" : "failing CI";
|
|
107061
|
+
try {
|
|
107062
|
+
await this.deps.postComment(issue2, buildRalphyComment({
|
|
107063
|
+
type: "recovery-gaveup",
|
|
107064
|
+
action: "gave up auto-recovering PR",
|
|
107065
|
+
body: `Gave up auto-recovering this PR (${prUrl}) after ${attempts} attempts \u2014 last failure: ${human}. The \`ralph:error\` label has been applied; clear it (or merge the PR) once a human has looked at it.`,
|
|
107066
|
+
fields: { pr: extractPrNumber(prUrl) ?? prUrl, attempts }
|
|
107067
|
+
}));
|
|
107068
|
+
} catch (err) {
|
|
107069
|
+
this.deps.onLog(`! Linear bail comment failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106448
107070
|
}
|
|
106449
107071
|
}
|
|
106450
|
-
return true;
|
|
106451
107072
|
}
|
|
106452
107073
|
spawnNext() {
|
|
106453
107074
|
if (this.stopped)
|
|
@@ -106762,7 +107383,14 @@ class AgentCoordinator {
|
|
|
106762
107383
|
}
|
|
106763
107384
|
}
|
|
106764
107385
|
if (this.opts.postComments !== false) {
|
|
106765
|
-
const body = completionCommentBody({
|
|
107386
|
+
const body = completionCommentBody({
|
|
107387
|
+
noChanges,
|
|
107388
|
+
ok,
|
|
107389
|
+
trigger,
|
|
107390
|
+
changeName,
|
|
107391
|
+
code,
|
|
107392
|
+
reachedDone: exitActorState === "done"
|
|
107393
|
+
});
|
|
106766
107394
|
try {
|
|
106767
107395
|
await this.deps.postComment(issue2, body);
|
|
106768
107396
|
this.deps.onLog(` ${issue2.identifier}: posted completion comment`, "gray");
|
|
@@ -106856,12 +107484,15 @@ var emptyPrStatus = () => ({
|
|
|
106856
107484
|
},
|
|
106857
107485
|
prStatus: emptyPrStatus(),
|
|
106858
107486
|
phase: {},
|
|
106859
|
-
flow: {}
|
|
107487
|
+
flow: {},
|
|
107488
|
+
board: []
|
|
106860
107489
|
});
|
|
106861
107490
|
var init_coordinator = __esm(() => {
|
|
106862
107491
|
init_types2();
|
|
106863
107492
|
init_linear_client();
|
|
106864
107493
|
init_post_task();
|
|
107494
|
+
init_scaffold();
|
|
107495
|
+
init_task_pipeline();
|
|
106865
107496
|
init_queue_order();
|
|
106866
107497
|
init_src();
|
|
106867
107498
|
init_src2();
|
|
@@ -106876,122 +107507,6 @@ var init_coordinator2 = __esm(() => {
|
|
|
106876
107507
|
init_coordinator();
|
|
106877
107508
|
});
|
|
106878
107509
|
|
|
106879
|
-
// apps/agent/src/shared/capabilities/gh-client.ts
|
|
106880
|
-
var init_gh_client = () => {};
|
|
106881
|
-
|
|
106882
|
-
// apps/agent/src/shared/capabilities/github/github-client.ts
|
|
106883
|
-
var STARTED_LABEL_NAMES, ISSUE_FIELDS = "id,number,title,body,state,stateReason,labels,assignees,author,createdAt,url", ISSUE_FIELDS_WITH_COMMENTS;
|
|
106884
|
-
var init_github_client = __esm(() => {
|
|
106885
|
-
init_worktree();
|
|
106886
|
-
init_gh_client();
|
|
106887
|
-
STARTED_LABEL_NAMES = new Set(["in progress", "in-progress", "started"]);
|
|
106888
|
-
ISSUE_FIELDS_WITH_COMMENTS = `${ISSUE_FIELDS},comments`;
|
|
106889
|
-
});
|
|
106890
|
-
|
|
106891
|
-
// apps/agent/src/shared/capabilities/github/identifier-strategy.ts
|
|
106892
|
-
function linearChangeName(issue2) {
|
|
106893
|
-
const slug = issue2.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40).replace(/^-+|-+$/g, "");
|
|
106894
|
-
return slug ? `${issue2.identifier.toLowerCase()}-${slug}` : issue2.identifier.toLowerCase();
|
|
106895
|
-
}
|
|
106896
|
-
var linearIdentifierStrategy;
|
|
106897
|
-
var init_identifier_strategy = __esm(() => {
|
|
106898
|
-
init_worktree();
|
|
106899
|
-
init_github_client();
|
|
106900
|
-
linearIdentifierStrategy = {
|
|
106901
|
-
scopeKey: (issue2) => issue2.identifier.split("-")[0],
|
|
106902
|
-
changeName: linearChangeName,
|
|
106903
|
-
branchName: (issue2) => branchForChange(linearChangeName(issue2))
|
|
106904
|
-
};
|
|
106905
|
-
});
|
|
106906
|
-
|
|
106907
|
-
// apps/agent/src/agent/scaffold.ts
|
|
106908
|
-
import { join as join24 } from "path";
|
|
106909
|
-
function changeNameForIssue(issue2) {
|
|
106910
|
-
return linearIdentifierStrategy.changeName(issue2);
|
|
106911
|
-
}
|
|
106912
|
-
async function scaffoldChangeForIssue(tasksDir, statesDir, issue2, comments = [], appendPrompt = "", attachments = []) {
|
|
106913
|
-
const name = changeNameForIssue(issue2);
|
|
106914
|
-
const changeDir = join24(tasksDir, name);
|
|
106915
|
-
const stateDir = join24(statesDir, name);
|
|
106916
|
-
const commentsBlock = comments.length > 0 ? [
|
|
106917
|
-
"",
|
|
106918
|
-
"## Linear comments",
|
|
106919
|
-
"",
|
|
106920
|
-
...comments.flatMap((c) => [
|
|
106921
|
-
`**${c.user?.name ?? "unknown"}** \u2014 ${c.createdAt}`,
|
|
106922
|
-
"",
|
|
106923
|
-
c.body.trim(),
|
|
106924
|
-
""
|
|
106925
|
-
])
|
|
106926
|
-
] : [];
|
|
106927
|
-
const attachmentsBlock = attachments.length > 0 ? [
|
|
106928
|
-
"",
|
|
106929
|
-
"## Ticket Attachments",
|
|
106930
|
-
"",
|
|
106931
|
-
...attachments.map((a) => `- [${a.title ?? "Attachment"}](${a.url})`)
|
|
106932
|
-
] : [];
|
|
106933
|
-
const descriptionBody = issue2.description?.trim() || "_No description provided in Linear._";
|
|
106934
|
-
const proposal = [
|
|
106935
|
-
`# ${issue2.identifier}: ${issue2.title}`,
|
|
106936
|
-
"",
|
|
106937
|
-
`Source: [${issue2.identifier}](${issue2.url})`,
|
|
106938
|
-
`Status: ${issue2.state.name}`,
|
|
106939
|
-
issue2.assignee ? `Assignee: ${issue2.assignee.name}` : "",
|
|
106940
|
-
issue2.labels.length ? `Labels: ${issue2.labels.join(", ")}` : "",
|
|
106941
|
-
"",
|
|
106942
|
-
"## Why",
|
|
106943
|
-
"",
|
|
106944
|
-
descriptionBody,
|
|
106945
|
-
"",
|
|
106946
|
-
"## What Changes",
|
|
106947
|
-
"",
|
|
106948
|
-
"_Describe the concrete changes this proposal introduces (one bullet per change)._",
|
|
106949
|
-
...commentsBlock,
|
|
106950
|
-
...attachmentsBlock,
|
|
106951
|
-
...appendPrompt.trim() ? ["", "## Additional instructions", "", appendPrompt.trim()] : [],
|
|
106952
|
-
"",
|
|
106953
|
-
"## Steering",
|
|
106954
|
-
"",
|
|
106955
|
-
"_Add steering notes here as the loop runs._",
|
|
106956
|
-
""
|
|
106957
|
-
].filter((l) => l !== "").join(`
|
|
106958
|
-
`);
|
|
106959
|
-
const tasks = [
|
|
106960
|
-
`# Tasks for ${issue2.identifier}`,
|
|
106961
|
-
"",
|
|
106962
|
-
"## Planning",
|
|
106963
|
-
"",
|
|
106964
|
-
`- [ ] Read the Linear issue at ${issue2.url} and research the codebase to understand the mission and its scope`,
|
|
106965
|
-
`- [ ] Refine proposal.md with the problem statement, approach, and acceptance criteria derived from the research`,
|
|
106966
|
-
`- [ ] Fill in \`## Why\` and \`## What Changes\` in proposal.md so \`openspec validate\` passes (these sections are required by the validator)`,
|
|
106967
|
-
`- [ ] Add at least one spec delta under \`specs/<capability>/spec.md\` describing the behavior added/modified/removed by this change`,
|
|
106968
|
-
`- [ ] Fill in design.md with the technical design (files to touch, data flow, edge cases). design.md holds prose and tables ONLY \u2014 never a task checklist; the implementation tasks belong in this tasks.md file (next item).`,
|
|
106969
|
-
`- [ ] Append an \`## Implementation\` section to **this tasks.md file** (below the \`## Planning\` section above \u2014 NOT in design.md) with concrete mission-specific tasks derived from the plan, including tests and \`bun run lint\` / \`bun run test\`. Every item in the new section MUST start as \`- [ ]\` (unchecked) \u2014 do not pre-check items even if you already did the work during planning. The loop ticks them off in later iterations after each one is verified.`,
|
|
106970
|
-
`- [ ] Is there anything else to add? Review the complete change context and document any additional edge cases, constraints, or open questions not captured above.`,
|
|
106971
|
-
""
|
|
106972
|
-
].join(`
|
|
106973
|
-
`);
|
|
106974
|
-
const design = [
|
|
106975
|
-
`# Design for ${issue2.identifier}`,
|
|
106976
|
-
"",
|
|
106977
|
-
"_Fill in the technical design as you work through the issue._",
|
|
106978
|
-
""
|
|
106979
|
-
].join(`
|
|
106980
|
-
`);
|
|
106981
|
-
await runCapability(fsChange.scaffold, {
|
|
106982
|
-
changeDir,
|
|
106983
|
-
stateDir,
|
|
106984
|
-
proposal,
|
|
106985
|
-
tasks,
|
|
106986
|
-
design
|
|
106987
|
-
});
|
|
106988
|
-
return name;
|
|
106989
|
-
}
|
|
106990
|
-
var init_scaffold = __esm(() => {
|
|
106991
|
-
init_fs_change();
|
|
106992
|
-
init_identifier_strategy();
|
|
106993
|
-
});
|
|
106994
|
-
|
|
106995
107510
|
// packages/core/src/detections/tasks.ts
|
|
106996
107511
|
function hasUnchecked(content) {
|
|
106997
107512
|
return /^- \[ \]/m.test(content);
|
|
@@ -107033,13 +107548,8 @@ function gateActive(inputs) {
|
|
|
107033
107548
|
}
|
|
107034
107549
|
|
|
107035
107550
|
// packages/core/src/detections/mention.ts
|
|
107036
|
-
function buildMentionAckComment(
|
|
107037
|
-
|
|
107038
|
-
return buildRalphyComment({
|
|
107039
|
-
type: "mention-ack",
|
|
107040
|
-
action: "picked up your mention",
|
|
107041
|
-
body: greeting
|
|
107042
|
-
});
|
|
107551
|
+
function buildMentionAckComment() {
|
|
107552
|
+
return buildRalphyMarker("mention-ack", { status: "handled" });
|
|
107043
107553
|
}
|
|
107044
107554
|
var init_mention2 = __esm(() => {
|
|
107045
107555
|
init_src8();
|
|
@@ -107051,7 +107561,7 @@ var init_detections = __esm(() => {
|
|
|
107051
107561
|
});
|
|
107052
107562
|
|
|
107053
107563
|
// apps/agent/src/features/confirmation/state.ts
|
|
107054
|
-
import { dirname as
|
|
107564
|
+
import { dirname as dirname9, join as join25 } from "path";
|
|
107055
107565
|
async function readInlineConfirmation(statePath) {
|
|
107056
107566
|
const f2 = Bun.file(statePath);
|
|
107057
107567
|
if (!await f2.exists())
|
|
@@ -107064,7 +107574,7 @@ async function readInlineConfirmation(statePath) {
|
|
|
107064
107574
|
}
|
|
107065
107575
|
}
|
|
107066
107576
|
async function readConfirmationState(statePath) {
|
|
107067
|
-
const changeDir =
|
|
107577
|
+
const changeDir = dirname9(statePath);
|
|
107068
107578
|
const sidecar = await readSlotSidecar(changeDir, "confirmation");
|
|
107069
107579
|
const existing = sidecar ?? await readInlineConfirmation(statePath) ?? null;
|
|
107070
107580
|
const confirmation = {
|
|
@@ -107080,7 +107590,7 @@ async function readConfirmationState(statePath) {
|
|
|
107080
107590
|
return { stateObj: {}, confirmation };
|
|
107081
107591
|
}
|
|
107082
107592
|
async function writeConfirmationState(statePath, _stateObj, confirmation) {
|
|
107083
|
-
await writeSlotField(
|
|
107593
|
+
await writeSlotField(dirname9(statePath), "confirmation", confirmation);
|
|
107084
107594
|
}
|
|
107085
107595
|
async function restartFromDesign(changeDir, changeName) {
|
|
107086
107596
|
const designStub = [
|
|
@@ -107794,7 +108304,7 @@ function createOpenDraftPr(deps) {
|
|
|
107794
108304
|
if (!branch)
|
|
107795
108305
|
return null;
|
|
107796
108306
|
const base2 = baseBranchFromLabels(issue2.labels) ?? deps.prBaseBranch;
|
|
107797
|
-
const result2 = await create3({ cwd: cwd2, branch, issue: issue2, base: base2, draft: true }, deps.cmdRunner);
|
|
108307
|
+
const result2 = await create3({ cwd: cwd2, branch, issue: issue2, base: base2, draft: true, labels: deps.prLabels ?? [] }, deps.cmdRunner);
|
|
107798
108308
|
const url2 = result2?.url ?? null;
|
|
107799
108309
|
if (url2) {
|
|
107800
108310
|
deps.prByChange.set(changeName, url2);
|
|
@@ -108360,7 +108870,7 @@ function createPrepareHelpers(input) {
|
|
|
108360
108870
|
let scaffoldStatesDir = statesDir;
|
|
108361
108871
|
let branch = null;
|
|
108362
108872
|
if (!useWorktree)
|
|
108363
|
-
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch };
|
|
108873
|
+
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch, worktreeCreated: null };
|
|
108364
108874
|
const probeName = worktreeDirNameForIssue(issue2);
|
|
108365
108875
|
const baseBranch = baseBranchFromLabels(issue2.labels) ?? cfg.prBaseBranch;
|
|
108366
108876
|
let wt;
|
|
@@ -108389,10 +108899,10 @@ function createPrepareHelpers(input) {
|
|
|
108389
108899
|
} catch (err) {
|
|
108390
108900
|
diag("worktree", `! seeding .mcp.json failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
108391
108901
|
}
|
|
108392
|
-
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch };
|
|
108902
|
+
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch, worktreeCreated: wt.created };
|
|
108393
108903
|
}
|
|
108394
108904
|
async function prepare(issue2) {
|
|
108395
|
-
const { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch } = await setupWorktree(issue2);
|
|
108905
|
+
const { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch, worktreeCreated } = await setupWorktree(issue2);
|
|
108396
108906
|
let changeName;
|
|
108397
108907
|
const wtLayoutPre = projectLayout(workerCwd);
|
|
108398
108908
|
const derivedName = changeNameForIssue(issue2);
|
|
@@ -108441,7 +108951,8 @@ function createPrepareHelpers(input) {
|
|
|
108441
108951
|
maps.issueByChange.set(changeName, issue2);
|
|
108442
108952
|
if (branch)
|
|
108443
108953
|
maps.branchByChange.set(changeName, branch);
|
|
108444
|
-
|
|
108954
|
+
const runSetup = worktreeCreated ?? isFresh;
|
|
108955
|
+
if (cfg.setupScript && runSetup) {
|
|
108445
108956
|
await runScript("setup", cfg.setupScript, workerCwd);
|
|
108446
108957
|
}
|
|
108447
108958
|
return {
|
|
@@ -108790,6 +109301,18 @@ function createPrDiscovery(input) {
|
|
|
108790
109301
|
} catch (err) {
|
|
108791
109302
|
diag("ci", `! gh pr checks ${prUrl} failed (PR scan): ${err.message}`, "yellow");
|
|
108792
109303
|
}
|
|
109304
|
+
try {
|
|
109305
|
+
const readiness = await getPollContext().fetchPrOnce(prUrl, ["isDraft", "reviewDecision"], cmdRunner, projectRoot);
|
|
109306
|
+
const isDraft = readiness.isDraft === true;
|
|
109307
|
+
const reviewDecision = readiness.reviewDecision?.toUpperCase();
|
|
109308
|
+
const awaitingApproval = reviewDecision === "REVIEW_REQUIRED" || reviewDecision === "CHANGES_REQUESTED";
|
|
109309
|
+
if (isDraft || awaitingApproval) {
|
|
109310
|
+
diag("pr", ` ${issue2.identifier}: PR ${prUrl} is green + conflict-free but ${isDraft ? "still a draft" : "awaiting review approval"} \u2014 holding (not done) until it is ready`, "gray");
|
|
109311
|
+
return { url: prUrl, status: "unknown" };
|
|
109312
|
+
}
|
|
109313
|
+
} catch (err) {
|
|
109314
|
+
diag("pr", `! gh pr view ${prUrl} readiness check failed (PR scan): ${err.message} \u2014 treating as ready`, "yellow");
|
|
109315
|
+
}
|
|
108793
109316
|
return { url: prUrl, status: "mergeable" };
|
|
108794
109317
|
}
|
|
108795
109318
|
async function resolvePrUrlForIssue(issue2) {
|
|
@@ -108829,17 +109352,17 @@ var init_pr_discovery = __esm(() => {
|
|
|
108829
109352
|
});
|
|
108830
109353
|
|
|
108831
109354
|
// apps/agent/src/features/review-followup/scan.ts
|
|
108832
|
-
import { dirname as
|
|
109355
|
+
import { dirname as dirname10, join as join28 } from "path";
|
|
108833
109356
|
async function resolveReviewStateDir(changeName, deps) {
|
|
108834
109357
|
const root = deps.cwdOf(changeName);
|
|
108835
109358
|
if (root)
|
|
108836
|
-
return
|
|
109359
|
+
return dirname10(projectLayout(root).stateFile(changeName));
|
|
108837
109360
|
if (!deps.useWorktree)
|
|
108838
|
-
return
|
|
109361
|
+
return dirname10(projectLayout(deps.projectRoot).stateFile(changeName));
|
|
108839
109362
|
const wtPath = join28(worktreesDir2(deps.projectRoot), changeName);
|
|
108840
109363
|
const statePath = projectLayout(wtPath).stateFile(changeName);
|
|
108841
109364
|
if (await Bun.file(statePath).exists())
|
|
108842
|
-
return
|
|
109365
|
+
return dirname10(statePath);
|
|
108843
109366
|
return null;
|
|
108844
109367
|
}
|
|
108845
109368
|
async function readReviewWatermark(stateDir) {
|
|
@@ -109172,7 +109695,7 @@ function createMentionScanner(input) {
|
|
|
109172
109695
|
}
|
|
109173
109696
|
if (cfg.linear.postComments !== false) {
|
|
109174
109697
|
try {
|
|
109175
|
-
await createIssueComment(apiKey, issue2.id, buildMentionAckComment(
|
|
109698
|
+
await createIssueComment(apiKey, issue2.id, buildMentionAckComment());
|
|
109176
109699
|
} catch (err) {
|
|
109177
109700
|
diag("mention", `! mention scan: ack comment failed for ${issue2.identifier}: ${formatLinearError(err)}`, "yellow");
|
|
109178
109701
|
}
|
|
@@ -109221,7 +109744,7 @@ function createMentionScanner(input) {
|
|
|
109221
109744
|
}
|
|
109222
109745
|
}
|
|
109223
109746
|
if (cfg.linear.postComments !== false) {
|
|
109224
|
-
await postGithubPrComment(cmdRunner, projectRoot, prUrl, buildMentionAckComment(
|
|
109747
|
+
await postGithubPrComment(cmdRunner, projectRoot, prUrl, buildMentionAckComment(), onLog);
|
|
109225
109748
|
}
|
|
109226
109749
|
}
|
|
109227
109750
|
queued.add(issue2.id);
|
|
@@ -109636,6 +110159,7 @@ function buildPostTaskInput(input) {
|
|
|
109636
110159
|
finalizeNoOpAsDone: cfg.finalizeNoOpAsDone,
|
|
109637
110160
|
manualMergeWhenAutoMergeDisabled: cfg.manualMergeWhenAutoMergeDisabled,
|
|
109638
110161
|
prDraft: cfg.prDraft,
|
|
110162
|
+
prLabels: cfg.prLabels,
|
|
109639
110163
|
validateCommands: [cfg.commands.test, cfg.commands.lint, cfg.commands.typecheck].filter((c) => Boolean(c))
|
|
109640
110164
|
},
|
|
109641
110165
|
respawnWorker: input.respawnWorker
|
|
@@ -110226,7 +110750,7 @@ var init_linear_sync = __esm(() => {
|
|
|
110226
110750
|
});
|
|
110227
110751
|
|
|
110228
110752
|
// apps/agent/src/agent/linear-sync/comment-sync.ts
|
|
110229
|
-
import { dirname as
|
|
110753
|
+
import { dirname as dirname11, join as join34 } from "path";
|
|
110230
110754
|
async function readInlineLinearComments(statePath) {
|
|
110231
110755
|
const file2 = Bun.file(statePath);
|
|
110232
110756
|
if (!await file2.exists())
|
|
@@ -110239,7 +110763,7 @@ async function readInlineLinearComments(statePath) {
|
|
|
110239
110763
|
}
|
|
110240
110764
|
}
|
|
110241
110765
|
async function readComments(statePath) {
|
|
110242
|
-
const changeDir =
|
|
110766
|
+
const changeDir = dirname11(statePath);
|
|
110243
110767
|
const raw = await readSlotSidecar(changeDir, "linearComments") ?? await readInlineLinearComments(statePath) ?? {};
|
|
110244
110768
|
const r = raw;
|
|
110245
110769
|
return {
|
|
@@ -110252,7 +110776,7 @@ async function readComments(statePath) {
|
|
|
110252
110776
|
async function patchComments(statePath, patch) {
|
|
110253
110777
|
const current = await readComments(statePath);
|
|
110254
110778
|
const next = { ...current, ...patch };
|
|
110255
|
-
await writeSlotField(
|
|
110779
|
+
await writeSlotField(dirname11(statePath), "linearComments", next);
|
|
110256
110780
|
}
|
|
110257
110781
|
function isCommentNotFoundError(err) {
|
|
110258
110782
|
if (!err)
|
|
@@ -262362,22 +262886,20 @@ function renderCodeBlock(doc2, token, indent) {
|
|
|
262362
262886
|
const text = token.text ?? "";
|
|
262363
262887
|
const x2 = MARGIN + indent;
|
|
262364
262888
|
const width = doc2.page.width - 2 * MARGIN - indent;
|
|
262889
|
+
const textWidth = width - 2 * CODE_PADDING_X;
|
|
262365
262890
|
doc2.font(FONT_MONO).fontSize(CODE_SIZE).fillColor(COLOR_TEXT);
|
|
262366
|
-
const lineHeight = doc2.currentLineHeight(true);
|
|
262367
262891
|
const lines = text.split(/\r?\n/);
|
|
262368
262892
|
doc2.y += CODE_PADDING_Y / 2;
|
|
262369
262893
|
for (const line of lines) {
|
|
262370
|
-
|
|
262894
|
+
const safe = toPdfSafe(line.length > 0 ? line : " ");
|
|
262895
|
+
const lineHeight = doc2.heightOfString(safe, { width: textWidth, lineBreak: true });
|
|
262896
|
+
if (doc2.y + lineHeight + CODE_PADDING_Y > doc2.page.height - MARGIN && doc2.y > doc2.page.margins.top) {
|
|
262371
262897
|
doc2.addPage();
|
|
262372
262898
|
}
|
|
262373
262899
|
const yTop = doc2.y;
|
|
262374
|
-
const safe = toPdfSafe(line);
|
|
262375
262900
|
doc2.rect(x2, yTop, width, lineHeight).fill(COLOR_CODE_BG);
|
|
262376
262901
|
doc2.fillColor(COLOR_TEXT);
|
|
262377
|
-
doc2.text(safe
|
|
262378
|
-
width: width - 2 * CODE_PADDING_X,
|
|
262379
|
-
lineBreak: false
|
|
262380
|
-
});
|
|
262902
|
+
doc2.text(safe, x2 + CODE_PADDING_X, yTop, { width: textWidth, lineBreak: true });
|
|
262381
262903
|
doc2.y = yTop + lineHeight;
|
|
262382
262904
|
}
|
|
262383
262905
|
doc2.y += CODE_PADDING_Y / 2;
|
|
@@ -262465,38 +262987,85 @@ function flattenInline(tokens, flags = {}) {
|
|
|
262465
262987
|
}
|
|
262466
262988
|
return out;
|
|
262467
262989
|
}
|
|
262990
|
+
function applyInlineStyle(doc2, run) {
|
|
262991
|
+
if (run.code) {
|
|
262992
|
+
doc2.font(FONT_MONO).fontSize(BODY_SIZE).fillColor(COLOR_INLINE_CODE_FG);
|
|
262993
|
+
return;
|
|
262994
|
+
}
|
|
262995
|
+
doc2.fontSize(BODY_SIZE).fillColor(COLOR_TEXT);
|
|
262996
|
+
if (run.bold && run.italic)
|
|
262997
|
+
doc2.font(FONT_BOLD_ITALIC);
|
|
262998
|
+
else if (run.bold)
|
|
262999
|
+
doc2.font(FONT_BOLD);
|
|
263000
|
+
else if (run.italic)
|
|
263001
|
+
doc2.font(FONT_ITALIC);
|
|
263002
|
+
else
|
|
263003
|
+
doc2.font(FONT_BODY);
|
|
263004
|
+
}
|
|
263005
|
+
function atomizeInline(flat) {
|
|
263006
|
+
const atoms = [];
|
|
263007
|
+
for (const run of flat) {
|
|
263008
|
+
const safe = toPdfSafe(run.text);
|
|
263009
|
+
for (const part of safe.split(/(\n|[ \t]+)/)) {
|
|
263010
|
+
if (part === "")
|
|
263011
|
+
continue;
|
|
263012
|
+
if (part === `
|
|
263013
|
+
`)
|
|
263014
|
+
atoms.push({ text: "", run, space: false, br: true });
|
|
263015
|
+
else if (/^[ \t]+$/.test(part))
|
|
263016
|
+
atoms.push({ text: part, run, space: true, br: false });
|
|
263017
|
+
else
|
|
263018
|
+
atoms.push({ text: part, run, space: false, br: false });
|
|
263019
|
+
}
|
|
263020
|
+
}
|
|
263021
|
+
return atoms;
|
|
263022
|
+
}
|
|
262468
263023
|
function emitInline(doc2, tokens, x2, width) {
|
|
262469
263024
|
const flat = flattenInline(tokens);
|
|
262470
263025
|
if (flat.length === 0)
|
|
262471
263026
|
return;
|
|
262472
|
-
|
|
262473
|
-
|
|
262474
|
-
|
|
262475
|
-
|
|
262476
|
-
|
|
262477
|
-
|
|
262478
|
-
|
|
262479
|
-
|
|
262480
|
-
|
|
262481
|
-
|
|
262482
|
-
|
|
262483
|
-
|
|
262484
|
-
|
|
262485
|
-
|
|
262486
|
-
|
|
262487
|
-
|
|
262488
|
-
|
|
262489
|
-
doc2.font(FONT_ITALIC);
|
|
262490
|
-
else
|
|
262491
|
-
doc2.font(FONT_BODY);
|
|
263027
|
+
const atoms = atomizeInline(flat);
|
|
263028
|
+
if (atoms.length === 0)
|
|
263029
|
+
return;
|
|
263030
|
+
doc2.font(FONT_BODY).fontSize(BODY_SIZE);
|
|
263031
|
+
const lineHeight = doc2.currentLineHeight(true);
|
|
263032
|
+
const right = x2 + width;
|
|
263033
|
+
const bottom = doc2.page.height - MARGIN;
|
|
263034
|
+
let cursorX = x2;
|
|
263035
|
+
let cursorY = doc2.y;
|
|
263036
|
+
let pendingSpace = 0;
|
|
263037
|
+
const newLine = () => {
|
|
263038
|
+
cursorX = x2;
|
|
263039
|
+
cursorY += lineHeight;
|
|
263040
|
+
pendingSpace = 0;
|
|
263041
|
+
if (cursorY + lineHeight > bottom) {
|
|
263042
|
+
doc2.addPage();
|
|
263043
|
+
cursorY = doc2.page.margins.top;
|
|
262492
263044
|
}
|
|
262493
|
-
|
|
262494
|
-
|
|
262495
|
-
|
|
263045
|
+
};
|
|
263046
|
+
for (const atom of atoms) {
|
|
263047
|
+
if (atom.br) {
|
|
263048
|
+
newLine();
|
|
263049
|
+
continue;
|
|
263050
|
+
}
|
|
263051
|
+
applyInlineStyle(doc2, atom.run);
|
|
263052
|
+
if (atom.space) {
|
|
263053
|
+
if (cursorX > x2)
|
|
263054
|
+
pendingSpace += doc2.widthOfString(atom.text);
|
|
263055
|
+
continue;
|
|
263056
|
+
}
|
|
263057
|
+
const wordWidth = doc2.widthOfString(atom.text);
|
|
263058
|
+
if (cursorX > x2 && cursorX + pendingSpace + wordWidth > right + 0.01) {
|
|
263059
|
+
newLine();
|
|
262496
263060
|
} else {
|
|
262497
|
-
|
|
263061
|
+
cursorX += pendingSpace;
|
|
263062
|
+
pendingSpace = 0;
|
|
262498
263063
|
}
|
|
263064
|
+
applyInlineStyle(doc2, atom.run);
|
|
263065
|
+
doc2.text(atom.text, cursorX, cursorY, { lineBreak: false, continued: false });
|
|
263066
|
+
cursorX += wordWidth;
|
|
262499
263067
|
}
|
|
263068
|
+
doc2.y = cursorY + lineHeight;
|
|
262500
263069
|
doc2.font(FONT_BODY).fontSize(BODY_SIZE).fillColor(COLOR_TEXT);
|
|
262501
263070
|
}
|
|
262502
263071
|
function plainInline(tokens) {
|
|
@@ -262676,7 +263245,7 @@ var init_render_pdf = __esm(() => {
|
|
|
262676
263245
|
});
|
|
262677
263246
|
|
|
262678
263247
|
// apps/agent/src/agent/linear-sync/spec-attachments.ts
|
|
262679
|
-
import { dirname as
|
|
263248
|
+
import { dirname as dirname12, join as join35 } from "path";
|
|
262680
263249
|
function describeLinearError(err) {
|
|
262681
263250
|
const e = err;
|
|
262682
263251
|
const parts = [e.message ?? String(err)];
|
|
@@ -262691,7 +263260,7 @@ function describeLinearError(err) {
|
|
|
262691
263260
|
return parts.join(" ");
|
|
262692
263261
|
}
|
|
262693
263262
|
function stateDirOf(statePath) {
|
|
262694
|
-
return
|
|
263263
|
+
return dirname12(statePath);
|
|
262695
263264
|
}
|
|
262696
263265
|
async function readInlineSpecAttachments(statePath) {
|
|
262697
263266
|
const file2 = Bun.file(statePath);
|
|
@@ -262709,7 +263278,7 @@ async function readInlineSpecAttachments(statePath) {
|
|
|
262709
263278
|
}
|
|
262710
263279
|
}
|
|
262711
263280
|
async function readSpecAttachmentsSubtree(statePath) {
|
|
262712
|
-
const sidecar = await readSlotSidecar(
|
|
263281
|
+
const sidecar = await readSlotSidecar(dirname12(statePath), "specAttachments");
|
|
262713
263282
|
return sidecar ?? await readInlineSpecAttachments(statePath);
|
|
262714
263283
|
}
|
|
262715
263284
|
function asRevisions(value) {
|
|
@@ -263201,105 +263770,8 @@ var init_comment_sync2 = __esm(() => {
|
|
|
263201
263770
|
init_linear();
|
|
263202
263771
|
});
|
|
263203
263772
|
|
|
263204
|
-
// apps/agent/src/features/pr-tracker/state.ts
|
|
263205
|
-
import { join as join36 } from "path";
|
|
263206
|
-
async function readState2(projectRoot) {
|
|
263207
|
-
const path = join36(projectRoot, PR_TRACKER_STATE_RELPATH);
|
|
263208
|
-
const file2 = Bun.file(path);
|
|
263209
|
-
if (!await file2.exists())
|
|
263210
|
-
return {};
|
|
263211
|
-
try {
|
|
263212
|
-
const raw = await file2.text();
|
|
263213
|
-
const parsed = JSON.parse(raw);
|
|
263214
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
263215
|
-
return parsed;
|
|
263216
|
-
}
|
|
263217
|
-
return {};
|
|
263218
|
-
} catch {
|
|
263219
|
-
return {};
|
|
263220
|
-
}
|
|
263221
|
-
}
|
|
263222
|
-
async function writeState2(projectRoot, state) {
|
|
263223
|
-
const path = join36(projectRoot, PR_TRACKER_STATE_RELPATH);
|
|
263224
|
-
await Bun.write(path, JSON.stringify(state, null, 2));
|
|
263225
|
-
}
|
|
263226
|
-
var PR_TRACKER_STATE_RELPATH = ".ralph/pr-tracker-state.json";
|
|
263227
|
-
var init_state3 = () => {};
|
|
263228
|
-
|
|
263229
|
-
// apps/agent/src/features/pr-tracker/tracker.ts
|
|
263230
|
-
class PrTracker {
|
|
263231
|
-
opts;
|
|
263232
|
-
state = {};
|
|
263233
|
-
loaded = false;
|
|
263234
|
-
now;
|
|
263235
|
-
constructor(opts) {
|
|
263236
|
-
this.opts = opts;
|
|
263237
|
-
this.now = opts.now ?? (() => new Date);
|
|
263238
|
-
}
|
|
263239
|
-
async load() {
|
|
263240
|
-
if (this.loaded)
|
|
263241
|
-
return;
|
|
263242
|
-
this.state = await readState2(this.opts.projectRoot);
|
|
263243
|
-
this.loaded = true;
|
|
263244
|
-
}
|
|
263245
|
-
snapshot() {
|
|
263246
|
-
return JSON.parse(JSON.stringify(this.state));
|
|
263247
|
-
}
|
|
263248
|
-
isBailed(identifier) {
|
|
263249
|
-
return this.state[identifier]?.bailed === true;
|
|
263250
|
-
}
|
|
263251
|
-
getAttempts(identifier) {
|
|
263252
|
-
return this.state[identifier]?.attempts ?? 0;
|
|
263253
|
-
}
|
|
263254
|
-
async recordFailure(identifier, reason) {
|
|
263255
|
-
await this.load();
|
|
263256
|
-
const nowIso = this.now().toISOString();
|
|
263257
|
-
const existing = this.state[identifier];
|
|
263258
|
-
if (existing?.bailed) {
|
|
263259
|
-
existing.lastReason = reason;
|
|
263260
|
-
await this.flush();
|
|
263261
|
-
return { kind: "bail", attempts: existing.attempts, firstBail: false };
|
|
263262
|
-
}
|
|
263263
|
-
const attempts = (existing?.attempts ?? 0) + 1;
|
|
263264
|
-
const entry = {
|
|
263265
|
-
attempts,
|
|
263266
|
-
firstFailedAt: existing?.firstFailedAt ?? nowIso,
|
|
263267
|
-
lastDemotedAt: nowIso,
|
|
263268
|
-
lastReason: reason
|
|
263269
|
-
};
|
|
263270
|
-
if (attempts >= this.opts.maxRecoveryAttempts) {
|
|
263271
|
-
entry.bailed = true;
|
|
263272
|
-
this.state[identifier] = entry;
|
|
263273
|
-
await this.flush();
|
|
263274
|
-
return { kind: "bail", attempts, firstBail: true };
|
|
263275
|
-
}
|
|
263276
|
-
this.state[identifier] = entry;
|
|
263277
|
-
await this.flush();
|
|
263278
|
-
return { kind: "demote", attempts };
|
|
263279
|
-
}
|
|
263280
|
-
async clear(identifier) {
|
|
263281
|
-
await this.load();
|
|
263282
|
-
if (!(identifier in this.state))
|
|
263283
|
-
return;
|
|
263284
|
-
delete this.state[identifier];
|
|
263285
|
-
await this.flush();
|
|
263286
|
-
}
|
|
263287
|
-
async flush() {
|
|
263288
|
-
await writeState2(this.opts.projectRoot, this.state);
|
|
263289
|
-
}
|
|
263290
|
-
}
|
|
263291
|
-
var init_tracker = __esm(() => {
|
|
263292
|
-
init_state3();
|
|
263293
|
-
});
|
|
263294
|
-
|
|
263295
|
-
// apps/agent/src/features/pr-tracker/index.ts
|
|
263296
|
-
var init_pr_tracker = __esm(() => {
|
|
263297
|
-
init_tracker();
|
|
263298
|
-
init_state3();
|
|
263299
|
-
});
|
|
263300
|
-
|
|
263301
263773
|
// apps/agent/src/agent/wire.ts
|
|
263302
|
-
import { join as
|
|
263774
|
+
import { join as join36 } from "path";
|
|
263303
263775
|
function buildAgentCoordinator(input) {
|
|
263304
263776
|
const {
|
|
263305
263777
|
args,
|
|
@@ -263318,7 +263790,7 @@ function buildAgentCoordinator(input) {
|
|
|
263318
263790
|
onWorkerCmd,
|
|
263319
263791
|
onAwaitingTicket
|
|
263320
263792
|
} = input;
|
|
263321
|
-
const logsDir =
|
|
263793
|
+
const logsDir = join36(projectRoot, ".ralph", "logs");
|
|
263322
263794
|
const bus = createBus();
|
|
263323
263795
|
subscribeAgentDiag(bus, onLog);
|
|
263324
263796
|
const diag = (area, message, color) => {
|
|
@@ -263498,6 +263970,7 @@ function buildAgentCoordinator(input) {
|
|
|
263498
263970
|
prByChange,
|
|
263499
263971
|
cmdRunner,
|
|
263500
263972
|
prBaseBranch: cfg.prBaseBranch,
|
|
263973
|
+
prLabels: cfg.prLabels,
|
|
263501
263974
|
invalidatePrUrlForIssue: (issueId) => prDiscovery.invalidatePrUrlForIssue(issueId)
|
|
263502
263975
|
});
|
|
263503
263976
|
const confirmationCaps = {
|
|
@@ -263537,10 +264010,6 @@ function buildAgentCoordinator(input) {
|
|
|
263537
264010
|
};
|
|
263538
264011
|
}
|
|
263539
264012
|
const prRecoveryEnabled = args.prRecoveryEnabled === undefined ? cfg.prRecovery.enabled : args.prRecoveryEnabled;
|
|
263540
|
-
const prTracker = prRecoveryEnabled ? new PrTracker({
|
|
263541
|
-
projectRoot,
|
|
263542
|
-
maxRecoveryAttempts: cfg.prRecovery.maxRecoverySessions
|
|
263543
|
-
}) : null;
|
|
263544
264013
|
const commentSync = isGithubTracker ? { enabled: false } : createCommentSyncHooks({
|
|
263545
264014
|
apiKey,
|
|
263546
264015
|
cfg,
|
|
@@ -263586,7 +264055,7 @@ function buildAgentCoordinator(input) {
|
|
|
263586
264055
|
const changeDir = projectLayout(root).changeDir(changeName);
|
|
263587
264056
|
const parts = [];
|
|
263588
264057
|
for (const name of ["tasks.md", "proposal.md", "design.md"]) {
|
|
263589
|
-
const file2 = Bun.file(
|
|
264058
|
+
const file2 = Bun.file(join36(changeDir, name));
|
|
263590
264059
|
if (!await file2.exists())
|
|
263591
264060
|
continue;
|
|
263592
264061
|
parts.push(`${name}:${file2.lastModified}:${file2.size}`);
|
|
@@ -263605,11 +264074,11 @@ function buildAgentCoordinator(input) {
|
|
|
263605
264074
|
commentEveryIterations: cfg.linear.updateEveryIterations,
|
|
263606
264075
|
...args.maxTickets > 0 ? { maxTickets: args.maxTickets } : {},
|
|
263607
264076
|
createsPrs: args.createPr || cfg.createPrOnSuccess,
|
|
263608
|
-
...prTracker ? { prTracker } : {},
|
|
263609
264077
|
prRecovery: {
|
|
263610
264078
|
enabled: prRecoveryEnabled,
|
|
263611
264079
|
fixCi: cfg.prRecovery.fixCi,
|
|
263612
|
-
fixConflicts: cfg.prRecovery.fixConflicts
|
|
264080
|
+
fixConflicts: cfg.prRecovery.fixConflicts,
|
|
264081
|
+
maxRecoverySessions: cfg.prRecovery.maxRecoverySessions
|
|
263613
264082
|
}
|
|
263614
264083
|
});
|
|
263615
264084
|
coordRef.current = coord;
|
|
@@ -263633,19 +264102,7 @@ function buildAgentCoordinator(input) {
|
|
|
263633
264102
|
pollInterval,
|
|
263634
264103
|
getWorkerCwd: (changeName) => cwdByChange.get(changeName),
|
|
263635
264104
|
syncTasksEnabled: commentSync.enabled,
|
|
263636
|
-
runBaselineGate: runBaselineGateOnce
|
|
263637
|
-
getGaveUpTotal: async () => {
|
|
263638
|
-
let total = 0;
|
|
263639
|
-
for (const [changeName, root] of cwdByChange) {
|
|
263640
|
-
const file2 = Bun.file(join37(projectLayout(root).taskStateDir(changeName), GAVEUP_COUNT_FILE));
|
|
263641
|
-
if (!await file2.exists())
|
|
263642
|
-
continue;
|
|
263643
|
-
try {
|
|
263644
|
-
total += Number.parseInt(await file2.text(), 10) || 0;
|
|
263645
|
-
} catch {}
|
|
263646
|
-
}
|
|
263647
|
-
return total;
|
|
263648
|
-
}
|
|
264105
|
+
runBaselineGate: runBaselineGateOnce
|
|
263649
264106
|
};
|
|
263650
264107
|
}
|
|
263651
264108
|
var init_wire = __esm(() => {
|
|
@@ -263669,18 +264126,17 @@ var init_wire = __esm(() => {
|
|
|
263669
264126
|
init_worker();
|
|
263670
264127
|
init_baseline();
|
|
263671
264128
|
init_comment_sync2();
|
|
263672
|
-
init_pr_tracker();
|
|
263673
264129
|
});
|
|
263674
264130
|
|
|
263675
264131
|
// apps/agent/src/agent/json-log/json-log-file.ts
|
|
263676
|
-
import { mkdir as mkdir11, appendFile as
|
|
263677
|
-
import { dirname as
|
|
264132
|
+
import { mkdir as mkdir11, appendFile as appendFile3 } from "fs/promises";
|
|
264133
|
+
import { dirname as dirname13 } from "path";
|
|
263678
264134
|
function createJsonLogFileSink(path) {
|
|
263679
264135
|
if (!path)
|
|
263680
264136
|
return { emit: () => {} };
|
|
263681
264137
|
let chain = (async () => {
|
|
263682
264138
|
try {
|
|
263683
|
-
await mkdir11(
|
|
264139
|
+
await mkdir11(dirname13(path), { recursive: true });
|
|
263684
264140
|
await Bun.write(path, "");
|
|
263685
264141
|
} catch {}
|
|
263686
264142
|
})();
|
|
@@ -263690,7 +264146,7 @@ function createJsonLogFileSink(path) {
|
|
|
263690
264146
|
`;
|
|
263691
264147
|
chain = chain.then(async () => {
|
|
263692
264148
|
try {
|
|
263693
|
-
await
|
|
264149
|
+
await appendFile3(path, line);
|
|
263694
264150
|
} catch {}
|
|
263695
264151
|
});
|
|
263696
264152
|
}
|
|
@@ -263926,7 +264382,7 @@ var init_output_utils = __esm(() => {
|
|
|
263926
264382
|
});
|
|
263927
264383
|
|
|
263928
264384
|
// apps/agent/src/agent/state/worker-state-poll.ts
|
|
263929
|
-
import { join as
|
|
264385
|
+
import { join as join37 } from "path";
|
|
263930
264386
|
function parseSubtasks(tasksMd) {
|
|
263931
264387
|
const out = [];
|
|
263932
264388
|
let skipSection = false;
|
|
@@ -263959,7 +264415,7 @@ function initialWorkerSnapshot() {
|
|
|
263959
264415
|
async function readWorkerSnapshot(input) {
|
|
263960
264416
|
const next = { ...input.prev };
|
|
263961
264417
|
try {
|
|
263962
|
-
const file2 = Bun.file(
|
|
264418
|
+
const file2 = Bun.file(join37(input.statesDir, input.changeName, ".ralph-state.json"));
|
|
263963
264419
|
if (await file2.exists()) {
|
|
263964
264420
|
const json2 = await file2.json();
|
|
263965
264421
|
next.iter = json2.iteration ?? next.iter;
|
|
@@ -263968,10 +264424,10 @@ async function readWorkerSnapshot(input) {
|
|
|
263968
264424
|
} catch {}
|
|
263969
264425
|
if (input.changeDir) {
|
|
263970
264426
|
try {
|
|
263971
|
-
const tasksFile = Bun.file(
|
|
263972
|
-
const proposalFile = Bun.file(
|
|
263973
|
-
const designFile = Bun.file(
|
|
263974
|
-
const reviewFindingsFile = Bun.file(
|
|
264427
|
+
const tasksFile = Bun.file(join37(input.changeDir, "tasks.md"));
|
|
264428
|
+
const proposalFile = Bun.file(join37(input.changeDir, "proposal.md"));
|
|
264429
|
+
const designFile = Bun.file(join37(input.changeDir, "design.md"));
|
|
264430
|
+
const reviewFindingsFile = Bun.file(join37(input.changeDir, "review-findings.md"));
|
|
263975
264431
|
const [tasksText, proposalText, designText, reviewFindingsText] = await Promise.all([
|
|
263976
264432
|
tasksFile.exists().then((ok) => ok ? tasksFile.text() : null),
|
|
263977
264433
|
proposalFile.exists().then((ok) => ok ? proposalFile.text() : null),
|
|
@@ -264034,7 +264490,7 @@ var init_worker_state_poll = __esm(() => {
|
|
|
264034
264490
|
});
|
|
264035
264491
|
|
|
264036
264492
|
// apps/agent/src/components/AgentMode.tsx
|
|
264037
|
-
import { join as
|
|
264493
|
+
import { join as join38 } from "path";
|
|
264038
264494
|
async function appendSteeringImpl(changeDir, message) {
|
|
264039
264495
|
await runWithContext(createDefaultContext(), async () => {
|
|
264040
264496
|
appendSteeringMessage(changeDir, message);
|
|
@@ -264051,16 +264507,6 @@ function orderSubtasksForCappedDisplay(subtasks) {
|
|
|
264051
264507
|
(s.done ? done : pending).push(s);
|
|
264052
264508
|
return [...pending, ...done];
|
|
264053
264509
|
}
|
|
264054
|
-
function pickLatestGatedTicket(tickets) {
|
|
264055
|
-
if (tickets.size === 0)
|
|
264056
|
-
return { top: null, moreCount: 0 };
|
|
264057
|
-
const sorted = Array.from(tickets.entries()).sort(([, a], [, b2]) => {
|
|
264058
|
-
const aTime = a.since ? new Date(a.since).getTime() : 0;
|
|
264059
|
-
const bTime = b2.since ? new Date(b2.since).getTime() : 0;
|
|
264060
|
-
return bTime - aTime;
|
|
264061
|
-
});
|
|
264062
|
-
return { top: sorted[0], moreCount: sorted.length - 1 };
|
|
264063
|
-
}
|
|
264064
264510
|
function fmtCmd(argv) {
|
|
264065
264511
|
const joined = argv.join(" ");
|
|
264066
264512
|
return joined.length > CMD_DISPLAY_MAX ? joined.slice(0, CMD_DISPLAY_MAX - 1) + "\u2026" : joined;
|
|
@@ -264156,20 +264602,6 @@ function Link({ url: url2, label, color }) {
|
|
|
264156
264602
|
}, undefined, false, undefined, this)
|
|
264157
264603
|
}, undefined, false, undefined, this);
|
|
264158
264604
|
}
|
|
264159
|
-
function priorityBadge(p) {
|
|
264160
|
-
switch (p) {
|
|
264161
|
-
case 1:
|
|
264162
|
-
return { text: "\u25B2", color: "red", label: "URGENT" };
|
|
264163
|
-
case 2:
|
|
264164
|
-
return { text: "\u2191", color: "yellow", label: "HIGH" };
|
|
264165
|
-
case 3:
|
|
264166
|
-
return { text: "\xB7", color: "blue", label: "MED" };
|
|
264167
|
-
case 4:
|
|
264168
|
-
return { text: "\u2193", color: "gray", label: "LOW" };
|
|
264169
|
-
default:
|
|
264170
|
-
return { text: " ", color: "gray", label: "" };
|
|
264171
|
-
}
|
|
264172
|
-
}
|
|
264173
264605
|
function modeBadge(mode) {
|
|
264174
264606
|
switch (mode) {
|
|
264175
264607
|
case "fresh":
|
|
@@ -264246,14 +264678,52 @@ function workerBorderColor(phase2) {
|
|
|
264246
264678
|
return "gray";
|
|
264247
264679
|
}
|
|
264248
264680
|
}
|
|
264249
|
-
function
|
|
264250
|
-
|
|
264251
|
-
|
|
264252
|
-
|
|
264253
|
-
|
|
264254
|
-
|
|
264255
|
-
|
|
264256
|
-
|
|
264681
|
+
function focusedCardTailLines(termHeight, fixedOverhead) {
|
|
264682
|
+
return Math.max(3, termHeight - fixedOverhead);
|
|
264683
|
+
}
|
|
264684
|
+
function glyphColor(status) {
|
|
264685
|
+
switch (status) {
|
|
264686
|
+
case "done":
|
|
264687
|
+
return "green";
|
|
264688
|
+
case "current":
|
|
264689
|
+
return "cyan";
|
|
264690
|
+
case "pending":
|
|
264691
|
+
return "gray";
|
|
264692
|
+
case "failed":
|
|
264693
|
+
return "red";
|
|
264694
|
+
case "bailed":
|
|
264695
|
+
return "magenta";
|
|
264696
|
+
}
|
|
264697
|
+
}
|
|
264698
|
+
function PipelineCells({
|
|
264699
|
+
glyphs
|
|
264700
|
+
}) {
|
|
264701
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264702
|
+
children: PIPELINE_NODES.map((node2, i) => {
|
|
264703
|
+
const isHeader = glyphs === null;
|
|
264704
|
+
const status = isHeader ? null : glyphs[i];
|
|
264705
|
+
const content = isHeader ? NODE_LABELS[node2] : STATUS_GLYPH[status];
|
|
264706
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264707
|
+
children: [
|
|
264708
|
+
i > 0 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264709
|
+
dimColor: true,
|
|
264710
|
+
children: PIPELINE_CONNECTOR
|
|
264711
|
+
}, undefined, false, undefined, this),
|
|
264712
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264713
|
+
width: NODE_CELL_WIDTH,
|
|
264714
|
+
justifyContent: "center",
|
|
264715
|
+
children: isHeader ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264716
|
+
dimColor: true,
|
|
264717
|
+
children: content
|
|
264718
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264719
|
+
color: glyphColor(status),
|
|
264720
|
+
children: content
|
|
264721
|
+
}, undefined, false, undefined, this)
|
|
264722
|
+
}, undefined, false, undefined, this)
|
|
264723
|
+
]
|
|
264724
|
+
}, node2, true, undefined, this);
|
|
264725
|
+
})
|
|
264726
|
+
}, undefined, false, undefined, this);
|
|
264257
264727
|
}
|
|
264258
264728
|
function AgentMode({
|
|
264259
264729
|
args,
|
|
@@ -264287,24 +264757,19 @@ function AgentMode({
|
|
|
264287
264757
|
}, [awaitingClose]);
|
|
264288
264758
|
const [, setTick] = import_react63.useState(0);
|
|
264289
264759
|
const [clock, setClock] = import_react63.useState(0);
|
|
264290
|
-
const [
|
|
264760
|
+
const [focusedId, setFocusedId] = import_react63.useState(null);
|
|
264291
264761
|
const [showPendingTasks, setShowPendingTasks] = import_react63.useState(false);
|
|
264292
264762
|
const [showAllSubtasks, setShowAllSubtasks] = import_react63.useState(false);
|
|
264293
|
-
const [gaveUpCount, setGaveUpCount] = import_react63.useState(0);
|
|
264294
264763
|
const coordRef = import_react63.useRef(null);
|
|
264295
264764
|
const workerMetaRef = import_react63.useRef(new Map);
|
|
264296
|
-
const gatedTicketsRef = import_react63.useRef(new Map);
|
|
264297
264765
|
const nextPollAtRef = import_react63.useRef(0);
|
|
264298
264766
|
const cfgRef = import_react63.useRef(null);
|
|
264299
264767
|
const [effective, setEffective] = import_react63.useState(null);
|
|
264300
264768
|
const [pollStatus, setPollStatus] = import_react63.useState({
|
|
264301
264769
|
state: "idle",
|
|
264302
|
-
lastFound: null,
|
|
264303
|
-
lastAdded: null,
|
|
264304
264770
|
lastAt: null,
|
|
264305
264771
|
filterDesc: "",
|
|
264306
|
-
|
|
264307
|
-
lastPrStatus: null
|
|
264772
|
+
lastBoard: []
|
|
264308
264773
|
});
|
|
264309
264774
|
function appendLog(text, color, workerLogFile) {
|
|
264310
264775
|
setLogs((prev) => [...prev, { id: nextId(), text, color }]);
|
|
@@ -264340,7 +264805,7 @@ function AgentMode({
|
|
|
264340
264805
|
setFatalExit(2);
|
|
264341
264806
|
return;
|
|
264342
264807
|
}
|
|
264343
|
-
const { coord: coord2, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2
|
|
264808
|
+
const { coord: coord2, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2 } = buildCoordinator({
|
|
264344
264809
|
args,
|
|
264345
264810
|
cfg: cfg2,
|
|
264346
264811
|
projectRoot,
|
|
@@ -264447,13 +264912,6 @@ function AgentMode({
|
|
|
264447
264912
|
since: info.since,
|
|
264448
264913
|
round: info.round
|
|
264449
264914
|
});
|
|
264450
|
-
gatedTicketsRef.current.set(info.changeName, {
|
|
264451
|
-
issueIdentifier: info.issueIdentifier,
|
|
264452
|
-
issueUrl: info.issueUrl,
|
|
264453
|
-
issueTitle: info.issueTitle,
|
|
264454
|
-
since: info.since,
|
|
264455
|
-
round: info.round
|
|
264456
|
-
});
|
|
264457
264915
|
}
|
|
264458
264916
|
});
|
|
264459
264917
|
setEffective({ concurrency, pollInterval });
|
|
@@ -264481,28 +264939,18 @@ function AgentMode({
|
|
|
264481
264939
|
}
|
|
264482
264940
|
if (cancelled)
|
|
264483
264941
|
return;
|
|
264484
|
-
|
|
264485
|
-
const { found, added, buckets, prStatus } = await coord2.pollOnce();
|
|
264942
|
+
const { found, added, buckets, prStatus, board: board2 } = await coord2.pollOnce();
|
|
264486
264943
|
if (cancelled)
|
|
264487
264944
|
return;
|
|
264488
264945
|
fileEmit({ type: "poll_done", found, added, buckets, prStatus });
|
|
264489
|
-
getGaveUpTotal().then((total) => {
|
|
264490
|
-
if (!cancelled)
|
|
264491
|
-
setGaveUpCount(total);
|
|
264492
|
-
}).catch(() => {
|
|
264493
|
-
return;
|
|
264494
|
-
});
|
|
264495
264946
|
if (added > 0) {
|
|
264496
264947
|
appendLog(` ${added} new issue${added === 1 ? "" : "s"} queued (found ${found} open)`);
|
|
264497
264948
|
}
|
|
264498
264949
|
setPollStatus({
|
|
264499
264950
|
state: "idle",
|
|
264500
|
-
lastFound: found,
|
|
264501
|
-
lastAdded: added,
|
|
264502
264951
|
lastAt: Date.now(),
|
|
264503
264952
|
filterDesc,
|
|
264504
|
-
|
|
264505
|
-
lastPrStatus: prStatus
|
|
264953
|
+
lastBoard: board2
|
|
264506
264954
|
});
|
|
264507
264955
|
nextPollAtRef.current = Date.now() + pollInterval * 1000;
|
|
264508
264956
|
pollTimer = setTimeout(tick, pollInterval * 1000);
|
|
@@ -264617,10 +265065,21 @@ function AgentMode({
|
|
|
264617
265065
|
const spinnerFrame = SPINNER_FRAMES[clock % SPINNER_FRAMES.length];
|
|
264618
265066
|
const now2 = Date.now();
|
|
264619
265067
|
const secsToNextPoll = nextPollAtRef.current ? Math.max(0, Math.ceil((nextPollAtRef.current - now2) / 1000)) : null;
|
|
265068
|
+
const pollState = pollStatus.state === "polling" ? "polling\u2026" : pollStatus.lastAt !== null ? "idle" : "starting\u2026";
|
|
265069
|
+
const tasksLiveness = `${pollState}${secsToNextPoll !== null ? ` \xB7 ${secsToNextPoll}s \u21BB` : ""}`;
|
|
264620
265070
|
const activeCount = coord?.activeCount ?? 0;
|
|
264621
265071
|
const termWidth = columns - 2;
|
|
264622
265072
|
const termHeight = rows;
|
|
264623
|
-
const
|
|
265073
|
+
const board = pollStatus.lastBoard;
|
|
265074
|
+
const tree = buildBoardTree(board);
|
|
265075
|
+
const focusedIndex = (() => {
|
|
265076
|
+
if (tree.length === 0)
|
|
265077
|
+
return -1;
|
|
265078
|
+
const i = tree.findIndex((t) => t.row.id === focusedId);
|
|
265079
|
+
return i >= 0 ? i : 0;
|
|
265080
|
+
})();
|
|
265081
|
+
const focusedRow = focusedIndex >= 0 ? tree[focusedIndex].row : undefined;
|
|
265082
|
+
const focusedWorker = focusedRow ? coordRef.current?.activeWorkers.find((w2) => w2.issueId === focusedRow.id) : undefined;
|
|
264624
265083
|
const steeringFocusedRef = import_react63.useRef(false);
|
|
264625
265084
|
const steeringBufferRef = import_react63.useRef("");
|
|
264626
265085
|
const steeringCursorRef = import_react63.useRef(0);
|
|
@@ -264638,26 +265097,23 @@ function AgentMode({
|
|
|
264638
265097
|
setShowPendingTasks((v2) => !v2);
|
|
264639
265098
|
return;
|
|
264640
265099
|
}
|
|
264641
|
-
if (
|
|
265100
|
+
if (tree.length === 0)
|
|
264642
265101
|
return;
|
|
264643
|
-
|
|
264644
|
-
|
|
264645
|
-
|
|
264646
|
-
|
|
265102
|
+
const idx = focusedIndex < 0 ? 0 : focusedIndex;
|
|
265103
|
+
if (key.tab || key.downArrow) {
|
|
265104
|
+
setFocusedId(tree[(idx + 1) % tree.length].row.id);
|
|
265105
|
+
} else if (key.upArrow) {
|
|
265106
|
+
setFocusedId(tree[(idx - 1 + tree.length) % tree.length].row.id);
|
|
264647
265107
|
} else {
|
|
264648
265108
|
const n = parseInt(input, 10);
|
|
264649
|
-
if (!isNaN(n) && n >= 1 && n <=
|
|
264650
|
-
|
|
264651
|
-
}
|
|
264652
|
-
}, { isActive: isRawModeSupported &&
|
|
264653
|
-
const
|
|
264654
|
-
const steeringActive = isRawModeSupported && activeCount > 0 && focusedWorker !== undefined;
|
|
264655
|
-
const nonFocusedCount = Math.max(0, activeCount - 1);
|
|
264656
|
-
const tasksBoxLines = activeCount > 1 ? 5 : 0;
|
|
265109
|
+
if (!isNaN(n) && n >= 1 && n <= Math.min(9, tree.length))
|
|
265110
|
+
setFocusedId(tree[n - 1].row.id);
|
|
265111
|
+
}
|
|
265112
|
+
}, { isActive: isRawModeSupported && board.length > 0 });
|
|
265113
|
+
const steeringActive = isRawModeSupported && focusedWorker !== undefined;
|
|
264657
265114
|
const steeringBoxLines = steeringActive ? 3 : 0;
|
|
264658
|
-
const FIXED_OVERHEAD = 5 +
|
|
264659
|
-
const focusedTailLines =
|
|
264660
|
-
const compactTailLines = displayTailLines(activeCount);
|
|
265115
|
+
const FIXED_OVERHEAD = 5 + (4 + board.length) + 8 + steeringBoxLines;
|
|
265116
|
+
const focusedTailLines = focusedCardTailLines(termHeight, FIXED_OVERHEAD);
|
|
264661
265117
|
if (preflightError) {
|
|
264662
265118
|
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264663
265119
|
flexDirection: "column",
|
|
@@ -264811,14 +265267,7 @@ function AgentMode({
|
|
|
264811
265267
|
cfg.useWorktree && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264812
265268
|
color: "green",
|
|
264813
265269
|
children: " \u25CF worktree"
|
|
264814
|
-
}, undefined, false, undefined, this)
|
|
264815
|
-
gaveUpCount > 0 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264816
|
-
color: "red",
|
|
264817
|
-
children: [
|
|
264818
|
-
" \u2502 gave-up \xD7",
|
|
264819
|
-
gaveUpCount
|
|
264820
|
-
]
|
|
264821
|
-
}, undefined, true, undefined, this)
|
|
265270
|
+
}, undefined, false, undefined, this)
|
|
264822
265271
|
]
|
|
264823
265272
|
}, undefined, true, undefined, this)
|
|
264824
265273
|
]
|
|
@@ -264845,418 +265294,196 @@ function AgentMode({
|
|
|
264845
265294
|
})()
|
|
264846
265295
|
]
|
|
264847
265296
|
}, undefined, true, undefined, this),
|
|
264848
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264849
|
-
flexDirection: "row",
|
|
264850
|
-
gap: 1,
|
|
264851
|
-
marginTop: 0,
|
|
264852
|
-
width: termWidth,
|
|
264853
|
-
children: [
|
|
264854
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
264855
|
-
label: "POLL STATUS",
|
|
264856
|
-
borderColor: "gray",
|
|
264857
|
-
width: termWidth - 17,
|
|
264858
|
-
paddingX: 1,
|
|
264859
|
-
flexDirection: "column",
|
|
264860
|
-
children: [
|
|
264861
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264862
|
-
gap: 2,
|
|
264863
|
-
children: [
|
|
264864
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264865
|
-
color: "gray",
|
|
264866
|
-
children: spinnerFrame
|
|
264867
|
-
}, undefined, false, undefined, this),
|
|
264868
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264869
|
-
children: pollStatus.state === "polling" ? "Polling Linear\u2026" : pollStatus.lastAt !== null ? "Idle" : "Starting\u2026"
|
|
264870
|
-
}, undefined, false, undefined, this),
|
|
264871
|
-
pollStatus.lastAt !== null && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
264872
|
-
children: pollStatus.lastBuckets && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
264873
|
-
children: [
|
|
264874
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264875
|
-
dimColor: true,
|
|
264876
|
-
children: "\u2502"
|
|
264877
|
-
}, undefined, false, undefined, this),
|
|
264878
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264879
|
-
dimColor: true,
|
|
264880
|
-
children: "todo"
|
|
264881
|
-
}, undefined, false, undefined, this),
|
|
264882
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264883
|
-
color: "white",
|
|
264884
|
-
children: pollStatus.lastBuckets.todo
|
|
264885
|
-
}, undefined, false, undefined, this),
|
|
264886
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264887
|
-
dimColor: true,
|
|
264888
|
-
children: "\xB7"
|
|
264889
|
-
}, undefined, false, undefined, this),
|
|
264890
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264891
|
-
dimColor: true,
|
|
264892
|
-
children: "resume"
|
|
264893
|
-
}, undefined, false, undefined, this),
|
|
264894
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264895
|
-
color: pollStatus.lastBuckets.inProgress > 0 ? "cyan" : "white",
|
|
264896
|
-
children: pollStatus.lastBuckets.inProgress
|
|
264897
|
-
}, undefined, false, undefined, this),
|
|
264898
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264899
|
-
dimColor: true,
|
|
264900
|
-
children: "\xB7"
|
|
264901
|
-
}, undefined, false, undefined, this),
|
|
264902
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264903
|
-
dimColor: true,
|
|
264904
|
-
children: "review"
|
|
264905
|
-
}, undefined, false, undefined, this),
|
|
264906
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264907
|
-
color: pollStatus.lastBuckets.review > 0 ? "yellow" : "white",
|
|
264908
|
-
children: pollStatus.lastBuckets.review
|
|
264909
|
-
}, undefined, false, undefined, this),
|
|
264910
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264911
|
-
dimColor: true,
|
|
264912
|
-
children: "\xB7"
|
|
264913
|
-
}, undefined, false, undefined, this),
|
|
264914
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264915
|
-
dimColor: true,
|
|
264916
|
-
children: "mentions"
|
|
264917
|
-
}, undefined, false, undefined, this),
|
|
264918
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264919
|
-
color: pollStatus.lastBuckets.mentions > 0 ? "magenta" : "white",
|
|
264920
|
-
children: pollStatus.lastBuckets.mentions
|
|
264921
|
-
}, undefined, false, undefined, this),
|
|
264922
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264923
|
-
dimColor: true,
|
|
264924
|
-
children: "\xB7"
|
|
264925
|
-
}, undefined, false, undefined, this),
|
|
264926
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264927
|
-
dimColor: true,
|
|
264928
|
-
children: "awaiting"
|
|
264929
|
-
}, undefined, false, undefined, this),
|
|
264930
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264931
|
-
color: pollStatus.lastBuckets.awaiting > 0 ? "yellow" : "white",
|
|
264932
|
-
children: pollStatus.lastBuckets.awaiting
|
|
264933
|
-
}, undefined, false, undefined, this)
|
|
264934
|
-
]
|
|
264935
|
-
}, undefined, true, undefined, this)
|
|
264936
|
-
}, undefined, false, undefined, this)
|
|
264937
|
-
]
|
|
264938
|
-
}, undefined, true, undefined, this),
|
|
264939
|
-
pollStatus.lastAt !== null && pollStatus.lastPrStatus && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264940
|
-
gap: 2,
|
|
264941
|
-
children: [
|
|
264942
|
-
secsToNextPoll !== null ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
264943
|
-
gap: 1,
|
|
264944
|
-
width: 7,
|
|
264945
|
-
children: [
|
|
264946
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264947
|
-
dimColor: true,
|
|
264948
|
-
children: "\u21BA"
|
|
264949
|
-
}, undefined, false, undefined, this),
|
|
264950
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264951
|
-
color: "gray",
|
|
264952
|
-
children: [
|
|
264953
|
-
secsToNextPoll,
|
|
264954
|
-
"s"
|
|
264955
|
-
]
|
|
264956
|
-
}, undefined, true, undefined, this)
|
|
264957
|
-
]
|
|
264958
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264959
|
-
children: " ".repeat(7)
|
|
264960
|
-
}, undefined, false, undefined, this),
|
|
264961
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264962
|
-
dimColor: true,
|
|
264963
|
-
children: "\u2502"
|
|
264964
|
-
}, undefined, false, undefined, this),
|
|
264965
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264966
|
-
dimColor: true,
|
|
264967
|
-
children: "mergeable"
|
|
264968
|
-
}, undefined, false, undefined, this),
|
|
264969
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264970
|
-
color: pollStatus.lastPrStatus.mergeable > 0 ? "green" : "white",
|
|
264971
|
-
children: pollStatus.lastPrStatus.mergeable
|
|
264972
|
-
}, undefined, false, undefined, this),
|
|
264973
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264974
|
-
dimColor: true,
|
|
264975
|
-
children: "\xB7"
|
|
264976
|
-
}, undefined, false, undefined, this),
|
|
264977
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264978
|
-
dimColor: true,
|
|
264979
|
-
children: "conflicted"
|
|
264980
|
-
}, undefined, false, undefined, this),
|
|
264981
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264982
|
-
color: pollStatus.lastPrStatus.conflicted > 0 ? "red" : "white",
|
|
264983
|
-
children: pollStatus.lastPrStatus.conflicted
|
|
264984
|
-
}, undefined, false, undefined, this),
|
|
264985
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264986
|
-
dimColor: true,
|
|
264987
|
-
children: "\xB7"
|
|
264988
|
-
}, undefined, false, undefined, this),
|
|
264989
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264990
|
-
dimColor: true,
|
|
264991
|
-
children: "ci-failed"
|
|
264992
|
-
}, undefined, false, undefined, this),
|
|
264993
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264994
|
-
color: pollStatus.lastPrStatus.ciFailed > 0 ? "red" : "white",
|
|
264995
|
-
children: pollStatus.lastPrStatus.ciFailed
|
|
264996
|
-
}, undefined, false, undefined, this),
|
|
264997
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
264998
|
-
dimColor: true,
|
|
264999
|
-
children: "\xB7"
|
|
265000
|
-
}, undefined, false, undefined, this),
|
|
265001
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265002
|
-
dimColor: true,
|
|
265003
|
-
children: "quarantined"
|
|
265004
|
-
}, undefined, false, undefined, this),
|
|
265005
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265006
|
-
color: pollStatus.lastPrStatus.quarantined > 0 ? "magenta" : "white",
|
|
265007
|
-
bold: true,
|
|
265008
|
-
children: pollStatus.lastPrStatus.quarantined
|
|
265009
|
-
}, undefined, false, undefined, this)
|
|
265010
|
-
]
|
|
265011
|
-
}, undefined, true, undefined, this)
|
|
265012
|
-
]
|
|
265013
|
-
}, undefined, true, undefined, this),
|
|
265014
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265015
|
-
label: "WORKERS",
|
|
265016
|
-
borderColor: "gray",
|
|
265017
|
-
width: 16,
|
|
265018
|
-
paddingX: 1,
|
|
265019
|
-
flexDirection: "column",
|
|
265020
|
-
children: [
|
|
265021
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265022
|
-
gap: 1,
|
|
265023
|
-
children: [
|
|
265024
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265025
|
-
dimColor: true,
|
|
265026
|
-
children: "active"
|
|
265027
|
-
}, undefined, false, undefined, this),
|
|
265028
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265029
|
-
color: activeCount > 0 ? "cyan" : "gray",
|
|
265030
|
-
bold: true,
|
|
265031
|
-
children: activeCount
|
|
265032
|
-
}, undefined, false, undefined, this)
|
|
265033
|
-
]
|
|
265034
|
-
}, undefined, true, undefined, this),
|
|
265035
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265036
|
-
gap: 1,
|
|
265037
|
-
children: [
|
|
265038
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265039
|
-
dimColor: true,
|
|
265040
|
-
children: "queue"
|
|
265041
|
-
}, undefined, false, undefined, this),
|
|
265042
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265043
|
-
color: (coord?.queuedCount ?? 0) > 0 ? "yellow" : "gray",
|
|
265044
|
-
bold: true,
|
|
265045
|
-
children: coord?.queuedCount ?? 0
|
|
265046
|
-
}, undefined, false, undefined, this)
|
|
265047
|
-
]
|
|
265048
|
-
}, undefined, true, undefined, this)
|
|
265049
|
-
]
|
|
265050
|
-
}, undefined, true, undefined, this)
|
|
265051
|
-
]
|
|
265052
|
-
}, undefined, true, undefined, this),
|
|
265053
|
-
activeCount > 1 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265054
|
-
label: `TASKS${activeCount > 1 ? " Tab/\u2190 \u2192 \xB7 1-9" : ""}`,
|
|
265055
|
-
borderColor: "gray",
|
|
265056
|
-
width: termWidth,
|
|
265057
|
-
paddingX: 1,
|
|
265058
|
-
flexDirection: "column",
|
|
265059
|
-
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265060
|
-
gap: 3,
|
|
265061
|
-
flexWrap: "wrap",
|
|
265062
|
-
children: coord?.activeWorkers.map((w2, idx) => {
|
|
265063
|
-
const meta3 = workerMetaRef.current.get(w2.changeName);
|
|
265064
|
-
const phase2 = meta3?.phase ?? "working";
|
|
265065
|
-
const pBadge = priorityBadge(w2.issue.priority);
|
|
265066
|
-
const isFocused = idx === safeFocusedIdx;
|
|
265067
|
-
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265068
|
-
gap: 1,
|
|
265069
|
-
children: [
|
|
265070
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265071
|
-
color: isFocused ? "white" : "gray",
|
|
265072
|
-
bold: isFocused,
|
|
265073
|
-
children: [
|
|
265074
|
-
"[",
|
|
265075
|
-
idx + 1,
|
|
265076
|
-
"]"
|
|
265077
|
-
]
|
|
265078
|
-
}, undefined, true, undefined, this),
|
|
265079
|
-
pBadge.label && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265080
|
-
color: pBadge.color,
|
|
265081
|
-
children: [
|
|
265082
|
-
pBadge.text,
|
|
265083
|
-
" ",
|
|
265084
|
-
pBadge.label
|
|
265085
|
-
]
|
|
265086
|
-
}, undefined, true, undefined, this),
|
|
265087
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265088
|
-
url: w2.issue.url,
|
|
265089
|
-
label: w2.issueIdentifier,
|
|
265090
|
-
color: isFocused ? "cyan" : "gray"
|
|
265091
|
-
}, undefined, false, undefined, this),
|
|
265092
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265093
|
-
color: phaseColor(phase2),
|
|
265094
|
-
dimColor: !isFocused,
|
|
265095
|
-
children: phase2
|
|
265096
|
-
}, undefined, false, undefined, this),
|
|
265097
|
-
isFocused && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265098
|
-
color: "white",
|
|
265099
|
-
children: "\u25C0"
|
|
265100
|
-
}, undefined, false, undefined, this)
|
|
265101
|
-
]
|
|
265102
|
-
}, w2.changeName, true, undefined, this);
|
|
265103
|
-
})
|
|
265104
|
-
}, undefined, false, undefined, this)
|
|
265105
|
-
}, undefined, false, undefined, this),
|
|
265106
265297
|
(() => {
|
|
265107
|
-
const
|
|
265108
|
-
|
|
265109
|
-
|
|
265110
|
-
|
|
265111
|
-
|
|
265112
|
-
|
|
265113
|
-
|
|
265114
|
-
|
|
265115
|
-
|
|
265116
|
-
|
|
265117
|
-
|
|
265118
|
-
const labelParts = [];
|
|
265119
|
-
entries.forEach(([, g3], i) => {
|
|
265120
|
-
labelParts.push(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265121
|
-
url: g3.issueUrl,
|
|
265122
|
-
label: g3.issueIdentifier,
|
|
265123
|
-
color: "yellow"
|
|
265124
|
-
}, g3.issueIdentifier, false, undefined, this));
|
|
265125
|
-
if (i < entries.length - 1) {
|
|
265126
|
-
labelParts.push(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265127
|
-
color: "yellow",
|
|
265128
|
-
children: " \xB7 "
|
|
265129
|
-
}, `sep-${i}`, false, undefined, this));
|
|
265130
|
-
}
|
|
265131
|
-
});
|
|
265132
|
-
const multiLabelNode = /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265298
|
+
const tasksInnerWidth = Math.max(0, termWidth - 2);
|
|
265299
|
+
const lead = "\u2500 ";
|
|
265300
|
+
const hint = " Tab/\u2191\u2193\xB71-9 ";
|
|
265301
|
+
const live = ` ${tasksLiveness} `;
|
|
265302
|
+
const trail = "\u2500";
|
|
265303
|
+
const fixed = lead.length + "TASKS".length + hint.length + live.length + trail.length;
|
|
265304
|
+
const fill2 = Math.max(1, tasksInnerWidth - fixed);
|
|
265305
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265306
|
+
labelVisualWidth: tasksInnerWidth,
|
|
265307
|
+
labelNode: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265308
|
+
flexDirection: "row",
|
|
265133
265309
|
children: [
|
|
265134
265310
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265135
|
-
color: "
|
|
265136
|
-
children:
|
|
265311
|
+
color: "gray",
|
|
265312
|
+
children: lead
|
|
265137
265313
|
}, undefined, false, undefined, this),
|
|
265138
|
-
labelParts,
|
|
265139
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265140
|
-
color: "yellow",
|
|
265141
|
-
children: " "
|
|
265142
|
-
}, undefined, false, undefined, this)
|
|
265143
|
-
]
|
|
265144
|
-
}, undefined, true, undefined, this);
|
|
265145
|
-
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265146
|
-
labelNode: multiLabelNode,
|
|
265147
|
-
labelVisualWidth: multiLabelWidth,
|
|
265148
|
-
borderColor: "yellow",
|
|
265149
|
-
paddingX: 1,
|
|
265150
|
-
gap: 2,
|
|
265151
|
-
width: termWidth,
|
|
265152
|
-
children: [
|
|
265153
265314
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265154
|
-
color: "yellow",
|
|
265155
265315
|
bold: true,
|
|
265156
|
-
children: "
|
|
265157
|
-
}, undefined, false, undefined, this),
|
|
265158
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265159
|
-
color: "yellow",
|
|
265160
|
-
children: "Awaiting confirmation"
|
|
265316
|
+
children: "TASKS"
|
|
265161
265317
|
}, undefined, false, undefined, this),
|
|
265162
265318
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265163
265319
|
dimColor: true,
|
|
265164
|
-
children:
|
|
265320
|
+
children: hint
|
|
265165
265321
|
}, undefined, false, undefined, this),
|
|
265166
265322
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265167
|
-
color: "
|
|
265168
|
-
|
|
265169
|
-
children: gated.size
|
|
265323
|
+
color: "gray",
|
|
265324
|
+
children: "\u2500".repeat(fill2)
|
|
265170
265325
|
}, undefined, false, undefined, this),
|
|
265171
265326
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265172
265327
|
dimColor: true,
|
|
265173
|
-
children:
|
|
265328
|
+
children: live
|
|
265329
|
+
}, undefined, false, undefined, this),
|
|
265330
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265331
|
+
color: "gray",
|
|
265332
|
+
children: trail
|
|
265174
265333
|
}, undefined, false, undefined, this)
|
|
265175
265334
|
]
|
|
265176
|
-
}, undefined, true, undefined, this)
|
|
265177
|
-
|
|
265178
|
-
const { top } = pickLatestGatedTicket(gated);
|
|
265179
|
-
if (!top)
|
|
265180
|
-
return null;
|
|
265181
|
-
const [changeName, g2] = top;
|
|
265182
|
-
const askedAgo = g2.since ? fmtElapsed(now2 - Date.parse(g2.since)) : "just now";
|
|
265183
|
-
const cardLabelWidth = g2.issueIdentifier.length + 2;
|
|
265184
|
-
const cardLabelNode = /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265185
|
-
children: [
|
|
265186
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265187
|
-
color: "yellow",
|
|
265188
|
-
children: " "
|
|
265189
|
-
}, undefined, false, undefined, this),
|
|
265190
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265191
|
-
url: g2.issueUrl,
|
|
265192
|
-
label: g2.issueIdentifier,
|
|
265193
|
-
color: "yellow"
|
|
265194
|
-
}, undefined, false, undefined, this),
|
|
265195
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265196
|
-
color: "yellow",
|
|
265197
|
-
children: " "
|
|
265198
|
-
}, undefined, false, undefined, this)
|
|
265199
|
-
]
|
|
265200
|
-
}, undefined, true, undefined, this);
|
|
265201
|
-
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265202
|
-
labelNode: cardLabelNode,
|
|
265203
|
-
labelVisualWidth: cardLabelWidth,
|
|
265204
|
-
borderColor: "yellow",
|
|
265205
|
-
paddingX: 1,
|
|
265206
|
-
gap: 2,
|
|
265335
|
+
}, undefined, true, undefined, this),
|
|
265336
|
+
borderColor: "gray",
|
|
265207
265337
|
width: termWidth,
|
|
265208
|
-
|
|
265209
|
-
|
|
265210
|
-
|
|
265211
|
-
|
|
265212
|
-
|
|
265213
|
-
|
|
265214
|
-
|
|
265215
|
-
|
|
265216
|
-
|
|
265217
|
-
|
|
265218
|
-
|
|
265219
|
-
|
|
265220
|
-
|
|
265221
|
-
|
|
265222
|
-
|
|
265223
|
-
|
|
265224
|
-
|
|
265225
|
-
|
|
265226
|
-
|
|
265227
|
-
|
|
265228
|
-
|
|
265229
|
-
children:
|
|
265230
|
-
|
|
265231
|
-
|
|
265232
|
-
|
|
265233
|
-
|
|
265234
|
-
|
|
265235
|
-
|
|
265236
|
-
|
|
265237
|
-
|
|
265238
|
-
|
|
265239
|
-
|
|
265240
|
-
|
|
265241
|
-
|
|
265242
|
-
|
|
265243
|
-
|
|
265244
|
-
|
|
265245
|
-
|
|
265246
|
-
|
|
265247
|
-
|
|
265248
|
-
|
|
265249
|
-
|
|
265250
|
-
|
|
265251
|
-
|
|
265252
|
-
|
|
265253
|
-
|
|
265254
|
-
|
|
265255
|
-
|
|
265256
|
-
|
|
265338
|
+
paddingX: 1,
|
|
265339
|
+
flexDirection: "column",
|
|
265340
|
+
children: board.length === 0 ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265341
|
+
dimColor: true,
|
|
265342
|
+
children: "no active tickets"
|
|
265343
|
+
}, undefined, false, undefined, this) : (() => {
|
|
265344
|
+
const idColWidth = Math.max(8, ...tree.map((t) => t.depth * 2 + t.row.identifier.length));
|
|
265345
|
+
const idxWidth = String(tree.length).length + 3;
|
|
265346
|
+
const prefixWidth = 2 + idxWidth + idColWidth + 1;
|
|
265347
|
+
const advancing = activeCount > 0 || tree.some((t) => ADVANCING_STATES.has(t.row.state));
|
|
265348
|
+
const hasStartableTodo = tree.some((t) => t.row.state === "todo" && !(t.row.blockedByIds?.length ?? 0));
|
|
265349
|
+
const stalled = !advancing && !hasStartableTodo;
|
|
265350
|
+
const blockedCount = tree.filter((t) => t.row.state === "todo" && (t.row.blockedByIds?.length ?? 0) > 0).length;
|
|
265351
|
+
const awaitingCount = tree.filter((t) => t.row.state === "awaiting").length;
|
|
265352
|
+
const quarantinedCount = tree.filter((t) => t.row.state === "quarantined").length;
|
|
265353
|
+
const stallParts = [
|
|
265354
|
+
blockedCount > 0 ? `${blockedCount} blocked` : null,
|
|
265355
|
+
awaitingCount > 0 ? `${awaitingCount} awaiting confirmation` : null,
|
|
265356
|
+
quarantinedCount > 0 ? `${quarantinedCount} quarantined` : null
|
|
265357
|
+
].filter((p) => p !== null);
|
|
265358
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265359
|
+
children: [
|
|
265360
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265361
|
+
children: [
|
|
265362
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265363
|
+
children: " ".repeat(prefixWidth)
|
|
265364
|
+
}, undefined, false, undefined, this),
|
|
265365
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(PipelineCells, {
|
|
265366
|
+
glyphs: null
|
|
265367
|
+
}, undefined, false, undefined, this)
|
|
265368
|
+
]
|
|
265369
|
+
}, undefined, true, undefined, this),
|
|
265370
|
+
tree.map(({ row, depth }, i) => {
|
|
265371
|
+
const isFocused = row.id === focusedRow?.id;
|
|
265372
|
+
const indent = depth > 0 ? " ".repeat(depth - 1) + "\u2514 " : "";
|
|
265373
|
+
const blockers = row.blockedByIdentifiers ?? [];
|
|
265374
|
+
const activeW = coordRef.current?.activeWorkers.find((w2) => w2.issueId === row.id);
|
|
265375
|
+
const meta3 = activeW ? workerMetaRef.current.get(activeW.changeName) : undefined;
|
|
265376
|
+
const waitingForWorker = !activeW && WORKER_WAIT_STATES.has(row.state);
|
|
265377
|
+
let age = "\u2013";
|
|
265378
|
+
if (meta3?.startedAt) {
|
|
265379
|
+
age = fmtElapsed(now2 - meta3.startedAt);
|
|
265380
|
+
} else if (!waitingForWorker && row.recovery?.firstFailedAt) {
|
|
265381
|
+
const failedAt = Date.parse(row.recovery.firstFailedAt);
|
|
265382
|
+
if (!Number.isNaN(failedAt))
|
|
265383
|
+
age = fmtElapsed(now2 - failedAt);
|
|
265384
|
+
}
|
|
265385
|
+
const prUrl = meta3?.prUrl ?? row.prUrl ?? null;
|
|
265386
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265387
|
+
children: [
|
|
265388
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265389
|
+
width: 2,
|
|
265390
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265391
|
+
color: "white",
|
|
265392
|
+
bold: true,
|
|
265393
|
+
children: isFocused ? "\u25B6" : " "
|
|
265394
|
+
}, undefined, false, undefined, this)
|
|
265395
|
+
}, undefined, false, undefined, this),
|
|
265396
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265397
|
+
width: idxWidth,
|
|
265398
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265399
|
+
dimColor: !isFocused,
|
|
265400
|
+
children: [
|
|
265401
|
+
"[",
|
|
265402
|
+
i + 1,
|
|
265403
|
+
"]"
|
|
265404
|
+
]
|
|
265405
|
+
}, undefined, true, undefined, this)
|
|
265406
|
+
}, undefined, false, undefined, this),
|
|
265407
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265408
|
+
width: idColWidth + 1,
|
|
265409
|
+
children: [
|
|
265410
|
+
indent && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265411
|
+
dimColor: true,
|
|
265412
|
+
children: indent
|
|
265413
|
+
}, undefined, false, undefined, this),
|
|
265414
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265415
|
+
url: row.url,
|
|
265416
|
+
label: row.identifier,
|
|
265417
|
+
color: isFocused ? "cyan" : "gray"
|
|
265418
|
+
}, undefined, false, undefined, this)
|
|
265419
|
+
]
|
|
265420
|
+
}, undefined, true, undefined, this),
|
|
265421
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(PipelineCells, {
|
|
265422
|
+
glyphs: pipelineStages(row).map((s) => s.status)
|
|
265423
|
+
}, undefined, false, undefined, this),
|
|
265424
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265425
|
+
color: isFocused ? "white" : "gray",
|
|
265426
|
+
dimColor: !isFocused,
|
|
265427
|
+
children: [
|
|
265428
|
+
" ",
|
|
265429
|
+
statusLabel(row)
|
|
265430
|
+
]
|
|
265431
|
+
}, undefined, true, undefined, this),
|
|
265432
|
+
blockers.length > 0 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265433
|
+
color: "yellow",
|
|
265434
|
+
dimColor: !isFocused,
|
|
265435
|
+
children: [
|
|
265436
|
+
" \u26D3 ",
|
|
265437
|
+
trunc(blockers.join(", "), 28)
|
|
265438
|
+
]
|
|
265439
|
+
}, undefined, true, undefined, this),
|
|
265440
|
+
waitingForWorker ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265441
|
+
color: "yellow",
|
|
265442
|
+
children: " waiting for worker"
|
|
265443
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265444
|
+
dimColor: true,
|
|
265445
|
+
children: [
|
|
265446
|
+
" ",
|
|
265447
|
+
age
|
|
265448
|
+
]
|
|
265449
|
+
}, undefined, true, undefined, this),
|
|
265450
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265451
|
+
children: [
|
|
265452
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265453
|
+
dimColor: true,
|
|
265454
|
+
children: " \u2197"
|
|
265455
|
+
}, undefined, false, undefined, this),
|
|
265456
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265457
|
+
url: prUrl,
|
|
265458
|
+
label: prLabel(prUrl),
|
|
265459
|
+
color: "green"
|
|
265460
|
+
}, undefined, false, undefined, this)
|
|
265461
|
+
]
|
|
265462
|
+
}, undefined, true, undefined, this)
|
|
265463
|
+
]
|
|
265464
|
+
}, row.id, true, undefined, this);
|
|
265465
|
+
}),
|
|
265466
|
+
stalled && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265467
|
+
marginTop: 1,
|
|
265468
|
+
children: [
|
|
265469
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265470
|
+
color: "yellow",
|
|
265471
|
+
bold: true,
|
|
265472
|
+
children: "\u23F8 nothing can start"
|
|
265473
|
+
}, undefined, false, undefined, this),
|
|
265474
|
+
stallParts.length > 0 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265475
|
+
color: "yellow",
|
|
265476
|
+
children: ` \u2014 ${stallParts.join(" \xB7 ")}`
|
|
265477
|
+
}, undefined, false, undefined, this)
|
|
265478
|
+
]
|
|
265479
|
+
}, undefined, true, undefined, this)
|
|
265480
|
+
]
|
|
265481
|
+
}, undefined, true, undefined, this);
|
|
265482
|
+
})()
|
|
265483
|
+
}, undefined, false, undefined, this);
|
|
265257
265484
|
})(),
|
|
265258
|
-
|
|
265259
|
-
const
|
|
265485
|
+
focusedWorker && (() => {
|
|
265486
|
+
const w2 = focusedWorker;
|
|
265260
265487
|
const meta3 = workerMetaRef.current.get(w2.changeName);
|
|
265261
265488
|
const elapsed = meta3 ? fmtElapsed(now2 - meta3.startedAt) : "\u2013";
|
|
265262
265489
|
const iter = meta3?.iter ?? 0;
|
|
@@ -265270,122 +265497,10 @@ function AgentMode({
|
|
|
265270
265497
|
const taskProgress = meta3?.taskProgress ?? null;
|
|
265271
265498
|
const openspecPhase = meta3?.openspecPhase ?? null;
|
|
265272
265499
|
const subtasks = meta3?.subtasks ?? [];
|
|
265273
|
-
const pBadge = priorityBadge(w2.issue.priority);
|
|
265274
265500
|
const mBadge = modeBadge(w2.trigger);
|
|
265275
265501
|
const pColor = phaseColor(phase2);
|
|
265276
|
-
const bColor =
|
|
265277
|
-
const visibleTailLines =
|
|
265278
|
-
if (!isFocused && activeCount > 1) {
|
|
265279
|
-
const cardLabelWidth2 = (prUrl ? prLabel(prUrl).length + 3 : 0) + w2.issueIdentifier.length + 2;
|
|
265280
|
-
const cardLabelNode2 = /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265281
|
-
children: [
|
|
265282
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265283
|
-
color: "gray",
|
|
265284
|
-
children: " "
|
|
265285
|
-
}, undefined, false, undefined, this),
|
|
265286
|
-
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265287
|
-
url: prUrl,
|
|
265288
|
-
label: prLabel(prUrl),
|
|
265289
|
-
color: "green"
|
|
265290
|
-
}, undefined, false, undefined, this),
|
|
265291
|
-
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265292
|
-
color: "gray",
|
|
265293
|
-
children: " \xB7 "
|
|
265294
|
-
}, undefined, false, undefined, this),
|
|
265295
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265296
|
-
url: w2.issue.url,
|
|
265297
|
-
label: w2.issueIdentifier,
|
|
265298
|
-
color: "cyan"
|
|
265299
|
-
}, undefined, false, undefined, this),
|
|
265300
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265301
|
-
color: "gray",
|
|
265302
|
-
children: " "
|
|
265303
|
-
}, undefined, false, undefined, this)
|
|
265304
|
-
]
|
|
265305
|
-
}, undefined, true, undefined, this);
|
|
265306
|
-
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265307
|
-
labelNode: cardLabelNode2,
|
|
265308
|
-
labelVisualWidth: cardLabelWidth2,
|
|
265309
|
-
borderColor: "gray",
|
|
265310
|
-
paddingX: 1,
|
|
265311
|
-
gap: 2,
|
|
265312
|
-
width: termWidth,
|
|
265313
|
-
children: [
|
|
265314
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265315
|
-
dimColor: true,
|
|
265316
|
-
children: [
|
|
265317
|
-
"[",
|
|
265318
|
-
idx + 1,
|
|
265319
|
-
"]"
|
|
265320
|
-
]
|
|
265321
|
-
}, undefined, true, undefined, this),
|
|
265322
|
-
pBadge.label && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265323
|
-
color: pBadge.color,
|
|
265324
|
-
children: pBadge.text
|
|
265325
|
-
}, undefined, false, undefined, this),
|
|
265326
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265327
|
-
color: "gray",
|
|
265328
|
-
bold: true,
|
|
265329
|
-
children: w2.issueIdentifier
|
|
265330
|
-
}, undefined, false, undefined, this),
|
|
265331
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265332
|
-
dimColor: true,
|
|
265333
|
-
children: trunc(w2.issue.title, 40)
|
|
265334
|
-
}, undefined, false, undefined, this),
|
|
265335
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265336
|
-
dimColor: true,
|
|
265337
|
-
children: "\u2502"
|
|
265338
|
-
}, undefined, false, undefined, this),
|
|
265339
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265340
|
-
color: pColor,
|
|
265341
|
-
dimColor: true,
|
|
265342
|
-
children: phase2
|
|
265343
|
-
}, undefined, false, undefined, this),
|
|
265344
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265345
|
-
dimColor: true,
|
|
265346
|
-
children: "\u2502"
|
|
265347
|
-
}, undefined, false, undefined, this),
|
|
265348
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265349
|
-
dimColor: true,
|
|
265350
|
-
children: elapsed
|
|
265351
|
-
}, undefined, false, undefined, this),
|
|
265352
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265353
|
-
dimColor: true,
|
|
265354
|
-
children: "\xB7"
|
|
265355
|
-
}, undefined, false, undefined, this),
|
|
265356
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265357
|
-
dimColor: true,
|
|
265358
|
-
children: [
|
|
265359
|
-
"\u21BA ",
|
|
265360
|
-
iter
|
|
265361
|
-
]
|
|
265362
|
-
}, undefined, true, undefined, this),
|
|
265363
|
-
currentTask && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265364
|
-
children: [
|
|
265365
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265366
|
-
dimColor: true,
|
|
265367
|
-
children: "\u2502"
|
|
265368
|
-
}, undefined, false, undefined, this),
|
|
265369
|
-
openspecPhase && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265370
|
-
color: openspecPhaseColor(openspecPhase),
|
|
265371
|
-
children: [
|
|
265372
|
-
"[",
|
|
265373
|
-
openspecPhase,
|
|
265374
|
-
"]"
|
|
265375
|
-
]
|
|
265376
|
-
}, undefined, true, undefined, this),
|
|
265377
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265378
|
-
dimColor: true,
|
|
265379
|
-
children: [
|
|
265380
|
-
"\u25B6 ",
|
|
265381
|
-
trunc(currentTask, 40)
|
|
265382
|
-
]
|
|
265383
|
-
}, undefined, true, undefined, this)
|
|
265384
|
-
]
|
|
265385
|
-
}, undefined, true, undefined, this)
|
|
265386
|
-
]
|
|
265387
|
-
}, w2.changeName, true, undefined, this);
|
|
265388
|
-
}
|
|
265502
|
+
const bColor = workerBorderColor(phase2);
|
|
265503
|
+
const visibleTailLines = focusedTailLines;
|
|
265389
265504
|
const cardLabelWidth = (prUrl ? prLabel(prUrl).length + 3 : 0) + w2.issueIdentifier.length + 2;
|
|
265390
265505
|
const cardLabelNode = /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265391
265506
|
children: [
|
|
@@ -265610,7 +265725,7 @@ function AgentMode({
|
|
|
265610
265725
|
}, undefined, false, undefined, this)
|
|
265611
265726
|
]
|
|
265612
265727
|
}, undefined, true, undefined, this),
|
|
265613
|
-
steeringActive &&
|
|
265728
|
+
steeringActive && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265614
265729
|
marginTop: 0,
|
|
265615
265730
|
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(SteeringField, {
|
|
265616
265731
|
active: steeringActive,
|
|
@@ -265628,8 +265743,12 @@ function AgentMode({
|
|
|
265628
265743
|
},
|
|
265629
265744
|
onSubmit: async (message) => {
|
|
265630
265745
|
try {
|
|
265631
|
-
await appendSteering2(
|
|
265632
|
-
fileEmit({
|
|
265746
|
+
await appendSteering2(join38(tasksDir, w2.changeName), message);
|
|
265747
|
+
fileEmit({
|
|
265748
|
+
type: "steering_submitted",
|
|
265749
|
+
changeName: w2.changeName,
|
|
265750
|
+
message
|
|
265751
|
+
});
|
|
265633
265752
|
} catch (err) {
|
|
265634
265753
|
const text = err.message;
|
|
265635
265754
|
fileEmit({
|
|
@@ -265705,7 +265824,108 @@ function AgentMode({
|
|
|
265705
265824
|
})()
|
|
265706
265825
|
]
|
|
265707
265826
|
}, w2.changeName, true, undefined, this);
|
|
265708
|
-
})
|
|
265827
|
+
})(),
|
|
265828
|
+
!focusedWorker && focusedRow && (() => {
|
|
265829
|
+
const row = focusedRow;
|
|
265830
|
+
let age = "\u2013";
|
|
265831
|
+
if (row.recovery?.firstFailedAt) {
|
|
265832
|
+
const failedAt = Date.parse(row.recovery.firstFailedAt);
|
|
265833
|
+
if (!Number.isNaN(failedAt))
|
|
265834
|
+
age = fmtElapsed(now2 - failedAt);
|
|
265835
|
+
}
|
|
265836
|
+
const prUrl = row.prUrl ?? null;
|
|
265837
|
+
const cardLabelWidth = (prUrl ? prLabel(prUrl).length + 3 : 0) + row.identifier.length + 2;
|
|
265838
|
+
const cardLabelNode = /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265839
|
+
children: [
|
|
265840
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265841
|
+
color: "gray",
|
|
265842
|
+
children: " "
|
|
265843
|
+
}, undefined, false, undefined, this),
|
|
265844
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265845
|
+
url: prUrl,
|
|
265846
|
+
label: prLabel(prUrl),
|
|
265847
|
+
color: "green"
|
|
265848
|
+
}, undefined, false, undefined, this),
|
|
265849
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265850
|
+
color: "gray",
|
|
265851
|
+
children: " \xB7 "
|
|
265852
|
+
}, undefined, false, undefined, this),
|
|
265853
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265854
|
+
url: row.url,
|
|
265855
|
+
label: row.identifier,
|
|
265856
|
+
color: "cyan"
|
|
265857
|
+
}, undefined, false, undefined, this),
|
|
265858
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265859
|
+
color: "gray",
|
|
265860
|
+
children: " "
|
|
265861
|
+
}, undefined, false, undefined, this)
|
|
265862
|
+
]
|
|
265863
|
+
}, undefined, true, undefined, this);
|
|
265864
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(LabeledBox, {
|
|
265865
|
+
labelNode: cardLabelNode,
|
|
265866
|
+
labelVisualWidth: cardLabelWidth,
|
|
265867
|
+
borderColor: "gray",
|
|
265868
|
+
flexDirection: "column",
|
|
265869
|
+
paddingX: 1,
|
|
265870
|
+
width: termWidth,
|
|
265871
|
+
children: [
|
|
265872
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265873
|
+
color: "white",
|
|
265874
|
+
bold: true,
|
|
265875
|
+
children: trunc(row.title, Math.max(20, termWidth - 20))
|
|
265876
|
+
}, undefined, false, undefined, this),
|
|
265877
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265878
|
+
marginTop: 0,
|
|
265879
|
+
children: [
|
|
265880
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(PipelineCells, {
|
|
265881
|
+
glyphs: pipelineStages(row).map((s) => s.status)
|
|
265882
|
+
}, undefined, false, undefined, this),
|
|
265883
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265884
|
+
color: "white",
|
|
265885
|
+
children: [
|
|
265886
|
+
" ",
|
|
265887
|
+
statusLabel(row)
|
|
265888
|
+
]
|
|
265889
|
+
}, undefined, true, undefined, this)
|
|
265890
|
+
]
|
|
265891
|
+
}, undefined, true, undefined, this),
|
|
265892
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
265893
|
+
gap: 2,
|
|
265894
|
+
marginTop: 0,
|
|
265895
|
+
children: [
|
|
265896
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265897
|
+
dimColor: true,
|
|
265898
|
+
children: "parked \xB7 no live worker"
|
|
265899
|
+
}, undefined, false, undefined, this),
|
|
265900
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265901
|
+
dimColor: true,
|
|
265902
|
+
children: "\u2502"
|
|
265903
|
+
}, undefined, false, undefined, this),
|
|
265904
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265905
|
+
dimColor: true,
|
|
265906
|
+
children: [
|
|
265907
|
+
"age ",
|
|
265908
|
+
age
|
|
265909
|
+
]
|
|
265910
|
+
}, undefined, true, undefined, this),
|
|
265911
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(jsx_dev_runtime11.Fragment, {
|
|
265912
|
+
children: [
|
|
265913
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
265914
|
+
dimColor: true,
|
|
265915
|
+
children: "\u2502"
|
|
265916
|
+
}, undefined, false, undefined, this),
|
|
265917
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Link, {
|
|
265918
|
+
url: prUrl,
|
|
265919
|
+
label: prLabel(prUrl),
|
|
265920
|
+
color: "green"
|
|
265921
|
+
}, undefined, false, undefined, this)
|
|
265922
|
+
]
|
|
265923
|
+
}, undefined, true, undefined, this)
|
|
265924
|
+
]
|
|
265925
|
+
}, undefined, true, undefined, this)
|
|
265926
|
+
]
|
|
265927
|
+
}, row.id, true, undefined, this);
|
|
265928
|
+
})()
|
|
265709
265929
|
]
|
|
265710
265930
|
}, undefined, true, undefined, this),
|
|
265711
265931
|
awaitingClose && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
@@ -265715,13 +265935,14 @@ function AgentMode({
|
|
|
265715
265935
|
]
|
|
265716
265936
|
}, resizeKey, true, undefined, this);
|
|
265717
265937
|
}
|
|
265718
|
-
var import_react63, jsx_dev_runtime11, lineCounter = 0, TAIL_BUFFER_SIZE = 30, CMD_DISPLAY_MAX = 80, MAX_PENDING_DISPLAY = 15, SPINNER_FRAMES, HYPERLINKS_SUPPORTED, SESSION_START;
|
|
265938
|
+
var import_react63, jsx_dev_runtime11, lineCounter = 0, TAIL_BUFFER_SIZE = 30, CMD_DISPLAY_MAX = 80, MAX_PENDING_DISPLAY = 15, SPINNER_FRAMES, WORKER_WAIT_STATES, ADVANCING_STATES, HYPERLINKS_SUPPORTED, NODE_LABELS, NODE_CELL_WIDTH = 4, PIPELINE_CONNECTOR = "\u2500\u2500", SESSION_START;
|
|
265719
265939
|
var init_AgentMode = __esm(async () => {
|
|
265720
265940
|
init_cli2();
|
|
265721
265941
|
init_config();
|
|
265722
265942
|
init_wire();
|
|
265723
265943
|
init_preflight();
|
|
265724
265944
|
init_json_log_file();
|
|
265945
|
+
init_task_pipeline();
|
|
265725
265946
|
init_phase();
|
|
265726
265947
|
init_log();
|
|
265727
265948
|
init_useTerminalSize();
|
|
@@ -265737,7 +265958,32 @@ var init_AgentMode = __esm(async () => {
|
|
|
265737
265958
|
import_react63 = __toESM(require_react(), 1);
|
|
265738
265959
|
jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
|
|
265739
265960
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
265961
|
+
WORKER_WAIT_STATES = new Set([
|
|
265962
|
+
"queued",
|
|
265963
|
+
"working",
|
|
265964
|
+
"in-progress",
|
|
265965
|
+
"conflict-fix",
|
|
265966
|
+
"ci-fix",
|
|
265967
|
+
"review"
|
|
265968
|
+
]);
|
|
265969
|
+
ADVANCING_STATES = new Set([
|
|
265970
|
+
"queued",
|
|
265971
|
+
"working",
|
|
265972
|
+
"in-progress",
|
|
265973
|
+
"conflict-fix",
|
|
265974
|
+
"ci-fix",
|
|
265975
|
+
"review",
|
|
265976
|
+
"awaiting-ci"
|
|
265977
|
+
]);
|
|
265740
265978
|
HYPERLINKS_SUPPORTED = !process.env["TMUX"];
|
|
265979
|
+
NODE_LABELS = {
|
|
265980
|
+
todo: "todo",
|
|
265981
|
+
confirmation: "conf",
|
|
265982
|
+
work: "work",
|
|
265983
|
+
PR: "PR",
|
|
265984
|
+
CI: "CI",
|
|
265985
|
+
done: "done"
|
|
265986
|
+
};
|
|
265741
265987
|
SESSION_START = new Date().toISOString();
|
|
265742
265988
|
});
|
|
265743
265989
|
|
|
@@ -265937,7 +266183,7 @@ __export(exports_list, {
|
|
|
265937
266183
|
buildBuckets: () => buildBuckets,
|
|
265938
266184
|
backlogRankByIssueId: () => backlogRankByIssueId
|
|
265939
266185
|
});
|
|
265940
|
-
import { join as
|
|
266186
|
+
import { join as join39 } from "path";
|
|
265941
266187
|
function countTaskItems(content) {
|
|
265942
266188
|
const checked = (content.match(/^- \[x\]/gm) ?? []).length;
|
|
265943
266189
|
const unchecked = (content.match(/^- \[ \]/gm) ?? []).length;
|
|
@@ -265953,13 +266199,13 @@ function buildLocalRows() {
|
|
|
265953
266199
|
const sources = [{ dir: statesDir, label: "main" }];
|
|
265954
266200
|
const worktreesRoot = worktreesDir2(projectRoot);
|
|
265955
266201
|
for (const wt of storage.list(worktreesRoot)) {
|
|
265956
|
-
sources.push({ dir:
|
|
266202
|
+
sources.push({ dir: join39(worktreesRoot, wt, ".ralph", "tasks"), label: `wt:${wt}` });
|
|
265957
266203
|
}
|
|
265958
266204
|
for (const { dir, label } of sources) {
|
|
265959
266205
|
for (const entry of storage.list(dir)) {
|
|
265960
266206
|
if (seen.has(entry))
|
|
265961
266207
|
continue;
|
|
265962
|
-
const raw = storage.read(
|
|
266208
|
+
const raw = storage.read(join39(dir, entry, ".ralph-state.json"));
|
|
265963
266209
|
if (raw === null)
|
|
265964
266210
|
continue;
|
|
265965
266211
|
let state;
|
|
@@ -265974,7 +266220,7 @@ function buildLocalRows() {
|
|
|
265974
266220
|
const firstLine = promptRaw.split(`
|
|
265975
266221
|
`).find((l3) => l3.trim() !== "") ?? "";
|
|
265976
266222
|
let progress = "\u2014";
|
|
265977
|
-
const tasksContent = storage.read(
|
|
266223
|
+
const tasksContent = storage.read(join39(dir, entry, "tasks.md"));
|
|
265978
266224
|
if (tasksContent !== null) {
|
|
265979
266225
|
const { checked, unchecked } = countTaskItems(tasksContent);
|
|
265980
266226
|
const total = checked + unchecked;
|
|
@@ -266307,8 +266553,8 @@ async function fetchIssueByIdentifier(apiKey, identifier) {
|
|
|
266307
266553
|
team { key }
|
|
266308
266554
|
labels { nodes { name } }
|
|
266309
266555
|
attachments(first: 25) { nodes { title subtitle } }
|
|
266310
|
-
|
|
266311
|
-
nodes { type
|
|
266556
|
+
inverseRelations(first: 50) {
|
|
266557
|
+
nodes { type issue { id identifier state { type } } }
|
|
266312
266558
|
}
|
|
266313
266559
|
}
|
|
266314
266560
|
}
|
|
@@ -266387,7 +266633,7 @@ Found ${issue2.identifier} \u2014 "${issue2.title}"
|
|
|
266387
266633
|
` + ` assignee: ${issue2.assignee ? `${issue2.assignee.name} <${issue2.assignee.email ?? "no-email"}>` : "(unassigned)"}
|
|
266388
266634
|
` + ` labels: ${issue2.labels.nodes.map((l3) => l3.name).join(", ") || "(none)"}
|
|
266389
266635
|
`);
|
|
266390
|
-
const blockedBy = issue2.
|
|
266636
|
+
const blockedBy = issue2.inverseRelations.nodes.filter((r) => r.type === "blocks" && r.issue.state.type !== "completed" && r.issue.state.type !== "cancelled").map((r) => r.issue.identifier);
|
|
266391
266637
|
process.stdout.write(`
|
|
266392
266638
|
Per-bucket diagnostics:
|
|
266393
266639
|
`);
|
|
@@ -266477,7 +266723,7 @@ var exports_json_runner = {};
|
|
|
266477
266723
|
__export(exports_json_runner, {
|
|
266478
266724
|
runAgentJson: () => runAgentJson
|
|
266479
266725
|
});
|
|
266480
|
-
import { join as
|
|
266726
|
+
import { join as join40 } from "path";
|
|
266481
266727
|
import { mkdir as mkdir12 } from "fs/promises";
|
|
266482
266728
|
import { homedir as homedir8 } from "os";
|
|
266483
266729
|
function makeEmit(fileSink) {
|
|
@@ -266499,7 +266745,7 @@ async function runAgentJson({
|
|
|
266499
266745
|
tasksDir,
|
|
266500
266746
|
runPreflight: runPreflight2 = runPreflight
|
|
266501
266747
|
}) {
|
|
266502
|
-
await mkdir12(
|
|
266748
|
+
await mkdir12(join40(homedir8(), ".ralph"), { recursive: true }).catch(() => {
|
|
266503
266749
|
return;
|
|
266504
266750
|
});
|
|
266505
266751
|
const fileSink = createJsonLogFileSink(args.jsonLogFile);
|
|
@@ -266719,7 +266965,7 @@ __export(exports_src3, {
|
|
|
266719
266965
|
main: () => main3
|
|
266720
266966
|
});
|
|
266721
266967
|
import { mkdir as mkdir13 } from "fs/promises";
|
|
266722
|
-
import { join as
|
|
266968
|
+
import { join as join41 } from "path";
|
|
266723
266969
|
async function main3(argv) {
|
|
266724
266970
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
266725
266971
|
printAgentHelp();
|
|
@@ -266784,7 +267030,7 @@ async function main3(argv) {
|
|
|
266784
267030
|
}
|
|
266785
267031
|
await mkdir13(statesDir, { recursive: true });
|
|
266786
267032
|
await mkdir13(tasksDir, { recursive: true });
|
|
266787
|
-
await mkdir13(
|
|
267033
|
+
await mkdir13(join41(projectRoot, ".ralph"), { recursive: true });
|
|
266788
267034
|
if (shouldFallbackToJsonOutput(args, process.stdin.isTTY)) {
|
|
266789
267035
|
process.stderr.write(`agent: stdin is not a TTY \u2014 falling back to --json-output mode.
|
|
266790
267036
|
`);
|