@neriros/ralphy 3.10.10 → 3.10.12
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/mcp/index.js +10 -0
- package/dist/shell/index.js +299 -92
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -24093,6 +24093,12 @@ var HistoryEntrySchema = exports_external.object({
|
|
|
24093
24093
|
appVersion: exports_external.string().optional(),
|
|
24094
24094
|
usage: IterationUsageSchema.partial().optional()
|
|
24095
24095
|
});
|
|
24096
|
+
var RevisionSchema = exports_external.object({
|
|
24097
|
+
version: exports_external.number(),
|
|
24098
|
+
attachmentId: exports_external.string(),
|
|
24099
|
+
sha256: exports_external.string(),
|
|
24100
|
+
trigger: exports_external.string()
|
|
24101
|
+
});
|
|
24096
24102
|
var StateSchema = exports_external.object({
|
|
24097
24103
|
version: exports_external.literal("2"),
|
|
24098
24104
|
name: exports_external.string(),
|
|
@@ -24141,12 +24147,16 @@ var StateSchema = exports_external.object({
|
|
|
24141
24147
|
attachmentId: exports_external.string().nullable().default(null),
|
|
24142
24148
|
sha256: exports_external.string().nullable().default(null)
|
|
24143
24149
|
}).default({ attachmentId: null, sha256: null }),
|
|
24150
|
+
designRevisions: exports_external.array(RevisionSchema).default([]),
|
|
24151
|
+
designPdfRevisions: exports_external.array(RevisionSchema).default([]),
|
|
24144
24152
|
legacyProposalPurged: exports_external.boolean().default(false)
|
|
24145
24153
|
}).default({
|
|
24146
24154
|
proposal: { attachmentId: null, sha256: null },
|
|
24147
24155
|
design: { attachmentId: null, sha256: null },
|
|
24148
24156
|
proposalPdf: { attachmentId: null, sha256: null },
|
|
24149
24157
|
designPdf: { attachmentId: null, sha256: null },
|
|
24158
|
+
designRevisions: [],
|
|
24159
|
+
designPdfRevisions: [],
|
|
24150
24160
|
legacyProposalPurged: false
|
|
24151
24161
|
}),
|
|
24152
24162
|
confirmation: exports_external.object({
|
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.12")
|
|
18932
|
+
return "3.10.12";
|
|
18933
18933
|
} catch {}
|
|
18934
18934
|
const dirsToTry = [];
|
|
18935
18935
|
try {
|
|
@@ -89590,7 +89590,7 @@ var init_zod2 = __esm(() => {
|
|
|
89590
89590
|
function markersOf(set3) {
|
|
89591
89591
|
return Array.isArray(set3) ? set3 : [set3];
|
|
89592
89592
|
}
|
|
89593
|
-
var IterationUsageSchema, UsageSchema, HistoryEntrySchema, StateSchema, PhaseFrontmatterSchema;
|
|
89593
|
+
var IterationUsageSchema, UsageSchema, HistoryEntrySchema, RevisionSchema, StateSchema, PhaseFrontmatterSchema;
|
|
89594
89594
|
var init_types2 = __esm(() => {
|
|
89595
89595
|
init_zod2();
|
|
89596
89596
|
IterationUsageSchema = exports_external2.object({
|
|
@@ -89623,6 +89623,12 @@ var init_types2 = __esm(() => {
|
|
|
89623
89623
|
appVersion: exports_external2.string().optional(),
|
|
89624
89624
|
usage: IterationUsageSchema.partial().optional()
|
|
89625
89625
|
});
|
|
89626
|
+
RevisionSchema = exports_external2.object({
|
|
89627
|
+
version: exports_external2.number(),
|
|
89628
|
+
attachmentId: exports_external2.string(),
|
|
89629
|
+
sha256: exports_external2.string(),
|
|
89630
|
+
trigger: exports_external2.string()
|
|
89631
|
+
});
|
|
89626
89632
|
StateSchema = exports_external2.object({
|
|
89627
89633
|
version: exports_external2.literal("2"),
|
|
89628
89634
|
name: exports_external2.string(),
|
|
@@ -89671,12 +89677,16 @@ var init_types2 = __esm(() => {
|
|
|
89671
89677
|
attachmentId: exports_external2.string().nullable().default(null),
|
|
89672
89678
|
sha256: exports_external2.string().nullable().default(null)
|
|
89673
89679
|
}).default({ attachmentId: null, sha256: null }),
|
|
89680
|
+
designRevisions: exports_external2.array(RevisionSchema).default([]),
|
|
89681
|
+
designPdfRevisions: exports_external2.array(RevisionSchema).default([]),
|
|
89674
89682
|
legacyProposalPurged: exports_external2.boolean().default(false)
|
|
89675
89683
|
}).default({
|
|
89676
89684
|
proposal: { attachmentId: null, sha256: null },
|
|
89677
89685
|
design: { attachmentId: null, sha256: null },
|
|
89678
89686
|
proposalPdf: { attachmentId: null, sha256: null },
|
|
89679
89687
|
designPdf: { attachmentId: null, sha256: null },
|
|
89688
|
+
designRevisions: [],
|
|
89689
|
+
designPdfRevisions: [],
|
|
89680
89690
|
legacyProposalPurged: false
|
|
89681
89691
|
}),
|
|
89682
89692
|
confirmation: exports_external2.object({
|
|
@@ -105470,6 +105480,7 @@ class AgentCoordinator {
|
|
|
105470
105480
|
opts;
|
|
105471
105481
|
workers = [];
|
|
105472
105482
|
pendingIds = new Set;
|
|
105483
|
+
inFlight = new Set;
|
|
105473
105484
|
queue = [];
|
|
105474
105485
|
stopped = false;
|
|
105475
105486
|
paused = null;
|
|
@@ -106036,7 +106047,31 @@ class AgentCoordinator {
|
|
|
106036
106047
|
while (this.workers.length + this.pendingIds.size < this.opts.concurrency && this.queue.length > 0) {
|
|
106037
106048
|
const next = this.queue.shift();
|
|
106038
106049
|
this.pendingIds.add(next.issue.id);
|
|
106039
|
-
this.launchWorker(next.issue, next.trigger, next.mention);
|
|
106050
|
+
this.track(this.launchWorker(next.issue, next.trigger, next.mention));
|
|
106051
|
+
}
|
|
106052
|
+
}
|
|
106053
|
+
track(p) {
|
|
106054
|
+
this.inFlight.add(p);
|
|
106055
|
+
p.finally(() => {
|
|
106056
|
+
this.inFlight.delete(p);
|
|
106057
|
+
});
|
|
106058
|
+
return p;
|
|
106059
|
+
}
|
|
106060
|
+
async whenSettled() {
|
|
106061
|
+
let consecutiveEmpty = 0;
|
|
106062
|
+
for (let guard = 0;guard < 1000; guard++) {
|
|
106063
|
+
if (this.inFlight.size > 0) {
|
|
106064
|
+
await Promise.allSettled(this.inFlight);
|
|
106065
|
+
consecutiveEmpty = 0;
|
|
106066
|
+
}
|
|
106067
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
106068
|
+
if (this.inFlight.size === 0) {
|
|
106069
|
+
consecutiveEmpty += 1;
|
|
106070
|
+
if (consecutiveEmpty >= WHEN_SETTLED_STABLE_HOPS)
|
|
106071
|
+
return;
|
|
106072
|
+
} else {
|
|
106073
|
+
consecutiveEmpty = 0;
|
|
106074
|
+
}
|
|
106040
106075
|
}
|
|
106041
106076
|
}
|
|
106042
106077
|
async launchWorker(issue2, trigger, mention) {
|
|
@@ -106115,6 +106150,7 @@ class AgentCoordinator {
|
|
|
106115
106150
|
issueIdentifier: issue2.identifier,
|
|
106116
106151
|
issue: issue2,
|
|
106117
106152
|
trigger,
|
|
106153
|
+
...prep.cwd ? { cwd: prep.cwd } : {},
|
|
106118
106154
|
kill: handle.kill,
|
|
106119
106155
|
lastReportedIteration: 0,
|
|
106120
106156
|
lastSyncedIteration: 0,
|
|
@@ -106154,7 +106190,10 @@ class AgentCoordinator {
|
|
|
106154
106190
|
this.deps.onLog(`! sync-tasks (launch) failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106155
106191
|
}
|
|
106156
106192
|
}
|
|
106157
|
-
handle.exited.then(
|
|
106193
|
+
handle.exited.then((code) => this.track(this.finalizeWorkerExit(worker, issue2, prep, trigger, code)));
|
|
106194
|
+
}
|
|
106195
|
+
async finalizeWorkerExit(worker, issue2, prep, trigger, code) {
|
|
106196
|
+
{
|
|
106158
106197
|
const idx = this.workers.indexOf(worker);
|
|
106159
106198
|
if (idx >= 0)
|
|
106160
106199
|
this.workers.splice(idx, 1);
|
|
@@ -106199,10 +106238,10 @@ class AgentCoordinator {
|
|
|
106199
106238
|
exit_code: code,
|
|
106200
106239
|
ok
|
|
106201
106240
|
});
|
|
106202
|
-
await this.notifyExited(issue2, prep.changeName, code, trigger);
|
|
106241
|
+
await this.notifyExited(issue2, prep.changeName, code, trigger, worker.cwd);
|
|
106203
106242
|
this.deps.onWorkersChanged();
|
|
106204
106243
|
this.spawnNext();
|
|
106205
|
-
}
|
|
106244
|
+
}
|
|
106206
106245
|
}
|
|
106207
106246
|
async restartWorker(changeName) {
|
|
106208
106247
|
if (this.stopped)
|
|
@@ -106259,7 +106298,7 @@ class AgentCoordinator {
|
|
|
106259
106298
|
this.deps.onLog(`! onSteeringAppended failed for ${changeName}: ${err.message}`, "yellow");
|
|
106260
106299
|
}
|
|
106261
106300
|
}
|
|
106262
|
-
async notifyExited(issue2, changeName, code, trigger) {
|
|
106301
|
+
async notifyExited(issue2, changeName, code, trigger, workerCwd) {
|
|
106263
106302
|
const noChanges = code === NO_CHANGES_EXIT;
|
|
106264
106303
|
const ok = code === 0 || noChanges;
|
|
106265
106304
|
const changeDir = this.deps.getChangeDir?.(issue2) ?? undefined;
|
|
@@ -106279,6 +106318,7 @@ class AgentCoordinator {
|
|
|
106279
106318
|
issueIdentifier: issue2.identifier,
|
|
106280
106319
|
issue: issue2,
|
|
106281
106320
|
trigger,
|
|
106321
|
+
...workerCwd ? { cwd: workerCwd } : {},
|
|
106282
106322
|
kill: () => {},
|
|
106283
106323
|
lastReportedIteration: 0,
|
|
106284
106324
|
lastSyncedIteration: 0,
|
|
@@ -106378,7 +106418,7 @@ var emptyPrStatus = () => ({
|
|
|
106378
106418
|
conflicted: 0,
|
|
106379
106419
|
ciFailed: 0,
|
|
106380
106420
|
quarantined: 0
|
|
106381
|
-
}), emptyPollResult = () => ({
|
|
106421
|
+
}), WHEN_SETTLED_STABLE_HOPS = 3, emptyPollResult = () => ({
|
|
106382
106422
|
found: 0,
|
|
106383
106423
|
added: 0,
|
|
106384
106424
|
buckets: {
|
|
@@ -106891,7 +106931,9 @@ async function applyAwaitingMarkerOnce(issue2, statePath, state, deps) {
|
|
|
106891
106931
|
}
|
|
106892
106932
|
state.confirmation.awaitingMarkerAppliedAt = new Date().toISOString();
|
|
106893
106933
|
try {
|
|
106894
|
-
await
|
|
106934
|
+
const fresh = await readConfirmationState(statePath);
|
|
106935
|
+
fresh.confirmation.awaitingMarkerAppliedAt = state.confirmation.awaitingMarkerAppliedAt;
|
|
106936
|
+
await writeConfirmationState(statePath, fresh.stateObj, fresh.confirmation);
|
|
106895
106937
|
} catch (err) {
|
|
106896
106938
|
deps.onLog(`! persist awaitingMarkerAppliedAt for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106897
106939
|
}
|
|
@@ -106911,7 +106953,9 @@ async function openDraftPrOnce(issue2, statePath, changeName, cwd2, state, deps)
|
|
|
106911
106953
|
}
|
|
106912
106954
|
state.confirmation.earlyDraftPrAt = new Date().toISOString();
|
|
106913
106955
|
try {
|
|
106914
|
-
await
|
|
106956
|
+
const fresh = await readConfirmationState(statePath);
|
|
106957
|
+
fresh.confirmation.earlyDraftPrAt = state.confirmation.earlyDraftPrAt;
|
|
106958
|
+
await writeConfirmationState(statePath, fresh.stateObj, fresh.confirmation);
|
|
106915
106959
|
} catch (err) {
|
|
106916
106960
|
deps.onLog(`! persist earlyDraftPrAt for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
106917
106961
|
}
|
|
@@ -107521,6 +107565,11 @@ var init_linear_resolvers = __esm(() => {
|
|
|
107521
107565
|
// apps/agent/src/agent/wire/prepare.ts
|
|
107522
107566
|
import { mkdir as mkdir8 } from "fs/promises";
|
|
107523
107567
|
import { join as join27 } from "path";
|
|
107568
|
+
function composeAppendPrompt(promptArg, cfgAppendPrompt, workflowPrompt) {
|
|
107569
|
+
return [promptArg || cfgAppendPrompt || "", workflowPrompt].filter(Boolean).join(`
|
|
107570
|
+
|
|
107571
|
+
`);
|
|
107572
|
+
}
|
|
107524
107573
|
function createPrepareHelpers(input) {
|
|
107525
107574
|
const {
|
|
107526
107575
|
args,
|
|
@@ -107617,9 +107666,7 @@ function createPrepareHelpers(input) {
|
|
|
107617
107666
|
} catch (err) {
|
|
107618
107667
|
diag("workflow", `! workflow render failed: ${err.message}`, "yellow");
|
|
107619
107668
|
}
|
|
107620
|
-
const appendPrompt =
|
|
107621
|
-
|
|
107622
|
-
`);
|
|
107669
|
+
const appendPrompt = composeAppendPrompt(args.prompt ?? "", cfg.appendPrompt ?? "", workflowPrompt);
|
|
107623
107670
|
changeName = await scaffoldChangeForIssue(scaffoldTasksDir, scaffoldStatesDir, issue2, comments, appendPrompt, attachments);
|
|
107624
107671
|
} else {
|
|
107625
107672
|
changeName = derivedName;
|
|
@@ -107636,6 +107683,7 @@ function createPrepareHelpers(input) {
|
|
|
107636
107683
|
}
|
|
107637
107684
|
return {
|
|
107638
107685
|
changeName,
|
|
107686
|
+
cwd: workerCwd,
|
|
107639
107687
|
...maps.prByChange.has(changeName) ? { prUrl: maps.prByChange.get(changeName) } : {}
|
|
107640
107688
|
};
|
|
107641
107689
|
}
|
|
@@ -108620,6 +108668,103 @@ function buildTicketDigest(issue2, comments) {
|
|
|
108620
108668
|
function retroDepEntry(agentDebug, hook) {
|
|
108621
108669
|
return agentDebug ? { runRetrospective: hook } : {};
|
|
108622
108670
|
}
|
|
108671
|
+
function computeWantPr(wantPrBase, isAwaiting, isAwaitingConfirmation) {
|
|
108672
|
+
return wantPrBase && !isAwaiting && !isAwaitingConfirmation;
|
|
108673
|
+
}
|
|
108674
|
+
function computeWantValidateOnly(hasValidateSpec, wantPrBase) {
|
|
108675
|
+
return hasValidateSpec && !wantPrBase;
|
|
108676
|
+
}
|
|
108677
|
+
function releaseWorkerMaps(maps, changeName) {
|
|
108678
|
+
maps.cwdByChange.delete(changeName);
|
|
108679
|
+
maps.statesDirByChange.delete(changeName);
|
|
108680
|
+
maps.branchByChange.delete(changeName);
|
|
108681
|
+
maps.issueByChange.delete(changeName);
|
|
108682
|
+
}
|
|
108683
|
+
function buildTaskCmd(args, cfg, changeName) {
|
|
108684
|
+
const engine = args.engineSet ? args.engine : cfg.engine;
|
|
108685
|
+
const model = args.engineSet ? args.model : cfg.model;
|
|
108686
|
+
const c = [
|
|
108687
|
+
process.execPath,
|
|
108688
|
+
process.argv[1] ?? "",
|
|
108689
|
+
"loop",
|
|
108690
|
+
"task",
|
|
108691
|
+
"--name",
|
|
108692
|
+
changeName,
|
|
108693
|
+
"--" + engine,
|
|
108694
|
+
"--model",
|
|
108695
|
+
model
|
|
108696
|
+
];
|
|
108697
|
+
const maxIter = args.maxIterations || cfg.maxIterationsPerTask;
|
|
108698
|
+
if (maxIter > 0)
|
|
108699
|
+
c.push("--max-iterations", String(maxIter));
|
|
108700
|
+
const maxCost = args.maxCostUsd || cfg.maxCostUsdPerTask;
|
|
108701
|
+
if (maxCost > 0)
|
|
108702
|
+
c.push("--max-cost", String(maxCost));
|
|
108703
|
+
const maxRuntime = args.maxRuntimeMinutes || cfg.maxRuntimeMinutesPerTask;
|
|
108704
|
+
if (maxRuntime > 0)
|
|
108705
|
+
c.push("--max-runtime", String(maxRuntime));
|
|
108706
|
+
const maxFailures = args.maxConsecutiveFailures !== 5 ? args.maxConsecutiveFailures : cfg.maxConsecutiveFailuresPerTask;
|
|
108707
|
+
if (maxFailures !== 5)
|
|
108708
|
+
c.push("--max-failures", String(maxFailures));
|
|
108709
|
+
const delay2 = args.delay || cfg.iterationDelaySeconds;
|
|
108710
|
+
if (delay2 > 0)
|
|
108711
|
+
c.push("--delay", String(delay2));
|
|
108712
|
+
if (args.log || cfg.logRawStream)
|
|
108713
|
+
c.push("--log");
|
|
108714
|
+
if (args.verbose || cfg.taskVerbose)
|
|
108715
|
+
c.push("--verbose");
|
|
108716
|
+
if (args.manualTest || cfg.enableManualTest)
|
|
108717
|
+
c.push("--manual-test");
|
|
108718
|
+
const rp = cfg.openspec.reviewPhase;
|
|
108719
|
+
if (rp.enabled) {
|
|
108720
|
+
c.push("--review-enabled");
|
|
108721
|
+
if (rp.maxRounds !== 1)
|
|
108722
|
+
c.push("--review-max-rounds", String(rp.maxRounds));
|
|
108723
|
+
if (rp.reviewerModel !== undefined)
|
|
108724
|
+
c.push("--review-model", rp.reviewerModel);
|
|
108725
|
+
if (rp.reviewerContextStrategy !== "fresh")
|
|
108726
|
+
c.push("--review-context-strategy", rp.reviewerContextStrategy);
|
|
108727
|
+
}
|
|
108728
|
+
c.push("--from-agent");
|
|
108729
|
+
return c;
|
|
108730
|
+
}
|
|
108731
|
+
function buildPostTaskInput(input) {
|
|
108732
|
+
const { args, cfg } = input;
|
|
108733
|
+
return {
|
|
108734
|
+
...input.trigger ? { mode: input.trigger } : {},
|
|
108735
|
+
...input.prUrl ? { prUrl: input.prUrl } : {},
|
|
108736
|
+
changeName: input.changeName,
|
|
108737
|
+
cwd: input.cwd,
|
|
108738
|
+
projectRoot: input.projectRoot,
|
|
108739
|
+
changeDir: input.changeDir,
|
|
108740
|
+
stateFilePath: input.stateFilePath,
|
|
108741
|
+
branch: input.branch,
|
|
108742
|
+
issue: input.issue,
|
|
108743
|
+
exitCode: input.exitCode,
|
|
108744
|
+
useWorktree: input.useWorktree,
|
|
108745
|
+
wantPr: input.wantPr,
|
|
108746
|
+
wantFixCi: input.wantFixCi,
|
|
108747
|
+
wantAutoMerge: input.wantAutoMerge,
|
|
108748
|
+
wantValidateOnly: input.wantValidateOnly,
|
|
108749
|
+
cfg: {
|
|
108750
|
+
teardownScript: cfg.teardownScript ?? null,
|
|
108751
|
+
prBaseBranch: cfg.prBaseBranch,
|
|
108752
|
+
autoMergeStrategy: cfg.autoMergeStrategy,
|
|
108753
|
+
maxCiFixAttempts: cfg.maxCiFixAttempts,
|
|
108754
|
+
ciPollIntervalSeconds: cfg.ciPollIntervalSeconds,
|
|
108755
|
+
cleanupWorktreeOnSuccess: cfg.cleanupWorktreeOnSuccess,
|
|
108756
|
+
ignoreCiChecks: cfg.ignoreCiChecks,
|
|
108757
|
+
stackPrsOnDependencies: args.stackPrs || cfg.stackPrsOnDependencies,
|
|
108758
|
+
neverTouch: cfg.boundaries.never_touch,
|
|
108759
|
+
metaOnlyFiles: cfg.boundaries.meta_only_files,
|
|
108760
|
+
finalizeNoOpAsDone: cfg.finalizeNoOpAsDone,
|
|
108761
|
+
manualMergeWhenAutoMergeDisabled: cfg.manualMergeWhenAutoMergeDisabled,
|
|
108762
|
+
prDraft: cfg.prDraft,
|
|
108763
|
+
validateCommands: [cfg.commands.test, cfg.commands.lint, cfg.commands.typecheck].filter((c) => Boolean(c))
|
|
108764
|
+
},
|
|
108765
|
+
respawnWorker: input.respawnWorker
|
|
108766
|
+
};
|
|
108767
|
+
}
|
|
108623
108768
|
function createSpawnWorker(input) {
|
|
108624
108769
|
const {
|
|
108625
108770
|
args,
|
|
@@ -108652,54 +108797,8 @@ function createSpawnWorker(input) {
|
|
|
108652
108797
|
onWorkerOutput,
|
|
108653
108798
|
onWorkerCmd
|
|
108654
108799
|
} = input;
|
|
108655
|
-
|
|
108656
|
-
|
|
108657
|
-
const model = args.engineSet ? args.model : cfg.model;
|
|
108658
|
-
const c = [
|
|
108659
|
-
process.execPath,
|
|
108660
|
-
process.argv[1] ?? "",
|
|
108661
|
-
"loop",
|
|
108662
|
-
"task",
|
|
108663
|
-
"--name",
|
|
108664
|
-
changeName,
|
|
108665
|
-
"--" + engine,
|
|
108666
|
-
"--model",
|
|
108667
|
-
model
|
|
108668
|
-
];
|
|
108669
|
-
const maxIter = args.maxIterations || cfg.maxIterationsPerTask;
|
|
108670
|
-
if (maxIter > 0)
|
|
108671
|
-
c.push("--max-iterations", String(maxIter));
|
|
108672
|
-
const maxCost = args.maxCostUsd || cfg.maxCostUsdPerTask;
|
|
108673
|
-
if (maxCost > 0)
|
|
108674
|
-
c.push("--max-cost", String(maxCost));
|
|
108675
|
-
const maxRuntime = args.maxRuntimeMinutes || cfg.maxRuntimeMinutesPerTask;
|
|
108676
|
-
if (maxRuntime > 0)
|
|
108677
|
-
c.push("--max-runtime", String(maxRuntime));
|
|
108678
|
-
const maxFailures = args.maxConsecutiveFailures !== 5 ? args.maxConsecutiveFailures : cfg.maxConsecutiveFailuresPerTask;
|
|
108679
|
-
if (maxFailures !== 5)
|
|
108680
|
-
c.push("--max-failures", String(maxFailures));
|
|
108681
|
-
const delay2 = args.delay || cfg.iterationDelaySeconds;
|
|
108682
|
-
if (delay2 > 0)
|
|
108683
|
-
c.push("--delay", String(delay2));
|
|
108684
|
-
if (args.log || cfg.logRawStream)
|
|
108685
|
-
c.push("--log");
|
|
108686
|
-
if (args.verbose || cfg.taskVerbose)
|
|
108687
|
-
c.push("--verbose");
|
|
108688
|
-
if (args.manualTest || cfg.enableManualTest)
|
|
108689
|
-
c.push("--manual-test");
|
|
108690
|
-
const rp = cfg.openspec.reviewPhase;
|
|
108691
|
-
if (rp.enabled) {
|
|
108692
|
-
c.push("--review-enabled");
|
|
108693
|
-
if (rp.maxRounds !== 1)
|
|
108694
|
-
c.push("--review-max-rounds", String(rp.maxRounds));
|
|
108695
|
-
if (rp.reviewerModel !== undefined)
|
|
108696
|
-
c.push("--review-model", rp.reviewerModel);
|
|
108697
|
-
if (rp.reviewerContextStrategy !== "fresh")
|
|
108698
|
-
c.push("--review-context-strategy", rp.reviewerContextStrategy);
|
|
108699
|
-
}
|
|
108700
|
-
c.push("--from-agent");
|
|
108701
|
-
return c;
|
|
108702
|
-
}
|
|
108800
|
+
const doPostTask = input.runners?.runPostTask ?? runPostTask;
|
|
108801
|
+
const buildTaskCmdFor = (changeName) => buildTaskCmd(args, cfg, changeName);
|
|
108703
108802
|
const retroSeen = new Set;
|
|
108704
108803
|
const runRetrospectiveHook = async (info) => {
|
|
108705
108804
|
try {
|
|
@@ -108777,7 +108876,7 @@ function createSpawnWorker(input) {
|
|
|
108777
108876
|
const workerLayout = projectLayout(cwd2);
|
|
108778
108877
|
const validateSpecPath = join33(workerLayout.changeDir(changeName), "specs", "validate.md");
|
|
108779
108878
|
const hasValidateSpec = await Bun.file(validateSpecPath).exists();
|
|
108780
|
-
const wantValidateOnly = hasValidateSpec
|
|
108879
|
+
const wantValidateOnly = computeWantValidateOnly(hasValidateSpec, wantPrBase);
|
|
108781
108880
|
if (hasValidateSpec) {
|
|
108782
108881
|
try {
|
|
108783
108882
|
const stateFile = workerLayout.stateFile(changeName);
|
|
@@ -108821,10 +108920,10 @@ function createSpawnWorker(input) {
|
|
|
108821
108920
|
} catch (err) {
|
|
108822
108921
|
diag("tasks", `! tasks.md normalization failed: ${err.message}`, "yellow");
|
|
108823
108922
|
}
|
|
108824
|
-
const wantPr = wantPrBase
|
|
108825
|
-
const effectiveCode = await
|
|
108826
|
-
|
|
108827
|
-
|
|
108923
|
+
const wantPr = computeWantPr(wantPrBase, awaitingChangeSet.has(changeName), coordRef.current?.isAwaitingConfirmation(changeName) ?? false);
|
|
108924
|
+
const effectiveCode = await doPostTask(buildPostTaskInput({
|
|
108925
|
+
args,
|
|
108926
|
+
cfg,
|
|
108828
108927
|
changeName,
|
|
108829
108928
|
cwd: cwd2,
|
|
108830
108929
|
projectRoot,
|
|
@@ -108838,24 +108937,10 @@ function createSpawnWorker(input) {
|
|
|
108838
108937
|
wantFixCi,
|
|
108839
108938
|
wantAutoMerge,
|
|
108840
108939
|
wantValidateOnly,
|
|
108841
|
-
|
|
108842
|
-
|
|
108843
|
-
prBaseBranch: cfg.prBaseBranch,
|
|
108844
|
-
autoMergeStrategy: cfg.autoMergeStrategy,
|
|
108845
|
-
maxCiFixAttempts: cfg.maxCiFixAttempts,
|
|
108846
|
-
ciPollIntervalSeconds: cfg.ciPollIntervalSeconds,
|
|
108847
|
-
cleanupWorktreeOnSuccess: cfg.cleanupWorktreeOnSuccess,
|
|
108848
|
-
ignoreCiChecks: cfg.ignoreCiChecks,
|
|
108849
|
-
stackPrsOnDependencies: args.stackPrs || cfg.stackPrsOnDependencies,
|
|
108850
|
-
neverTouch: cfg.boundaries.never_touch,
|
|
108851
|
-
metaOnlyFiles: cfg.boundaries.meta_only_files,
|
|
108852
|
-
finalizeNoOpAsDone: cfg.finalizeNoOpAsDone,
|
|
108853
|
-
manualMergeWhenAutoMergeDisabled: cfg.manualMergeWhenAutoMergeDisabled,
|
|
108854
|
-
prDraft: cfg.prDraft,
|
|
108855
|
-
validateCommands: [cfg.commands.test, cfg.commands.lint, cfg.commands.typecheck].filter((c) => Boolean(c))
|
|
108856
|
-
},
|
|
108940
|
+
...trigger ? { trigger } : {},
|
|
108941
|
+
...prByChange?.get(changeName) ? { prUrl: prByChange.get(changeName) } : {},
|
|
108857
108942
|
respawnWorker: respawn
|
|
108858
|
-
}, {
|
|
108943
|
+
}), {
|
|
108859
108944
|
cmd: tracedCmd,
|
|
108860
108945
|
git: gitRunner,
|
|
108861
108946
|
log: onLog,
|
|
@@ -108894,10 +108979,7 @@ function createSpawnWorker(input) {
|
|
|
108894
108979
|
},
|
|
108895
108980
|
resolveDependencyBaseBranch: (issue2) => resolveDependencyBaseBranchImpl(issue2, tracedCmd, cwd2, { apiKey, onLog })
|
|
108896
108981
|
});
|
|
108897
|
-
cwdByChange
|
|
108898
|
-
statesDirByChange.delete(changeName);
|
|
108899
|
-
branchByChange.delete(changeName);
|
|
108900
|
-
issueByChange.delete(changeName);
|
|
108982
|
+
releaseWorkerMaps({ cwdByChange, statesDirByChange, branchByChange, issueByChange }, changeName);
|
|
108901
108983
|
onWorkerExited(changeName);
|
|
108902
108984
|
return effectiveCode;
|
|
108903
108985
|
});
|
|
@@ -261725,6 +261807,25 @@ async function readSpecAttachmentsSubtree(statePath) {
|
|
|
261725
261807
|
const sidecar = await readSlotSidecar(dirname13(statePath), "specAttachments");
|
|
261726
261808
|
return sidecar ?? await readInlineSpecAttachments(statePath);
|
|
261727
261809
|
}
|
|
261810
|
+
function asRevisions(value) {
|
|
261811
|
+
if (!Array.isArray(value))
|
|
261812
|
+
return [];
|
|
261813
|
+
const out = [];
|
|
261814
|
+
for (const entry of value) {
|
|
261815
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
261816
|
+
const e = entry;
|
|
261817
|
+
if (typeof e.version === "number" && typeof e.attachmentId === "string" && typeof e.sha256 === "string" && typeof e.trigger === "string") {
|
|
261818
|
+
out.push({
|
|
261819
|
+
version: e.version,
|
|
261820
|
+
attachmentId: e.attachmentId,
|
|
261821
|
+
sha256: e.sha256,
|
|
261822
|
+
trigger: e.trigger
|
|
261823
|
+
});
|
|
261824
|
+
}
|
|
261825
|
+
}
|
|
261826
|
+
}
|
|
261827
|
+
return out;
|
|
261828
|
+
}
|
|
261728
261829
|
async function readSpecAttachments(statePath) {
|
|
261729
261830
|
const sa = await readSpecAttachmentsSubtree(statePath);
|
|
261730
261831
|
return {
|
|
@@ -261743,12 +261844,45 @@ async function readSpecAttachments(statePath) {
|
|
|
261743
261844
|
designPdf: {
|
|
261744
261845
|
attachmentId: sa.designPdf?.attachmentId ?? null,
|
|
261745
261846
|
sha256: sa.designPdf?.sha256 ?? null
|
|
261746
|
-
}
|
|
261847
|
+
},
|
|
261848
|
+
designRevisions: asRevisions(sa.designRevisions),
|
|
261849
|
+
designPdfRevisions: asRevisions(sa.designPdfRevisions)
|
|
261747
261850
|
};
|
|
261748
261851
|
}
|
|
261749
261852
|
async function persistSlot(statePath, slot, value) {
|
|
261750
261853
|
await writeField(stateDirOf(statePath), "linear-attachments", `specAttachments.${slot}`, value);
|
|
261751
261854
|
}
|
|
261855
|
+
async function persistRevision(statePath, slot, revisions) {
|
|
261856
|
+
await writeField(stateDirOf(statePath), "linear-attachments", `specAttachments.${REVISIONS_KEY[slot]}`, revisions);
|
|
261857
|
+
}
|
|
261858
|
+
async function isDesignSealed(stateDir) {
|
|
261859
|
+
try {
|
|
261860
|
+
const pr2 = await readSlotSidecar(stateDir, "pr");
|
|
261861
|
+
const url2 = pr2?.url;
|
|
261862
|
+
if (typeof url2 === "string" && url2.length > 0)
|
|
261863
|
+
return true;
|
|
261864
|
+
} catch {}
|
|
261865
|
+
try {
|
|
261866
|
+
const confirmation = await readSlotSidecar(stateDir, "confirmation");
|
|
261867
|
+
if (confirmation?.earlyDraftPrAt != null)
|
|
261868
|
+
return true;
|
|
261869
|
+
} catch {}
|
|
261870
|
+
return false;
|
|
261871
|
+
}
|
|
261872
|
+
async function resolveTriggerLabel(stateDir) {
|
|
261873
|
+
try {
|
|
261874
|
+
const flow2 = await readSlotSidecar(stateDir, "flow");
|
|
261875
|
+
const snapshot = flow2?.actorSnapshot;
|
|
261876
|
+
const value = snapshot?.value;
|
|
261877
|
+
if (typeof value === "string" && TRIGGER_LABELS[value])
|
|
261878
|
+
return TRIGGER_LABELS[value];
|
|
261879
|
+
} catch {}
|
|
261880
|
+
return "revision";
|
|
261881
|
+
}
|
|
261882
|
+
function versionedTitle(slot, n, label) {
|
|
261883
|
+
const base2 = `Ralph design #${n} (${label})`;
|
|
261884
|
+
return slot === "designPdf" ? `${base2} (PDF)` : base2;
|
|
261885
|
+
}
|
|
261752
261886
|
async function adopt(deps, slot) {
|
|
261753
261887
|
const spec = SLOT_SPECS[slot];
|
|
261754
261888
|
try {
|
|
@@ -261793,6 +261927,65 @@ function extractImplementationSection(tasksMarkdown) {
|
|
|
261793
261927
|
return captured.join(`
|
|
261794
261928
|
`).trim();
|
|
261795
261929
|
}
|
|
261930
|
+
async function syncSlotSealed(deps, slot, sourceBytes, hash2, state) {
|
|
261931
|
+
const spec = SLOT_SPECS[slot];
|
|
261932
|
+
const revisions = state[REVISIONS_KEY[slot]];
|
|
261933
|
+
const v1Sha = state[slot]?.sha256 ?? null;
|
|
261934
|
+
if (hash2 === v1Sha || revisions.some((r) => r.sha256 === hash2)) {
|
|
261935
|
+
deps.log(` spec-attachments: ${spec.uploadFilename} unchanged (sealed), skipping`, "gray");
|
|
261936
|
+
return;
|
|
261937
|
+
}
|
|
261938
|
+
const n = 2 + revisions.length;
|
|
261939
|
+
const label = await resolveTriggerLabel(stateDirOf(deps.statePath));
|
|
261940
|
+
const title = versionedTitle(slot, n, label);
|
|
261941
|
+
let uploadBytes;
|
|
261942
|
+
try {
|
|
261943
|
+
uploadBytes = await spec.renderBytes(sourceBytes);
|
|
261944
|
+
} catch (err) {
|
|
261945
|
+
deps.log(`! spec-attachments: render ${spec.uploadFilename} (sealed) failed: ${err.message}`, "yellow");
|
|
261946
|
+
return;
|
|
261947
|
+
}
|
|
261948
|
+
let assetUrl;
|
|
261949
|
+
try {
|
|
261950
|
+
const uploaded = await deps.mutations.uploadFileToLinear(deps.apiKey, {
|
|
261951
|
+
filename: spec.uploadFilename,
|
|
261952
|
+
contentType: spec.contentType,
|
|
261953
|
+
bytes: uploadBytes
|
|
261954
|
+
});
|
|
261955
|
+
assetUrl = uploaded.assetUrl;
|
|
261956
|
+
} catch (err) {
|
|
261957
|
+
deps.log(`! spec-attachments: upload ${spec.uploadFilename} (sealed) failed: ${describeLinearError(err)}`, "yellow");
|
|
261958
|
+
return;
|
|
261959
|
+
}
|
|
261960
|
+
let attachmentId = null;
|
|
261961
|
+
try {
|
|
261962
|
+
attachmentId = await deps.mutations.findIssueAttachmentByTitle(deps.apiKey, deps.issueId, title);
|
|
261963
|
+
if (attachmentId) {
|
|
261964
|
+
deps.log(` spec-attachments: adopted existing ${title} attachment ${attachmentId}`, "gray");
|
|
261965
|
+
}
|
|
261966
|
+
} catch (err) {
|
|
261967
|
+
deps.log(`! spec-attachments: findIssueAttachmentByTitle ${title} failed (treating as no match): ${describeLinearError(err)}`, "yellow");
|
|
261968
|
+
attachmentId = null;
|
|
261969
|
+
}
|
|
261970
|
+
if (!attachmentId) {
|
|
261971
|
+
try {
|
|
261972
|
+
attachmentId = await deps.mutations.createAttachmentForUrl(deps.apiKey, {
|
|
261973
|
+
issueId: deps.issueId,
|
|
261974
|
+
url: assetUrl,
|
|
261975
|
+
title,
|
|
261976
|
+
subtitle: `iteration ${deps.iteration}`
|
|
261977
|
+
});
|
|
261978
|
+
} catch (err) {
|
|
261979
|
+
deps.log(`! spec-attachments: createAttachmentForUrl ${title} failed: ${describeLinearError(err)}`, "yellow");
|
|
261980
|
+
return;
|
|
261981
|
+
}
|
|
261982
|
+
deps.log(` spec-attachments: created ${title} attachment`, "gray");
|
|
261983
|
+
}
|
|
261984
|
+
await persistRevision(deps.statePath, slot, [
|
|
261985
|
+
...revisions,
|
|
261986
|
+
{ version: n, attachmentId, sha256: hash2, trigger: label }
|
|
261987
|
+
]);
|
|
261988
|
+
}
|
|
261796
261989
|
async function syncSlot(deps, slot) {
|
|
261797
261990
|
const spec = SLOT_SPECS[slot];
|
|
261798
261991
|
const [primaryName, ...trailingNames] = spec.sourceFiles;
|
|
@@ -261848,7 +262041,12 @@ ${body}
|
|
|
261848
262041
|
offset += p.length;
|
|
261849
262042
|
}
|
|
261850
262043
|
const hash2 = sha256Hex(sourceBytes);
|
|
261851
|
-
|
|
262044
|
+
const state = await readSpecAttachments(deps.statePath);
|
|
262045
|
+
if (await isDesignSealed(stateDirOf(deps.statePath))) {
|
|
262046
|
+
await syncSlotSealed(deps, slot, sourceBytes, hash2, state);
|
|
262047
|
+
return;
|
|
262048
|
+
}
|
|
262049
|
+
let current = state[slot] ?? EMPTY_SLOT;
|
|
261852
262050
|
if (!current.attachmentId) {
|
|
261853
262051
|
const { adoptedId } = await adopt(deps, slot);
|
|
261854
262052
|
if (adoptedId) {
|
|
@@ -261950,7 +262148,7 @@ async function syncSpecAttachments(deps) {
|
|
|
261950
262148
|
await syncSlot(deps, slot);
|
|
261951
262149
|
}
|
|
261952
262150
|
}
|
|
261953
|
-
var identityRender = async (b2) => b2, pdfRender = (title) => async (b2) => renderMarkdownToPdf(new TextDecoder().decode(b2), title), SLOT_SPECS, LEGACY_SLOT_TITLES, EMPTY_SLOT;
|
|
262151
|
+
var identityRender = async (b2) => b2, pdfRender = (title) => async (b2) => renderMarkdownToPdf(new TextDecoder().decode(b2), title), SLOT_SPECS, LEGACY_SLOT_TITLES, REVISIONS_KEY, EMPTY_SLOT, TRIGGER_LABELS;
|
|
261954
262152
|
var init_spec_attachments = __esm(() => {
|
|
261955
262153
|
init_store();
|
|
261956
262154
|
init_comment_sync();
|
|
@@ -261977,7 +262175,16 @@ var init_spec_attachments = __esm(() => {
|
|
|
261977
262175
|
proposal: "Ralph proposal",
|
|
261978
262176
|
proposalPdf: "Ralph proposal (PDF)"
|
|
261979
262177
|
};
|
|
262178
|
+
REVISIONS_KEY = {
|
|
262179
|
+
design: "designRevisions",
|
|
262180
|
+
designPdf: "designPdfRevisions"
|
|
262181
|
+
};
|
|
261980
262182
|
EMPTY_SLOT = { attachmentId: null, sha256: null };
|
|
262183
|
+
TRIGGER_LABELS = {
|
|
262184
|
+
review: "review follow-up",
|
|
262185
|
+
"ci-fix": "CI fix",
|
|
262186
|
+
"conflict-fix": "conflict fix"
|
|
262187
|
+
};
|
|
261981
262188
|
});
|
|
261982
262189
|
|
|
261983
262190
|
// apps/agent/src/agent/wire/comment-sync.ts
|
|
@@ -262002,7 +262209,7 @@ function createCommentSyncHooks(input) {
|
|
|
262002
262209
|
return {
|
|
262003
262210
|
enabled: enabled2,
|
|
262004
262211
|
syncTasks: async (worker, iteration) => {
|
|
262005
|
-
const root = cwdByChange.get(worker.changeName) ?? projectRoot;
|
|
262212
|
+
const root = worker.cwd ?? cwdByChange.get(worker.changeName) ?? projectRoot;
|
|
262006
262213
|
const layout = projectLayout(root);
|
|
262007
262214
|
const changeDir = layout.changeDir(worker.changeName);
|
|
262008
262215
|
const statePath = layout.stateFile(worker.changeName);
|
package/package.json
CHANGED