@open-tomato/rafa 0.17.0 → 0.19.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/NOTICE +9 -1
- package/README.md +40 -26
- package/dist/PROMPT.md +2 -1
- package/dist/bundled/agents/build-error-resolver.md +144 -0
- package/dist/bundled/agents/code-reviewer.md +335 -0
- package/dist/bundled/agents/doc-updater.md +108 -0
- package/dist/bundled/agents/loop-implementer.md +57 -0
- package/dist/bundled/agents/qa-bug-reporter.md +164 -0
- package/dist/bundled/agents/tdd-guide.md +121 -0
- package/dist/bundled/bin/ts-symbols +272 -0
- package/dist/{SKILL.md → bundled/skills/dev-planner/SKILL.md} +7 -5
- package/dist/bundled/skills/documentation/SKILL.md +93 -0
- package/dist/bundled/skills/git-workflow/SKILL.md +242 -0
- package/dist/bundled/skills/ts-symbols/SKILL.md +82 -0
- package/dist/cli.js +6952 -4721
- package/dist/{describe-wbn759vf.js → describe-cenk70n5.js} +4 -3
- package/dist/effort/store/index.js +6 -4
- package/dist/{index-64wec0k7.js → index-09p41s0n.js} +11 -224
- package/dist/{index-qzhpqmfy.js → index-c5cecsga.js} +2 -2
- package/dist/{index-4qd537z6.js → index-ca0fccvr.js} +3527 -1402
- package/dist/{index-n3rw8rhr.js → index-cedghpva.js} +78 -2
- package/dist/index-d6d0942q.js +218 -0
- package/dist/{index-7t0qz29r.js → index-gb51x34c.js} +1020 -58
- package/dist/{index-r7cnr44m.js → index-mh5hyw8g.js} +1681 -3101
- package/dist/index-pqrpcfaz.js +1020 -0
- package/dist/{index-p901zs2p.js → index-vg7ycs94.js} +1 -1
- package/dist/index-wp8c28fd.js +18 -0
- package/dist/index.js +13 -11
- package/dist/learning/index.js +25 -0
- package/dist/plan/index.js +8 -7
- package/dist/plan-prompt.md +2 -0
- package/package.json +4 -3
- package/dist/index-ps5sac9p.js +0 -531
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
2
|
+
import {
|
|
3
|
+
CONFIDENCE_MAX,
|
|
4
|
+
CONFIDENCE_MIN
|
|
5
|
+
} from "./index-wp8c28fd.js";
|
|
3
6
|
|
|
4
7
|
// src/pr/types.ts
|
|
5
8
|
var MERGE_METHODS = Object.freeze([
|
|
@@ -11,6 +14,65 @@ function isMergeMethod(value) {
|
|
|
11
14
|
return typeof value === "string" && MERGE_METHODS.includes(value);
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
// src/schema/tiers.ts
|
|
18
|
+
import { existsSync, realpathSync } from "fs";
|
|
19
|
+
import { dirname, join } from "path";
|
|
20
|
+
var SKILL_TIERS = ["project", "rafa", "user"];
|
|
21
|
+
var INSTINCT_SCOPES = ["project", "user"];
|
|
22
|
+
var CLAUDE_SKILLS_PATH = join(".claude", "skills");
|
|
23
|
+
var RAFA_INSTINCTS_PATH = join(".rafa", "instincts");
|
|
24
|
+
var BUNDLED_SKILLS_DIR = join("bundled", "skills");
|
|
25
|
+
var BUNDLED_BIN_DIR = join("bundled", "bin");
|
|
26
|
+
function isSkillTier(value) {
|
|
27
|
+
return SKILL_TIERS.includes(value);
|
|
28
|
+
}
|
|
29
|
+
function realEntry(entry) {
|
|
30
|
+
try {
|
|
31
|
+
return realpathSync(entry);
|
|
32
|
+
} catch {
|
|
33
|
+
return entry;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function bundledSkillsDirectory(entry) {
|
|
37
|
+
return join(dirname(realEntry(entry ?? Bun.main)), BUNDLED_SKILLS_DIR);
|
|
38
|
+
}
|
|
39
|
+
function bundledBinDirectory(entry) {
|
|
40
|
+
return join(dirname(realEntry(entry ?? Bun.main)), BUNDLED_BIN_DIR);
|
|
41
|
+
}
|
|
42
|
+
function skillTierDirectory(tier, seams) {
|
|
43
|
+
if (tier === "user")
|
|
44
|
+
return join(seams.home, CLAUDE_SKILLS_PATH);
|
|
45
|
+
if (tier === "rafa")
|
|
46
|
+
return bundledSkillsDirectory(seams.entry);
|
|
47
|
+
return seams.projectRoot === null ? null : join(seams.projectRoot, CLAUDE_SKILLS_PATH);
|
|
48
|
+
}
|
|
49
|
+
function resolveSkillTiers(seams) {
|
|
50
|
+
const located = [];
|
|
51
|
+
for (const tier of SKILL_TIERS) {
|
|
52
|
+
const dir = skillTierDirectory(tier, seams);
|
|
53
|
+
if (dir !== null)
|
|
54
|
+
located.push({ tier, dir });
|
|
55
|
+
}
|
|
56
|
+
return located;
|
|
57
|
+
}
|
|
58
|
+
function instinctScopeDirectory(scope, seams) {
|
|
59
|
+
if (scope === "user")
|
|
60
|
+
return join(seams.home, RAFA_INSTINCTS_PATH);
|
|
61
|
+
return seams.projectRoot === null ? null : join(seams.projectRoot, RAFA_INSTINCTS_PATH);
|
|
62
|
+
}
|
|
63
|
+
function resolveInstinctScopes(seams) {
|
|
64
|
+
const located = [];
|
|
65
|
+
for (const scope of INSTINCT_SCOPES) {
|
|
66
|
+
const dir = instinctScopeDirectory(scope, seams);
|
|
67
|
+
if (dir !== null)
|
|
68
|
+
located.push({ scope, dir });
|
|
69
|
+
}
|
|
70
|
+
return located;
|
|
71
|
+
}
|
|
72
|
+
function tierExists(dir) {
|
|
73
|
+
return existsSync(dir);
|
|
74
|
+
}
|
|
75
|
+
|
|
14
76
|
// src/utils/declaration.ts
|
|
15
77
|
var DECLARATION_KEYS = [
|
|
16
78
|
"agent",
|
|
@@ -255,6 +317,7 @@ var OUTPUT_MODES = ["text", "json"];
|
|
|
255
317
|
var CLAUDE_SETTING_SOURCES = ["user", "project", "local"];
|
|
256
318
|
var PR_PROVIDERS = ["gh", "none"];
|
|
257
319
|
var RELEASE_AUTO = "auto";
|
|
320
|
+
var TIER_SWITCHES = ["on", "off"];
|
|
258
321
|
function accepted(value) {
|
|
259
322
|
return { value, problems: [], extras: [] };
|
|
260
323
|
}
|
|
@@ -289,7 +352,20 @@ var usdAmount = (raw, at) => {
|
|
|
289
352
|
};
|
|
290
353
|
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");
|
|
291
354
|
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");
|
|
355
|
+
var confidence = (raw, at) => typeof raw === "number" && Number.isFinite(raw) && toHundredths(raw) >= toHundredths(CONFIDENCE_MIN) && toHundredths(raw) <= toHundredths(CONFIDENCE_MAX) ? accepted(raw) : refused(at, raw, `a confidence from ${String(CONFIDENCE_MIN)} to ${String(CONFIDENCE_MAX)}`);
|
|
356
|
+
function toHundredths(value) {
|
|
357
|
+
return Math.round(value * 100);
|
|
358
|
+
}
|
|
359
|
+
var recurrenceCount = (raw, at) => typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1 ? accepted(raw) : refused(at, raw, "a count, a whole number of 1 or more");
|
|
292
360
|
var releaseEnabled = (raw, at) => typeof raw === "boolean" || raw === RELEASE_AUTO ? accepted(raw) : refused(at, raw, `true, false or ${RELEASE_AUTO}`);
|
|
361
|
+
var tierSwitch = oneOf(TIER_SWITCHES);
|
|
362
|
+
var tierPin = (raw, at) => {
|
|
363
|
+
if (raw === false)
|
|
364
|
+
return accepted(false);
|
|
365
|
+
const tier = SKILL_TIERS.find((name) => name === raw);
|
|
366
|
+
return tier === undefined ? refused(at, raw, `false or one of: ${SKILL_TIERS.join(", ")}`) : accepted(tier);
|
|
367
|
+
};
|
|
368
|
+
var routeTarget = (raw, at) => raw === false || typeof raw === "string" && raw.trim() !== "" ? accepted(raw) : refused(at, raw, "false or an agent name");
|
|
293
369
|
var GITHUB_LOGIN = /^[A-Za-z0-9][A-Za-z0-9-]*(?:\[bot\])?$/;
|
|
294
370
|
function isGitHubLogin(value) {
|
|
295
371
|
return typeof value === "string" && GITHUB_LOGIN.test(value);
|
|
@@ -394,4 +470,4 @@ var moduleSource = (raw, at) => {
|
|
|
394
470
|
}));
|
|
395
471
|
};
|
|
396
472
|
|
|
397
|
-
export {
|
|
473
|
+
export { MERGE_METHODS, isMergeMethod, SKILL_TIERS, RAFA_INSTINCTS_PATH, BUNDLED_SKILLS_DIR, isSkillTier, realEntry, bundledBinDirectory, skillTierDirectory, resolveSkillTiers, resolveInstinctScopes, tierExists, isAgentName, BUDGET_FLAG, parseBudgetUsd, parseTaskDeclaration, stripTaskDeclaration, resolveDeclarationFlags, isMapping, describeValue, messageOf, CONFIG_VERSIONS, STORE_BACKENDS, INJECT_MODES, OUTPUT_MODES, CLAUDE_SETTING_SOURCES, PR_PROVIDERS, RELEASE_AUTO, oneOf, text, flag, mergeMethod, usdAmount, issueNumber, dayCount, confidence, recurrenceCount, releaseEnabled, tierSwitch, tierPin, routeTarget, isGitHubLogin, githubLogin, listOf, subsetOf, PREREQUISITE_KINDS, REQUIRED_ITEM_KEYS, OPTIONAL_ITEM_KEYS, requiredPrerequisite, optionalPrerequisite, MODULE_SOURCE_KINDS, MODULE_SOURCE_KEYS, moduleSource };
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
CONFIDENCE_MAX,
|
|
4
|
+
CONFIDENCE_MIN,
|
|
5
|
+
GAP,
|
|
6
|
+
SOURCE_STEP,
|
|
7
|
+
triggerKey
|
|
8
|
+
} from "./index-wp8c28fd.js";
|
|
9
|
+
|
|
10
|
+
// src/learning/bless.ts
|
|
11
|
+
import { createHash } from "crypto";
|
|
12
|
+
var HUNDREDTHS = 100;
|
|
13
|
+
function hundredths(confidence) {
|
|
14
|
+
return Math.round(confidence * HUNDREDTHS);
|
|
15
|
+
}
|
|
16
|
+
function compareText(left, right) {
|
|
17
|
+
if (left < right) {
|
|
18
|
+
return -1;
|
|
19
|
+
}
|
|
20
|
+
if (left > right) {
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
function byTrust(left, right) {
|
|
26
|
+
return hundredths(right.confidence) - hundredths(left.confidence) || right.usage_count - left.usage_count || compareText(left.id, right.id);
|
|
27
|
+
}
|
|
28
|
+
function blessedRecords(held, minConfidence) {
|
|
29
|
+
const floor = hundredths(minConfidence);
|
|
30
|
+
return held.filter((each) => each.status === "active" && each.promoted_to === undefined && hundredths(each.confidence) >= floor).sort(byTrust);
|
|
31
|
+
}
|
|
32
|
+
function versionOf(instincts) {
|
|
33
|
+
return createHash("sha256").update(JSON.stringify(instincts)).digest("hex");
|
|
34
|
+
}
|
|
35
|
+
function bless(held, options) {
|
|
36
|
+
const instincts = blessedRecords(held, options.minConfidence);
|
|
37
|
+
return { version: versionOf(instincts), instincts };
|
|
38
|
+
}
|
|
39
|
+
function promotable(held, options) {
|
|
40
|
+
return blessedRecords(held, options.minConfidence).filter((each) => each.usage_count >= options.after);
|
|
41
|
+
}
|
|
42
|
+
// src/learning/merge.ts
|
|
43
|
+
var HUNDREDTHS2 = 100;
|
|
44
|
+
var GAP_H = Math.round(GAP * HUNDREDTHS2);
|
|
45
|
+
var STEP_H = Math.round(SOURCE_STEP * HUNDREDTHS2);
|
|
46
|
+
var MIN_H = Math.round(CONFIDENCE_MIN * HUNDREDTHS2);
|
|
47
|
+
var MAX_H = Math.round(CONFIDENCE_MAX * HUNDREDTHS2);
|
|
48
|
+
function hundredths2(confidence) {
|
|
49
|
+
return Math.round(confidence * HUNDREDTHS2);
|
|
50
|
+
}
|
|
51
|
+
function compareText2(left, right) {
|
|
52
|
+
if (left < right) {
|
|
53
|
+
return -1;
|
|
54
|
+
}
|
|
55
|
+
if (left > right) {
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
function byAge(left, right) {
|
|
61
|
+
return compareText2(left.created_at, right.created_at) || compareText2(left.id, right.id);
|
|
62
|
+
}
|
|
63
|
+
function byConfidence(left, right) {
|
|
64
|
+
return hundredths2(right.confidence) - hundredths2(left.confidence) || compareText2(left.id, right.id);
|
|
65
|
+
}
|
|
66
|
+
function sourcesOf(record) {
|
|
67
|
+
return record.sources !== undefined && record.sources.length > 0 ? [...new Set(record.sources)] : [record.id];
|
|
68
|
+
}
|
|
69
|
+
function withSource(record, sourceId) {
|
|
70
|
+
const sources = [...new Set([...record.sources ?? [], sourceId])].sort();
|
|
71
|
+
return { ...record, sources, usage_count: sources.length };
|
|
72
|
+
}
|
|
73
|
+
function firstOptional(ordered, key) {
|
|
74
|
+
const found = ordered.find((record) => record[key] !== undefined);
|
|
75
|
+
return found === undefined ? {} : { [key]: found[key] };
|
|
76
|
+
}
|
|
77
|
+
function collapse(group) {
|
|
78
|
+
const ordered = [...[...group.held].sort(byAge), ...[...group.incoming].sort(byAge)];
|
|
79
|
+
if (ordered.length === 1) {
|
|
80
|
+
return ordered[0];
|
|
81
|
+
}
|
|
82
|
+
const seen = new Set;
|
|
83
|
+
let weighted = 0;
|
|
84
|
+
for (const member of ordered) {
|
|
85
|
+
const own = sourcesOf(member);
|
|
86
|
+
const fresh = own.filter((source) => !seen.has(source));
|
|
87
|
+
const base = hundredths2(member.confidence) - STEP_H * (own.length - 1);
|
|
88
|
+
weighted += base * fresh.length;
|
|
89
|
+
for (const source of fresh) {
|
|
90
|
+
seen.add(source);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const sources = [...seen].sort();
|
|
94
|
+
const stepped = Math.round(weighted / sources.length + STEP_H * (sources.length - 1));
|
|
95
|
+
const confidence = Math.min(MAX_H, Math.max(MIN_H, stepped)) / HUNDREDTHS2;
|
|
96
|
+
const byAgeAll = [...ordered].sort(byAge);
|
|
97
|
+
const lead = byAgeAll[0];
|
|
98
|
+
const rest = {};
|
|
99
|
+
for (const [key, value] of Object.entries(lead)) {
|
|
100
|
+
if (key !== "artifact" && key !== "promoted_to") {
|
|
101
|
+
Object.assign(rest, { [key]: value });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...rest,
|
|
106
|
+
...firstOptional(byAgeAll, "artifact"),
|
|
107
|
+
...firstOptional(byAgeAll, "promoted_to"),
|
|
108
|
+
confidence,
|
|
109
|
+
usage_count: sources.length,
|
|
110
|
+
sources
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function sameButStamp(left, right) {
|
|
114
|
+
const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
|
|
115
|
+
keys.delete("updated_at");
|
|
116
|
+
return [...keys].every((key) => {
|
|
117
|
+
const field = key;
|
|
118
|
+
return JSON.stringify(left[field]) === JSON.stringify(right[field]);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function stamp(record, held, now) {
|
|
122
|
+
const before = held.find((candidate) => candidate.id === record.id);
|
|
123
|
+
if (before !== undefined && sameButStamp(before, record)) {
|
|
124
|
+
return before;
|
|
125
|
+
}
|
|
126
|
+
return { ...record, updated_at: now };
|
|
127
|
+
}
|
|
128
|
+
function withStatus(record, status) {
|
|
129
|
+
return record.status === status ? record : { ...record, status };
|
|
130
|
+
}
|
|
131
|
+
function groupByAction(held, incoming) {
|
|
132
|
+
const groups = new Map;
|
|
133
|
+
const groupOf = (hash) => {
|
|
134
|
+
const found = groups.get(hash);
|
|
135
|
+
if (found !== undefined) {
|
|
136
|
+
return found;
|
|
137
|
+
}
|
|
138
|
+
const made = { held: [], incoming: [] };
|
|
139
|
+
groups.set(hash, made);
|
|
140
|
+
return made;
|
|
141
|
+
};
|
|
142
|
+
for (const record of held) {
|
|
143
|
+
groupOf(record.action_hash).held.push(record);
|
|
144
|
+
}
|
|
145
|
+
for (const record of incoming) {
|
|
146
|
+
groupOf(record.action_hash).incoming.push(record);
|
|
147
|
+
}
|
|
148
|
+
return groups;
|
|
149
|
+
}
|
|
150
|
+
function settleOne(hash, group, held, now) {
|
|
151
|
+
if (group.held.length === 0 && group.incoming.length === 1) {
|
|
152
|
+
return {
|
|
153
|
+
produced: [group.incoming[0]],
|
|
154
|
+
discarded: [],
|
|
155
|
+
rules: new Map([[hash, "new-trigger"]])
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const record = stamp(withStatus(collapse(group), "active"), held, now);
|
|
159
|
+
return { produced: [record], discarded: [], rules: new Map([[hash, "same-action"]]) };
|
|
160
|
+
}
|
|
161
|
+
function settleMany(collapsed, held, now) {
|
|
162
|
+
const leaderH = Math.max(...[...collapsed.values()].map((record) => hundredths2(record.confidence)));
|
|
163
|
+
const kept = new Map;
|
|
164
|
+
const discarded = [];
|
|
165
|
+
for (const [hash, record] of collapsed) {
|
|
166
|
+
if (leaderH - hundredths2(record.confidence) > GAP_H) {
|
|
167
|
+
discarded.push(record);
|
|
168
|
+
} else {
|
|
169
|
+
kept.set(hash, record);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const status = kept.size > 1 ? "flagged" : "active";
|
|
173
|
+
const rule = kept.size > 1 ? "flagged" : "higher-confidence";
|
|
174
|
+
const rules = new Map;
|
|
175
|
+
for (const hash of collapsed.keys()) {
|
|
176
|
+
rules.set(hash, kept.has(hash) ? rule : "higher-confidence");
|
|
177
|
+
}
|
|
178
|
+
const produced = [...kept.values()].map((record) => stamp(withStatus(record, status), held, now));
|
|
179
|
+
return {
|
|
180
|
+
produced: produced.sort(byConfidence),
|
|
181
|
+
discarded: discarded.sort(byConfidence),
|
|
182
|
+
rules
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function settleTrigger(held, incoming, now) {
|
|
186
|
+
const groups = groupByAction(held, incoming);
|
|
187
|
+
if (groups.size === 1) {
|
|
188
|
+
const [hash, group] = [...groups.entries()][0];
|
|
189
|
+
return settleOne(hash, group, held, now);
|
|
190
|
+
}
|
|
191
|
+
const collapsed = new Map;
|
|
192
|
+
for (const [hash, group] of groups) {
|
|
193
|
+
collapsed.set(hash, collapse(group));
|
|
194
|
+
}
|
|
195
|
+
return settleMany(collapsed, held, now);
|
|
196
|
+
}
|
|
197
|
+
function merge(held, payload, now) {
|
|
198
|
+
const incoming = payload.instincts.map((record) => withSource(record, payload.source_id));
|
|
199
|
+
const keys = [...new Set(incoming.map((record) => triggerKey(record.trigger)))];
|
|
200
|
+
const outcomes = new Map;
|
|
201
|
+
for (const key of keys) {
|
|
202
|
+
const onKey = (record) => triggerKey(record.trigger) === key;
|
|
203
|
+
outcomes.set(key, settleTrigger(held.filter(onKey), incoming.filter(onKey), now));
|
|
204
|
+
}
|
|
205
|
+
const decisions = payload.instincts.map((record) => {
|
|
206
|
+
const outcome = outcomes.get(triggerKey(record.trigger));
|
|
207
|
+
return {
|
|
208
|
+
incoming: record,
|
|
209
|
+
rule: outcome.rules.get(record.action_hash),
|
|
210
|
+
produced: [...outcome.produced]
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
return {
|
|
214
|
+
decisions,
|
|
215
|
+
discarded: keys.flatMap((key) => outcomes.get(key).discarded)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
export { bless, promotable, merge };
|