@open-tomato/rafa 0.18.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/README.md +13 -10
- package/dist/PROMPT.md +2 -1
- package/dist/bundled/skills/dev-planner/SKILL.md +2 -0
- package/dist/cli.js +2212 -950
- package/dist/{describe-vq037dyt.js → describe-cenk70n5.js} +4 -3
- package/dist/effort/store/index.js +6 -4
- package/dist/{index-0pdsq2hy.js → index-09p41s0n.js} +11 -224
- package/dist/{index-kvnggvyk.js → index-c5cecsga.js} +2 -2
- package/dist/{index-6vkd153j.js → index-ca0fccvr.js} +1220 -1104
- package/dist/{index-944pncd8.js → index-cedghpva.js} +10 -2
- package/dist/index-d6d0942q.js +218 -0
- package/dist/{index-at9f1z2z.js → index-gb51x34c.js} +1007 -51
- package/dist/{index-cvpdvmtg.js → index-mh5hyw8g.js} +602 -665
- package/dist/{index-jva32qe6.js → index-pqrpcfaz.js} +246 -2
- package/dist/{index-ddf85qac.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/package.json +4 -3
|
@@ -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([
|
|
@@ -349,6 +352,11 @@ var usdAmount = (raw, at) => {
|
|
|
349
352
|
};
|
|
350
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");
|
|
351
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");
|
|
352
360
|
var releaseEnabled = (raw, at) => typeof raw === "boolean" || raw === RELEASE_AUTO ? accepted(raw) : refused(at, raw, `true, false or ${RELEASE_AUTO}`);
|
|
353
361
|
var tierSwitch = oneOf(TIER_SWITCHES);
|
|
354
362
|
var tierPin = (raw, at) => {
|
|
@@ -462,4 +470,4 @@ var moduleSource = (raw, at) => {
|
|
|
462
470
|
}));
|
|
463
471
|
};
|
|
464
472
|
|
|
465
|
-
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 };
|