@open-tomato/rafa 0.35.0 → 0.37.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 +5 -4
- package/dist/bundled/operators/agents/rafa-stretch-engineer.md +4 -4
- package/dist/bundled/operators/agents/rafa-stretch-watchtower.md +9 -9
- package/dist/cli.js +13025 -11058
- package/dist/describe-5hqfwbjc.js +14 -0
- package/dist/effort/store/index.js +36 -33
- package/dist/{index-ckqfhynj.js → index-1mxv55ec.js} +588 -531
- package/dist/{index-dvrq9nfb.js → index-35ze56rz.js} +4991 -4683
- package/dist/index-3mzw3kzh.js +129 -0
- package/dist/{index-41vzahew.js → index-7bb0fdb7.js} +33 -31
- package/dist/{index-se13pvag.js → index-b16va6he.js} +3645 -2403
- package/dist/{index-hgcvjke7.js → index-d6d0942q.js} +17 -17
- package/dist/index-fzhd3d4y.js +446 -0
- package/dist/{index-2tjmxwvp.js → index-jfas157k.js} +111 -513
- package/dist/index-k6sd4ym5.js +243 -0
- package/dist/index-wp8c28fd.js +18 -0
- package/dist/index.js +152 -147
- package/dist/learning/index.js +20 -20
- package/dist/plan/index.js +45 -42
- package/package.json +1 -1
- package/dist/describe-59899b0p.js +0 -11
- package/dist/index-21jcfatr.js +0 -16
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
describeValue
|
|
4
|
+
} from "./index-fzhd3d4y.js";
|
|
5
|
+
|
|
6
|
+
// src/cli/spends.ts
|
|
7
|
+
var SPENDS_GLYPH = "\uD83E\uDE99";
|
|
8
|
+
var SPENDS_WHEN = ["always", "with", "unless", "through"];
|
|
9
|
+
var FLAGGED = ["with", "unless"];
|
|
10
|
+
var FLAG_SPELLING = /^--[^\s-]\S*$/;
|
|
11
|
+
function flagProblem(when, flag) {
|
|
12
|
+
if (FLAGGED.includes(when)) {
|
|
13
|
+
return typeof flag === "string" && FLAG_SPELLING.test(flag) ? null : `spends.flag is ${describeValue(flag)}, expected a flag as typed, starting with --`;
|
|
14
|
+
}
|
|
15
|
+
return flag === undefined ? null : `spends.flag is ${describeValue(flag)}, expected absent when spends.when is "${when}"`;
|
|
16
|
+
}
|
|
17
|
+
function spendsProblem(value) {
|
|
18
|
+
if (value === undefined)
|
|
19
|
+
return null;
|
|
20
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
21
|
+
return `spends is ${describeValue(value)}, expected absent or a mapping`;
|
|
22
|
+
}
|
|
23
|
+
const { when, what, flag } = value;
|
|
24
|
+
if (!SPENDS_WHEN.includes(when)) {
|
|
25
|
+
return `spends.when is ${describeValue(when)}, expected one of ${SPENDS_WHEN.join(", ")}`;
|
|
26
|
+
}
|
|
27
|
+
if (typeof what !== "string") {
|
|
28
|
+
return `spends.what is ${describeValue(what)}, expected a string`;
|
|
29
|
+
}
|
|
30
|
+
return flagProblem(when, flag);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/cli/command.ts
|
|
34
|
+
var COMMAND_OUTPUTS = ["text", "json", "events", "tui"];
|
|
35
|
+
var MAX_EXIT_CODE = 255;
|
|
36
|
+
|
|
37
|
+
class CommandExit extends Error {
|
|
38
|
+
exitCode;
|
|
39
|
+
constructor(exitCode, message = "") {
|
|
40
|
+
super(message);
|
|
41
|
+
if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > MAX_EXIT_CODE) {
|
|
42
|
+
throw new TypeError(`CommandExit: exit code is ${describeValue(exitCode)}, expected a whole number from 0 to ${MAX_EXIT_CODE}`);
|
|
43
|
+
}
|
|
44
|
+
this.name = "CommandExit";
|
|
45
|
+
this.exitCode = exitCode;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function isListOf(value, check) {
|
|
49
|
+
return Array.isArray(value) && value.every(check);
|
|
50
|
+
}
|
|
51
|
+
function hasStrings(value, keys) {
|
|
52
|
+
if (typeof value !== "object" || value === null)
|
|
53
|
+
return false;
|
|
54
|
+
const record = value;
|
|
55
|
+
return keys.every((key) => typeof record[key] === "string");
|
|
56
|
+
}
|
|
57
|
+
function isRoutingWord(value) {
|
|
58
|
+
return typeof value === "string" && /^[^\s/-][^\s/]*$/.test(value);
|
|
59
|
+
}
|
|
60
|
+
function isFlag(item) {
|
|
61
|
+
if (!hasStrings(item, ["name"]))
|
|
62
|
+
return false;
|
|
63
|
+
const { deprecated } = item;
|
|
64
|
+
return deprecated === undefined || hasStrings(deprecated, ["use"]);
|
|
65
|
+
}
|
|
66
|
+
function fieldProblem(fields) {
|
|
67
|
+
const checks = [
|
|
68
|
+
["subject", isRoutingWord(fields.subject), "a word with no space, no slash and no leading dash"],
|
|
69
|
+
["action", isRoutingWord(fields.action), "a word with no space, no slash and no leading dash"],
|
|
70
|
+
["name", typeof fields.name === "string", "a string"],
|
|
71
|
+
["summary", typeof fields.summary === "string", "a string"],
|
|
72
|
+
["description", typeof fields.description === "string", "a string"],
|
|
73
|
+
["args", isListOf(fields.args, (item) => hasStrings(item, ["name"])), "a list of named arguments"],
|
|
74
|
+
["flags", isListOf(fields.flags, isFlag), "a list of named flags, each deprecation naming its use"],
|
|
75
|
+
["examples", isListOf(fields.examples, (item) => hasStrings(item, ["cmd", "note"])), "a list of examples"],
|
|
76
|
+
[
|
|
77
|
+
"outputs",
|
|
78
|
+
isListOf(fields.outputs, (item) => COMMAND_OUTPUTS.includes(item)),
|
|
79
|
+
`a list of ${COMMAND_OUTPUTS.join(", ")}`
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
"aliases",
|
|
83
|
+
fields.aliases === undefined || isListOf(fields.aliases, (item) => typeof item === "string"),
|
|
84
|
+
"absent or a list of strings"
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
"lastingAliases",
|
|
88
|
+
fields.lastingAliases === undefined || isListOf(fields.lastingAliases, (item) => typeof item === "string"),
|
|
89
|
+
"absent or a list of strings"
|
|
90
|
+
],
|
|
91
|
+
[
|
|
92
|
+
"deprecated",
|
|
93
|
+
fields.deprecated === undefined || hasStrings(fields.deprecated, ["since", "use"]),
|
|
94
|
+
"absent or a mapping of since and use"
|
|
95
|
+
],
|
|
96
|
+
["hidden", fields.hidden === undefined || typeof fields.hidden === "boolean", "absent or a boolean"],
|
|
97
|
+
[
|
|
98
|
+
"needsProject",
|
|
99
|
+
fields.needsProject === undefined || typeof fields.needsProject === "boolean",
|
|
100
|
+
"absent or a boolean"
|
|
101
|
+
],
|
|
102
|
+
["exec", fields.exec === undefined || fields.exec === true, "absent or true"],
|
|
103
|
+
["run", typeof fields.run === "function", "a function"]
|
|
104
|
+
];
|
|
105
|
+
const failed = checks.find(([, passes]) => !passes);
|
|
106
|
+
if (failed === undefined)
|
|
107
|
+
return null;
|
|
108
|
+
const [key, , expected] = failed;
|
|
109
|
+
return `${key} is ${describeValue(fields[key])}, expected ${expected}`;
|
|
110
|
+
}
|
|
111
|
+
function commandProblem(value) {
|
|
112
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
113
|
+
return `a command is ${describeValue(value)}, expected a mapping`;
|
|
114
|
+
}
|
|
115
|
+
const fields = value;
|
|
116
|
+
const problem = fieldProblem(fields) ?? spendsProblem(fields.spends);
|
|
117
|
+
if (problem === null)
|
|
118
|
+
return null;
|
|
119
|
+
const named = isRoutingWord(fields.subject) && isRoutingWord(fields.action) ? `command "${commandSpelling(fields)}"` : "a command";
|
|
120
|
+
return `${named}: ${problem}`;
|
|
121
|
+
}
|
|
122
|
+
function isTopLevel(command) {
|
|
123
|
+
return command.subject === command.action;
|
|
124
|
+
}
|
|
125
|
+
function commandSpelling(command) {
|
|
126
|
+
return isTopLevel(command) ? command.subject : `${command.subject} ${command.action}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { SPENDS_GLYPH, CommandExit, isRoutingWord, commandProblem, isTopLevel, commandSpelling };
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
parseTaskDeclaration,
|
|
4
|
-
messageOf,
|
|
5
|
-
isStampableStub,
|
|
6
3
|
activeOutput,
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
isStampableStub,
|
|
5
|
+
readRafaBlocks
|
|
6
|
+
} from "./index-jfas157k.js";
|
|
7
|
+
import {
|
|
8
|
+
messageOf,
|
|
9
|
+
parseTaskDeclaration
|
|
10
|
+
} from "./index-fzhd3d4y.js";
|
|
9
11
|
// src/preflight/prerequisites-md.ts
|
|
10
12
|
import { basename, dirname, join } from "path";
|
|
11
13
|
var SECTION_AUTO_RE = /\[auto\]/i;
|
|
@@ -87,7 +89,7 @@ function readItem(lines, lineIndex, inherited) {
|
|
|
87
89
|
const probe = isProbedTag(tag) ? extractProbe(description) : null;
|
|
88
90
|
return Object.freeze({ raw, description, tag, lineIndex, probe });
|
|
89
91
|
}
|
|
90
|
-
function
|
|
92
|
+
function parsePrerequisites(content) {
|
|
91
93
|
const lines = content.split(`
|
|
92
94
|
`);
|
|
93
95
|
const items = [];
|
|
@@ -130,8 +132,8 @@ function namedItemOf(item) {
|
|
|
130
132
|
function isMalformed(item) {
|
|
131
133
|
return isProbedTag(item.tag) && item.probe === null;
|
|
132
134
|
}
|
|
133
|
-
function
|
|
134
|
-
const items =
|
|
135
|
+
function planPrerequisites(content) {
|
|
136
|
+
const items = parsePrerequisites(content);
|
|
135
137
|
return Object.freeze({
|
|
136
138
|
required: requiredItemsTagged(items, "auto"),
|
|
137
139
|
startRequired: requiredItemsTagged(items, "start"),
|
|
@@ -147,8 +149,8 @@ function malformedPrerequisiteLines(file, malformed) {
|
|
|
147
149
|
`Write each as ${PROBE_ITEM_EXAMPLE}, its one backticked span a complete command run as written;` + " prove a tool is there with `<tool> --version`, `<tool> --help` or `which <tool>`."
|
|
148
150
|
];
|
|
149
151
|
}
|
|
150
|
-
function
|
|
151
|
-
const plan =
|
|
152
|
+
function mergePlanPrerequisites(settings, content) {
|
|
153
|
+
const plan = planPrerequisites(content ?? "");
|
|
152
154
|
return Object.freeze({
|
|
153
155
|
required: Object.freeze([...settings.prerequisitesRequired, ...plan.required]),
|
|
154
156
|
startRequired: plan.startRequired,
|
|
@@ -157,7 +159,7 @@ function mergePlanPrerequisites2(settings, content) {
|
|
|
157
159
|
malformed: plan.malformed
|
|
158
160
|
});
|
|
159
161
|
}
|
|
160
|
-
function
|
|
162
|
+
function prerequisitesPathForPlan(planPath) {
|
|
161
163
|
const stub = PLAN_FILE_RE.exec(basename(planPath))?.[1];
|
|
162
164
|
if (stub === undefined)
|
|
163
165
|
return null;
|
|
@@ -173,13 +175,13 @@ async function readIfPresent(path) {
|
|
|
173
175
|
throw new Error(`${path}: cannot be read (${messageOf(error)})`, { cause: error });
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
|
-
async function
|
|
177
|
-
const path =
|
|
178
|
+
async function loadPlanPrerequisites(planPath, settings) {
|
|
179
|
+
const path = prerequisitesPathForPlan(planPath);
|
|
178
180
|
const content = path === null ? null : await readIfPresent(path);
|
|
179
|
-
return
|
|
181
|
+
return mergePlanPrerequisites(settings, content);
|
|
180
182
|
}
|
|
181
183
|
// src/preflight/run.ts
|
|
182
|
-
var
|
|
184
|
+
var PROBE_TIMEOUT_MS = 30000;
|
|
183
185
|
var SHELL = "/bin/sh";
|
|
184
186
|
var PASS = Object.freeze({ outcome: "pass", failure: null });
|
|
185
187
|
function spawnShell(probe, options) {
|
|
@@ -221,13 +223,13 @@ function collect(stream) {
|
|
|
221
223
|
};
|
|
222
224
|
return { text: read(), stop };
|
|
223
225
|
}
|
|
224
|
-
async function
|
|
226
|
+
async function runShellProbe(probe, options) {
|
|
225
227
|
let proc;
|
|
226
228
|
try {
|
|
227
229
|
proc = spawnShell(probe, options);
|
|
228
230
|
} catch (error) {
|
|
229
|
-
const
|
|
230
|
-
return Object.freeze({ exitCode: null, stderr, timedOut: false });
|
|
231
|
+
const stderr2 = `could not run ${SHELL} in ${options.cwd}: ${messageOf(error)}`;
|
|
232
|
+
return Object.freeze({ exitCode: null, stderr: stderr2, timedOut: false });
|
|
231
233
|
}
|
|
232
234
|
const stderr = collect(proc.stderr);
|
|
233
235
|
let timedOut = false;
|
|
@@ -346,14 +348,14 @@ function contextOf(options) {
|
|
|
346
348
|
return {
|
|
347
349
|
cwd: options.cwd,
|
|
348
350
|
env: options.env ?? process.env,
|
|
349
|
-
timeoutMs: options.timeoutMs ??
|
|
350
|
-
runProbe: options.runProbe ??
|
|
351
|
+
timeoutMs: options.timeoutMs ?? PROBE_TIMEOUT_MS,
|
|
352
|
+
runProbe: options.runProbe ?? runShellProbe,
|
|
351
353
|
request: options.request ?? ((url, init) => fetch(url, init)),
|
|
352
354
|
warn: options.warn ?? warnThroughActiveOutput,
|
|
353
355
|
now: options.now ?? (() => performance.now())
|
|
354
356
|
};
|
|
355
357
|
}
|
|
356
|
-
async function
|
|
358
|
+
async function runPreflight(items, options) {
|
|
357
359
|
const context = contextOf(options);
|
|
358
360
|
const checks = [];
|
|
359
361
|
const knownMissing = [];
|
|
@@ -450,7 +452,7 @@ function withoutBlockerComment(line) {
|
|
|
450
452
|
}
|
|
451
453
|
function closedBlockLines(trackerContent) {
|
|
452
454
|
const inside = new Set;
|
|
453
|
-
for (const block of
|
|
455
|
+
for (const block of readRafaBlocks(trackerContent)) {
|
|
454
456
|
if (!block.closed)
|
|
455
457
|
continue;
|
|
456
458
|
for (let line = block.span.first;line <= block.span.last; line += 1) {
|
|
@@ -560,8 +562,8 @@ function trackerPathFor(planPath) {
|
|
|
560
562
|
}
|
|
561
563
|
|
|
562
564
|
// src/plan/parse.ts
|
|
563
|
-
var
|
|
564
|
-
var
|
|
565
|
+
var PLAN_BLOCK_KINDS = ["plan", "context", "stage-context"];
|
|
566
|
+
var PLAN_HEADER_FIELDS = ["stub", "issue", "spec", "release"];
|
|
565
567
|
var PLAN_RELEASE_LEVELS = ["patch", "minor", "major", "none"];
|
|
566
568
|
var TASK_LINES = [
|
|
567
569
|
["unchecked", /^- \[ \] (.+)/],
|
|
@@ -570,10 +572,10 @@ var TASK_LINES = [
|
|
|
570
572
|
];
|
|
571
573
|
var STAGE_HEADING = /^# Stage: (.+)/;
|
|
572
574
|
function isPlanBlockKind(kind) {
|
|
573
|
-
return
|
|
575
|
+
return PLAN_BLOCK_KINDS.includes(kind);
|
|
574
576
|
}
|
|
575
577
|
function isHeaderField(key) {
|
|
576
|
-
return
|
|
578
|
+
return PLAN_HEADER_FIELDS.includes(key);
|
|
577
579
|
}
|
|
578
580
|
function isReleaseLevel(value) {
|
|
579
581
|
return PLAN_RELEASE_LEVELS.includes(value);
|
|
@@ -782,8 +784,8 @@ function readHeader(block) {
|
|
|
782
784
|
}
|
|
783
785
|
return readFields(document, line);
|
|
784
786
|
}
|
|
785
|
-
function
|
|
786
|
-
const blocks =
|
|
787
|
+
function parsePlan(markdown) {
|
|
788
|
+
const blocks = readRafaBlocks(markdown);
|
|
787
789
|
const checklist = readChecklist(markdown, blocks);
|
|
788
790
|
const bound = bindBlocks(blocks, checklist.headings);
|
|
789
791
|
const reading = readHeader(bound.header);
|
|
@@ -896,15 +898,15 @@ var RENDERERS = {
|
|
|
896
898
|
stage: renderStage,
|
|
897
899
|
task: renderTask
|
|
898
900
|
};
|
|
899
|
-
function
|
|
901
|
+
function renderInjection(request) {
|
|
900
902
|
const { mode, plan, task } = request;
|
|
901
903
|
if (mode === "full")
|
|
902
904
|
return { requested: mode, mode, text: plan, fallback: null };
|
|
903
|
-
const model =
|
|
905
|
+
const model = parsePlan(plan);
|
|
904
906
|
const location = locate(model, task);
|
|
905
907
|
if (!location.found) {
|
|
906
908
|
return { requested: mode, mode: "full", text: plan, fallback: location.fallback };
|
|
907
909
|
}
|
|
908
910
|
return { requested: mode, mode, text: RENDERERS[mode](model, location.task), fallback: null };
|
|
909
911
|
}
|
|
910
|
-
export { escapeBlockerText, splitBlockerComment, findNextTask, updateTrackerLine, writeTrackerBlocker, insertTrackerTask, trackerPathFor,
|
|
912
|
+
export { escapeBlockerText, splitBlockerComment, findNextTask, updateTrackerLine, writeTrackerBlocker, insertTrackerTask, trackerPathFor, PLAN_BLOCK_KINDS, PLAN_HEADER_FIELDS, PLAN_RELEASE_LEVELS, parsePlan, parsePrerequisites, planPrerequisites, malformedPrerequisiteLines, mergePlanPrerequisites, prerequisitesPathForPlan, loadPlanPrerequisites, PROBE_TIMEOUT_MS, runShellProbe, runPreflight, renderInjection };
|