@neriros/ralphy 3.3.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp/index.js +64 -17
- package/dist/shell/index.js +109 -30
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -25106,22 +25106,6 @@ ${existing.trimStart()}` : `${message}
|
|
|
25106
25106
|
await mkdir(dirname3(tasksPath), { recursive: true });
|
|
25107
25107
|
await Bun.write(tasksPath, next);
|
|
25108
25108
|
}
|
|
25109
|
-
async readSection(name, artifact, heading) {
|
|
25110
|
-
const file = Bun.file(join4("openspec", "changes", name, artifact));
|
|
25111
|
-
if (!await file.exists())
|
|
25112
|
-
return "";
|
|
25113
|
-
const content = await file.text();
|
|
25114
|
-
const headingIndex = content.indexOf(heading);
|
|
25115
|
-
if (headingIndex === -1)
|
|
25116
|
-
return "";
|
|
25117
|
-
const afterHeading = content.slice(headingIndex + heading.length);
|
|
25118
|
-
const levelMatch = heading.match(/^(#+)/);
|
|
25119
|
-
const level = levelMatch ? levelMatch[1].length : 2;
|
|
25120
|
-
const nextHeadingPattern = new RegExp(`\\n#{1,${level}} `);
|
|
25121
|
-
const nextMatch = afterHeading.match(nextHeadingPattern);
|
|
25122
|
-
const sectionContent = nextMatch ? afterHeading.slice(0, nextMatch.index) : afterHeading;
|
|
25123
|
-
return sectionContent.trim();
|
|
25124
|
-
}
|
|
25125
25109
|
async validateChange(name) {
|
|
25126
25110
|
const result = runOpenspec(["validate", name, "--json", "--no-interactive"]);
|
|
25127
25111
|
if (result.stdout) {
|
|
@@ -25140,8 +25124,71 @@ ${existing.trimStart()}` : `${message}
|
|
|
25140
25124
|
errors: result.stderr ? [result.stderr] : []
|
|
25141
25125
|
};
|
|
25142
25126
|
}
|
|
25127
|
+
async getStatus(name) {
|
|
25128
|
+
const result = runOpenspec(["status", "--change", name, "--json"]);
|
|
25129
|
+
if (result.stdout) {
|
|
25130
|
+
try {
|
|
25131
|
+
const parsed = JSON.parse(result.stdout);
|
|
25132
|
+
const status = {
|
|
25133
|
+
changeName: parsed.changeName ?? name,
|
|
25134
|
+
isComplete: parsed.isComplete ?? false,
|
|
25135
|
+
applyRequires: parsed.applyRequires ?? [],
|
|
25136
|
+
artifacts: parsed.artifacts ?? []
|
|
25137
|
+
};
|
|
25138
|
+
if (parsed.schemaName !== undefined)
|
|
25139
|
+
status.schemaName = parsed.schemaName;
|
|
25140
|
+
return status;
|
|
25141
|
+
} catch {}
|
|
25142
|
+
}
|
|
25143
|
+
return {
|
|
25144
|
+
changeName: name,
|
|
25145
|
+
isComplete: false,
|
|
25146
|
+
applyRequires: [],
|
|
25147
|
+
artifacts: []
|
|
25148
|
+
};
|
|
25149
|
+
}
|
|
25150
|
+
async getInstructions(name, artifact) {
|
|
25151
|
+
const result = runOpenspec(["instructions", artifact, "--change", name, "--json"]);
|
|
25152
|
+
if (result.stdout) {
|
|
25153
|
+
try {
|
|
25154
|
+
const parsed = JSON.parse(result.stdout);
|
|
25155
|
+
const out = {
|
|
25156
|
+
changeName: parsed.changeName ?? name,
|
|
25157
|
+
artifactId: parsed.artifactId ?? artifact,
|
|
25158
|
+
instruction: parsed.instruction ?? ""
|
|
25159
|
+
};
|
|
25160
|
+
if (parsed.outputPath !== undefined)
|
|
25161
|
+
out.outputPath = parsed.outputPath;
|
|
25162
|
+
if (parsed.description !== undefined)
|
|
25163
|
+
out.description = parsed.description;
|
|
25164
|
+
if (parsed.template !== undefined)
|
|
25165
|
+
out.template = parsed.template;
|
|
25166
|
+
if (parsed.dependencies !== undefined)
|
|
25167
|
+
out.dependencies = parsed.dependencies;
|
|
25168
|
+
return out;
|
|
25169
|
+
} catch {}
|
|
25170
|
+
}
|
|
25171
|
+
return { changeName: name, artifactId: artifact, instruction: "" };
|
|
25172
|
+
}
|
|
25173
|
+
async showChange(name) {
|
|
25174
|
+
const result = runOpenspec(["show", name, "--json", "--type", "change"]);
|
|
25175
|
+
if (result.stdout) {
|
|
25176
|
+
try {
|
|
25177
|
+
const parsed = JSON.parse(result.stdout);
|
|
25178
|
+
const out = {
|
|
25179
|
+
id: parsed.id ?? name,
|
|
25180
|
+
deltaCount: parsed.deltaCount ?? 0,
|
|
25181
|
+
deltas: parsed.deltas ?? []
|
|
25182
|
+
};
|
|
25183
|
+
if (parsed.title !== undefined)
|
|
25184
|
+
out.title = parsed.title;
|
|
25185
|
+
return out;
|
|
25186
|
+
} catch {}
|
|
25187
|
+
}
|
|
25188
|
+
return { id: name, deltaCount: 0, deltas: [] };
|
|
25189
|
+
}
|
|
25143
25190
|
async archiveChange(name) {
|
|
25144
|
-
const result = runOpenspec(["archive", name, "-y"
|
|
25191
|
+
const result = runOpenspec(["archive", name, "-y"], { inherit: true });
|
|
25145
25192
|
if (result.status !== 0) {
|
|
25146
25193
|
throw new Error("openspec archive failed");
|
|
25147
25194
|
}
|
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.
|
|
18932
|
-
return "3.
|
|
18931
|
+
if ("3.4.0")
|
|
18932
|
+
return "3.4.0";
|
|
18933
18933
|
} catch {}
|
|
18934
18934
|
const dirsToTry = [];
|
|
18935
18935
|
try {
|
|
@@ -59558,22 +59558,6 @@ ${existing.trimStart()}` : `${message}
|
|
|
59558
59558
|
await mkdir(dirname4(tasksPath), { recursive: true });
|
|
59559
59559
|
await Bun.write(tasksPath, next);
|
|
59560
59560
|
}
|
|
59561
|
-
async readSection(name, artifact, heading) {
|
|
59562
|
-
const file = Bun.file(join6("openspec", "changes", name, artifact));
|
|
59563
|
-
if (!await file.exists())
|
|
59564
|
-
return "";
|
|
59565
|
-
const content = await file.text();
|
|
59566
|
-
const headingIndex = content.indexOf(heading);
|
|
59567
|
-
if (headingIndex === -1)
|
|
59568
|
-
return "";
|
|
59569
|
-
const afterHeading = content.slice(headingIndex + heading.length);
|
|
59570
|
-
const levelMatch = heading.match(/^(#+)/);
|
|
59571
|
-
const level = levelMatch ? levelMatch[1].length : 2;
|
|
59572
|
-
const nextHeadingPattern = new RegExp(`\\n#{1,${level}} `);
|
|
59573
|
-
const nextMatch = afterHeading.match(nextHeadingPattern);
|
|
59574
|
-
const sectionContent = nextMatch ? afterHeading.slice(0, nextMatch.index) : afterHeading;
|
|
59575
|
-
return sectionContent.trim();
|
|
59576
|
-
}
|
|
59577
59561
|
async validateChange(name) {
|
|
59578
59562
|
const result2 = runOpenspec(["validate", name, "--json", "--no-interactive"]);
|
|
59579
59563
|
if (result2.stdout) {
|
|
@@ -59592,8 +59576,71 @@ ${existing.trimStart()}` : `${message}
|
|
|
59592
59576
|
errors: result2.stderr ? [result2.stderr] : []
|
|
59593
59577
|
};
|
|
59594
59578
|
}
|
|
59579
|
+
async getStatus(name) {
|
|
59580
|
+
const result2 = runOpenspec(["status", "--change", name, "--json"]);
|
|
59581
|
+
if (result2.stdout) {
|
|
59582
|
+
try {
|
|
59583
|
+
const parsed = JSON.parse(result2.stdout);
|
|
59584
|
+
const status = {
|
|
59585
|
+
changeName: parsed.changeName ?? name,
|
|
59586
|
+
isComplete: parsed.isComplete ?? false,
|
|
59587
|
+
applyRequires: parsed.applyRequires ?? [],
|
|
59588
|
+
artifacts: parsed.artifacts ?? []
|
|
59589
|
+
};
|
|
59590
|
+
if (parsed.schemaName !== undefined)
|
|
59591
|
+
status.schemaName = parsed.schemaName;
|
|
59592
|
+
return status;
|
|
59593
|
+
} catch {}
|
|
59594
|
+
}
|
|
59595
|
+
return {
|
|
59596
|
+
changeName: name,
|
|
59597
|
+
isComplete: false,
|
|
59598
|
+
applyRequires: [],
|
|
59599
|
+
artifacts: []
|
|
59600
|
+
};
|
|
59601
|
+
}
|
|
59602
|
+
async getInstructions(name, artifact) {
|
|
59603
|
+
const result2 = runOpenspec(["instructions", artifact, "--change", name, "--json"]);
|
|
59604
|
+
if (result2.stdout) {
|
|
59605
|
+
try {
|
|
59606
|
+
const parsed = JSON.parse(result2.stdout);
|
|
59607
|
+
const out = {
|
|
59608
|
+
changeName: parsed.changeName ?? name,
|
|
59609
|
+
artifactId: parsed.artifactId ?? artifact,
|
|
59610
|
+
instruction: parsed.instruction ?? ""
|
|
59611
|
+
};
|
|
59612
|
+
if (parsed.outputPath !== undefined)
|
|
59613
|
+
out.outputPath = parsed.outputPath;
|
|
59614
|
+
if (parsed.description !== undefined)
|
|
59615
|
+
out.description = parsed.description;
|
|
59616
|
+
if (parsed.template !== undefined)
|
|
59617
|
+
out.template = parsed.template;
|
|
59618
|
+
if (parsed.dependencies !== undefined)
|
|
59619
|
+
out.dependencies = parsed.dependencies;
|
|
59620
|
+
return out;
|
|
59621
|
+
} catch {}
|
|
59622
|
+
}
|
|
59623
|
+
return { changeName: name, artifactId: artifact, instruction: "" };
|
|
59624
|
+
}
|
|
59625
|
+
async showChange(name) {
|
|
59626
|
+
const result2 = runOpenspec(["show", name, "--json", "--type", "change"]);
|
|
59627
|
+
if (result2.stdout) {
|
|
59628
|
+
try {
|
|
59629
|
+
const parsed = JSON.parse(result2.stdout);
|
|
59630
|
+
const out = {
|
|
59631
|
+
id: parsed.id ?? name,
|
|
59632
|
+
deltaCount: parsed.deltaCount ?? 0,
|
|
59633
|
+
deltas: parsed.deltas ?? []
|
|
59634
|
+
};
|
|
59635
|
+
if (parsed.title !== undefined)
|
|
59636
|
+
out.title = parsed.title;
|
|
59637
|
+
return out;
|
|
59638
|
+
} catch {}
|
|
59639
|
+
}
|
|
59640
|
+
return { id: name, deltaCount: 0, deltas: [] };
|
|
59641
|
+
}
|
|
59595
59642
|
async archiveChange(name) {
|
|
59596
|
-
const result2 = runOpenspec(["archive", name, "-y"
|
|
59643
|
+
const result2 = runOpenspec(["archive", name, "-y"], { inherit: true });
|
|
59597
59644
|
if (result2.status !== 0) {
|
|
59598
59645
|
throw new Error("openspec archive failed");
|
|
59599
59646
|
}
|
|
@@ -70726,6 +70773,14 @@ function useLoop(opts) {
|
|
|
70726
70773
|
writeState(stateDir, currentState);
|
|
70727
70774
|
setState(currentState);
|
|
70728
70775
|
try {
|
|
70776
|
+
if (typeof opts.changeStore.getStatus === "function") {
|
|
70777
|
+
const status = await opts.changeStore.getStatus(opts.name);
|
|
70778
|
+
if (!status.isComplete) {
|
|
70779
|
+
const blocked = status.artifacts.filter((a) => a.status !== "done").map((a) => `${a.id}=${a.status}`).join(", ");
|
|
70780
|
+
addInfo(`Archive skipped: openspec status reports change incomplete (${blocked || "no artifacts"}).`);
|
|
70781
|
+
throw new Error("openspec status: change not complete");
|
|
70782
|
+
}
|
|
70783
|
+
}
|
|
70729
70784
|
await opts.changeStore.archiveChange(opts.name);
|
|
70730
70785
|
addInfo("Change archived.");
|
|
70731
70786
|
} catch (err) {
|
|
@@ -95184,6 +95239,14 @@ ${truncated}`);
|
|
|
95184
95239
|
|
|
95185
95240
|
`);
|
|
95186
95241
|
}
|
|
95242
|
+
async function safeSha(getHeadSha) {
|
|
95243
|
+
try {
|
|
95244
|
+
const sha = (await getHeadSha()).trim();
|
|
95245
|
+
return sha || null;
|
|
95246
|
+
} catch {
|
|
95247
|
+
return null;
|
|
95248
|
+
}
|
|
95249
|
+
}
|
|
95187
95250
|
async function fixCiUntilGreen(deps, opts) {
|
|
95188
95251
|
for (let attempt2 = 1;attempt2 <= opts.maxAttempts; attempt2++) {
|
|
95189
95252
|
let pollN = 0;
|
|
@@ -95213,10 +95276,18 @@ async function fixCiUntilGreen(deps, opts) {
|
|
|
95213
95276
|
\`\`\`
|
|
95214
95277
|
${logs}
|
|
95215
95278
|
\`\`\``;
|
|
95279
|
+
const shaBefore = deps.getHeadSha ? await safeSha(deps.getHeadSha) : null;
|
|
95216
95280
|
const code = await deps.runTaskWithSteering(steering);
|
|
95217
95281
|
if (code !== 0) {
|
|
95218
95282
|
deps.log(`! task loop exited code ${code} during CI fix attempt ${attempt2}`, "red");
|
|
95219
95283
|
}
|
|
95284
|
+
if (shaBefore !== null) {
|
|
95285
|
+
const shaAfter = await safeSha(deps.getHeadSha);
|
|
95286
|
+
if (shaAfter !== null && shaAfter === shaBefore) {
|
|
95287
|
+
deps.log(`! worker produced no new commits on CI fix attempt ${attempt2} \u2014 failure looks external (e.g. rate-limited deploy). Giving up CI watch.`, "yellow");
|
|
95288
|
+
return { success: false, attempts: attempt2, reason: "no-progress" };
|
|
95289
|
+
}
|
|
95290
|
+
}
|
|
95220
95291
|
try {
|
|
95221
95292
|
deps.onPhase?.("ci-fix", `attempt ${attempt2}/${opts.maxAttempts} \xB7 pushing fix`);
|
|
95222
95293
|
await deps.pushBranch();
|
|
@@ -95657,6 +95728,10 @@ async function fixConflictsAndCiLoop(ctx, prUrl, wantFixCi, checkPrConflict) {
|
|
|
95657
95728
|
pushBranch: async () => {
|
|
95658
95729
|
await ctx.cmd.run(["git", "push", "origin", ctx.branch], ctx.cwd);
|
|
95659
95730
|
},
|
|
95731
|
+
getHeadSha: async () => {
|
|
95732
|
+
const r = await ctx.cmd.run(["git", "rev-parse", "HEAD"], ctx.cwd);
|
|
95733
|
+
return r.stdout.trim();
|
|
95734
|
+
},
|
|
95660
95735
|
log: ctx.log,
|
|
95661
95736
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
95662
95737
|
}, {
|
|
@@ -96215,24 +96290,28 @@ function truncate4(s, max2) {
|
|
|
96215
96290
|
\u2026(truncated)`;
|
|
96216
96291
|
}
|
|
96217
96292
|
function renderTasksBlock(tasksMd, meta3) {
|
|
96218
|
-
const sections = parseTasksMd(tasksMd);
|
|
96293
|
+
const sections = parseTasksMd(tasksMd).filter((s) => s.heading.trim().toLowerCase() !== "planning");
|
|
96219
96294
|
const out = [];
|
|
96220
96295
|
out.push(RALPHY_TASKS_START);
|
|
96221
96296
|
out.push("### Ralph progress");
|
|
96222
96297
|
out.push("");
|
|
96223
|
-
|
|
96224
|
-
|
|
96225
|
-
|
|
96226
|
-
out.push(`**${section.heading}**`);
|
|
96298
|
+
const renderable = sections.filter((s) => s.items.length > 0);
|
|
96299
|
+
if (renderable.length === 0) {
|
|
96300
|
+
out.push("_No mission tasks yet \u2014 planning in progress._");
|
|
96227
96301
|
out.push("");
|
|
96228
|
-
|
|
96229
|
-
|
|
96230
|
-
|
|
96231
|
-
|
|
96232
|
-
|
|
96302
|
+
} else {
|
|
96303
|
+
for (const section of renderable) {
|
|
96304
|
+
out.push(`**${section.heading}**`);
|
|
96305
|
+
out.push("");
|
|
96306
|
+
for (const item of section.items) {
|
|
96307
|
+
out.push(item.bullet);
|
|
96308
|
+
if (item.code !== undefined) {
|
|
96309
|
+
const inner = truncate4(item.code, MAX_CODE_BLOCK_BYTES);
|
|
96310
|
+
out.push(` <details><summary>output</summary><pre>${inner}</pre></details>`);
|
|
96311
|
+
}
|
|
96233
96312
|
}
|
|
96313
|
+
out.push("");
|
|
96234
96314
|
}
|
|
96235
|
-
out.push("");
|
|
96236
96315
|
}
|
|
96237
96316
|
out.push(`<sub>\`${meta3.changeName}\` \xB7 iteration ${meta3.iteration}</sub>`);
|
|
96238
96317
|
out.push(RALPHY_TASKS_END);
|