@open-tomato/rafa 0.33.0 → 0.34.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 +25 -0
- package/dist/bundled/operators/agents/rafa-stretch-engineer.md +10 -5
- package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +8 -2
- package/dist/bundled/skills/dev-planner/SKILL.md +3 -3
- package/dist/bundled/skills/git-workflow/SKILL.md +1 -1
- package/dist/cli.js +1415 -600
- package/dist/effort/store/index.js +2 -2
- package/dist/{index-w3vyb08t.js → index-4b3m7s0z.js} +688 -197
- package/dist/{index-13caphhp.js → index-b8t7q5hc.js} +220 -22
- package/dist/{index-kz7e4gtt.js → index-bvfbfa63.js} +112 -58
- package/dist/{index-zn08ywsv.js → index-v8d7c6sw.js} +1 -1
- package/dist/{index-dv0ycmp8.js → index-vp0xghk2.js} +40 -0
- package/dist/index.js +4 -4
- package/dist/plan/index.js +2 -2
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
parseConfigText,
|
|
16
16
|
readRafaBlocks,
|
|
17
17
|
resolveConfig
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-vp0xghk2.js";
|
|
19
19
|
import {
|
|
20
20
|
bless,
|
|
21
21
|
merge
|
|
@@ -161,7 +161,7 @@ function appendRows(path, rows, keyOf) {
|
|
|
161
161
|
// src/effort/store/location.ts
|
|
162
162
|
import { existsSync as existsSync2, realpathSync } from "fs";
|
|
163
163
|
import { tmpdir } from "os";
|
|
164
|
-
import { isAbsolute, join as join2, relative, resolve, sep } from "path";
|
|
164
|
+
import { basename, dirname as dirname2, isAbsolute, join as join2, relative, resolve, sep } from "path";
|
|
165
165
|
var EFFORT_DIR_VARIABLE = "RAFA_EFFORT_DIR";
|
|
166
166
|
var TEST_PROCESS_VARIABLE = "RAFA_TEST";
|
|
167
167
|
var TEST_ENTRY_SUFFIX = ".test.ts";
|
|
@@ -169,6 +169,13 @@ function canonical(path) {
|
|
|
169
169
|
const resolved = resolve(path);
|
|
170
170
|
return existsSync2(resolved) ? realpathSync(resolved) : resolved;
|
|
171
171
|
}
|
|
172
|
+
function realPathOf(path) {
|
|
173
|
+
const resolved = resolve(path);
|
|
174
|
+
if (existsSync2(resolved))
|
|
175
|
+
return realpathSync(resolved);
|
|
176
|
+
const parent = dirname2(resolved);
|
|
177
|
+
return parent === resolved ? resolved : join2(realPathOf(parent), basename(resolved));
|
|
178
|
+
}
|
|
172
179
|
function isWithin(path, dir) {
|
|
173
180
|
const between = relative(resolve(dir), resolve(path));
|
|
174
181
|
const climbsOut = between === ".." || between.startsWith(`..${sep}`);
|
|
@@ -193,7 +200,7 @@ function isTestProcess(main = Bun.main, env = process.env) {
|
|
|
193
200
|
return main.endsWith(TEST_ENTRY_SUFFIX) || env[TEST_PROCESS_VARIABLE] === "1";
|
|
194
201
|
}
|
|
195
202
|
function isUnderTempDir(path, tempDir = tmpdir()) {
|
|
196
|
-
return isWithin(path, tempDir) || isWithin(path,
|
|
203
|
+
return isWithin(path, tempDir) || isWithin(realPathOf(path), realPathOf(tempDir));
|
|
197
204
|
}
|
|
198
205
|
function currentProbe() {
|
|
199
206
|
return { main: Bun.main, env: process.env, tempDir: tmpdir() };
|
|
@@ -247,12 +254,12 @@ function openNdjsonStore(repoRoot) {
|
|
|
247
254
|
|
|
248
255
|
// src/effort/store/sqlite.ts
|
|
249
256
|
import { existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
250
|
-
import { dirname as
|
|
257
|
+
import { dirname as dirname10, join as join9 } from "path";
|
|
251
258
|
import { Database } from "bun:sqlite";
|
|
252
259
|
|
|
253
260
|
// package.json
|
|
254
261
|
var name = "@open-tomato/rafa";
|
|
255
|
-
var version = "0.
|
|
262
|
+
var version = "0.34.0";
|
|
256
263
|
|
|
257
264
|
// src/cli/version.ts
|
|
258
265
|
var RAFA_VERSION = version;
|
|
@@ -262,7 +269,7 @@ function versionLine() {
|
|
|
262
269
|
|
|
263
270
|
// src/effort/store/development-build.ts
|
|
264
271
|
import { tmpdir as tmpdir2 } from "os";
|
|
265
|
-
import { basename as
|
|
272
|
+
import { basename as basename3, dirname as dirname8, isAbsolute as isAbsolute5 } from "path";
|
|
266
273
|
|
|
267
274
|
// src/loop/sessions.ts
|
|
268
275
|
import {
|
|
@@ -274,11 +281,11 @@ import {
|
|
|
274
281
|
rmSync as rmSync3,
|
|
275
282
|
writeFileSync as writeFileSync3
|
|
276
283
|
} from "fs";
|
|
277
|
-
import { dirname as
|
|
284
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
278
285
|
|
|
279
286
|
// src/project/scope.ts
|
|
280
287
|
import { existsSync as existsSync3, realpathSync as realpathSync2 } from "fs";
|
|
281
|
-
import { dirname as
|
|
288
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join4 } from "path";
|
|
282
289
|
|
|
283
290
|
// src/project/worktree-root.ts
|
|
284
291
|
import { isAbsolute as isAbsolute2 } from "path";
|
|
@@ -345,7 +352,7 @@ function mainCheckoutOf(dir, seams = {}) {
|
|
|
345
352
|
}
|
|
346
353
|
|
|
347
354
|
// src/project/scope.ts
|
|
348
|
-
var SCOPE_DIR =
|
|
355
|
+
var SCOPE_DIR = dirname3(CONFIG_FILE);
|
|
349
356
|
var INIT_COMMAND = "rafa init";
|
|
350
357
|
var DISK_FILE_SYSTEM = Object.freeze({
|
|
351
358
|
exists: (path) => existsSync3(path),
|
|
@@ -393,7 +400,7 @@ function realHomeOf(home, fs) {
|
|
|
393
400
|
}
|
|
394
401
|
}
|
|
395
402
|
function selfAndAncestors(path) {
|
|
396
|
-
const parent =
|
|
403
|
+
const parent = dirname3(path);
|
|
397
404
|
return parent === path ? [path] : [path, ...selfAndAncestors(parent)];
|
|
398
405
|
}
|
|
399
406
|
var GIT_MARKER = ".git";
|
|
@@ -453,17 +460,17 @@ function resolveScope(start, seams) {
|
|
|
453
460
|
}
|
|
454
461
|
|
|
455
462
|
// src/loop/session-record-parse.ts
|
|
456
|
-
import { basename, isAbsolute as isAbsolute4 } from "path";
|
|
463
|
+
import { basename as basename2, isAbsolute as isAbsolute4 } from "path";
|
|
457
464
|
|
|
458
465
|
// src/next/hop-record.ts
|
|
459
466
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
460
467
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
461
|
-
import { dirname as
|
|
468
|
+
import { dirname as dirname5, join as join6 } from "path";
|
|
462
469
|
|
|
463
470
|
// src/project/position.ts
|
|
464
471
|
import { randomUUID } from "crypto";
|
|
465
472
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "fs";
|
|
466
|
-
import { dirname as
|
|
473
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
467
474
|
var POSITION_FILE = "position.json";
|
|
468
475
|
function positionFilePath(root) {
|
|
469
476
|
return join5(scopeAt(root).dir, POSITION_FILE);
|
|
@@ -513,7 +520,7 @@ function readPositionFile(root) {
|
|
|
513
520
|
}
|
|
514
521
|
function writePositionFile(root, position) {
|
|
515
522
|
const file = positionFilePath(root);
|
|
516
|
-
mkdirSync2(
|
|
523
|
+
mkdirSync2(dirname4(file), { recursive: true });
|
|
517
524
|
const temporary = `${file}.${String(process.pid)}.${randomUUID()}.tmp`;
|
|
518
525
|
const { current, previous, home } = position;
|
|
519
526
|
try {
|
|
@@ -627,7 +634,7 @@ function ownKeys(record) {
|
|
|
627
634
|
}
|
|
628
635
|
function writeHopRecord(root, record) {
|
|
629
636
|
const file = hopFilePath(root);
|
|
630
|
-
mkdirSync3(
|
|
637
|
+
mkdirSync3(dirname5(file), { recursive: true });
|
|
631
638
|
const temporary = `${file}.${String(process.pid)}.${randomUUID2()}.tmp`;
|
|
632
639
|
try {
|
|
633
640
|
writeFileSync2(temporary, `${JSON.stringify(ownKeys(record), null, 2)}
|
|
@@ -759,7 +766,7 @@ function sessionIdProblem(sessionId, file) {
|
|
|
759
766
|
if (typeof sessionId !== "string" || !isSessionId(sessionId)) {
|
|
760
767
|
return `sessionId is ${describeValue2(sessionId)}, expected a plain file name`;
|
|
761
768
|
}
|
|
762
|
-
return
|
|
769
|
+
return basename2(file) === `${sessionId}${RECORD_EXTENSION}` ? null : `sessionId ${JSON.stringify(sessionId)} is not the file's name`;
|
|
763
770
|
}
|
|
764
771
|
function planStubProblem(planStub) {
|
|
765
772
|
return planStub === null || typeof planStub === "string" && isStampableStub(planStub) ? null : `planStub is ${describeValue2(planStub)}, expected null or a plan stub`;
|
|
@@ -956,7 +963,7 @@ function checkRecord(record, file) {
|
|
|
956
963
|
}
|
|
957
964
|
function writeRecordFile(file, record, isNew) {
|
|
958
965
|
checkRecord(record, file);
|
|
959
|
-
mkdirSync4(
|
|
966
|
+
mkdirSync4(dirname6(file), { recursive: true });
|
|
960
967
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
961
968
|
writeFileSync3(temporary, `${JSON.stringify(record, null, 2)}
|
|
962
969
|
`);
|
|
@@ -1000,7 +1007,7 @@ function updateSession(root, sessionId, change) {
|
|
|
1000
1007
|
|
|
1001
1008
|
// src/runtime/identity.ts
|
|
1002
1009
|
import { existsSync as existsSync4, readFileSync as readFileSync5, realpathSync as realpathSync3 } from "fs";
|
|
1003
|
-
import { dirname as
|
|
1010
|
+
import { dirname as dirname7, join as join8, resolve as resolve2 } from "path";
|
|
1004
1011
|
var MANIFEST = "package.json";
|
|
1005
1012
|
var CHECKOUT_ENTRY = join8("src", "rafa.ts");
|
|
1006
1013
|
function realOrResolved(path) {
|
|
@@ -1025,7 +1032,7 @@ function nearestRafaPackage(start) {
|
|
|
1025
1032
|
const manifest = join8(dir, MANIFEST);
|
|
1026
1033
|
if (existsSync4(manifest) && manifestName(manifest) === name)
|
|
1027
1034
|
return dir;
|
|
1028
|
-
const parent =
|
|
1035
|
+
const parent = dirname7(dir);
|
|
1029
1036
|
if (parent === dir)
|
|
1030
1037
|
return null;
|
|
1031
1038
|
dir = parent;
|
|
@@ -1033,7 +1040,7 @@ function nearestRafaPackage(start) {
|
|
|
1033
1040
|
}
|
|
1034
1041
|
function readRuntimeIdentity(entry = Bun.main) {
|
|
1035
1042
|
const real = realOrResolved(entry);
|
|
1036
|
-
const packageDir = nearestRafaPackage(
|
|
1043
|
+
const packageDir = nearestRafaPackage(dirname7(real));
|
|
1037
1044
|
if (packageDir !== null && existsSync4(join8(packageDir, CHECKOUT_ENTRY))) {
|
|
1038
1045
|
return { kind: "development", entry: real, checkout: packageDir };
|
|
1039
1046
|
}
|
|
@@ -1060,11 +1067,11 @@ class DevelopmentBuildRefusedError extends Error {
|
|
|
1060
1067
|
}
|
|
1061
1068
|
}
|
|
1062
1069
|
function storeProjectRoot(path) {
|
|
1063
|
-
const storeDir =
|
|
1064
|
-
const scopeDir =
|
|
1065
|
-
if (
|
|
1070
|
+
const storeDir = dirname8(path);
|
|
1071
|
+
const scopeDir = dirname8(storeDir);
|
|
1072
|
+
if (basename3(storeDir) !== EFFORT_DIR_NAME || basename3(scopeDir) !== SCOPE_DIR)
|
|
1066
1073
|
return null;
|
|
1067
|
-
return
|
|
1074
|
+
return dirname8(scopeDir);
|
|
1068
1075
|
}
|
|
1069
1076
|
function isOwnedStore(path, env, tempDir) {
|
|
1070
1077
|
if (isUnderTempDir(path, tempDir))
|
|
@@ -1694,7 +1701,7 @@ function activeStoreSettings() {
|
|
|
1694
1701
|
|
|
1695
1702
|
// src/effort/store/store-meta.ts
|
|
1696
1703
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
1697
|
-
import { dirname as
|
|
1704
|
+
import { dirname as dirname9 } from "path";
|
|
1698
1705
|
|
|
1699
1706
|
// src/effort/store/store-identity.ts
|
|
1700
1707
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -1836,7 +1843,7 @@ function readStoreMeta(db) {
|
|
|
1836
1843
|
};
|
|
1837
1844
|
}
|
|
1838
1845
|
function projectFor(storePath, recorded, seams) {
|
|
1839
|
-
const read = (seams.readProject ?? readProjectIdentity)(
|
|
1846
|
+
const read = (seams.readProject ?? readProjectIdentity)(dirname9(storePath));
|
|
1840
1847
|
if (read.rootCommit !== null)
|
|
1841
1848
|
return { rootCommit: read.rootCommit, remote: read.remote };
|
|
1842
1849
|
if (recorded === null)
|
|
@@ -1907,7 +1914,7 @@ function batchEntries(kind, rows) {
|
|
|
1907
1914
|
function withSqliteStore(path, access, create, use, identity = {}) {
|
|
1908
1915
|
guardTestProcess(path);
|
|
1909
1916
|
if (create)
|
|
1910
|
-
mkdirSync5(
|
|
1917
|
+
mkdirSync5(dirname10(path), { recursive: true });
|
|
1911
1918
|
const db = new Database(path, { readwrite: true, create });
|
|
1912
1919
|
try {
|
|
1913
1920
|
db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
|
|
@@ -2567,7 +2574,7 @@ function copyEffortStore(request) {
|
|
|
2567
2574
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
2568
2575
|
import { existsSync as existsSync11, mkdtempSync, rmSync as rmSync6 } from "fs";
|
|
2569
2576
|
import { tmpdir as tmpdir3 } from "os";
|
|
2570
|
-
import { dirname as
|
|
2577
|
+
import { dirname as dirname11, join as join11 } from "path";
|
|
2571
2578
|
import { Database as Database5, SQLiteError as SQLiteError2 } from "bun:sqlite";
|
|
2572
2579
|
|
|
2573
2580
|
// src/effort/commits.ts
|
|
@@ -3123,7 +3130,7 @@ function recordedMeta(path) {
|
|
|
3123
3130
|
}
|
|
3124
3131
|
function refuseOtherProject(options) {
|
|
3125
3132
|
const other = recordedMeta(options.otherPath);
|
|
3126
|
-
const here = recordedMeta(options.path)?.projectRootCommit ?? (options.readProject ?? readProjectIdentity)(
|
|
3133
|
+
const here = recordedMeta(options.path)?.projectRootCommit ?? (options.readProject ?? readProjectIdentity)(dirname11(options.path)).rootCommit;
|
|
3127
3134
|
const there = other?.projectRootCommit ?? null;
|
|
3128
3135
|
if (here !== null && there !== null && here !== there) {
|
|
3129
3136
|
throw new MergeRefusal("other-project", `REFUSED \u2014 ${options.otherPath} is the effort store of another project (root commit ${there});` + ` this store's project has root commit ${here}. ${NOTHING_MERGED}`);
|
|
@@ -4965,9 +4972,12 @@ var GITHUB_LABELS = Object.freeze({
|
|
|
4965
4972
|
blockedByPrefix: "blocked-by:OPT-"
|
|
4966
4973
|
});
|
|
4967
4974
|
var VIEW_FIELDS = "number,title,body,state,stateReason,labels,url";
|
|
4975
|
+
var LIST_COMMAND = "gh issue list";
|
|
4968
4976
|
var LIST_FIELDS = "number,url,labels";
|
|
4977
|
+
var OPEN_LIST_FIELDS = "number,url,labels,title,body";
|
|
4978
|
+
var OPEN_ISSUES_LIMIT = 1000;
|
|
4969
4979
|
var DEFAULT_FIND_LIMIT = 30;
|
|
4970
|
-
var
|
|
4980
|
+
var CANCELLED_REASONS = new Set(["NOT_PLANNED", "DUPLICATE"]);
|
|
4971
4981
|
var ISSUE_NUMBER = /^[1-9]\d*$/;
|
|
4972
4982
|
var REPO_PART = /^[\w.-]+$/;
|
|
4973
4983
|
var CREATED_ISSUE_URL = /^https:\/\/[^\s/]+\/[\w.-]+\/[\w.-]+\/issues\/([1-9]\d*)$/;
|
|
@@ -5139,28 +5149,49 @@ function viewedIssue(stdout, number) {
|
|
|
5139
5149
|
const checked = payload;
|
|
5140
5150
|
return { ...checked, labels: labelNames(checked.labels) ?? [] };
|
|
5141
5151
|
}
|
|
5142
|
-
function
|
|
5143
|
-
const
|
|
5144
|
-
const payload = parseJson(stdout, command);
|
|
5152
|
+
function listedRows(stdout) {
|
|
5153
|
+
const payload = parseJson(stdout, LIST_COMMAND);
|
|
5145
5154
|
if (!Array.isArray(payload)) {
|
|
5146
|
-
throw new Error(`${PREFIX2}: ${
|
|
5147
|
-
}
|
|
5148
|
-
return payload
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5155
|
+
throw new Error(`${PREFIX2}: ${LIST_COMMAND} answered ${describeValue(payload)}, expected a list`);
|
|
5156
|
+
}
|
|
5157
|
+
return payload;
|
|
5158
|
+
}
|
|
5159
|
+
function rowRefusal(index, problem) {
|
|
5160
|
+
return new Error(`${PREFIX2}: ${LIST_COMMAND} answered row ${index} ${problem}`);
|
|
5161
|
+
}
|
|
5162
|
+
function listedRow(row, index) {
|
|
5163
|
+
if (!isMapping(row))
|
|
5164
|
+
throw rowRefusal(index, `${describeValue(row)}, expected a mapping`);
|
|
5165
|
+
const { number, url } = row;
|
|
5166
|
+
const labels = labelNames(row["labels"]);
|
|
5167
|
+
if (typeof number !== "number" || !isIssueNumber3(String(number))) {
|
|
5168
|
+
throw rowRefusal(index, `with number ${describeValue(number)}, expected an issue number`);
|
|
5169
|
+
}
|
|
5170
|
+
if (typeof url !== "string")
|
|
5171
|
+
throw rowRefusal(index, `with url ${describeValue(url)}, expected a string`);
|
|
5172
|
+
if (labels === null)
|
|
5173
|
+
throw rowRefusal(index, "with labels that are not a list of named labels");
|
|
5174
|
+
return { number, url, labels };
|
|
5175
|
+
}
|
|
5176
|
+
function listedIssues(stdout) {
|
|
5177
|
+
return listedRows(stdout).map(listedRow);
|
|
5178
|
+
}
|
|
5179
|
+
function listedOpenIssues(stdout) {
|
|
5180
|
+
return listedRows(stdout).map((row, index) => {
|
|
5181
|
+
const listed2 = listedRow(row, index);
|
|
5182
|
+
const { title, body } = row;
|
|
5183
|
+
if (typeof title !== "string")
|
|
5184
|
+
throw rowRefusal(index, `with title ${describeValue(title)}, expected a string`);
|
|
5185
|
+
if (typeof body !== "string")
|
|
5186
|
+
throw rowRefusal(index, `with body ${describeValue(body)}, expected a string`);
|
|
5187
|
+
return { ...listed2, title, body };
|
|
5162
5188
|
});
|
|
5163
5189
|
}
|
|
5190
|
+
function refOfRow(row) {
|
|
5191
|
+
const module = labelValue(row.labels, GITHUB_LABELS.modulePrefix);
|
|
5192
|
+
const ref = { opt: 0, kind: "github", externalId: String(row.number), url: row.url };
|
|
5193
|
+
return module === undefined ? ref : { ...ref, module };
|
|
5194
|
+
}
|
|
5164
5195
|
function labelValue(labels, prefix) {
|
|
5165
5196
|
return labels.find((label) => label.startsWith(prefix))?.slice(prefix.length);
|
|
5166
5197
|
}
|
|
@@ -5174,7 +5205,7 @@ function moduleOfLabels(labels) {
|
|
|
5174
5205
|
function stateOf(viewed) {
|
|
5175
5206
|
if (viewed.state === "OPEN")
|
|
5176
5207
|
return "todo";
|
|
5177
|
-
return viewed.stateReason
|
|
5208
|
+
return viewed.stateReason !== null && CANCELLED_REASONS.has(viewed.stateReason) ? "cancelled" : "done";
|
|
5178
5209
|
}
|
|
5179
5210
|
function issueOf(ref, viewed) {
|
|
5180
5211
|
const priority = labelValue(viewed.labels, GITHUB_LABELS.priorityPrefix);
|
|
@@ -5285,12 +5316,26 @@ function createGithubTracker(options) {
|
|
|
5285
5316
|
...optionalFlag("--label", moduleLabel),
|
|
5286
5317
|
...optionalFlag("--label", typeLabel),
|
|
5287
5318
|
...optionalFlag("--search", query.text)
|
|
5288
|
-
],
|
|
5289
|
-
return listedIssues(stdout).map(
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5319
|
+
], LIST_COMMAND);
|
|
5320
|
+
return listedIssues(stdout).map(refOfRow);
|
|
5321
|
+
},
|
|
5322
|
+
openIssues: async (type) => {
|
|
5323
|
+
if (!isOneOf(ISSUE_TYPES, type)) {
|
|
5324
|
+
throw new TypeError(`${PREFIX2}: openIssues refused type ${describeValue(type)}, expected one of: ${ISSUE_TYPES.join(", ")}`);
|
|
5325
|
+
}
|
|
5326
|
+
const stdout = await run([
|
|
5327
|
+
"issue",
|
|
5328
|
+
"list",
|
|
5329
|
+
"--state",
|
|
5330
|
+
"open",
|
|
5331
|
+
"--json",
|
|
5332
|
+
OPEN_LIST_FIELDS,
|
|
5333
|
+
"--limit",
|
|
5334
|
+
String(OPEN_ISSUES_LIMIT),
|
|
5335
|
+
"--label",
|
|
5336
|
+
`${GITHUB_LABELS.typePrefix}${type}`
|
|
5337
|
+
], LIST_COMMAND);
|
|
5338
|
+
return listedOpenIssues(stdout).map((row) => ({ ref: refOfRow(row), title: row.title, body: row.body }));
|
|
5294
5339
|
},
|
|
5295
5340
|
comment: async (ref, body) => {
|
|
5296
5341
|
const number = issueNumberOfRef(ref);
|
|
@@ -5328,6 +5373,7 @@ import { join as join16 } from "path";
|
|
|
5328
5373
|
var PREFIX3 = "local tracker";
|
|
5329
5374
|
var FRONTMATTER = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
|
|
5330
5375
|
var ISSUE_NUMBER2 = /^[1-9]\d*$/;
|
|
5376
|
+
var CLOSED_STATES = new Set(["done", "released", "cancelled"]);
|
|
5331
5377
|
var ISSUE_EXTENSION = ".md";
|
|
5332
5378
|
function isString2(value) {
|
|
5333
5379
|
return typeof value === "string";
|
|
@@ -5459,7 +5505,7 @@ function parseLocalIssue(contents, sourcePath) {
|
|
|
5459
5505
|
function warnThroughActiveOutput2(message) {
|
|
5460
5506
|
activeOutput().warn(message);
|
|
5461
5507
|
}
|
|
5462
|
-
async function listLocalIssues(issuesDir, warn = warnThroughActiveOutput2) {
|
|
5508
|
+
async function listLocalIssues(issuesDir, warn = warnThroughActiveOutput2, reader = "find") {
|
|
5463
5509
|
const numbers = await issueNumbers(issuesDir);
|
|
5464
5510
|
const settled = await Promise.allSettled(numbers.map(async (number) => {
|
|
5465
5511
|
const path = issuePath(issuesDir, number);
|
|
@@ -5474,7 +5520,7 @@ async function listLocalIssues(issuesDir, warn = warnThroughActiveOutput2) {
|
|
|
5474
5520
|
return settled.flatMap((result) => {
|
|
5475
5521
|
if (result.status === "fulfilled")
|
|
5476
5522
|
return [result.value];
|
|
5477
|
-
warn(`${messageOf(result.reason)};
|
|
5523
|
+
warn(`${messageOf(result.reason)}; ${reader} skipped it`);
|
|
5478
5524
|
return [];
|
|
5479
5525
|
});
|
|
5480
5526
|
}
|
|
@@ -5560,6 +5606,14 @@ function createLocalTracker(options) {
|
|
|
5560
5606
|
const matched = (await listLocalIssues(issuesDir, warn)).filter(({ record }) => matchesQuery(record, query));
|
|
5561
5607
|
return matched.slice(0, query.limit ?? matched.length).map(({ number, record }) => refFor(number, record.draft.opt));
|
|
5562
5608
|
},
|
|
5609
|
+
openIssues: async (type) => {
|
|
5610
|
+
const open = (await listLocalIssues(issuesDir, warn, "openIssues")).filter(({ record }) => record.draft.type === type && !CLOSED_STATES.has(record.state));
|
|
5611
|
+
return open.map(({ number, record }) => ({
|
|
5612
|
+
ref: refFor(number, record.draft.opt),
|
|
5613
|
+
title: record.draft.title,
|
|
5614
|
+
body: record.draft.body
|
|
5615
|
+
}));
|
|
5616
|
+
},
|
|
5563
5617
|
comment: async (ref, body) => {
|
|
5564
5618
|
const { number, record } = await read(ref);
|
|
5565
5619
|
await rewrite(number, { ...record, comments: [...record.comments, `${now()}: ${body}`] });
|
|
@@ -324,6 +324,35 @@ var TESTS_SETTINGS = {
|
|
|
324
324
|
testsIntegration: { key: "tests.integration", read: globList, cli: false }
|
|
325
325
|
};
|
|
326
326
|
|
|
327
|
+
// src/config-schema-triage.ts
|
|
328
|
+
var SIMILARITY_THRESHOLD_MAX = 1;
|
|
329
|
+
var SIMILARITY_CANDIDATES_MIN = 1;
|
|
330
|
+
var SIMILARITY_CANDIDATES_MAX = 10;
|
|
331
|
+
function isThreshold(raw) {
|
|
332
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 && raw <= SIMILARITY_THRESHOLD_MAX;
|
|
333
|
+
}
|
|
334
|
+
function isCandidateCount(raw) {
|
|
335
|
+
return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= SIMILARITY_CANDIDATES_MIN && raw <= SIMILARITY_CANDIDATES_MAX;
|
|
336
|
+
}
|
|
337
|
+
var similarityThreshold = (raw, at) => raw === false || isThreshold(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, `false or a number above 0 and at most ${String(SIMILARITY_THRESHOLD_MAX)}`);
|
|
338
|
+
var similarityCandidates = (raw, at) => isCandidateCount(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, `a whole number from ${String(SIMILARITY_CANDIDATES_MIN)} to ${String(SIMILARITY_CANDIDATES_MAX)}`);
|
|
339
|
+
var TRIAGE_DEFAULTS = Object.freeze({
|
|
340
|
+
triageSimilarityThreshold: 0.3,
|
|
341
|
+
triageSimilarityCandidates: 3
|
|
342
|
+
});
|
|
343
|
+
var TRIAGE_SETTINGS = {
|
|
344
|
+
triageSimilarityThreshold: {
|
|
345
|
+
key: "triage.similarity.threshold",
|
|
346
|
+
read: similarityThreshold,
|
|
347
|
+
cli: false
|
|
348
|
+
},
|
|
349
|
+
triageSimilarityCandidates: {
|
|
350
|
+
key: "triage.similarity.candidates",
|
|
351
|
+
read: similarityCandidates,
|
|
352
|
+
cli: false
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
327
356
|
// src/config-schema-wrap-up.ts
|
|
328
357
|
var WRAP_UP_RETRIES_MIN = 1;
|
|
329
358
|
var WRAP_UP_RETRIES_MAX = 3;
|
|
@@ -536,6 +565,7 @@ var CONFIG_DEFAULTS = Object.freeze({
|
|
|
536
565
|
roadmapIssue: null,
|
|
537
566
|
claimsStaleAfter: "3d",
|
|
538
567
|
claimsAhead: "off",
|
|
568
|
+
...TRIAGE_DEFAULTS,
|
|
539
569
|
...RELEASE_DEFAULTS,
|
|
540
570
|
cleanupStaleDays: 30,
|
|
541
571
|
cleanupWorktreeIdleDays: 7,
|
|
@@ -623,6 +653,7 @@ var SETTINGS = {
|
|
|
623
653
|
roadmapIssue: { key: "roadmap.issue", read: issueNumber, cli: false },
|
|
624
654
|
claimsStaleAfter: { key: "claims.staleAfter", read: claimsStaleAfter, cli: false },
|
|
625
655
|
claimsAhead: { key: "claims.ahead", read: claimsAhead, cli: false },
|
|
656
|
+
...TRIAGE_SETTINGS,
|
|
626
657
|
...RELEASE_SETTINGS,
|
|
627
658
|
cleanupStaleDays: { key: "cleanup.staleDays", read: dayCount, cli: false },
|
|
628
659
|
cleanupWorktreeIdleDays: {
|
|
@@ -758,6 +789,8 @@ function readLayer(rawOf, atOf) {
|
|
|
758
789
|
roadmapIssue: read("roadmapIssue"),
|
|
759
790
|
claimsStaleAfter: read("claimsStaleAfter"),
|
|
760
791
|
claimsAhead: read("claimsAhead"),
|
|
792
|
+
triageSimilarityThreshold: read("triageSimilarityThreshold"),
|
|
793
|
+
triageSimilarityCandidates: read("triageSimilarityCandidates"),
|
|
761
794
|
releaseEnabled: read("releaseEnabled"),
|
|
762
795
|
releaseVersionFile: read("releaseVersionFile"),
|
|
763
796
|
releaseChangelog: read("releaseChangelog"),
|
|
@@ -821,7 +854,14 @@ function sortKeys(document, path) {
|
|
|
821
854
|
}
|
|
822
855
|
return { named, extras, problems };
|
|
823
856
|
}
|
|
857
|
+
var TAB_INDENTED_LINE = /^[ \t]*\t[ \t]*[^\s#]/;
|
|
858
|
+
function tabIndentProblems(text2, path) {
|
|
859
|
+
return text2.split(/\r?\n/).flatMap((line, index) => TAB_INDENTED_LINE.test(line) ? [`${path}: line ${index + 1} is indented with a tab; YAML indents with spaces only`] : []);
|
|
860
|
+
}
|
|
824
861
|
function parseYaml(text2, path) {
|
|
862
|
+
const tabProblems = tabIndentProblems(text2, path);
|
|
863
|
+
if (tabProblems.length > 0)
|
|
864
|
+
throw new ConfigError(tabProblems);
|
|
825
865
|
try {
|
|
826
866
|
return Bun.YAML.parse(text2);
|
|
827
867
|
} catch (error) {
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
start,
|
|
11
11
|
usage,
|
|
12
12
|
validateManifest
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-4b3m7s0z.js";
|
|
14
14
|
import {
|
|
15
15
|
PLAN_BLOCK_KINDS,
|
|
16
16
|
PLAN_HEADER_FIELDS,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
renderInjection,
|
|
25
25
|
runPreflight,
|
|
26
26
|
runShellProbe
|
|
27
|
-
} from "./index-
|
|
27
|
+
} from "./index-v8d7c6sw.js";
|
|
28
28
|
import {
|
|
29
29
|
CORE_ADAPTER_REGISTRY,
|
|
30
30
|
DISK_FILE_SYSTEM,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
scopeAt,
|
|
54
54
|
selectEffortStore,
|
|
55
55
|
selfAndAncestors
|
|
56
|
-
} from "./index-
|
|
56
|
+
} from "./index-bvfbfa63.js";
|
|
57
57
|
import {
|
|
58
58
|
CONFIG_DEFAULTS,
|
|
59
59
|
CONFIG_FILE,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
parseReport,
|
|
71
71
|
readRafaBlocks,
|
|
72
72
|
resolveConfig
|
|
73
|
-
} from "./index-
|
|
73
|
+
} from "./index-vp0xghk2.js";
|
|
74
74
|
import"./index-d6d0942q.js";
|
|
75
75
|
import"./index-k6sd4ym5.js";
|
|
76
76
|
import"./index-3mzw3kzh.js";
|
package/dist/plan/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
renderInjection,
|
|
13
13
|
runPreflight,
|
|
14
14
|
runShellProbe
|
|
15
|
-
} from "../index-
|
|
15
|
+
} from "../index-v8d7c6sw.js";
|
|
16
16
|
import {
|
|
17
17
|
FINDING_KINDS,
|
|
18
18
|
FINDING_SIGNALS,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
isRafaBlockKind,
|
|
22
22
|
parseReport,
|
|
23
23
|
readRafaBlocks
|
|
24
|
-
} from "../index-
|
|
24
|
+
} from "../index-vp0xghk2.js";
|
|
25
25
|
import {
|
|
26
26
|
INJECT_MODES
|
|
27
27
|
} from "../index-fzhd3d4y.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-tomato/rafa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.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": {
|