@open-tomato/rafa 0.11.0 → 0.14.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/README.md +65 -30
- package/dist/cli.js +20172 -16066
- package/dist/effort/store/index.js +1 -1
- package/dist/{index-srdtw7w1.js → index-g9kvby04.js} +34 -16
- package/dist/index.js +142 -143
- package/package.json +1 -1
|
@@ -867,6 +867,14 @@ function runningCommand() {
|
|
|
867
867
|
return running;
|
|
868
868
|
}
|
|
869
869
|
|
|
870
|
+
// src/utils/session-env.ts
|
|
871
|
+
function sessionSpawnEnv(base) {
|
|
872
|
+
return {
|
|
873
|
+
...base,
|
|
874
|
+
CLAUDE_CODE_ENTRYPOINT: "cli"
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
|
|
870
878
|
// src/utils/claude.ts
|
|
871
879
|
async function getClaudeUsagePercent() {
|
|
872
880
|
const envPct = process.env["CLAUDE_USAGE_PERCENT"];
|
|
@@ -912,12 +920,6 @@ function interruptClaudeSessions() {
|
|
|
912
920
|
session.kill("SIGINT");
|
|
913
921
|
return liveSessions.size;
|
|
914
922
|
}
|
|
915
|
-
function claudeSessionEnv() {
|
|
916
|
-
return {
|
|
917
|
-
...process.env,
|
|
918
|
-
CLAUDE_CODE_ENTRYPOINT: "cli"
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
923
|
|
|
922
924
|
class UndeclaredSpendError extends Error {
|
|
923
925
|
name = "UndeclaredSpendError";
|
|
@@ -962,7 +964,7 @@ async function spawnClaude(args, prompt) {
|
|
|
962
964
|
stdin: new TextEncoder().encode(prompt),
|
|
963
965
|
stdout: "inherit",
|
|
964
966
|
stderr: "inherit",
|
|
965
|
-
env:
|
|
967
|
+
env: sessionSpawnEnv(process.env)
|
|
966
968
|
});
|
|
967
969
|
liveSessions.add(proc);
|
|
968
970
|
try {
|
|
@@ -1006,16 +1008,17 @@ async function teeToOperator(stream) {
|
|
|
1006
1008
|
}
|
|
1007
1009
|
return text + tail;
|
|
1008
1010
|
}
|
|
1009
|
-
async function spawnClaudeCaptured(args, prompt) {
|
|
1011
|
+
async function spawnClaudeCaptured(args, prompt, options = {}) {
|
|
1010
1012
|
guardSpend();
|
|
1011
|
-
return spawnCaptured(args, prompt);
|
|
1013
|
+
return spawnCaptured(args, prompt, options);
|
|
1012
1014
|
}
|
|
1013
|
-
async function spawnCaptured(args, prompt) {
|
|
1015
|
+
async function spawnCaptured(args, prompt, options = {}) {
|
|
1014
1016
|
const proc = Bun.spawn([CLAUDE_BIN, ...args], {
|
|
1015
1017
|
stdin: new TextEncoder().encode(prompt),
|
|
1016
1018
|
stdout: "pipe",
|
|
1017
1019
|
stderr: "inherit",
|
|
1018
|
-
env:
|
|
1020
|
+
env: sessionSpawnEnv(process.env),
|
|
1021
|
+
...options.cwd === undefined ? {} : { cwd: options.cwd }
|
|
1019
1022
|
});
|
|
1020
1023
|
liveSessions.add(proc);
|
|
1021
1024
|
let stdout;
|
|
@@ -1130,11 +1133,16 @@ var REST_STATES = {
|
|
|
1130
1133
|
cancelled: "closed"
|
|
1131
1134
|
};
|
|
1132
1135
|
function createGhRunner(options) {
|
|
1133
|
-
const { cwd, command = "gh" } = options;
|
|
1136
|
+
const { cwd, command = "gh", env } = options;
|
|
1134
1137
|
return async (args) => {
|
|
1138
|
+
const executable = env === undefined ? command : Bun.which(command, { PATH: env.PATH ?? "", cwd });
|
|
1139
|
+
if (executable === null) {
|
|
1140
|
+
return { ok: false, stdout: "", stderr: notOnPath(command, cwd, env?.PATH) };
|
|
1141
|
+
}
|
|
1135
1142
|
try {
|
|
1136
|
-
const proc = Bun.spawn([
|
|
1143
|
+
const proc = Bun.spawn([executable, ...args], {
|
|
1137
1144
|
cwd,
|
|
1145
|
+
...env === undefined ? {} : { env: { ...env } },
|
|
1138
1146
|
stdin: "ignore",
|
|
1139
1147
|
stdout: "pipe",
|
|
1140
1148
|
stderr: "pipe"
|
|
@@ -1150,6 +1158,10 @@ function createGhRunner(options) {
|
|
|
1150
1158
|
}
|
|
1151
1159
|
};
|
|
1152
1160
|
}
|
|
1161
|
+
function notOnPath(command, cwd, path) {
|
|
1162
|
+
const searched = path === undefined ? "an environment with no PATH" : `PATH ${JSON.stringify(path)}`;
|
|
1163
|
+
return `could not run ${command} in ${cwd}: not found on ${searched} (ENOENT)`;
|
|
1164
|
+
}
|
|
1153
1165
|
function isOneOf(members, value) {
|
|
1154
1166
|
return typeof value === "string" && members.includes(value);
|
|
1155
1167
|
}
|
|
@@ -1283,20 +1295,26 @@ function listedIssues(stdout) {
|
|
|
1283
1295
|
function labelValue(labels, prefix) {
|
|
1284
1296
|
return labels.find((label) => label.startsWith(prefix))?.slice(prefix.length);
|
|
1285
1297
|
}
|
|
1298
|
+
function typeOfLabels(labels) {
|
|
1299
|
+
const type = labelValue(labels, GITHUB_LABELS.typePrefix);
|
|
1300
|
+
return isOneOf(ISSUE_TYPES, type) ? type : "code";
|
|
1301
|
+
}
|
|
1302
|
+
function moduleOfLabels(labels) {
|
|
1303
|
+
return labelValue(labels, GITHUB_LABELS.modulePrefix) ?? "unassigned";
|
|
1304
|
+
}
|
|
1286
1305
|
function stateOf(viewed) {
|
|
1287
1306
|
if (viewed.state === "OPEN")
|
|
1288
1307
|
return "todo";
|
|
1289
1308
|
return viewed.stateReason === NOT_PLANNED ? "cancelled" : "done";
|
|
1290
1309
|
}
|
|
1291
1310
|
function issueOf(ref, viewed) {
|
|
1292
|
-
const type = labelValue(viewed.labels, GITHUB_LABELS.typePrefix);
|
|
1293
1311
|
const priority = labelValue(viewed.labels, GITHUB_LABELS.priorityPrefix);
|
|
1294
1312
|
return {
|
|
1295
1313
|
opt: ref.opt,
|
|
1296
1314
|
title: viewed.title,
|
|
1297
1315
|
body: viewed.body,
|
|
1298
|
-
type:
|
|
1299
|
-
module:
|
|
1316
|
+
type: typeOfLabels(viewed.labels),
|
|
1317
|
+
module: moduleOfLabels(viewed.labels),
|
|
1300
1318
|
priority: isOneOf(ISSUE_PRIORITIES, priority) ? priority : null,
|
|
1301
1319
|
project: null,
|
|
1302
1320
|
blockedBy: viewed.labels.map((label) => label.startsWith(GITHUB_LABELS.blockedByPrefix) ? label.slice(GITHUB_LABELS.blockedByPrefix.length) : "").filter(isIssueNumber).map(Number),
|
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
sqliteStorePath,
|
|
51
51
|
withSqliteStore,
|
|
52
52
|
writeSqliteStore
|
|
53
|
-
} from "./index-
|
|
53
|
+
} from "./index-g9kvby04.js";
|
|
54
54
|
import {
|
|
55
55
|
BUDGET_FLAG,
|
|
56
56
|
CLAUDE_SETTING_SOURCES,
|
|
@@ -337,6 +337,13 @@ var PROMPT_SHAPES = [
|
|
|
337
337
|
prefix: "The pull request for branch ",
|
|
338
338
|
firstLineInfix: " is not mergeable: ",
|
|
339
339
|
source: "src/start/pr-lifecycle.ts"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
kind: "search",
|
|
343
|
+
label: "search",
|
|
344
|
+
prefix: "# Inventory search instructions",
|
|
345
|
+
firstLineInfix: null,
|
|
346
|
+
source: "src/inventory/search/prompt.ts"
|
|
340
347
|
}
|
|
341
348
|
];
|
|
342
349
|
var ENQUEUE_SCAN_WINDOW = 10;
|
|
@@ -1895,7 +1902,7 @@ async function report(args, repoRoot) {
|
|
|
1895
1902
|
}
|
|
1896
1903
|
}
|
|
1897
1904
|
// package.json
|
|
1898
|
-
var version = "0.
|
|
1905
|
+
var version = "0.14.0";
|
|
1899
1906
|
|
|
1900
1907
|
// src/modules/manifest.ts
|
|
1901
1908
|
var MANIFEST_VERSION = 1;
|
|
@@ -2378,8 +2385,7 @@ function definitionName(text) {
|
|
|
2378
2385
|
const name = frontmatter["name"];
|
|
2379
2386
|
return typeof name === "string" && name.length > 0 ? name : null;
|
|
2380
2387
|
}
|
|
2381
|
-
function
|
|
2382
|
-
const dir = join3(root, AGENT_DEFINITION_DIR);
|
|
2388
|
+
function readAgentDirectory(dir) {
|
|
2383
2389
|
const found = [];
|
|
2384
2390
|
for (const file of markdownFiles(dir)) {
|
|
2385
2391
|
const path = join3(dir, file);
|
|
@@ -2393,6 +2399,9 @@ function readAgentDefinitions(root) {
|
|
|
2393
2399
|
}
|
|
2394
2400
|
return found.sort((a, b) => a.name.localeCompare(b.name));
|
|
2395
2401
|
}
|
|
2402
|
+
function readAgentDefinitions(root) {
|
|
2403
|
+
return readAgentDirectory(join3(root, AGENT_DEFINITION_DIR));
|
|
2404
|
+
}
|
|
2396
2405
|
function firstByName(files) {
|
|
2397
2406
|
const byName = new Map;
|
|
2398
2407
|
for (const file of files) {
|
|
@@ -4182,6 +4191,7 @@ var BLOCKED_BY_FIELD = "Blocked by";
|
|
|
4182
4191
|
var FENCE_LINE2 = /^ {0,3}(?:```|~~~)/u;
|
|
4183
4192
|
var FIELD_LINE = /^ {0,3}(?:[-*+]\s+)?[*_]{0,2}blocked\s+by[*_]{0,2}\s*:(.*)$/iu;
|
|
4184
4193
|
var ISSUE_ID = /#(\d+)/gu;
|
|
4194
|
+
var FOREIGN_ID = /[A-Za-z0-9][A-Za-z0-9-]*\/[A-Za-z0-9._-]+#\d+/gu;
|
|
4185
4195
|
var REMEDY4 = `name them as "${BLOCKED_BY_FIELD}: #24 #26", or take the ${SPEC_BLOCKED_LABEL} label off`;
|
|
4186
4196
|
function hasSpecBlockedLabel(labels) {
|
|
4187
4197
|
return labels.some((label) => label.trim().toLowerCase() === SPEC_BLOCKED_LABEL);
|
|
@@ -4214,29 +4224,41 @@ function idsIn(text) {
|
|
|
4214
4224
|
}
|
|
4215
4225
|
return found;
|
|
4216
4226
|
}
|
|
4217
|
-
function
|
|
4227
|
+
function foreignIn(text) {
|
|
4228
|
+
const found = [];
|
|
4229
|
+
for (const [token] of text.matchAll(FOREIGN_ID)) {
|
|
4230
|
+
if (!found.includes(token))
|
|
4231
|
+
found.push(token);
|
|
4232
|
+
}
|
|
4233
|
+
return found;
|
|
4234
|
+
}
|
|
4235
|
+
var NAMED_NOTHING = { ids: [], foreign: [] };
|
|
4236
|
+
function reading(kind, issue, found, named, unknown) {
|
|
4218
4237
|
return {
|
|
4219
4238
|
kind,
|
|
4220
4239
|
issue,
|
|
4221
4240
|
line: found?.number ?? null,
|
|
4222
4241
|
text: found?.text ?? null,
|
|
4223
|
-
blockers,
|
|
4242
|
+
blockers: named.ids,
|
|
4243
|
+
foreign: named.foreign,
|
|
4224
4244
|
unknown
|
|
4225
4245
|
};
|
|
4226
4246
|
}
|
|
4227
4247
|
function readBlockedBy(issue, body, known) {
|
|
4228
4248
|
const found = findFieldLine(body);
|
|
4229
4249
|
if (found === null)
|
|
4230
|
-
return reading("no-line", issue, null,
|
|
4231
|
-
const
|
|
4250
|
+
return reading("no-line", issue, null, NAMED_NOTHING, []);
|
|
4251
|
+
const foreign = foreignIn(found.text);
|
|
4252
|
+
const ids = idsIn(found.text.replace(FOREIGN_ID, " "));
|
|
4253
|
+
const named = { ids, foreign };
|
|
4232
4254
|
if (ids.length === 0)
|
|
4233
|
-
return reading("no-ids", issue, found,
|
|
4255
|
+
return reading("no-ids", issue, found, named, []);
|
|
4234
4256
|
const unknown = known === undefined ? [] : ids.filter((id) => id !== issue && !known.has(id));
|
|
4235
4257
|
if (ids.includes(issue))
|
|
4236
|
-
return reading("self-reference", issue, found,
|
|
4258
|
+
return reading("self-reference", issue, found, named, unknown);
|
|
4237
4259
|
if (unknown.length > 0)
|
|
4238
|
-
return reading("unknown-issue", issue, found,
|
|
4239
|
-
return reading("blocked", issue, found,
|
|
4260
|
+
return reading("unknown-issue", issue, found, named, unknown);
|
|
4261
|
+
return reading("blocked", issue, found, named, unknown);
|
|
4240
4262
|
}
|
|
4241
4263
|
function nameIds(ids) {
|
|
4242
4264
|
return ids.map((id) => `#${String(id)}`).join(" ");
|
|
@@ -4246,6 +4268,9 @@ function faultClause(read) {
|
|
|
4246
4268
|
if (read.kind === "no-line") {
|
|
4247
4269
|
return `is labelled ${SPEC_BLOCKED_LABEL} and its body carries no "${BLOCKED_BY_FIELD}:" line`;
|
|
4248
4270
|
}
|
|
4271
|
+
if (read.kind === "no-ids" && read.foreign.length > 0) {
|
|
4272
|
+
return `has a "${BLOCKED_BY_FIELD}:" line ${at} naming only issues on other repositories: ${read.foreign.join(" ")}`;
|
|
4273
|
+
}
|
|
4249
4274
|
if (read.kind === "no-ids") {
|
|
4250
4275
|
return `has a "${BLOCKED_BY_FIELD}:" line ${at} naming no issue: "${read.text ?? ""}"`;
|
|
4251
4276
|
}
|
|
@@ -4726,112 +4751,8 @@ async function resolvePlanSpec(options) {
|
|
|
4726
4751
|
});
|
|
4727
4752
|
}
|
|
4728
4753
|
|
|
4729
|
-
// src/
|
|
4754
|
+
// src/cli/prompt/confirm.ts
|
|
4730
4755
|
import { createInterface as createInterface2 } from "readline";
|
|
4731
|
-
|
|
4732
|
-
// src/project/roots.ts
|
|
4733
|
-
import { accessSync, constants, readFileSync as readFileSync8, statSync as statSync7 } from "fs";
|
|
4734
|
-
|
|
4735
|
-
// src/project/scope.ts
|
|
4736
|
-
import { existsSync as existsSync9, realpathSync as realpathSync2 } from "fs";
|
|
4737
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6 } from "path";
|
|
4738
|
-
var SCOPE_DIR = dirname3(CONFIG_FILE);
|
|
4739
|
-
var INIT_COMMAND = "rafa init";
|
|
4740
|
-
var DISK_FILE_SYSTEM = Object.freeze({
|
|
4741
|
-
exists: (path3) => existsSync9(path3),
|
|
4742
|
-
realpath: (path3) => realpathSync2(path3)
|
|
4743
|
-
});
|
|
4744
|
-
|
|
4745
|
-
class ScopeError extends Error {
|
|
4746
|
-
constructor(message, options) {
|
|
4747
|
-
super(`rafa scope: ${message}`, options);
|
|
4748
|
-
this.name = "ScopeError";
|
|
4749
|
-
}
|
|
4750
|
-
}
|
|
4751
|
-
function scopeAt(base) {
|
|
4752
|
-
return { dir: join6(base, SCOPE_DIR), configFile: configFilePath(base) };
|
|
4753
|
-
}
|
|
4754
|
-
function initHint(start, passedUserConfig = null) {
|
|
4755
|
-
const passed2 = passedUserConfig === null ? [] : [`${passedUserConfig} is the user scope's config and marks no project`];
|
|
4756
|
-
return [
|
|
4757
|
-
`not inside a rafa project: no ${CONFIG_FILE} in ${start} or any directory above it`,
|
|
4758
|
-
...passed2,
|
|
4759
|
-
`run \`${INIT_COMMAND}\` to set one up`
|
|
4760
|
-
].join(`
|
|
4761
|
-
`);
|
|
4762
|
-
}
|
|
4763
|
-
function requireAbsolute(label, path3) {
|
|
4764
|
-
if (!isAbsolute2(path3)) {
|
|
4765
|
-
throw new ScopeError(`${label} is ${describeValue(path3)}, expected an absolute path`);
|
|
4766
|
-
}
|
|
4767
|
-
}
|
|
4768
|
-
function realStartOf(start, fs2) {
|
|
4769
|
-
try {
|
|
4770
|
-
return fs2.realpath(start);
|
|
4771
|
-
} catch (error) {
|
|
4772
|
-
const message = `start directory ${start} does not resolve (${messageOf(error)})`;
|
|
4773
|
-
throw new ScopeError(message, { cause: error });
|
|
4774
|
-
}
|
|
4775
|
-
}
|
|
4776
|
-
function realHomeOf(home, fs2) {
|
|
4777
|
-
try {
|
|
4778
|
-
return fs2.realpath(home);
|
|
4779
|
-
} catch {
|
|
4780
|
-
return null;
|
|
4781
|
-
}
|
|
4782
|
-
}
|
|
4783
|
-
function selfAndAncestors(path3) {
|
|
4784
|
-
const parent = dirname3(path3);
|
|
4785
|
-
return parent === path3 ? [path3] : [path3, ...selfAndAncestors(parent)];
|
|
4786
|
-
}
|
|
4787
|
-
function walkUp(realStart, realHome, fs2) {
|
|
4788
|
-
let passedUserConfig = false;
|
|
4789
|
-
for (const dir of selfAndAncestors(realStart)) {
|
|
4790
|
-
if (!fs2.exists(configFilePath(dir)))
|
|
4791
|
-
continue;
|
|
4792
|
-
if (dir !== realHome)
|
|
4793
|
-
return { root: dir, passedUserConfig };
|
|
4794
|
-
passedUserConfig = true;
|
|
4795
|
-
}
|
|
4796
|
-
return { root: null, passedUserConfig };
|
|
4797
|
-
}
|
|
4798
|
-
function resolveScope(start, seams) {
|
|
4799
|
-
const { home, fs: fs2 = DISK_FILE_SYSTEM } = seams;
|
|
4800
|
-
requireAbsolute("start directory", start);
|
|
4801
|
-
requireAbsolute("home directory", home);
|
|
4802
|
-
const user = scopeAt(home);
|
|
4803
|
-
const walk = walkUp(realStartOf(start, fs2), realHomeOf(home, fs2), fs2);
|
|
4804
|
-
if (walk.root === null) {
|
|
4805
|
-
const passed2 = walk.passedUserConfig ? user.configFile : null;
|
|
4806
|
-
return { found: false, start, home, user, hint: initHint(start, passed2) };
|
|
4807
|
-
}
|
|
4808
|
-
return { found: true, root: walk.root, home, project: scopeAt(walk.root), user };
|
|
4809
|
-
}
|
|
4810
|
-
|
|
4811
|
-
// src/project/roots.ts
|
|
4812
|
-
var REFUSED_ROOTS = Object.freeze([
|
|
4813
|
-
{ path: "/", why: "is the filesystem root" },
|
|
4814
|
-
{ path: "/var", why: "holds system state" },
|
|
4815
|
-
{ path: "/etc", why: "holds system configuration" },
|
|
4816
|
-
{ path: "/usr", why: "holds system programs" },
|
|
4817
|
-
{ path: "/home", why: "holds the home directories of every user" },
|
|
4818
|
-
{ path: "/Users", why: "holds the home directories of every user" }
|
|
4819
|
-
]);
|
|
4820
|
-
var HOME_WHY = `is the home directory, whose ${SCOPE_DIR}/ is the user scope`;
|
|
4821
|
-
var MONOREPO_MARKER_FILES = Object.freeze([
|
|
4822
|
-
"turbo.json",
|
|
4823
|
-
"pnpm-workspace.yaml",
|
|
4824
|
-
"nx.json",
|
|
4825
|
-
"lerna.json"
|
|
4826
|
-
]);
|
|
4827
|
-
var DISK_ROOTS_FILE_SYSTEM = Object.freeze({
|
|
4828
|
-
...DISK_FILE_SYSTEM,
|
|
4829
|
-
readFile: (path3) => readFileSync8(path3, "utf8"),
|
|
4830
|
-
isDirectory: (path3) => statSync7(path3).isDirectory(),
|
|
4831
|
-
assertWritable: (path3) => accessSync(path3, constants.W_OK)
|
|
4832
|
-
});
|
|
4833
|
-
|
|
4834
|
-
// src/project/root-choice.ts
|
|
4835
4756
|
function createLinePrompter(input, output) {
|
|
4836
4757
|
const buffered = [];
|
|
4837
4758
|
const waiting = [];
|
|
@@ -5639,12 +5560,90 @@ import {
|
|
|
5639
5560
|
linkSync as linkSync2,
|
|
5640
5561
|
mkdirSync as mkdirSync4,
|
|
5641
5562
|
readdirSync as readdirSync4,
|
|
5642
|
-
readFileSync as
|
|
5563
|
+
readFileSync as readFileSync8,
|
|
5643
5564
|
renameSync as renameSync2,
|
|
5644
5565
|
rmSync,
|
|
5645
5566
|
writeFileSync as writeFileSync3
|
|
5646
5567
|
} from "fs";
|
|
5647
5568
|
import { basename as basename4, dirname as dirname4, join as join7 } from "path";
|
|
5569
|
+
|
|
5570
|
+
// src/project/scope.ts
|
|
5571
|
+
import { existsSync as existsSync9, realpathSync as realpathSync2 } from "fs";
|
|
5572
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6 } from "path";
|
|
5573
|
+
var SCOPE_DIR = dirname3(CONFIG_FILE);
|
|
5574
|
+
var INIT_COMMAND = "rafa init";
|
|
5575
|
+
var DISK_FILE_SYSTEM = Object.freeze({
|
|
5576
|
+
exists: (path3) => existsSync9(path3),
|
|
5577
|
+
realpath: (path3) => realpathSync2(path3)
|
|
5578
|
+
});
|
|
5579
|
+
|
|
5580
|
+
class ScopeError extends Error {
|
|
5581
|
+
constructor(message, options) {
|
|
5582
|
+
super(`rafa scope: ${message}`, options);
|
|
5583
|
+
this.name = "ScopeError";
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
function scopeAt(base) {
|
|
5587
|
+
return { dir: join6(base, SCOPE_DIR), configFile: configFilePath(base) };
|
|
5588
|
+
}
|
|
5589
|
+
function initHint(start, passedUserConfig = null) {
|
|
5590
|
+
const passed2 = passedUserConfig === null ? [] : [`${passedUserConfig} is the user scope's config and marks no project`];
|
|
5591
|
+
return [
|
|
5592
|
+
`not inside a rafa project: no ${CONFIG_FILE} in ${start} or any directory above it`,
|
|
5593
|
+
...passed2,
|
|
5594
|
+
`run \`${INIT_COMMAND}\` to set one up`
|
|
5595
|
+
].join(`
|
|
5596
|
+
`);
|
|
5597
|
+
}
|
|
5598
|
+
function requireAbsolute(label, path3) {
|
|
5599
|
+
if (!isAbsolute2(path3)) {
|
|
5600
|
+
throw new ScopeError(`${label} is ${describeValue(path3)}, expected an absolute path`);
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
function realStartOf(start, fs2) {
|
|
5604
|
+
try {
|
|
5605
|
+
return fs2.realpath(start);
|
|
5606
|
+
} catch (error) {
|
|
5607
|
+
const message = `start directory ${start} does not resolve (${messageOf(error)})`;
|
|
5608
|
+
throw new ScopeError(message, { cause: error });
|
|
5609
|
+
}
|
|
5610
|
+
}
|
|
5611
|
+
function realHomeOf(home, fs2) {
|
|
5612
|
+
try {
|
|
5613
|
+
return fs2.realpath(home);
|
|
5614
|
+
} catch {
|
|
5615
|
+
return null;
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
function selfAndAncestors(path3) {
|
|
5619
|
+
const parent = dirname3(path3);
|
|
5620
|
+
return parent === path3 ? [path3] : [path3, ...selfAndAncestors(parent)];
|
|
5621
|
+
}
|
|
5622
|
+
function walkUp(realStart, realHome, fs2) {
|
|
5623
|
+
let passedUserConfig = false;
|
|
5624
|
+
for (const dir of selfAndAncestors(realStart)) {
|
|
5625
|
+
if (!fs2.exists(configFilePath(dir)))
|
|
5626
|
+
continue;
|
|
5627
|
+
if (dir !== realHome)
|
|
5628
|
+
return { root: dir, passedUserConfig };
|
|
5629
|
+
passedUserConfig = true;
|
|
5630
|
+
}
|
|
5631
|
+
return { root: null, passedUserConfig };
|
|
5632
|
+
}
|
|
5633
|
+
function resolveScope(start, seams) {
|
|
5634
|
+
const { home, fs: fs2 = DISK_FILE_SYSTEM } = seams;
|
|
5635
|
+
requireAbsolute("start directory", start);
|
|
5636
|
+
requireAbsolute("home directory", home);
|
|
5637
|
+
const user = scopeAt(home);
|
|
5638
|
+
const walk = walkUp(realStartOf(start, fs2), realHomeOf(home, fs2), fs2);
|
|
5639
|
+
if (walk.root === null) {
|
|
5640
|
+
const passed2 = walk.passedUserConfig ? user.configFile : null;
|
|
5641
|
+
return { found: false, start, home, user, hint: initHint(start, passed2) };
|
|
5642
|
+
}
|
|
5643
|
+
return { found: true, root: walk.root, home, project: scopeAt(walk.root), user };
|
|
5644
|
+
}
|
|
5645
|
+
|
|
5646
|
+
// src/loop/sessions.ts
|
|
5648
5647
|
var SESSION_STATES = Object.freeze(["running", "paused", "stopped", "done"]);
|
|
5649
5648
|
var RUNS_DIR = "runs";
|
|
5650
5649
|
var RECORD_EXTENSION = ".json";
|
|
@@ -5792,7 +5791,7 @@ function readState2(record, isAlive = isPidAlive) {
|
|
|
5792
5791
|
function readRecordFile(file) {
|
|
5793
5792
|
let text;
|
|
5794
5793
|
try {
|
|
5795
|
-
text =
|
|
5794
|
+
text = readFileSync8(file, "utf8");
|
|
5796
5795
|
} catch (error) {
|
|
5797
5796
|
throw new SessionRecordError(file, `cannot be read: ${messageOf(error)}`);
|
|
5798
5797
|
}
|
|
@@ -6005,15 +6004,15 @@ function openNextSources(context, seams = DEFAULT_NEXT_SOURCE_SEAMS) {
|
|
|
6005
6004
|
}
|
|
6006
6005
|
|
|
6007
6006
|
// src/commands/plan/list.ts
|
|
6008
|
-
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as
|
|
6007
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "fs";
|
|
6009
6008
|
import { join as join9 } from "path";
|
|
6010
6009
|
var USAGE2 = "rafa plan list";
|
|
6011
6010
|
function listing(dir, stub) {
|
|
6012
6011
|
const plan = join9(dir, planFileName(stub, false));
|
|
6013
6012
|
const trackerPath = join9(dir, planFileName(stub, true));
|
|
6014
6013
|
const tracker = isFile(trackerPath) ? trackerPath : null;
|
|
6015
|
-
const planModel = parsePlan(
|
|
6016
|
-
const counted2 = tracker === null ? planModel : parsePlan(
|
|
6014
|
+
const planModel = parsePlan(readFileSync9(plan, "utf8"));
|
|
6015
|
+
const counted2 = tracker === null ? planModel : parsePlan(readFileSync9(tracker, "utf8"));
|
|
6017
6016
|
return { stub, plan, tracker, tasks: countTasks(counted2.tasks), issues: planModel.issues.length };
|
|
6018
6017
|
}
|
|
6019
6018
|
function listPlans(plans) {
|
|
@@ -7029,7 +7028,7 @@ import { homedir as homedir3 } from "os";
|
|
|
7029
7028
|
var RAFA_VERSION = version;
|
|
7030
7029
|
|
|
7031
7030
|
// src/notices/notices.ts
|
|
7032
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
7031
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
|
|
7033
7032
|
import { dirname as dirname5, join as join10 } from "path";
|
|
7034
7033
|
var NOTICE_IDS = Object.freeze(["alpha", "danger"]);
|
|
7035
7034
|
var FEEDBACK_URL = "https://github.com/open-tomato/rafa/issues/new/choose";
|
|
@@ -7043,7 +7042,7 @@ function isNoticeId(value) {
|
|
|
7043
7042
|
function readDismissed(home) {
|
|
7044
7043
|
let raw;
|
|
7045
7044
|
try {
|
|
7046
|
-
raw =
|
|
7045
|
+
raw = readFileSync10(noticesPath(home), "utf8");
|
|
7047
7046
|
} catch {
|
|
7048
7047
|
return [];
|
|
7049
7048
|
}
|
|
@@ -8260,16 +8259,16 @@ function writeProgress(repoRoot, planStub2) {
|
|
|
8260
8259
|
|
|
8261
8260
|
// src/start/preflight.ts
|
|
8262
8261
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
8263
|
-
import { existsSync as existsSync14, readFileSync as
|
|
8262
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
8264
8263
|
import { homedir as homedir5 } from "os";
|
|
8265
8264
|
import { basename as basename5 } from "path";
|
|
8266
8265
|
|
|
8267
8266
|
// src/preflight/first-dispatch.ts
|
|
8268
|
-
import { readFileSync as
|
|
8267
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
8269
8268
|
var TICKED_TASK = /^- \[[xX]\] (.+)/;
|
|
8270
8269
|
function readIfReadable(path5) {
|
|
8271
8270
|
try {
|
|
8272
|
-
return
|
|
8271
|
+
return readFileSync11(path5, "utf8");
|
|
8273
8272
|
} catch {
|
|
8274
8273
|
return null;
|
|
8275
8274
|
}
|
|
@@ -8306,7 +8305,7 @@ function agentSourcePath(planPath) {
|
|
|
8306
8305
|
}
|
|
8307
8306
|
function readIfReadable2(path5) {
|
|
8308
8307
|
try {
|
|
8309
|
-
return
|
|
8308
|
+
return readFileSync12(path5, "utf8");
|
|
8310
8309
|
} catch {
|
|
8311
8310
|
return null;
|
|
8312
8311
|
}
|
|
@@ -8800,7 +8799,7 @@ async function handleRedChecks(io, branch, prNumber, rows) {
|
|
|
8800
8799
|
}
|
|
8801
8800
|
|
|
8802
8801
|
// src/release/prepare.ts
|
|
8803
|
-
import { readFileSync as
|
|
8802
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
8804
8803
|
|
|
8805
8804
|
// src/release/changelog.ts
|
|
8806
8805
|
var RELEASE_HEADING_FIELDS = ["version", "date", "title"];
|
|
@@ -8985,11 +8984,11 @@ function changelogDate(now) {
|
|
|
8985
8984
|
}
|
|
8986
8985
|
|
|
8987
8986
|
// src/release/enabled.ts
|
|
8988
|
-
import { statSync as
|
|
8987
|
+
import { statSync as statSync7 } from "fs";
|
|
8989
8988
|
import { resolve as resolve9 } from "path";
|
|
8990
8989
|
function isRegularFile(full) {
|
|
8991
8990
|
try {
|
|
8992
|
-
return
|
|
8991
|
+
return statSync7(full).isFile();
|
|
8993
8992
|
} catch {
|
|
8994
8993
|
return false;
|
|
8995
8994
|
}
|
|
@@ -9032,7 +9031,7 @@ function resolveReleaseLevel(declared, notes) {
|
|
|
9032
9031
|
}
|
|
9033
9032
|
|
|
9034
9033
|
// src/release/version.ts
|
|
9035
|
-
import { readFileSync as
|
|
9034
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
|
|
9036
9035
|
var RELEASE_REMOTE = "origin";
|
|
9037
9036
|
var RELEASE_BASE_BRANCH = "main";
|
|
9038
9037
|
var VERSION_SHAPE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/;
|
|
@@ -9124,7 +9123,7 @@ function writeManifestVersion(path5, next) {
|
|
|
9124
9123
|
const unwritten = { path: path5, written: false, previous: null, version: next };
|
|
9125
9124
|
let text;
|
|
9126
9125
|
try {
|
|
9127
|
-
text =
|
|
9126
|
+
text = readFileSync13(path5, "utf8");
|
|
9128
9127
|
} catch (error) {
|
|
9129
9128
|
return { ...unwritten, problem: `${path5} could not be read: ${messageOf(error)}` };
|
|
9130
9129
|
}
|
|
@@ -9227,7 +9226,7 @@ function planVersion(input, versionFile, level) {
|
|
|
9227
9226
|
}
|
|
9228
9227
|
function textOf(path5) {
|
|
9229
9228
|
try {
|
|
9230
|
-
return
|
|
9229
|
+
return readFileSync14(path5, "utf8");
|
|
9231
9230
|
} catch {
|
|
9232
9231
|
return null;
|
|
9233
9232
|
}
|
|
@@ -9340,7 +9339,7 @@ function changelogFailure(failed3, versionEdit, restored) {
|
|
|
9340
9339
|
}
|
|
9341
9340
|
|
|
9342
9341
|
// src/release/verify.ts
|
|
9343
|
-
import { readFileSync as
|
|
9342
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
|
|
9344
9343
|
function changelogInsertionSpan(before, after) {
|
|
9345
9344
|
const beforeLines = before.split(`
|
|
9346
9345
|
`);
|
|
@@ -9357,7 +9356,7 @@ function changelogInsertionSpan(before, after) {
|
|
|
9357
9356
|
}
|
|
9358
9357
|
function textOf2(path5) {
|
|
9359
9358
|
try {
|
|
9360
|
-
return
|
|
9359
|
+
return readFileSync15(path5, "utf8");
|
|
9361
9360
|
} catch {
|
|
9362
9361
|
return null;
|
|
9363
9362
|
}
|
|
@@ -9692,10 +9691,10 @@ async function finishRelease(input, seams = {}) {
|
|
|
9692
9691
|
}
|
|
9693
9692
|
|
|
9694
9693
|
// src/start/risk-total.ts
|
|
9695
|
-
import { readFileSync as
|
|
9694
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
9696
9695
|
|
|
9697
9696
|
// src/plan/risk.ts
|
|
9698
|
-
import { readFileSync as
|
|
9697
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
9699
9698
|
import { isAbsolute as isAbsolute3, join as join13, relative as relative2 } from "path";
|
|
9700
9699
|
|
|
9701
9700
|
// src/schema/tiers.ts
|
|
@@ -10349,7 +10348,7 @@ function located(finding2, file, task) {
|
|
|
10349
10348
|
}
|
|
10350
10349
|
function readText4(path5) {
|
|
10351
10350
|
try {
|
|
10352
|
-
return
|
|
10351
|
+
return readFileSync16(path5, "utf8");
|
|
10353
10352
|
} catch {
|
|
10354
10353
|
return null;
|
|
10355
10354
|
}
|
|
@@ -10423,7 +10422,7 @@ function spawningRunners(root) {
|
|
|
10423
10422
|
}
|
|
10424
10423
|
async function readRiskTotalLine(input, seams = {}) {
|
|
10425
10424
|
const makeRunners = seams.runners ?? spawningRunners;
|
|
10426
|
-
const report2 = await assessPlanRisk({ path: input.planPath, text:
|
|
10425
|
+
const report2 = await assessPlanRisk({ path: input.planPath, text: readFileSync17(input.planPath, "utf8") }, {
|
|
10427
10426
|
repoRoot: input.repoRoot,
|
|
10428
10427
|
home: input.home,
|
|
10429
10428
|
settingSources: input.config.settingSources,
|
|
@@ -10595,7 +10594,7 @@ function announcePlanIssues(planContent) {
|
|
|
10595
10594
|
}
|
|
10596
10595
|
|
|
10597
10596
|
// src/start/runtime.ts
|
|
10598
|
-
import { existsSync as existsSync17, readdirSync as readdirSync6, realpathSync as realpathSync4, statSync as
|
|
10597
|
+
import { existsSync as existsSync17, readdirSync as readdirSync6, realpathSync as realpathSync4, statSync as statSync8 } from "fs";
|
|
10599
10598
|
import { homedir as homedir6 } from "os";
|
|
10600
10599
|
import { isAbsolute as isAbsolute4, join as join14, relative as relative4, resolve as resolve10, sep } from "path";
|
|
10601
10600
|
var RUNTIME_FLAG = "--runtime";
|
|
@@ -10671,14 +10670,14 @@ function installedVersions(root) {
|
|
|
10671
10670
|
}
|
|
10672
10671
|
function isFile2(path5) {
|
|
10673
10672
|
try {
|
|
10674
|
-
return
|
|
10673
|
+
return statSync8(path5).isFile();
|
|
10675
10674
|
} catch {
|
|
10676
10675
|
return false;
|
|
10677
10676
|
}
|
|
10678
10677
|
}
|
|
10679
10678
|
function isDirectory(path5) {
|
|
10680
10679
|
try {
|
|
10681
|
-
return
|
|
10680
|
+
return statSync8(path5).isDirectory();
|
|
10682
10681
|
} catch {
|
|
10683
10682
|
return false;
|
|
10684
10683
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-tomato/rafa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Alpha. Runs a plan through the ralph loop: one Claude Code session per task, one commit per task, then a pull request and a CI wait.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|