@open-tomato/rafa 0.12.0 → 0.15.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 +32 -3
- package/dist/cli.js +15157 -12772
- package/dist/effort/store/index.js +2 -2
- package/dist/{index-4g6vyznd.js → index-1x5t4t9r.js} +31 -14
- package/dist/{index-96pz9023.js → index-2256nwj0.js} +20 -2
- package/dist/{index-p96zrptw.js → index-p572cxex.js} +1 -1
- package/dist/index.js +45 -12
- package/dist/plan/index.js +2 -2
- package/package.json +1 -1
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
openNdjsonStore,
|
|
5
5
|
openSqliteStore,
|
|
6
6
|
selectEffortStore
|
|
7
|
-
} from "../../index-
|
|
7
|
+
} from "../../index-1x5t4t9r.js";
|
|
8
8
|
import {
|
|
9
9
|
STORE_BACKENDS
|
|
10
|
-
} from "../../index-
|
|
10
|
+
} from "../../index-2256nwj0.js";
|
|
11
11
|
export {
|
|
12
12
|
selectEffortStore,
|
|
13
13
|
openSqliteStore,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isMapping,
|
|
9
9
|
messageOf,
|
|
10
10
|
readRafaBlocks
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-2256nwj0.js";
|
|
12
12
|
|
|
13
13
|
// src/effort/store.ts
|
|
14
14
|
import {
|
|
@@ -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 {
|
|
@@ -1015,7 +1017,7 @@ async function spawnCaptured(args, prompt, options = {}) {
|
|
|
1015
1017
|
stdin: new TextEncoder().encode(prompt),
|
|
1016
1018
|
stdout: "pipe",
|
|
1017
1019
|
stderr: "inherit",
|
|
1018
|
-
env:
|
|
1020
|
+
env: sessionSpawnEnv(process.env),
|
|
1019
1021
|
...options.cwd === undefined ? {} : { cwd: options.cwd }
|
|
1020
1022
|
});
|
|
1021
1023
|
liveSessions.add(proc);
|
|
@@ -1131,11 +1133,16 @@ var REST_STATES = {
|
|
|
1131
1133
|
cancelled: "closed"
|
|
1132
1134
|
};
|
|
1133
1135
|
function createGhRunner(options) {
|
|
1134
|
-
const { cwd, command = "gh" } = options;
|
|
1136
|
+
const { cwd, command = "gh", env } = options;
|
|
1135
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
|
+
}
|
|
1136
1142
|
try {
|
|
1137
|
-
const proc = Bun.spawn([
|
|
1143
|
+
const proc = Bun.spawn([executable, ...args], {
|
|
1138
1144
|
cwd,
|
|
1145
|
+
...env === undefined ? {} : { env: { ...env } },
|
|
1139
1146
|
stdin: "ignore",
|
|
1140
1147
|
stdout: "pipe",
|
|
1141
1148
|
stderr: "pipe"
|
|
@@ -1151,6 +1158,10 @@ function createGhRunner(options) {
|
|
|
1151
1158
|
}
|
|
1152
1159
|
};
|
|
1153
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
|
+
}
|
|
1154
1165
|
function isOneOf(members, value) {
|
|
1155
1166
|
return typeof value === "string" && members.includes(value);
|
|
1156
1167
|
}
|
|
@@ -1284,20 +1295,26 @@ function listedIssues(stdout) {
|
|
|
1284
1295
|
function labelValue(labels, prefix) {
|
|
1285
1296
|
return labels.find((label) => label.startsWith(prefix))?.slice(prefix.length);
|
|
1286
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
|
+
}
|
|
1287
1305
|
function stateOf(viewed) {
|
|
1288
1306
|
if (viewed.state === "OPEN")
|
|
1289
1307
|
return "todo";
|
|
1290
1308
|
return viewed.stateReason === NOT_PLANNED ? "cancelled" : "done";
|
|
1291
1309
|
}
|
|
1292
1310
|
function issueOf(ref, viewed) {
|
|
1293
|
-
const type = labelValue(viewed.labels, GITHUB_LABELS.typePrefix);
|
|
1294
1311
|
const priority = labelValue(viewed.labels, GITHUB_LABELS.priorityPrefix);
|
|
1295
1312
|
return {
|
|
1296
1313
|
opt: ref.opt,
|
|
1297
1314
|
title: viewed.title,
|
|
1298
1315
|
body: viewed.body,
|
|
1299
|
-
type:
|
|
1300
|
-
module:
|
|
1316
|
+
type: typeOfLabels(viewed.labels),
|
|
1317
|
+
module: moduleOfLabels(viewed.labels),
|
|
1301
1318
|
priority: isOneOf(ISSUE_PRIORITIES, priority) ? priority : null,
|
|
1302
1319
|
project: null,
|
|
1303
1320
|
blockedBy: viewed.labels.map((label) => label.startsWith(GITHUB_LABELS.blockedByPrefix) ? label.slice(GITHUB_LABELS.blockedByPrefix.length) : "").filter(isIssueNumber).map(Number),
|
|
@@ -286,6 +286,7 @@ var usdAmount = (raw, at) => {
|
|
|
286
286
|
return usd === null ? refused(at, raw, "a number of US dollars above zero, at most six digits either side of the point") : accepted(usd);
|
|
287
287
|
};
|
|
288
288
|
var issueNumber = (raw, at) => typeof raw === "number" && Number.isSafeInteger(raw) && raw > 0 ? accepted(raw) : refused(at, raw, "an issue number, a whole number above zero");
|
|
289
|
+
var dayCount = (raw, at) => typeof raw === "number" && Number.isSafeInteger(raw) && raw > 0 ? accepted(raw) : refused(at, raw, "a number of days, a whole number above zero");
|
|
289
290
|
var releaseEnabled = (raw, at) => typeof raw === "boolean" || raw === RELEASE_AUTO ? accepted(raw) : refused(at, raw, `true, false or ${RELEASE_AUTO}`);
|
|
290
291
|
var GITHUB_LOGIN = /^[A-Za-z0-9][A-Za-z0-9-]*(?:\[bot\])?$/;
|
|
291
292
|
function isGitHubLogin(value) {
|
|
@@ -421,7 +422,10 @@ var CONFIG_DEFAULTS = Object.freeze({
|
|
|
421
422
|
releaseEnabled: RELEASE_AUTO,
|
|
422
423
|
releaseVersionFile: "package.json",
|
|
423
424
|
releaseChangelog: "CHANGELOG.md",
|
|
424
|
-
releaseHeading: "## {version} \u2014 {date}, {title}"
|
|
425
|
+
releaseHeading: "## {version} \u2014 {date}, {title}",
|
|
426
|
+
cleanupStaleDays: 30,
|
|
427
|
+
cleanupWorktreeIdleDays: 7,
|
|
428
|
+
cleanupKeep: Object.freeze([])
|
|
425
429
|
});
|
|
426
430
|
var directory = text("a directory path");
|
|
427
431
|
var trackerKind = text("a tracker kind name");
|
|
@@ -496,6 +500,17 @@ var SETTINGS = {
|
|
|
496
500
|
key: "release.heading",
|
|
497
501
|
read: text("a changelog heading template"),
|
|
498
502
|
cli: false
|
|
503
|
+
},
|
|
504
|
+
cleanupStaleDays: { key: "cleanup.staleDays", read: dayCount, cli: false },
|
|
505
|
+
cleanupWorktreeIdleDays: {
|
|
506
|
+
key: "cleanup.worktreeIdleDays",
|
|
507
|
+
read: dayCount,
|
|
508
|
+
cli: false
|
|
509
|
+
},
|
|
510
|
+
cleanupKeep: {
|
|
511
|
+
key: "cleanup.keep",
|
|
512
|
+
read: listOf(text("a glob pattern"), "glob patterns"),
|
|
513
|
+
cli: false
|
|
499
514
|
}
|
|
500
515
|
};
|
|
501
516
|
var SETTING_NAMES = Object.keys(SETTINGS);
|
|
@@ -590,7 +605,10 @@ function readLayer(rawOf, atOf) {
|
|
|
590
605
|
releaseEnabled: read("releaseEnabled"),
|
|
591
606
|
releaseVersionFile: read("releaseVersionFile"),
|
|
592
607
|
releaseChangelog: read("releaseChangelog"),
|
|
593
|
-
releaseHeading: read("releaseHeading")
|
|
608
|
+
releaseHeading: read("releaseHeading"),
|
|
609
|
+
cleanupStaleDays: read("cleanupStaleDays"),
|
|
610
|
+
cleanupWorktreeIdleDays: read("cleanupWorktreeIdleDays"),
|
|
611
|
+
cleanupKeep: read("cleanupKeep")
|
|
594
612
|
};
|
|
595
613
|
return { layer, problems, extras };
|
|
596
614
|
}
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
trackerPathFor,
|
|
27
27
|
updateTrackerLine,
|
|
28
28
|
writeTrackerBlocker
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-p572cxex.js";
|
|
30
30
|
import {
|
|
31
31
|
CORE_ADAPTER_REGISTRY,
|
|
32
32
|
ClaudePlannerError,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
sqliteStorePath,
|
|
51
51
|
withSqliteStore,
|
|
52
52
|
writeSqliteStore
|
|
53
|
-
} from "./index-
|
|
53
|
+
} from "./index-1x5t4t9r.js";
|
|
54
54
|
import {
|
|
55
55
|
BUDGET_FLAG,
|
|
56
56
|
CLAUDE_SETTING_SOURCES,
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
resolveConfig,
|
|
87
87
|
resolveDeclarationFlags,
|
|
88
88
|
stripTaskDeclaration
|
|
89
|
-
} from "./index-
|
|
89
|
+
} from "./index-2256nwj0.js";
|
|
90
90
|
// src/config-load.ts
|
|
91
91
|
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
92
92
|
import { isAbsolute } from "path";
|
|
@@ -1902,7 +1902,7 @@ async function report(args, repoRoot) {
|
|
|
1902
1902
|
}
|
|
1903
1903
|
}
|
|
1904
1904
|
// package.json
|
|
1905
|
-
var version = "0.
|
|
1905
|
+
var version = "0.15.0";
|
|
1906
1906
|
|
|
1907
1907
|
// src/modules/manifest.ts
|
|
1908
1908
|
var MANIFEST_VERSION = 1;
|
|
@@ -4191,6 +4191,7 @@ var BLOCKED_BY_FIELD = "Blocked by";
|
|
|
4191
4191
|
var FENCE_LINE2 = /^ {0,3}(?:```|~~~)/u;
|
|
4192
4192
|
var FIELD_LINE = /^ {0,3}(?:[-*+]\s+)?[*_]{0,2}blocked\s+by[*_]{0,2}\s*:(.*)$/iu;
|
|
4193
4193
|
var ISSUE_ID = /#(\d+)/gu;
|
|
4194
|
+
var FOREIGN_ID = /[A-Za-z0-9][A-Za-z0-9-]*\/[A-Za-z0-9._-]+#\d+/gu;
|
|
4194
4195
|
var REMEDY4 = `name them as "${BLOCKED_BY_FIELD}: #24 #26", or take the ${SPEC_BLOCKED_LABEL} label off`;
|
|
4195
4196
|
function hasSpecBlockedLabel(labels) {
|
|
4196
4197
|
return labels.some((label) => label.trim().toLowerCase() === SPEC_BLOCKED_LABEL);
|
|
@@ -4223,29 +4224,41 @@ function idsIn(text) {
|
|
|
4223
4224
|
}
|
|
4224
4225
|
return found;
|
|
4225
4226
|
}
|
|
4226
|
-
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) {
|
|
4227
4237
|
return {
|
|
4228
4238
|
kind,
|
|
4229
4239
|
issue,
|
|
4230
4240
|
line: found?.number ?? null,
|
|
4231
4241
|
text: found?.text ?? null,
|
|
4232
|
-
blockers,
|
|
4242
|
+
blockers: named.ids,
|
|
4243
|
+
foreign: named.foreign,
|
|
4233
4244
|
unknown
|
|
4234
4245
|
};
|
|
4235
4246
|
}
|
|
4236
4247
|
function readBlockedBy(issue, body, known) {
|
|
4237
4248
|
const found = findFieldLine(body);
|
|
4238
4249
|
if (found === null)
|
|
4239
|
-
return reading("no-line", issue, null,
|
|
4240
|
-
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 };
|
|
4241
4254
|
if (ids.length === 0)
|
|
4242
|
-
return reading("no-ids", issue, found,
|
|
4255
|
+
return reading("no-ids", issue, found, named, []);
|
|
4243
4256
|
const unknown = known === undefined ? [] : ids.filter((id) => id !== issue && !known.has(id));
|
|
4244
4257
|
if (ids.includes(issue))
|
|
4245
|
-
return reading("self-reference", issue, found,
|
|
4258
|
+
return reading("self-reference", issue, found, named, unknown);
|
|
4246
4259
|
if (unknown.length > 0)
|
|
4247
|
-
return reading("unknown-issue", issue, found,
|
|
4248
|
-
return reading("blocked", issue, found,
|
|
4260
|
+
return reading("unknown-issue", issue, found, named, unknown);
|
|
4261
|
+
return reading("blocked", issue, found, named, unknown);
|
|
4249
4262
|
}
|
|
4250
4263
|
function nameIds(ids) {
|
|
4251
4264
|
return ids.map((id) => `#${String(id)}`).join(" ");
|
|
@@ -4255,6 +4268,9 @@ function faultClause(read) {
|
|
|
4255
4268
|
if (read.kind === "no-line") {
|
|
4256
4269
|
return `is labelled ${SPEC_BLOCKED_LABEL} and its body carries no "${BLOCKED_BY_FIELD}:" line`;
|
|
4257
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
|
+
}
|
|
4258
4274
|
if (read.kind === "no-ids") {
|
|
4259
4275
|
return `has a "${BLOCKED_BY_FIELD}:" line ${at} naming no issue: "${read.text ?? ""}"`;
|
|
4260
4276
|
}
|
|
@@ -5001,8 +5017,10 @@ var REPO_PATH3 = "{owner}/{repo}";
|
|
|
5001
5017
|
var SUMMARY_FIELDS = "author,baseRefName,headRefName,isCrossRepository,number,state,title,updatedAt,url";
|
|
5002
5018
|
var DETAIL_FIELDS = `${SUMMARY_FIELDS},body,headRefOid,labels,mergeStateStatus,mergeable`;
|
|
5003
5019
|
var CHECK_FIELDS = "name,state,link";
|
|
5020
|
+
var MERGED_FIELDS = "headRefName,headRefOid,mergedAt,number";
|
|
5004
5021
|
var WORKFLOWS_PATH = `repos/${REPO_PATH3}/actions/workflows`;
|
|
5005
5022
|
var LIST_LIMIT = 30;
|
|
5023
|
+
var MERGED_LIMIT = 100;
|
|
5006
5024
|
var FIND_LIMIT = 1;
|
|
5007
5025
|
var MISSING_PULL = "Could not resolve to a PullRequest";
|
|
5008
5026
|
var NO_CHECKS = "no checks reported on the";
|
|
@@ -5111,6 +5129,15 @@ function readDetail(value, command, where) {
|
|
|
5111
5129
|
labels: readLabels(pull["labels"], command, `${where}.labels`)
|
|
5112
5130
|
};
|
|
5113
5131
|
}
|
|
5132
|
+
function readMerged(value, command, where) {
|
|
5133
|
+
const pull = readMapping(value, command, where);
|
|
5134
|
+
return {
|
|
5135
|
+
number: readWholeNumber(pull["number"], command, `${where}.number`),
|
|
5136
|
+
headRefName: readString2(pull["headRefName"], command, `${where}.headRefName`),
|
|
5137
|
+
headRefOid: readString2(pull["headRefOid"], command, `${where}.headRefOid`),
|
|
5138
|
+
mergedAt: readString2(pull["mergedAt"], command, `${where}.mergedAt`)
|
|
5139
|
+
};
|
|
5140
|
+
}
|
|
5114
5141
|
function readComment2(value, command, where) {
|
|
5115
5142
|
const comment = readMapping(value, command, where);
|
|
5116
5143
|
const user = readMapping(comment["user"], command, `${where}.user`);
|
|
@@ -5191,6 +5218,12 @@ function createGhPullRequests(options) {
|
|
|
5191
5218
|
const rows = readList(parseJson2(stdout, command), command, "its output");
|
|
5192
5219
|
return rows.map((row, index) => readSummary(row, command, `row ${index}`));
|
|
5193
5220
|
},
|
|
5221
|
+
listMerged: async () => {
|
|
5222
|
+
const command = "gh pr list --state merged";
|
|
5223
|
+
const stdout = await succeed(["pr", "list", "--state", "merged", "--limit", String(MERGED_LIMIT), "--json", MERGED_FIELDS], command);
|
|
5224
|
+
const rows = readList(parseJson2(stdout, command), command, "its output");
|
|
5225
|
+
return rows.map((row, index) => readMerged(row, command, `row ${index}`));
|
|
5226
|
+
},
|
|
5194
5227
|
get: async (number) => {
|
|
5195
5228
|
const target = pullNumber(number, "get");
|
|
5196
5229
|
const command = `gh pr view ${target}`;
|
package/dist/plan/index.js
CHANGED
|
@@ -16,13 +16,13 @@ import {
|
|
|
16
16
|
renderInjection,
|
|
17
17
|
runPreflight,
|
|
18
18
|
runShellProbe
|
|
19
|
-
} from "../index-
|
|
19
|
+
} from "../index-p572cxex.js";
|
|
20
20
|
import {
|
|
21
21
|
INJECT_MODES,
|
|
22
22
|
RAFA_BLOCK_KINDS,
|
|
23
23
|
isRafaBlockKind,
|
|
24
24
|
readRafaBlocks
|
|
25
|
-
} from "../index-
|
|
25
|
+
} from "../index-2256nwj0.js";
|
|
26
26
|
export {
|
|
27
27
|
runShellProbe,
|
|
28
28
|
runPreflight,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-tomato/rafa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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": {
|