@open-tomato/rafa 0.34.0 → 0.35.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.
@@ -1,45 +1,447 @@
1
1
  // @bun
2
2
  import {
3
- BOARD_RELATIONSHIP_MODES,
4
- CLAUDE_SETTING_SOURCES,
5
- CONFIG_VERSIONS,
6
- INJECT_MODES,
7
- OUTPUT_MODES,
8
- PR_PROVIDERS,
9
- RELEASE_AUTO,
10
- SKILL_TIERS,
11
- STORE_BACKENDS,
12
- SYNC_STRATEGIES,
13
- below,
14
- busyTimeoutMs,
15
- claimsAhead,
16
- claimsStaleAfter,
17
- confidence,
18
- dayCount,
19
- describeValue,
20
- flag,
21
- githubLogin,
22
- isMapping,
23
- isSkillTier,
24
- issueNumber,
25
- lessonSwitch,
26
- listOf,
27
- mapReading,
28
- mergeMethod,
29
- messageOf,
30
- oneOf,
31
- recurrenceCount,
32
- refused,
33
- refusedWith,
34
- releaseEnabled,
35
- routeTarget,
36
- skillResolverName,
37
- subsetOf,
38
- text,
39
- tierPin,
40
- tierSwitch,
41
- usdAmount
42
- } from "./index-fzhd3d4y.js";
3
+ CONFIDENCE_MIN2,
4
+ CONFIDENCE_MAX2
5
+ } from "./index-21jcfatr.js";
6
+
7
+ // src/pr/types.ts
8
+ var MERGE_METHODS = Object.freeze([
9
+ "squash",
10
+ "merge",
11
+ "rebase"
12
+ ]);
13
+ function isMergeMethod(value) {
14
+ return typeof value === "string" && MERGE_METHODS.includes(value);
15
+ }
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
+
76
+ // src/utils/declaration.ts
77
+ var DECLARATION_KEYS = [
78
+ "agent",
79
+ "model",
80
+ "effort",
81
+ "budget",
82
+ "tools",
83
+ "skills",
84
+ "tests"
85
+ ];
86
+ var GRANULAR_KEYS = ["model", "effort", "tools"];
87
+ var AGENT_OWNED_KEYS = ["model", "tools"];
88
+ var MODEL_ALIASES = ["opus", "sonnet", "haiku", "fable"];
89
+ var EFFORT_LEVELS = [
90
+ "low",
91
+ "medium",
92
+ "high",
93
+ "xhigh",
94
+ "max"
95
+ ];
96
+ var TEST_SCOPES = ["affected", "module", "full"];
97
+ var DEFAULT_TEST_SCOPE = "affected";
98
+ var DECLARATION_BLOCK = /\{([^{}]*)\}$/;
99
+ var ENTRY_TOKEN = /^([A-Za-z_][A-Za-z0-9_-]*)=(.*)$/;
100
+ var FULL_MODEL_NAME = /^claude-[a-z0-9][a-z0-9.-]*$/;
101
+ var AGENT_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
102
+ function isAgentName(value) {
103
+ return AGENT_NAME.test(value);
104
+ }
105
+ var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_-]*$/;
106
+ var SKILL_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
107
+ var BUDGET_FLAG = "--max-budget-usd";
108
+ var BUDGET_VALUE = /^(?:0|[1-9]\d{0,5})(?:\.\d{1,6})?$/;
109
+ function parseBudgetUsd(value) {
110
+ if (!BUDGET_VALUE.test(value))
111
+ return null;
112
+ const usd = Number(value);
113
+ return usd > 0 ? usd : null;
114
+ }
115
+ function isEffortLevel(value) {
116
+ return EFFORT_LEVELS.includes(value);
117
+ }
118
+ function isTestScope(value) {
119
+ return TEST_SCOPES.includes(value);
120
+ }
121
+ function readTestScope(declaration) {
122
+ return declaration?.tests ?? DEFAULT_TEST_SCOPE;
123
+ }
124
+ function isModelValue(value) {
125
+ if (MODEL_ALIASES.includes(value))
126
+ return true;
127
+ return FULL_MODEL_NAME.test(value);
128
+ }
129
+ function parseToolList(value) {
130
+ const parts = value.split(",");
131
+ if (parts.length === 0)
132
+ return null;
133
+ const tools = [];
134
+ for (const part of parts) {
135
+ if (!TOOL_NAME.test(part))
136
+ return null;
137
+ if (!tools.includes(part))
138
+ tools.push(part);
139
+ }
140
+ return tools;
141
+ }
142
+ function parseSkillList(value) {
143
+ const parts = value.split(",");
144
+ if (parts.length === 0)
145
+ return null;
146
+ const skills = [];
147
+ for (const part of parts) {
148
+ if (!SKILL_NAME.test(part))
149
+ return null;
150
+ if (!skills.includes(part))
151
+ skills.push(part);
152
+ }
153
+ return skills;
154
+ }
155
+ function unusableValue(key, token) {
156
+ return { reason: "unusable-value", key, text: token };
157
+ }
158
+ function isDeclarationKey(key) {
159
+ return DECLARATION_KEYS.includes(key);
160
+ }
161
+ function tokenise(body) {
162
+ const trimmed = body.trim();
163
+ if (trimmed.length === 0)
164
+ return [];
165
+ return trimmed.split(/\s+/);
166
+ }
167
+ function readBlock(raw, body) {
168
+ const entries = [];
169
+ const extras = [];
170
+ const issues = [];
171
+ const seen = new Set;
172
+ let agent = null;
173
+ let model = null;
174
+ let effort = null;
175
+ let budget = null;
176
+ let tools = null;
177
+ let skills = null;
178
+ let tests = null;
179
+ for (const token of tokenise(body)) {
180
+ const match = token.match(ENTRY_TOKEN);
181
+ const key = match?.[1];
182
+ const value = match?.[2];
183
+ if (key === undefined || value === undefined) {
184
+ issues.push({ reason: "stray-token", key: "", text: token });
185
+ continue;
186
+ }
187
+ const entry = { key, value };
188
+ entries.push(entry);
189
+ if (!isDeclarationKey(key)) {
190
+ extras.push(entry);
191
+ continue;
192
+ }
193
+ if (seen.has(key)) {
194
+ issues.push({ reason: "duplicate-key", key, text: token });
195
+ continue;
196
+ }
197
+ seen.add(key);
198
+ if (key === "agent") {
199
+ if (AGENT_NAME.test(value))
200
+ agent = value;
201
+ else
202
+ issues.push(unusableValue(key, token));
203
+ continue;
204
+ }
205
+ if (key === "model") {
206
+ if (isModelValue(value))
207
+ model = value;
208
+ else
209
+ issues.push(unusableValue(key, token));
210
+ continue;
211
+ }
212
+ if (key === "effort") {
213
+ if (isEffortLevel(value))
214
+ effort = value;
215
+ else
216
+ issues.push(unusableValue(key, token));
217
+ continue;
218
+ }
219
+ if (key === "budget") {
220
+ const usd = parseBudgetUsd(value);
221
+ if (usd === null)
222
+ issues.push(unusableValue(key, token));
223
+ else
224
+ budget = usd;
225
+ continue;
226
+ }
227
+ if (key === "tools") {
228
+ const parsed = parseToolList(value);
229
+ if (parsed === null)
230
+ issues.push(unusableValue(key, token));
231
+ else
232
+ tools = parsed;
233
+ continue;
234
+ }
235
+ if (key === "tests") {
236
+ if (isTestScope(value))
237
+ tests = value;
238
+ else
239
+ issues.push(unusableValue(key, token));
240
+ continue;
241
+ }
242
+ const named = parseSkillList(value);
243
+ if (named === null)
244
+ issues.push(unusableValue(key, token));
245
+ else
246
+ skills = named;
247
+ }
248
+ if (seen.size === 0)
249
+ return null;
250
+ return {
251
+ raw,
252
+ entries,
253
+ extras,
254
+ issues,
255
+ agent,
256
+ model,
257
+ effort,
258
+ budget,
259
+ tools,
260
+ skills,
261
+ tests
262
+ };
263
+ }
264
+ function parseTaskDeclaration(taskText) {
265
+ const trimmed = taskText.trimEnd();
266
+ const match = trimmed.match(DECLARATION_BLOCK);
267
+ const raw = match?.[0];
268
+ const body = match?.[1];
269
+ if (raw === undefined || body === undefined) {
270
+ return { text: taskText, declaration: null };
271
+ }
272
+ const before = trimmed.slice(0, trimmed.length - raw.length).trimEnd();
273
+ if (before.length === 0)
274
+ return { text: taskText, declaration: null };
275
+ const declaration = readBlock(raw, body);
276
+ if (declaration === null)
277
+ return { text: taskText, declaration: null };
278
+ return { text: before, declaration };
279
+ }
280
+ function stripTaskDeclaration(taskText) {
281
+ return parseTaskDeclaration(taskText).text;
282
+ }
283
+ function budgetArgs(budget) {
284
+ return budget === null ? [] : [BUDGET_FLAG, String(budget)];
285
+ }
286
+ function resolveDeclarationFlags(declaration, agentDeclaresEffort) {
287
+ if (declaration === null)
288
+ return { args: [], suppressed: [] };
289
+ const { agent, effort } = declaration;
290
+ const isPresent = (key) => declaration[key] !== null;
291
+ const budget = budgetArgs(declaration.budget);
292
+ if (agent !== null) {
293
+ if (effort === null || agentDeclaresEffort(agent)) {
294
+ return { args: ["--agent", agent, ...budget], suppressed: GRANULAR_KEYS.filter(isPresent) };
295
+ }
296
+ return {
297
+ args: ["--agent", agent, "--effort", effort, ...budget],
298
+ suppressed: AGENT_OWNED_KEYS.filter(isPresent)
299
+ };
300
+ }
301
+ const args = [];
302
+ if (declaration.model !== null)
303
+ args.push("--model", declaration.model);
304
+ if (declaration.effort !== null)
305
+ args.push("--effort", declaration.effort);
306
+ args.push(...budget);
307
+ if (declaration.tools !== null) {
308
+ args.push("--tools", declaration.tools.join(","));
309
+ }
310
+ return { args, suppressed: [] };
311
+ }
312
+
313
+ // src/config-sections.ts
314
+ function isMapping(value) {
315
+ return typeof value === "object" && value !== null && !Array.isArray(value);
316
+ }
317
+ function describeValue(value) {
318
+ if (typeof value === "string")
319
+ return JSON.stringify(value);
320
+ if (value === null)
321
+ return "null";
322
+ if (Array.isArray(value))
323
+ return "a list";
324
+ if (typeof value === "object")
325
+ return "a mapping";
326
+ return String(value);
327
+ }
328
+ function messageOf(error) {
329
+ return error instanceof Error ? error.message : String(error);
330
+ }
331
+ var CONFIG_VERSIONS2 = [1];
332
+ var STORE_BACKENDS2 = ["sqlite", "ndjson"];
333
+ var SYNC_STRATEGIES2 = ["local", "file", "git", "service", "p2p"];
334
+ var BOARD_RELATIONSHIP_MODES2 = ["labels", "native"];
335
+ var INJECT_MODES2 = ["full", "stage", "task"];
336
+ var OUTPUT_MODES2 = ["text", "json", "events"];
337
+ var CLAUDE_SETTING_SOURCES2 = ["user", "project", "local"];
338
+ var PR_PROVIDERS2 = ["gh", "none"];
339
+ var RELEASE_AUTO2 = "auto";
340
+ var TIER_SWITCHES = ["on", "off"];
341
+ var SKILL_RESOLVERS = ["planner", "tag", "none"];
342
+ var LESSON_SWITCHES = ["on", "off"];
343
+ var CLAIMS_STALE_DISABLED = "disabled";
344
+ var CLAIMS_AHEAD = ["off", "allow"];
345
+ function accepted(value) {
346
+ return { value, problems: [], extras: [] };
347
+ }
348
+ function refused(at, raw, expected) {
349
+ const problem = `${at.label} is ${describeValue(raw)}, expected ${expected}`;
350
+ return { value: undefined, problems: [problem], extras: [] };
351
+ }
352
+ function refusedWith(problems) {
353
+ return { value: undefined, problems, extras: [] };
354
+ }
355
+ function mapReading(reading, map) {
356
+ return reading.value === undefined ? { ...reading, value: undefined } : { ...reading, value: map(reading.value) };
357
+ }
358
+ function below(at, step) {
359
+ return { label: `${at.label}${step}`, key: `${at.key}${step}` };
360
+ }
361
+ function oneOf(values) {
362
+ const expected = `one of: ${values.join(", ")}`;
363
+ return (raw, at) => {
364
+ const hit = values.find((value) => value === raw);
365
+ return hit === undefined ? refused(at, raw, expected) : accepted(hit);
366
+ };
367
+ }
368
+ function text(expected) {
369
+ return (raw, at) => typeof raw === "string" && raw.trim() !== "" ? accepted(raw) : refused(at, raw, expected);
370
+ }
371
+ var flag = (raw, at) => typeof raw === "boolean" ? accepted(raw) : refused(at, raw, "true or false");
372
+ var mergeMethod = oneOf(MERGE_METHODS);
373
+ var usdAmount = (raw, at) => {
374
+ const usd = typeof raw === "number" ? parseBudgetUsd(String(raw)) : null;
375
+ return usd === null ? refused(at, raw, "a number of US dollars above zero, at most six digits either side of the point") : accepted(usd);
376
+ };
377
+ 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");
378
+ 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");
379
+ var BUSY_TIMEOUT_MIN_MS = 1;
380
+ var BUSY_TIMEOUT_MAX_MS = 60000;
381
+ function isBusyTimeoutMs(raw) {
382
+ return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= BUSY_TIMEOUT_MIN_MS && raw <= BUSY_TIMEOUT_MAX_MS;
383
+ }
384
+ var busyTimeoutMs = (raw, at) => isBusyTimeoutMs(raw) ? accepted(raw) : refused(at, raw, `a lock wait in milliseconds, a whole number from ${String(BUSY_TIMEOUT_MIN_MS)} to ${String(BUSY_TIMEOUT_MAX_MS)}`);
385
+ var confidence = (raw, at) => typeof raw === "number" && Number.isFinite(raw) && toHundredths(raw) >= toHundredths(CONFIDENCE_MIN2) && toHundredths(raw) <= toHundredths(CONFIDENCE_MAX2) ? accepted(raw) : refused(at, raw, `a confidence from ${String(CONFIDENCE_MIN2)} to ${String(CONFIDENCE_MAX2)}`);
386
+ function toHundredths(value) {
387
+ return Math.round(value * 100);
388
+ }
389
+ 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");
390
+ var releaseEnabled = (raw, at) => typeof raw === "boolean" || raw === RELEASE_AUTO2 ? accepted(raw) : refused(at, raw, `true, false or ${RELEASE_AUTO2}`);
391
+ var tierSwitch = oneOf(TIER_SWITCHES);
392
+ var tierPin = (raw, at) => {
393
+ if (raw === false)
394
+ return accepted(false);
395
+ const tier = SKILL_TIERS.find((name) => name === raw);
396
+ return tier === undefined ? refused(at, raw, `false or one of: ${SKILL_TIERS.join(", ")}`) : accepted(tier);
397
+ };
398
+ var routeTarget = (raw, at) => raw === false || typeof raw === "string" && raw.trim() !== "" ? accepted(raw) : refused(at, raw, "false or an agent name");
399
+ var skillResolverName = oneOf(SKILL_RESOLVERS);
400
+ var lessonSwitch = oneOf(LESSON_SWITCHES);
401
+ var CLAIM_DURATION = /^(\d+)([hd])$/;
402
+ var HOURS_PER_DAY = 24;
403
+ function claimDurationHours(raw) {
404
+ const match = typeof raw === "string" ? CLAIM_DURATION.exec(raw) : null;
405
+ if (match === null)
406
+ return null;
407
+ const hours = Number(match[1]) * (match[2] === "d" ? HOURS_PER_DAY : 1);
408
+ return Number.isSafeInteger(hours) && hours > 0 ? hours : null;
409
+ }
410
+ var claimsStaleAfter = (raw, at) => raw === CLAIMS_STALE_DISABLED || claimDurationHours(raw) !== null ? accepted(raw) : refused(at, raw, `a duration of whole hours or days above zero, such as 36h or 3d, or ${CLAIMS_STALE_DISABLED}`);
411
+ var claimsAhead = oneOf(CLAIMS_AHEAD);
412
+ var GITHUB_LOGIN = /^[A-Za-z0-9][A-Za-z0-9-]*(?:\[bot\])?$/;
413
+ function isGitHubLogin(value) {
414
+ return typeof value === "string" && GITHUB_LOGIN.test(value);
415
+ }
416
+ var githubLogin = (raw, at) => isGitHubLogin(raw) ? accepted(raw) : refused(at, raw, "a GitHub login");
417
+ function listOf(item, expected) {
418
+ return (raw, at) => {
419
+ if (!Array.isArray(raw))
420
+ return refused(at, raw, `a list of ${expected}`);
421
+ const readings = raw.map((entry, index) => item(entry, below(at, `[${index}]`)));
422
+ const problems = readings.flatMap((reading) => reading.problems);
423
+ const extras = readings.flatMap((reading) => reading.extras);
424
+ if (problems.length > 0)
425
+ return { value: undefined, problems, extras };
426
+ const values = readings.flatMap((reading) => reading.value === undefined ? [] : [reading.value]);
427
+ return { value: Object.freeze(values), problems, extras };
428
+ };
429
+ }
430
+ function subsetOf(values) {
431
+ const expected = `a comma-separated subset of: ${values.join(", ")}`;
432
+ return (raw, at) => {
433
+ if (typeof raw !== "string")
434
+ return refused(at, raw, expected);
435
+ const named = [];
436
+ for (const entry of raw.split(",")) {
437
+ const hit = values.find((value) => value === entry.trim());
438
+ if (hit === undefined || named.includes(hit))
439
+ return refused(at, raw, expected);
440
+ named.push(hit);
441
+ }
442
+ return accepted(Object.freeze(named));
443
+ };
444
+ }
43
445
 
44
446
  // src/config-items.ts
45
447
  var itemText = text("a non-empty string");
@@ -48,13 +450,13 @@ function readKeyedItem(shape, raw, at) {
48
450
  if (!isMapping(raw))
49
451
  return refused(at, raw, `a mapping naming one of: ${choices}`);
50
452
  const entries = Object.entries(raw);
51
- const kinds = shape.kinds.filter((kind2) => entries.some(([name]) => name === kind2));
453
+ const kinds = shape.kinds.filter((kind) => entries.some(([name]) => name === kind));
52
454
  const [kind] = kinds;
53
455
  if (kind === undefined)
54
456
  return refusedWith([`${at.label} names none of: ${choices}`]);
55
457
  if (kinds.length > 1) {
56
- const named2 = kinds.join(" and ");
57
- return refusedWith([`${at.label} names ${named2}, expected exactly one of: ${choices}`]);
458
+ const named = kinds.join(" and ");
459
+ return refusedWith([`${at.label} names ${named}, expected exactly one of: ${choices}`]);
58
460
  }
59
461
  const optionalKeys = shape.optionalFor(kind);
60
462
  const problems = [];
@@ -79,11 +481,11 @@ function readKeyedItem(shape, raw, at) {
79
481
  }
80
482
  return problems.length > 0 || named === undefined ? { value: undefined, problems, extras } : { value: { kind, named, optional }, problems, extras };
81
483
  }
82
- var PREREQUISITE_KINDS = ["tool", "env", "service", "lsp"];
83
- var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS, "probe"];
484
+ var PREREQUISITE_KINDS2 = ["tool", "env", "service", "lsp"];
485
+ var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS2, "probe"];
84
486
  var OPTIONAL_ITEM_KEYS = [...REQUIRED_ITEM_KEYS, "reason"];
85
487
  var requiredPrerequisite = (raw, at) => {
86
- const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe"] };
488
+ const shape = { kinds: PREREQUISITE_KINDS2, optionalFor: () => ["probe"] };
87
489
  return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
88
490
  kind: item.kind,
89
491
  name: item.named,
@@ -91,7 +493,7 @@ var requiredPrerequisite = (raw, at) => {
91
493
  }));
92
494
  };
93
495
  var optionalPrerequisite = (raw, at) => {
94
- const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe", "reason"] };
496
+ const shape = { kinds: PREREQUISITE_KINDS2, optionalFor: () => ["probe", "reason"] };
95
497
  return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
96
498
  kind: item.kind,
97
499
  name: item.named,
@@ -99,11 +501,11 @@ var optionalPrerequisite = (raw, at) => {
99
501
  reason: item.optional.get("reason") ?? null
100
502
  }));
101
503
  };
102
- var MODULE_SOURCE_KINDS = ["npm", "github", "path"];
103
- var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS, "ref"];
504
+ var MODULE_SOURCE_KINDS2 = ["npm", "github", "path"];
505
+ var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS2, "ref"];
104
506
  var moduleSource = (raw, at) => {
105
507
  const shape = {
106
- kinds: MODULE_SOURCE_KINDS,
508
+ kinds: MODULE_SOURCE_KINDS2,
107
509
  optionalFor: (kind) => kind === "github" ? ["ref"] : []
108
510
  };
109
511
  return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
@@ -114,7 +516,7 @@ var moduleSource = (raw, at) => {
114
516
  };
115
517
 
116
518
  // src/config-schema.ts
117
- import { join } from "path";
519
+ import { join as join2 } from "path";
118
520
 
119
521
  // src/config-readers.ts
120
522
  import { isAbsolute, normalize } from "path";
@@ -236,7 +638,7 @@ var PR_DEFAULTS = Object.freeze({
236
638
  prVersionCollision: "report"
237
639
  });
238
640
  var RELEASE_DEFAULTS = Object.freeze({
239
- releaseEnabled: RELEASE_AUTO,
641
+ releaseEnabled: RELEASE_AUTO2,
240
642
  releaseVersionFile: "package.json",
241
643
  releaseChangelog: "CHANGELOG.md",
242
644
  releaseHeading: "## {version} \u2014 {date}, {title}",
@@ -250,7 +652,7 @@ var DANGEROUS_RELEASE_DEFAULTS = Object.freeze({
250
652
  dangerousAcceptVersionCollision: false
251
653
  });
252
654
  var PR_SETTINGS = {
253
- prProvider: { key: "pr.provider", read: oneOf(PR_PROVIDERS), cli: false },
655
+ prProvider: { key: "pr.provider", read: oneOf(PR_PROVIDERS2), cli: false },
254
656
  prMergeMethod: { key: "pr.mergeMethod", read: mergeMethod, cli: false },
255
657
  prBase: { key: "pr.base", read: text("a branch name"), cli: false },
256
658
  prResolveBudget: { key: "pr.resolveBudget", read: usdAmount, cli: false },
@@ -313,7 +715,8 @@ var TESTS_DEFAULTS = Object.freeze({
313
715
  "**/*.integration.test.ts",
314
716
  "**/*-spawned*.test.ts",
315
717
  "**/*-cli.test.ts"
316
- ])
718
+ ]),
719
+ testsAlwaysRun: Object.freeze(["src/**/*.sweep.test.ts"])
317
720
  });
318
721
  var TESTS_SETTINGS = {
319
722
  testsFullSuiteTriggers: {
@@ -321,7 +724,8 @@ var TESTS_SETTINGS = {
321
724
  read: globList,
322
725
  cli: false
323
726
  },
324
- testsIntegration: { key: "tests.integration", read: globList, cli: false }
727
+ testsIntegration: { key: "tests.integration", read: globList, cli: false },
728
+ testsAlwaysRun: { key: "tests.alwaysRun", read: globList, cli: false }
325
729
  };
326
730
 
327
731
  // src/config-schema-triage.ts
@@ -435,10 +839,10 @@ function sameItemGroups(holders, read) {
435
839
  const groups = [];
436
840
  for (const row of holders) {
437
841
  const bytes = read(row.path);
438
- const text2 = bytes === null ? null : comparableText(bytes);
439
- const group = text2 === null ? undefined : groups.find((candidate) => candidate.text === text2);
842
+ const text = bytes === null ? null : comparableText(bytes);
843
+ const group = text === null ? undefined : groups.find((candidate) => candidate.text === text);
440
844
  if (group === undefined)
441
- groups.push({ text: text2, rows: [row] });
845
+ groups.push({ text, rows: [row] });
442
846
  else
443
847
  group.rows.push(row);
444
848
  }
@@ -532,16 +936,16 @@ var DEFAULT_ROUTES = Object.freeze([
532
936
  var DEFAULT_ROUTING = new Map(DEFAULT_ROUTES);
533
937
 
534
938
  // src/config-schema.ts
535
- var CONFIG_FILE = join(".rafa", "config.yaml");
536
- var CONFIG_DEFAULTS = Object.freeze({
939
+ var CONFIG_FILE2 = join2(".rafa", "config.yaml");
940
+ var CONFIG_DEFAULTS2 = Object.freeze({
537
941
  version: 1,
538
942
  store: "sqlite",
539
943
  effortBusyTimeoutMs: 5000,
540
944
  effortSync: "local",
541
945
  ...HUB_DEFAULTS,
542
946
  inject: "stage",
543
- planDir: join(".rafa", "plans"),
544
- specsDir: join(".rafa", "specs"),
947
+ planDir: join2(".rafa", "plans"),
948
+ specsDir: join2(".rafa", "specs"),
545
949
  trackerDefault: "github",
546
950
  trackerFallback: Object.freeze(["local"]),
547
951
  learningAdapter: "local",
@@ -557,7 +961,7 @@ var CONFIG_DEFAULTS = Object.freeze({
557
961
  modules: Object.freeze([]),
558
962
  allowList: Object.freeze([]),
559
963
  settingSources: Object.freeze(["project", "local"]),
560
- loopWorktreeDir: join(".rafa", "worktrees"),
964
+ loopWorktreeDir: join2(".rafa", "worktrees"),
561
965
  ...WRAP_UP_DEFAULTS,
562
966
  ...PR_DEFAULTS,
563
967
  boardTrustedAuthors: Object.freeze([]),
@@ -583,12 +987,12 @@ var CONFIG_DEFAULTS = Object.freeze({
583
987
  ...TESTS_DEFAULTS
584
988
  });
585
989
  var SETTINGS = {
586
- version: { key: "version", read: oneOf(CONFIG_VERSIONS), cli: false },
587
- store: { key: "store", read: oneOf(STORE_BACKENDS), cli: true },
990
+ version: { key: "version", read: oneOf(CONFIG_VERSIONS2), cli: false },
991
+ store: { key: "store", read: oneOf(STORE_BACKENDS2), cli: true },
588
992
  effortBusyTimeoutMs: { key: "effort.busyTimeoutMs", read: busyTimeoutMs, cli: false },
589
- effortSync: { key: "effort.sync", read: oneOf(SYNC_STRATEGIES), cli: false },
993
+ effortSync: { key: "effort.sync", read: oneOf(SYNC_STRATEGIES2), cli: false },
590
994
  ...HUB_SETTINGS,
591
- inject: { key: "plan.inject", read: oneOf(INJECT_MODES), cli: true },
995
+ inject: { key: "plan.inject", read: oneOf(INJECT_MODES2), cli: true },
592
996
  planDir: { key: "plan.dir", read: directory, cli: true },
593
997
  specsDir: { key: "specs.dir", read: directory, cli: true },
594
998
  trackerDefault: { key: "tracker.default", read: trackerKind, cli: true },
@@ -605,7 +1009,7 @@ var SETTINGS = {
605
1009
  learningBlessMinConfidence: { key: "learning.bless.minConfidence", read: confidence, cli: false },
606
1010
  learningPromoteAfter: { key: "learning.promote.after", read: recurrenceCount, cli: false },
607
1011
  learningPromoteMinConfidence: { key: "learning.promote.minConfidence", read: confidence, cli: false },
608
- outputMode: { key: "output.mode", read: oneOf(OUTPUT_MODES), cli: true },
1012
+ outputMode: { key: "output.mode", read: oneOf(OUTPUT_MODES2), cli: true },
609
1013
  prerequisitesRequired: {
610
1014
  key: "prerequisites.required",
611
1015
  read: listOf(requiredPrerequisite, "prerequisite items"),
@@ -634,7 +1038,7 @@ var SETTINGS = {
634
1038
  },
635
1039
  settingSources: {
636
1040
  key: "loop.settingSources",
637
- read: subsetOf(CLAUDE_SETTING_SOURCES),
1041
+ read: subsetOf(CLAUDE_SETTING_SOURCES2),
638
1042
  cli: true
639
1043
  },
640
1044
  loopWorktreeDir: { key: "loop.worktreeDir", read: directory, cli: false },
@@ -647,7 +1051,7 @@ var SETTINGS = {
647
1051
  },
648
1052
  boardRelationships: {
649
1053
  key: "board.relationships",
650
- read: oneOf(BOARD_RELATIONSHIP_MODES),
1054
+ read: oneOf(BOARD_RELATIONSHIP_MODES2),
651
1055
  cli: false
652
1056
  },
653
1057
  roadmapIssue: { key: "roadmap.issue", read: issueNumber, cli: false },
@@ -730,8 +1134,8 @@ function knownKeysAbove(key) {
730
1134
  }
731
1135
 
732
1136
  // src/config.ts
733
- import { join as join2 } from "path";
734
- class ConfigError extends Error {
1137
+ import { join as join3 } from "path";
1138
+ class ConfigError2 extends Error {
735
1139
  problems;
736
1140
  constructor(problems, options) {
737
1141
  super(`rafa config: ${problems.join("; ")}`, options);
@@ -814,7 +1218,8 @@ function readLayer(rawOf, atOf) {
814
1218
  taskSkills: read("taskSkills"),
815
1219
  taskLessons: read("taskLessons"),
816
1220
  testsFullSuiteTriggers: read("testsFullSuiteTriggers"),
817
- testsIntegration: read("testsIntegration")
1221
+ testsIntegration: read("testsIntegration"),
1222
+ testsAlwaysRun: read("testsAlwaysRun")
818
1223
  };
819
1224
  return { layer, problems, extras };
820
1225
  }
@@ -855,28 +1260,28 @@ function sortKeys(document, path) {
855
1260
  return { named, extras, problems };
856
1261
  }
857
1262
  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`] : []);
1263
+ function tabIndentProblems(text, path) {
1264
+ return text.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
1265
  }
861
- function parseYaml(text2, path) {
862
- const tabProblems = tabIndentProblems(text2, path);
1266
+ function parseYaml(text, path) {
1267
+ const tabProblems = tabIndentProblems(text, path);
863
1268
  if (tabProblems.length > 0)
864
- throw new ConfigError(tabProblems);
1269
+ throw new ConfigError2(tabProblems);
865
1270
  try {
866
- return Bun.YAML.parse(text2);
1271
+ return Bun.YAML.parse(text);
867
1272
  } catch (error) {
868
1273
  const problem = `${path}: not valid YAML (${messageOf(error)})`;
869
- throw new ConfigError([problem], { cause: error });
1274
+ throw new ConfigError2([problem], { cause: error });
870
1275
  }
871
1276
  }
872
- function configFilePath(root) {
873
- return join2(root, CONFIG_FILE);
1277
+ function configFilePath2(root) {
1278
+ return join3(root, CONFIG_FILE2);
874
1279
  }
875
- function parseConfigText(text2, path) {
876
- const document = parseYaml(text2, path) ?? {};
1280
+ function parseConfigText2(text, path) {
1281
+ const document = parseYaml(text, path) ?? {};
877
1282
  if (!isMapping(document)) {
878
1283
  const found = describeValue(document);
879
- throw new ConfigError([
1284
+ throw new ConfigError2([
880
1285
  `${path}: expected a mapping at the top level, found ${found}`
881
1286
  ]);
882
1287
  }
@@ -887,7 +1292,7 @@ function parseConfigText(text2, path) {
887
1292
  }));
888
1293
  const all = [...sorted.problems, ...read.problems];
889
1294
  if (all.length > 0)
890
- throw new ConfigError(all);
1295
+ throw new ConfigError2(all);
891
1296
  return { path, values: read.layer, extras: [...sorted.extras, ...read.extras] };
892
1297
  }
893
1298
  var MAP_SETTINGS = new Set([
@@ -918,13 +1323,13 @@ function unknownKeyWarning(key, path) {
918
1323
  const where = under === "" ? "" : ` under ${under}`;
919
1324
  return `rafa config: unknown key ${quoted} in ${path} has no effect ` + `in this version (known keys${where}: ${names.join(", ")})`;
920
1325
  }
921
- function resolveConfig(layers = {}) {
1326
+ function resolveConfig2(layers = {}) {
922
1327
  const file = layers.file ?? null;
923
1328
  const user = layers.user ?? null;
924
1329
  const overrides = layers.cli ?? {};
925
1330
  const { layer: cli, problems } = readLayer((setting) => isCommandLineSetting(setting) ? overrides[setting] : undefined, (setting) => ({ label: `command line: ${setting}`, key: setting }));
926
1331
  if (problems.length > 0)
927
- throw new ConfigError(problems);
1332
+ throw new ConfigError2(problems);
928
1333
  const rank = (setting) => {
929
1334
  const fromCli = cli[setting];
930
1335
  if (fromCli !== undefined)
@@ -932,7 +1337,7 @@ function resolveConfig(layers = {}) {
932
1337
  const fromFile = file?.values[setting];
933
1338
  const fromUser = user?.values[setting];
934
1339
  if (MAP_SETTINGS.has(setting)) {
935
- const merged = mergeMaps(CONFIG_DEFAULTS[setting], fromUser, fromFile);
1340
+ const merged = mergeMaps(CONFIG_DEFAULTS2[setting], fromUser, fromFile);
936
1341
  const source = fromFile !== undefined ? "file" : fromUser !== undefined ? "user" : "default";
937
1342
  return { value: merged, source };
938
1343
  }
@@ -940,7 +1345,7 @@ function resolveConfig(layers = {}) {
940
1345
  return { value: fromFile, source: "file" };
941
1346
  if (fromUser !== undefined)
942
1347
  return { value: fromUser, source: "user" };
943
- return { value: CONFIG_DEFAULTS[setting], source: "default" };
1348
+ return { value: CONFIG_DEFAULTS2[setting], source: "default" };
944
1349
  };
945
1350
  const ranked = SETTING_NAMES.map((setting) => [setting, rank(setting)]);
946
1351
  const effortSync = rank("effortSync");
@@ -951,7 +1356,7 @@ function resolveConfig(layers = {}) {
951
1356
  paths: { file: file?.path ?? null, user: user?.path ?? null }
952
1357
  });
953
1358
  if (hubProblems.length > 0)
954
- throw new ConfigError(hubProblems);
1359
+ throw new ConfigError2(hubProblems);
955
1360
  const rafaLoaded = ranked.find(([setting]) => setting === "tiersRafa")?.[1].value !== "off";
956
1361
  const warnings = [user, file].flatMap((layer) => layer === null ? [] : [
957
1362
  ...layer.extras.map((extra) => unknownKeyWarning(extra.key, layer.path)),
@@ -969,7 +1374,7 @@ function resolveConfig(layers = {}) {
969
1374
  }
970
1375
 
971
1376
  // src/plan/blocks.ts
972
- var RAFA_BLOCK_KINDS = [
1377
+ var RAFA_BLOCK_KINDS2 = [
973
1378
  "plan",
974
1379
  "context",
975
1380
  "stage-context",
@@ -978,8 +1383,8 @@ var RAFA_BLOCK_KINDS = [
978
1383
  var RAFA_PREFIX = "rafa:";
979
1384
  var FENCE_RUN = /^( {0,3})(`{3,}|~{3,})/;
980
1385
  var CLOSING_FENCE = /^ {0,3}(`{3,}|~{3,})[ \t]*$/;
981
- function isRafaBlockKind(kind) {
982
- return RAFA_BLOCK_KINDS.includes(kind);
1386
+ function isRafaBlockKind2(kind) {
1387
+ return RAFA_BLOCK_KINDS2.includes(kind);
983
1388
  }
984
1389
  function linesOf(markdown) {
985
1390
  const lines = markdown.split(`
@@ -1023,7 +1428,7 @@ function dedent(line, indent) {
1023
1428
  cut += 1;
1024
1429
  return line.slice(cut);
1025
1430
  }
1026
- function readRafaBlocks(markdown) {
1431
+ function readRafaBlocks2(markdown) {
1027
1432
  const lines = linesOf(markdown);
1028
1433
  const blocks = [];
1029
1434
  let index = 0;
@@ -1047,9 +1452,9 @@ function readRafaBlocks(markdown) {
1047
1452
  }
1048
1453
 
1049
1454
  // src/report/parse.ts
1050
- var REPORT_STATUSES = ["done", "blocked"];
1051
- var FINDING_KINDS = ["gotcha", "pattern", "location", "skill-suggestion"];
1052
- var FINDING_SIGNALS = ["loud", "silent"];
1455
+ var REPORT_STATUSES2 = ["done", "blocked"];
1456
+ var FINDING_KINDS2 = ["gotcha", "pattern", "location", "skill-suggestion"];
1457
+ var FINDING_SIGNALS2 = ["loud", "silent"];
1053
1458
  var FINDING_DOMAINS = [
1054
1459
  "code-style",
1055
1460
  "testing",
@@ -1105,11 +1510,11 @@ function describeValue2(value) {
1105
1510
  function messageOf2(error) {
1106
1511
  return error instanceof Error ? error.message : String(error);
1107
1512
  }
1108
- function reportIssue(reason, field, text2) {
1109
- return { reason, field, text: text2 };
1513
+ function reportIssue(reason, field, text) {
1514
+ return { reason, field, text };
1110
1515
  }
1111
- function absent(reason, block, text2) {
1112
- return { present: false, reason, block, text: text2 };
1516
+ function absent(reason, block, text) {
1517
+ return { present: false, reason, block, text };
1113
1518
  }
1114
1519
  function scopeOf(mapping, keys, prefix, issues) {
1115
1520
  const fields = new Map;
@@ -1181,8 +1586,8 @@ function listField(scope, key, readEntry) {
1181
1586
  function entryScope(item, field, keys, issues) {
1182
1587
  if (isMapping2(item))
1183
1588
  return scopeOf(item, keys, `${field}.`, issues);
1184
- const text2 = `${field} is ${describeValue2(item)}, not a mapping of ${keys.join(", ")}; dropped`;
1185
- issues.push(reportIssue("unusable-field", field, text2));
1589
+ const text = `${field} is ${describeValue2(item)}, not a mapping of ${keys.join(", ")}; dropped`;
1590
+ issues.push(reportIssue("unusable-field", field, text));
1186
1591
  return null;
1187
1592
  }
1188
1593
  function readSkill(item, field, issues) {
@@ -1198,12 +1603,12 @@ function readFinding(item, field, issues) {
1198
1603
  return null;
1199
1604
  return {
1200
1605
  trigger: stringField(scope, "trigger", REQUIRED),
1201
- kind: choiceField(scope, "kind", FINDING_KINDS, REQUIRED),
1606
+ kind: choiceField(scope, "kind", FINDING_KINDS2, REQUIRED),
1202
1607
  what: stringField(scope, "what", REQUIRED),
1203
1608
  cause: stringField(scope, "cause", OPTIONAL),
1204
1609
  resolution: stringField(scope, "resolution", OPTIONAL),
1205
1610
  artifact: stringField(scope, "artifact", OPTIONAL),
1206
- signal: choiceField(scope, "signal", FINDING_SIGNALS, REQUIRED),
1611
+ signal: choiceField(scope, "signal", FINDING_SIGNALS2, REQUIRED),
1207
1612
  domain: choiceField(scope, "domain", FINDING_DOMAINS, OPTIONAL),
1208
1613
  extras: scope.extras
1209
1614
  };
@@ -1243,7 +1648,7 @@ function readChange(item, field, issues) {
1243
1648
  function readReport(document, issues) {
1244
1649
  const scope = scopeOf(document, REPORT_KEYS, "", issues);
1245
1650
  return {
1246
- status: choiceField(scope, "status", REPORT_STATUSES, REQUIRED),
1651
+ status: choiceField(scope, "status", REPORT_STATUSES2, REQUIRED),
1247
1652
  feedback: stringField(scope, "feedback", OPTIONAL),
1248
1653
  findings: listField(scope, "findings", readFinding),
1249
1654
  skillsUsed: listField(scope, "skills_used", readSkill),
@@ -1253,8 +1658,8 @@ function readReport(document, issues) {
1253
1658
  extras: scope.extras
1254
1659
  };
1255
1660
  }
1256
- function parseReport(output) {
1257
- const reports = readRafaBlocks(output).filter((block2) => block2.kind === REPORT_KIND);
1661
+ function parseReport2(output) {
1662
+ const reports = readRafaBlocks2(output).filter((block) => block.kind === REPORT_KIND);
1258
1663
  const block = reports.at(-1);
1259
1664
  if (block === undefined) {
1260
1665
  return absent("no-block", null, "the session output holds no rafa:report block");
@@ -1267,12 +1672,12 @@ function parseReport(output) {
1267
1672
  try {
1268
1673
  document = Bun.YAML.parse(block.body);
1269
1674
  } catch (error) {
1270
- const text2 = `rafa:report block at line ${line} is not valid YAML (${messageOf2(error)})`;
1271
- return absent("malformed-block", block, text2);
1675
+ const text = `rafa:report block at line ${line} is not valid YAML (${messageOf2(error)})`;
1676
+ return absent("malformed-block", block, text);
1272
1677
  }
1273
1678
  if (!isMapping2(document)) {
1274
- const text2 = `rafa:report block at line ${line} holds ${describeValue2(document)}, ` + "not a mapping of report fields";
1275
- return absent("malformed-block", block, text2);
1679
+ const text = `rafa:report block at line ${line} holds ${describeValue2(document)}, ` + "not a mapping of report fields";
1680
+ return absent("malformed-block", block, text);
1276
1681
  }
1277
1682
  const issues = [];
1278
1683
  const report = readReport(document, issues);
@@ -1400,4 +1805,4 @@ function activeOutputMode() {
1400
1805
  return activeMode;
1401
1806
  }
1402
1807
 
1403
- export { hubContextOf, PREREQUISITE_KINDS, requiredPrerequisite, optionalPrerequisite, MODULE_SOURCE_KINDS, pinKey, pinLine, collisionMessage, readItemBytes, resolveTiers, findTierItem, DEFAULT_ROUTES, DEFAULT_ROUTING, CONFIG_FILE, CONFIG_DEFAULTS, SETTINGS, ConfigError, configFilePath, parseConfigText, resolveConfig, isStampableStub, planStubFromPrompt, stampPrompt, planStubFromPath, createTextOutput, activeOutput, activeOutputMode, RAFA_BLOCK_KINDS, isRafaBlockKind, readRafaBlocks, REPORT_STATUSES, FINDING_KINDS, FINDING_SIGNALS, FINDING_DOMAINS, CHANGE_LEVELS, parseReport };
1808
+ export { MERGE_METHODS, isMergeMethod, SKILL_TIERS, RAFA_INSTINCTS_PATH, BUNDLED_SKILLS_DIR, isSkillTier, realEntry, bundledBinDirectory, skillTierDirectory, resolveSkillTiers, resolveInstinctScopes, tierExists, TEST_SCOPES, isAgentName, BUDGET_FLAG, parseBudgetUsd, readTestScope, parseTaskDeclaration, stripTaskDeclaration, resolveDeclarationFlags, isMapping, describeValue, messageOf, CONFIG_VERSIONS2, STORE_BACKENDS2, SYNC_STRATEGIES2, BOARD_RELATIONSHIP_MODES2, INJECT_MODES2, OUTPUT_MODES2, CLAUDE_SETTING_SOURCES2, PR_PROVIDERS2, RELEASE_AUTO2, SKILL_RESOLVERS, CLAIMS_STALE_DISABLED, BUSY_TIMEOUT_MIN_MS, BUSY_TIMEOUT_MAX_MS, isBusyTimeoutMs, claimDurationHours, isGitHubLogin, listOf, hubContextOf, PREREQUISITE_KINDS2, requiredPrerequisite, optionalPrerequisite, MODULE_SOURCE_KINDS2, pinKey, pinLine, collisionMessage, readItemBytes, resolveTiers, findTierItem, DEFAULT_ROUTES, DEFAULT_ROUTING, CONFIG_FILE2, CONFIG_DEFAULTS2, SETTINGS, ConfigError2, configFilePath2, parseConfigText2, resolveConfig2, isStampableStub, planStubFromPrompt, stampPrompt, planStubFromPath, createTextOutput, activeOutput, activeOutputMode, RAFA_BLOCK_KINDS2, isRafaBlockKind2, readRafaBlocks2, REPORT_STATUSES2, FINDING_KINDS2, FINDING_SIGNALS2, FINDING_DOMAINS, CHANGE_LEVELS, parseReport2 };