@open-tomato/rafa 0.16.0 → 0.17.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 +17 -1
- package/dist/SKILL.md +8 -5
- package/dist/cli.js +672 -29
- package/dist/effort/store/index.js +2 -2
- package/dist/{index-1vtd5fr7.js → index-4qd537z6.js} +53 -17
- package/dist/{index-krjzghpz.js → index-64wec0k7.js} +20 -7
- package/dist/{index-q491ekzm.js → index-7t0qz29r.js} +24 -3
- package/dist/{index-6cw1n0qy.js → index-ps5sac9p.js} +6 -3
- package/dist/{index-kph6p7rp.js → index-r7cnr44m.js} +362 -11
- package/dist/index.js +4 -4
- package/dist/plan/index.js +2 -2
- package/dist/plan-prompt.md +3 -1
- package/package.json +1 -1
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
announceRiskTotal,
|
|
45
45
|
assessPlanRisk,
|
|
46
46
|
blockedFaultMessage,
|
|
47
|
+
blockedLineSentence,
|
|
47
48
|
boardId,
|
|
48
49
|
branchClaims,
|
|
49
50
|
checkbox,
|
|
@@ -86,6 +87,7 @@ import {
|
|
|
86
87
|
ghHostOf,
|
|
87
88
|
ghIssueReader,
|
|
88
89
|
ghMissingMessage,
|
|
90
|
+
ghNextBoard,
|
|
89
91
|
ghPreflightItems,
|
|
90
92
|
ghPullRequestsIn,
|
|
91
93
|
ghUnauthenticatedMessage,
|
|
@@ -139,6 +141,8 @@ import {
|
|
|
139
141
|
readAgentDirectory,
|
|
140
142
|
readAuthorTrust,
|
|
141
143
|
readBlockedBy,
|
|
144
|
+
readBranch,
|
|
145
|
+
readBranchPlan,
|
|
142
146
|
readChoice,
|
|
143
147
|
readChoiceFlag,
|
|
144
148
|
readCopyRefs,
|
|
@@ -148,7 +152,9 @@ import {
|
|
|
148
152
|
readMergeRefusal,
|
|
149
153
|
readNextState,
|
|
150
154
|
readNonBlankFlag,
|
|
155
|
+
readOpenPull,
|
|
151
156
|
readPlanChanges,
|
|
157
|
+
readPlans,
|
|
152
158
|
readRecords,
|
|
153
159
|
readRefsText,
|
|
154
160
|
readRequiredFlag,
|
|
@@ -210,7 +216,7 @@ import {
|
|
|
210
216
|
waitForChecks,
|
|
211
217
|
writeFrontmatter,
|
|
212
218
|
writeSession
|
|
213
|
-
} from "./index-
|
|
219
|
+
} from "./index-4qd537z6.js";
|
|
214
220
|
import {
|
|
215
221
|
FINDING_KINDS,
|
|
216
222
|
FINDING_SIGNALS,
|
|
@@ -218,6 +224,7 @@ import {
|
|
|
218
224
|
findNextTask,
|
|
219
225
|
isStampableStub,
|
|
220
226
|
loadPlanPrerequisites,
|
|
227
|
+
malformedPrerequisiteLines,
|
|
221
228
|
mergePlanPrerequisites,
|
|
222
229
|
parsePlan,
|
|
223
230
|
parsePrerequisites,
|
|
@@ -225,7 +232,7 @@ import {
|
|
|
225
232
|
runPreflight,
|
|
226
233
|
splitBlockerComment,
|
|
227
234
|
trackerPathFor
|
|
228
|
-
} from "./index-
|
|
235
|
+
} from "./index-64wec0k7.js";
|
|
229
236
|
import {
|
|
230
237
|
CORE_ADAPTER_REGISTRY,
|
|
231
238
|
EFFORT_STORE_DIR,
|
|
@@ -243,7 +250,7 @@ import {
|
|
|
243
250
|
spawnClaudeCaptured,
|
|
244
251
|
sqliteStorePath,
|
|
245
252
|
typeOfLabels
|
|
246
|
-
} from "./index-
|
|
253
|
+
} from "./index-7t0qz29r.js";
|
|
247
254
|
import {
|
|
248
255
|
CONFIG_DEFAULTS,
|
|
249
256
|
CONFIG_FILE,
|
|
@@ -252,7 +259,7 @@ import {
|
|
|
252
259
|
configFilePath,
|
|
253
260
|
parseConfigText,
|
|
254
261
|
readRafaBlocks
|
|
255
|
-
} from "./index-
|
|
262
|
+
} from "./index-ps5sac9p.js";
|
|
256
263
|
import {
|
|
257
264
|
createCommandRegistry,
|
|
258
265
|
describeRegistry,
|
|
@@ -8355,6 +8362,17 @@ async function loadItems(plan2, config) {
|
|
|
8355
8362
|
throw refusal2(["rafa doctor: the plan's prerequisites cannot be read:", ` ${messageOf(error)}`]);
|
|
8356
8363
|
}
|
|
8357
8364
|
}
|
|
8365
|
+
function refuseMalformedItems(plan2, items) {
|
|
8366
|
+
if (plan2 === null || items.malformed.length === 0)
|
|
8367
|
+
return;
|
|
8368
|
+
const file = basename6(prerequisitesPathForPlan(plan2) ?? plan2);
|
|
8369
|
+
const [head = "", ...rest] = malformedPrerequisiteLines(file, items.malformed);
|
|
8370
|
+
throw refusal2([
|
|
8371
|
+
`rafa doctor: ${head}`,
|
|
8372
|
+
...rest,
|
|
8373
|
+
"rafa loop start would refuse here, before any probe. No run was started and nothing was stored."
|
|
8374
|
+
]);
|
|
8375
|
+
}
|
|
8358
8376
|
function mergedFile(plan2) {
|
|
8359
8377
|
const file = plan2 === null ? null : prerequisitesPathForPlan(plan2);
|
|
8360
8378
|
return file !== null && isFile(file) ? file : null;
|
|
@@ -8388,6 +8406,7 @@ async function checkPreflight(context, project, seams) {
|
|
|
8388
8406
|
const { config } = resolved;
|
|
8389
8407
|
const { plan: plan2, lookedFor } = choosePlan(project.root, config, named);
|
|
8390
8408
|
const items = await loadItems(plan2, config);
|
|
8409
|
+
refuseMalformedItems(plan2, items);
|
|
8391
8410
|
const automatic = readProvider(project.root, config, seams);
|
|
8392
8411
|
const start2 = readStartTier(plan2, items);
|
|
8393
8412
|
const tiers = {
|
|
@@ -9177,7 +9196,9 @@ var CONFIG_SETTINGS_LINES = Object.freeze([
|
|
|
9177
9196
|
`# worktreeIdleDays: ${String(CONFIG_DEFAULTS.cleanupWorktreeIdleDays)} # days before rafa cleanup lists a worktree as idle`,
|
|
9178
9197
|
"# keep: [] # glob patterns naming branches rafa cleanup never lists",
|
|
9179
9198
|
"# dangerous:",
|
|
9180
|
-
`# acceptStaleRefs: ${String(CONFIG_DEFAULTS.dangerousAcceptStaleRefs)} # true plans past dangling and suspect spec references on every run
|
|
9199
|
+
`# acceptStaleRefs: ${String(CONFIG_DEFAULTS.dangerousAcceptStaleRefs)} # true plans past dangling and suspect spec references on every run`,
|
|
9200
|
+
"# status:",
|
|
9201
|
+
`# notice: ${String(CONFIG_DEFAULTS.statusNotice)} # false drops the one-line notice of what is new since the last command`
|
|
9181
9202
|
]);
|
|
9182
9203
|
var VERSION_LINE = `version: ${String(CONFIG_DEFAULTS.version)}`;
|
|
9183
9204
|
var PROJECT_HEADER = Object.freeze([
|
|
@@ -12758,7 +12779,7 @@ function openPrContext(context, seams = DEFAULT_PR_SEAMS) {
|
|
|
12758
12779
|
readRemote: seams.readRemote
|
|
12759
12780
|
}));
|
|
12760
12781
|
const makeProvider = seams.pullRequests ?? ghPullRequestsIn;
|
|
12761
|
-
const
|
|
12782
|
+
const readBranch2 = seams.readBranch ?? gitBranch;
|
|
12762
12783
|
return {
|
|
12763
12784
|
project,
|
|
12764
12785
|
reading,
|
|
@@ -12768,7 +12789,7 @@ function openPrContext(context, seams = DEFAULT_PR_SEAMS) {
|
|
|
12768
12789
|
resolveBudget: config.prResolveBudget,
|
|
12769
12790
|
trustedAuthors: config.boardTrustedAuthors,
|
|
12770
12791
|
roadmapIssue: config.roadmapIssue,
|
|
12771
|
-
readBranch: () =>
|
|
12792
|
+
readBranch: () => readBranch2(project.root)
|
|
12772
12793
|
};
|
|
12773
12794
|
}
|
|
12774
12795
|
async function onProvider(doing, call) {
|
|
@@ -16543,7 +16564,7 @@ function readUntagged(root, configured, tags) {
|
|
|
16543
16564
|
const released = changelogVersions(text);
|
|
16544
16565
|
return { path: configured, released, versions: untaggedVersions(released, tags), problem: null };
|
|
16545
16566
|
}
|
|
16546
|
-
function
|
|
16567
|
+
function readBranch2(git) {
|
|
16547
16568
|
const result = git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
16548
16569
|
const branch = result.stdout.trim();
|
|
16549
16570
|
return result.ok && branch !== "" && branch !== "HEAD" ? branch : null;
|
|
@@ -16707,7 +16728,7 @@ function readStatus(context, seams = DEFAULT_RELEASE_SEAMS) {
|
|
|
16707
16728
|
versionFile: readVersionFile(project.root, config.versionFile),
|
|
16708
16729
|
tags,
|
|
16709
16730
|
untagged: readUntagged(project.root, config.changelog, tags.tags),
|
|
16710
|
-
plan: readPending(project.root, asked,
|
|
16731
|
+
plan: readPending(project.root, asked, readBranch2(git), planStubsUnder(project.root, config.planDir), readNotes)
|
|
16711
16732
|
};
|
|
16712
16733
|
return { reading, text: renderStatus2(reading) };
|
|
16713
16734
|
}
|
|
@@ -16758,7 +16779,7 @@ var DEFAULT_RELEASE_BRANCH = "main";
|
|
|
16758
16779
|
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
16759
16780
|
var RELEASE_REMOTE = "origin";
|
|
16760
16781
|
var INDENT9 = " ";
|
|
16761
|
-
function
|
|
16782
|
+
function readBranch3(git) {
|
|
16762
16783
|
const result = git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
16763
16784
|
if (!result.ok) {
|
|
16764
16785
|
return { branch: null, problem: `the branch could not be read: ${gitSaid(result)}` };
|
|
@@ -16910,7 +16931,7 @@ function tagConfig(project, warn) {
|
|
|
16910
16931
|
function readTagInputs(root, git, config) {
|
|
16911
16932
|
return {
|
|
16912
16933
|
releaseBranch: config.releaseBranch,
|
|
16913
|
-
branch:
|
|
16934
|
+
branch: readBranch3(git),
|
|
16914
16935
|
version: readVersion(root, config.versionFile),
|
|
16915
16936
|
changelog: readNewestRelease(root, config.changelog),
|
|
16916
16937
|
tags: readTags(git)
|
|
@@ -19411,6 +19432,335 @@ function createSkillShowCommand(seams = DEFAULT_SKILL_SHOW_SEAMS) {
|
|
|
19411
19432
|
}
|
|
19412
19433
|
var show_default6 = createSkillShowCommand();
|
|
19413
19434
|
|
|
19435
|
+
// src/status/render.ts
|
|
19436
|
+
var STATUS_SECTION_TITLES = Object.freeze({
|
|
19437
|
+
branch: "Branch",
|
|
19438
|
+
loops: "Loops",
|
|
19439
|
+
pull: "Pull request",
|
|
19440
|
+
board: "Board",
|
|
19441
|
+
housekeeping: "Housekeeping"
|
|
19442
|
+
});
|
|
19443
|
+
var INDENT10 = " ";
|
|
19444
|
+
var MERGEABILITY_WORDS = Object.freeze({
|
|
19445
|
+
mergeable: "mergeable",
|
|
19446
|
+
conflicting: "conflicting",
|
|
19447
|
+
unknown: "mergeability unknown"
|
|
19448
|
+
});
|
|
19449
|
+
var VERDICT_WORDS = Object.freeze({
|
|
19450
|
+
green: "checks green",
|
|
19451
|
+
red: "checks red",
|
|
19452
|
+
pending: "checks pending",
|
|
19453
|
+
none: "no checks"
|
|
19454
|
+
});
|
|
19455
|
+
function counted3(count, noun, plural5 = `${noun}s`) {
|
|
19456
|
+
return `${String(count)} ${count === 1 ? noun : plural5}`;
|
|
19457
|
+
}
|
|
19458
|
+
function info(text) {
|
|
19459
|
+
return { level: "info", text };
|
|
19460
|
+
}
|
|
19461
|
+
function branchText(reading) {
|
|
19462
|
+
const plan2 = reading.plan === null ? "no plan" : `plan \`${reading.plan.stub}\` (${formatCounts(reading.plan.tasks)})`;
|
|
19463
|
+
return `\`${reading.branch}\`, ${plan2}`;
|
|
19464
|
+
}
|
|
19465
|
+
function blockedTaskCount(blocked) {
|
|
19466
|
+
return blocked.reduce((sum, one) => sum + one.tasks.length, 0);
|
|
19467
|
+
}
|
|
19468
|
+
function loopsText(reading) {
|
|
19469
|
+
const tasks = blockedTaskCount(reading.blocked);
|
|
19470
|
+
return `${String(reading.live.length)} running, ${counted3(tasks, "task")} blocked`;
|
|
19471
|
+
}
|
|
19472
|
+
function loopsBody(reading) {
|
|
19473
|
+
const running = reading.live.map((record) => info(`${INDENT10}${sessionLine(record)}`));
|
|
19474
|
+
const blocked = reading.blocked.flatMap((one) => one.tasks.map((task) => {
|
|
19475
|
+
const blocker = task.blocker === null ? "" : ` (${task.blocker})`;
|
|
19476
|
+
return info(`${INDENT10}blocked: plan \`${planLabel(one.session)}\` line ${String(task.line)}: ${task.text}${blocker}`);
|
|
19477
|
+
}));
|
|
19478
|
+
return [...running, ...blocked];
|
|
19479
|
+
}
|
|
19480
|
+
function pullText(reading) {
|
|
19481
|
+
if (reading.pull === null)
|
|
19482
|
+
return "none open";
|
|
19483
|
+
const { summary, mergeable, verdict } = reading.pull;
|
|
19484
|
+
return `#${String(summary.number)} ${summary.title}, ${MERGEABILITY_WORDS[mergeable]}, ${VERDICT_WORDS[verdict]}`;
|
|
19485
|
+
}
|
|
19486
|
+
function boardText(reading) {
|
|
19487
|
+
const roadmap = `roadmap #${String(reading.roadmap)}`;
|
|
19488
|
+
const next = reading.next === null ? `${roadmap} has no line left` : `next is #${String(reading.next.line.issue)} on ${roadmap}, ${nextStanding(reading.next)}`;
|
|
19489
|
+
const blocked = reading.blockedIssues === null ? `the ${SPEC_BLOCKED_LABEL} issues were not read` : `${counted3(reading.blockedIssues, "issue")} labelled ${SPEC_BLOCKED_LABEL}`;
|
|
19490
|
+
return `${next}; ${blocked}`;
|
|
19491
|
+
}
|
|
19492
|
+
function nextStanding(next) {
|
|
19493
|
+
if (next.blocked !== null)
|
|
19494
|
+
return blockedLineSentence(next.blocked);
|
|
19495
|
+
return next.ready ? "ready" : "not ready";
|
|
19496
|
+
}
|
|
19497
|
+
function housekeepingText(reading) {
|
|
19498
|
+
const { merged: merged2, stale, notPushed, worktrees } = reading.counts;
|
|
19499
|
+
return `${String(merged2)} merged, ${String(stale)} stale, ${String(notPushed)} not pushed,` + ` ${counted3(worktrees, "worktree")} (${String(reading.idleWorktrees)} idle)`;
|
|
19500
|
+
}
|
|
19501
|
+
function sectionLines(key, section, text, body = () => []) {
|
|
19502
|
+
const title = STATUS_SECTION_TITLES[key];
|
|
19503
|
+
if (!section.read)
|
|
19504
|
+
return [{ level: "warn", text: `${title}: not read: ${section.problem}` }];
|
|
19505
|
+
return [info(`${title}: ${text(section)}`), ...body(section)];
|
|
19506
|
+
}
|
|
19507
|
+
function renderStatus3(sections) {
|
|
19508
|
+
return [
|
|
19509
|
+
...sectionLines("branch", sections.branch, branchText),
|
|
19510
|
+
...sectionLines("loops", sections.loops, loopsText, loopsBody),
|
|
19511
|
+
...sectionLines("pull", sections.pull, pullText),
|
|
19512
|
+
...sectionLines("board", sections.board, boardText),
|
|
19513
|
+
...sectionLines("housekeeping", sections.housekeeping, housekeepingText)
|
|
19514
|
+
];
|
|
19515
|
+
}
|
|
19516
|
+
function sectionData(section) {
|
|
19517
|
+
const copy = JSON.parse(JSON.stringify(section));
|
|
19518
|
+
const reading = Object.fromEntries(Object.entries(copy).filter(([key]) => key !== "read"));
|
|
19519
|
+
return { read: section.read, ...reading };
|
|
19520
|
+
}
|
|
19521
|
+
function statusData(sections) {
|
|
19522
|
+
return {
|
|
19523
|
+
branch: sectionData(sections.branch),
|
|
19524
|
+
loops: sectionData(sections.loops),
|
|
19525
|
+
pull: sectionData(sections.pull),
|
|
19526
|
+
board: sectionData(sections.board),
|
|
19527
|
+
housekeeping: sectionData(sections.housekeeping)
|
|
19528
|
+
};
|
|
19529
|
+
}
|
|
19530
|
+
|
|
19531
|
+
// src/status/sections.ts
|
|
19532
|
+
var STATUS_NETWORK_TIMEOUT_MS = 5000;
|
|
19533
|
+
function isIdleWorktree(row) {
|
|
19534
|
+
return !row.blockers.some((blocker) => blocker.kind === "recent");
|
|
19535
|
+
}
|
|
19536
|
+
function unread2(problem2) {
|
|
19537
|
+
return { read: false, problem: problem2 };
|
|
19538
|
+
}
|
|
19539
|
+
function read2(reading) {
|
|
19540
|
+
return { ...reading, read: true };
|
|
19541
|
+
}
|
|
19542
|
+
function localSection(work) {
|
|
19543
|
+
try {
|
|
19544
|
+
const reading = work();
|
|
19545
|
+
return isUnread(reading) ? reading : read2(reading);
|
|
19546
|
+
} catch (error) {
|
|
19547
|
+
return unread2(messageOf(error));
|
|
19548
|
+
}
|
|
19549
|
+
}
|
|
19550
|
+
function isUnread(value) {
|
|
19551
|
+
return typeof value === "object" && value !== null && value.read === false;
|
|
19552
|
+
}
|
|
19553
|
+
function openDeadline(ms) {
|
|
19554
|
+
let endsAt = null;
|
|
19555
|
+
return {
|
|
19556
|
+
ms,
|
|
19557
|
+
start: () => {
|
|
19558
|
+
endsAt = Date.now() + ms;
|
|
19559
|
+
},
|
|
19560
|
+
left: () => endsAt === null ? ms : endsAt - Date.now()
|
|
19561
|
+
};
|
|
19562
|
+
}
|
|
19563
|
+
function boundedRunner(open, root, deadline) {
|
|
19564
|
+
return (args) => {
|
|
19565
|
+
const left = deadline.left();
|
|
19566
|
+
if (left <= 0) {
|
|
19567
|
+
return Promise.resolve({
|
|
19568
|
+
ok: false,
|
|
19569
|
+
stdout: "",
|
|
19570
|
+
stderr: `gh ${args.join(" ")} was not run: the ${String(deadline.ms)}ms network deadline had passed`
|
|
19571
|
+
});
|
|
19572
|
+
}
|
|
19573
|
+
return open(root, left)(args);
|
|
19574
|
+
};
|
|
19575
|
+
}
|
|
19576
|
+
async function networkSection(what, deadline, work) {
|
|
19577
|
+
let timer;
|
|
19578
|
+
const expired = new Promise((resolve18) => {
|
|
19579
|
+
timer = setTimeout(() => {
|
|
19580
|
+
resolve18(unread2(`the ${what} was not read within the ${String(deadline.ms)}ms network deadline`));
|
|
19581
|
+
}, Math.max(0, deadline.left()));
|
|
19582
|
+
});
|
|
19583
|
+
try {
|
|
19584
|
+
return await Promise.race([work().then((reading) => read2(reading)), expired]);
|
|
19585
|
+
} catch (error) {
|
|
19586
|
+
return unread2(messageOf(error));
|
|
19587
|
+
} finally {
|
|
19588
|
+
clearTimeout(timer);
|
|
19589
|
+
}
|
|
19590
|
+
}
|
|
19591
|
+
function notGhProblem(what, provider) {
|
|
19592
|
+
const from = provider.source === "config" ? "as the config names it" : "as origin is no GitHub remote";
|
|
19593
|
+
return `pr.provider is ${provider.provider}, ${from}, and rafa status reads the ${what} through gh alone`;
|
|
19594
|
+
}
|
|
19595
|
+
function readBranchSection(sources) {
|
|
19596
|
+
let notes = [];
|
|
19597
|
+
const note = (problem2) => {
|
|
19598
|
+
notes = [...notes, problem2];
|
|
19599
|
+
};
|
|
19600
|
+
const branch = readBranch(sources, note);
|
|
19601
|
+
if (branch === "") {
|
|
19602
|
+
return unread2(notes.join("; ") || "the branch at the project root could not be read");
|
|
19603
|
+
}
|
|
19604
|
+
const plans = readPlans(sources, note);
|
|
19605
|
+
return { branch, plan: readBranchPlan(branch, plans), notes };
|
|
19606
|
+
}
|
|
19607
|
+
function blockedSessions(root, records) {
|
|
19608
|
+
let seen = new Set;
|
|
19609
|
+
let found = [];
|
|
19610
|
+
for (const session of [...records].reverse()) {
|
|
19611
|
+
const checklist = readSessionChecklist(root, session);
|
|
19612
|
+
if (checklist === null || seen.has(checklist.file))
|
|
19613
|
+
continue;
|
|
19614
|
+
seen = new Set([...seen, checklist.file]);
|
|
19615
|
+
const tasks = blockedTasks(checklist);
|
|
19616
|
+
if (tasks.length > 0)
|
|
19617
|
+
found = [...found, { session, checklist: checklist.file, tasks }];
|
|
19618
|
+
}
|
|
19619
|
+
return found;
|
|
19620
|
+
}
|
|
19621
|
+
function readLoopsSection(root, sources) {
|
|
19622
|
+
return localSection(() => {
|
|
19623
|
+
const records = sources.runs();
|
|
19624
|
+
return { live: records.filter((record) => isLive(record)), blocked: blockedSessions(root, records) };
|
|
19625
|
+
});
|
|
19626
|
+
}
|
|
19627
|
+
function pullSection(sources, branch, provider, deadline) {
|
|
19628
|
+
if (provider.provider !== "gh")
|
|
19629
|
+
return Promise.resolve(unread2(notGhProblem("pull request", provider)));
|
|
19630
|
+
if (!branch.read) {
|
|
19631
|
+
return Promise.resolve(unread2(`no pull request was looked for, as the branch was not read: ${branch.problem}`));
|
|
19632
|
+
}
|
|
19633
|
+
return networkSection("pull request", deadline, () => readPull(sources, branch.branch));
|
|
19634
|
+
}
|
|
19635
|
+
async function readPull(sources, branch) {
|
|
19636
|
+
let notes = [];
|
|
19637
|
+
const pull = await readOpenPull(sources, branch, (problem2) => {
|
|
19638
|
+
notes = [...notes, problem2];
|
|
19639
|
+
});
|
|
19640
|
+
return { pull, notes };
|
|
19641
|
+
}
|
|
19642
|
+
async function readBoard(board, blocked) {
|
|
19643
|
+
const [walk, report3] = await Promise.all([board.next(), blocked]);
|
|
19644
|
+
const { line } = walk;
|
|
19645
|
+
const next = line === null ? null : { line, ready: await board.isReady(line.issue), blocked: await board.blocking(line.issue) };
|
|
19646
|
+
const listed2 = report3.problem === null ? [] : [`the issues labelled ${SPEC_BLOCKED_LABEL} could not be read: ${report3.problem}`];
|
|
19647
|
+
return {
|
|
19648
|
+
roadmap: walk.roadmap,
|
|
19649
|
+
next,
|
|
19650
|
+
passed: walk.passed,
|
|
19651
|
+
blockedIssues: report3.problem === null ? report3.readings.length : null,
|
|
19652
|
+
notes: [...walk.problems, ...listed2]
|
|
19653
|
+
};
|
|
19654
|
+
}
|
|
19655
|
+
async function readHousekeeping(input, cleanup, now) {
|
|
19656
|
+
try {
|
|
19657
|
+
const settings = doctorCleanupSettings({ root: input.root, home: input.home, config: input.config, gh: null }, now);
|
|
19658
|
+
const reading = await readCleanup(cleanup, settings);
|
|
19659
|
+
if (!reading.ok)
|
|
19660
|
+
return unread2(reading.detail);
|
|
19661
|
+
const idle = reading.worktrees.filter((row) => isIdleWorktree(row));
|
|
19662
|
+
return read2({ counts: cleanupCounts(reading), idleWorktrees: idle.length, notes: reading.notes });
|
|
19663
|
+
} catch (error) {
|
|
19664
|
+
return unread2(messageOf(error));
|
|
19665
|
+
}
|
|
19666
|
+
}
|
|
19667
|
+
async function readStatusSections(input, seams = {}) {
|
|
19668
|
+
const { root, config } = input;
|
|
19669
|
+
const git = (seams.openGit ?? createGitRunner)(root);
|
|
19670
|
+
const openGh2 = seams.openGh ?? ((cwd, timeoutMs) => createGhRunner({ cwd, timeoutMs }));
|
|
19671
|
+
const deadline = openDeadline(seams.timeoutMs ?? STATUS_NETWORK_TIMEOUT_MS);
|
|
19672
|
+
const gh = boundedRunner(openGh2, root, deadline);
|
|
19673
|
+
const pulls = (seams.pullRequests ?? ((runner) => createGhPullRequests({ gh: runner })))(gh);
|
|
19674
|
+
const board = (seams.board ?? ghNextBoard)({ gh, git, configured: config.roadmapIssue });
|
|
19675
|
+
const sources = {
|
|
19676
|
+
base: config.prBase ?? DEFAULT_BASE_BRANCH,
|
|
19677
|
+
plans: plansDirAt(root, config.planDir),
|
|
19678
|
+
runs: () => readSessions(root, { isAlive: seams.isAlive }),
|
|
19679
|
+
git,
|
|
19680
|
+
pulls,
|
|
19681
|
+
board
|
|
19682
|
+
};
|
|
19683
|
+
const branch = localSection(() => readBranchSection(sources));
|
|
19684
|
+
const loops = readLoopsSection(root, sources);
|
|
19685
|
+
const provider = resolvePrProvider({ configured: config.prProvider, dir: root, readRemote: seams.readRemote });
|
|
19686
|
+
const isGh = provider.provider === "gh";
|
|
19687
|
+
const cleanup = (seams.cleanupSeams ?? defaultCleanupSeams)(root, isGh ? pulls : null);
|
|
19688
|
+
const now = (seams.now ?? (() => new Date))();
|
|
19689
|
+
const blockedIssues = seams.blockedIssues ?? ((runner) => readBlockedIssues({ gh: runner }));
|
|
19690
|
+
deadline.start();
|
|
19691
|
+
const pull = pullSection(sources, branch, provider, deadline);
|
|
19692
|
+
const boardSection = isGh ? networkSection("board", deadline, () => readBoard(board, blockedIssues(gh))) : Promise.resolve(unread2(notGhProblem("board", provider)));
|
|
19693
|
+
const housekeeping = readHousekeeping(input, cleanup, now);
|
|
19694
|
+
return {
|
|
19695
|
+
branch,
|
|
19696
|
+
loops,
|
|
19697
|
+
pull: await pull,
|
|
19698
|
+
board: await boardSection,
|
|
19699
|
+
housekeeping: await housekeeping
|
|
19700
|
+
};
|
|
19701
|
+
}
|
|
19702
|
+
|
|
19703
|
+
// src/commands/status.ts
|
|
19704
|
+
var COMMAND_NAME6 = "rafa status";
|
|
19705
|
+
var STATUS_USAGE = "rafa status";
|
|
19706
|
+
var STATUS_ARGUMENT_EXIT = 2;
|
|
19707
|
+
var DEFAULT_STATUS_SEAMS = Object.freeze({});
|
|
19708
|
+
function projectOf15(context) {
|
|
19709
|
+
if (context.project === null)
|
|
19710
|
+
throw new Error("rafa status runs inside a project, and was handed none");
|
|
19711
|
+
return context.project;
|
|
19712
|
+
}
|
|
19713
|
+
function expectNoWord(args) {
|
|
19714
|
+
if (args.length === 0)
|
|
19715
|
+
return;
|
|
19716
|
+
throw new CommandExit(STATUS_ARGUMENT_EXIT, `\u274C ${COMMAND_NAME6}: expected no argument, got ${String(args.length)}: ${args.join(" ")}
|
|
19717
|
+
Usage: ${STATUS_USAGE}`);
|
|
19718
|
+
}
|
|
19719
|
+
async function runStatus2(context, seams) {
|
|
19720
|
+
expectNoWord(context.args);
|
|
19721
|
+
const project = projectOf15(context);
|
|
19722
|
+
const config = resolveProjectConfig(project, COMMAND_NAME6, (message) => {
|
|
19723
|
+
context.output.warn(message);
|
|
19724
|
+
});
|
|
19725
|
+
const read3 = seams.read ?? ((input) => readStatusSections(input));
|
|
19726
|
+
const sections = await read3({ root: project.root, home: project.home, config });
|
|
19727
|
+
if (context.outputMode === "json") {
|
|
19728
|
+
context.output.result(statusData(sections));
|
|
19729
|
+
return;
|
|
19730
|
+
}
|
|
19731
|
+
for (const line of renderStatus3(sections)) {
|
|
19732
|
+
if (line.level === "warn")
|
|
19733
|
+
context.output.warn(line.text);
|
|
19734
|
+
else
|
|
19735
|
+
context.output.info(line.text);
|
|
19736
|
+
}
|
|
19737
|
+
}
|
|
19738
|
+
function createStatusCommand(seams = DEFAULT_STATUS_SEAMS) {
|
|
19739
|
+
const command = {
|
|
19740
|
+
name: "status",
|
|
19741
|
+
subject: "status",
|
|
19742
|
+
action: "status",
|
|
19743
|
+
summary: "where the project stands: branch and plan, loops, pull request, board and housekeeping",
|
|
19744
|
+
description: "Prints one line for each of five sections. Branch: the branch checked out at the project root" + " and the plan its `feat/<stub>` names, with its task counts. Loops: how many sessions are running and" + " how many tasks are blocked, with a line under it for each running loop and each blocked task. Pull" + " request: the branch's open pull request, whether it can be merged and its checks. Board: the" + " Roadmap's next issue and whether it is ready, and how many issues carry `spec:blocked`. Housekeeping:" + " what `rafa cleanup` would list, counted per group, and how many worktrees are idle. Git, the session" + " records and the plans are read first; the pull request and the board are read through `gh` under a" + " short deadline, and nothing is fetched. A section that cannot be read is one `warn` line saying why," + " and the others are printed all the same: it exits 1 only for a config that cannot be used. With" + " `--output=json` the five sections are the data of the terminal result event. Starts no session.",
|
|
19745
|
+
args: [],
|
|
19746
|
+
flags: [],
|
|
19747
|
+
examples: [
|
|
19748
|
+
{
|
|
19749
|
+
cmd: "rafa status",
|
|
19750
|
+
note: "Prints the five sections, one line each, with the running loops and blocked tasks under Loops."
|
|
19751
|
+
},
|
|
19752
|
+
{
|
|
19753
|
+
cmd: "rafa status --output=json",
|
|
19754
|
+
note: "Gives the five sections as data, each with `read` and its reading or the problem."
|
|
19755
|
+
}
|
|
19756
|
+
],
|
|
19757
|
+
outputs: ["text", "json"],
|
|
19758
|
+
run: async (context) => runStatus2(context, seams)
|
|
19759
|
+
};
|
|
19760
|
+
return Object.freeze(command);
|
|
19761
|
+
}
|
|
19762
|
+
var status_default3 = createStatusCommand();
|
|
19763
|
+
|
|
19414
19764
|
// src/commands/usage.ts
|
|
19415
19765
|
var usage_default = wrapPhaseZeroCommand({
|
|
19416
19766
|
name: "usage",
|
|
@@ -19489,6 +19839,7 @@ var CORE_COMMANDS = Object.freeze([
|
|
|
19489
19839
|
show_default2,
|
|
19490
19840
|
status_default2,
|
|
19491
19841
|
tag_default,
|
|
19842
|
+
status_default3,
|
|
19492
19843
|
next_default,
|
|
19493
19844
|
roadmap_default,
|
|
19494
19845
|
init_default,
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
start,
|
|
21
21
|
usage,
|
|
22
22
|
validateManifest
|
|
23
|
-
} from "./index-
|
|
23
|
+
} from "./index-4qd537z6.js";
|
|
24
24
|
import {
|
|
25
25
|
FINDING_KINDS,
|
|
26
26
|
FINDING_SIGNALS,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
renderInjection,
|
|
39
39
|
runPreflight,
|
|
40
40
|
runShellProbe
|
|
41
|
-
} from "./index-
|
|
41
|
+
} from "./index-64wec0k7.js";
|
|
42
42
|
import {
|
|
43
43
|
CORE_ADAPTER_REGISTRY,
|
|
44
44
|
EFFORT_KEY_PROJECTIONS,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
openNdjsonStore,
|
|
48
48
|
openSqliteStore,
|
|
49
49
|
selectEffortStore
|
|
50
|
-
} from "./index-
|
|
50
|
+
} from "./index-7t0qz29r.js";
|
|
51
51
|
import {
|
|
52
52
|
CONFIG_DEFAULTS,
|
|
53
53
|
CONFIG_FILE,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
parseConfigText,
|
|
59
59
|
readRafaBlocks,
|
|
60
60
|
resolveConfig
|
|
61
|
-
} from "./index-
|
|
61
|
+
} from "./index-ps5sac9p.js";
|
|
62
62
|
import"./index-qzhpqmfy.js";
|
|
63
63
|
import"./index-p901zs2p.js";
|
|
64
64
|
import {
|
package/dist/plan/index.js
CHANGED
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
renderInjection,
|
|
17
17
|
runPreflight,
|
|
18
18
|
runShellProbe
|
|
19
|
-
} from "../index-
|
|
19
|
+
} from "../index-64wec0k7.js";
|
|
20
20
|
import {
|
|
21
21
|
RAFA_BLOCK_KINDS,
|
|
22
22
|
isRafaBlockKind,
|
|
23
23
|
readRafaBlocks
|
|
24
|
-
} from "../index-
|
|
24
|
+
} from "../index-ps5sac9p.js";
|
|
25
25
|
import {
|
|
26
26
|
INJECT_MODES
|
|
27
27
|
} from "../index-n3rw8rhr.js";
|
package/dist/plan-prompt.md
CHANGED
|
@@ -66,7 +66,9 @@ criteria — **do not execute the plan**.
|
|
|
66
66
|
as a checklist in the PREREQUISITES.md format of the dev-planner
|
|
67
67
|
specification below. Only genuinely non-automatable steps; do not duplicate
|
|
68
68
|
what `README.md`/`AGENTS.md` already require of every contributor. Link to
|
|
69
|
-
it from the plan.
|
|
69
|
+
it from the plan. An `[auto]` item holds exactly one backticked span, and
|
|
70
|
+
that span is its command, ending the item after `: ` and run as written:
|
|
71
|
+
prove a tool with `<tool> --version`, `<tool> --help` or `which <tool>`.
|
|
70
72
|
* Do not create or touch any tracker file — the loop derives it from the plan.
|
|
71
73
|
|
|
72
74
|
{PLAN_FORMAT}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-tomato/rafa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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": {
|