@open-tomato/rafa 0.32.0 → 0.34.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.
Files changed (27) hide show
  1. package/README.md +134 -4
  2. package/dist/bundled/agents/build-error-resolver.md +22 -14
  3. package/dist/bundled/agents/code-reviewer.md +22 -14
  4. package/dist/bundled/agents/loop-implementer.md +22 -8
  5. package/dist/bundled/agents/tdd-guide.md +23 -15
  6. package/dist/bundled/operators/agents/rafa-stretch-engineer.md +177 -0
  7. package/dist/bundled/operators/agents/rafa-stretch-watchtower.md +91 -0
  8. package/dist/bundled/operators/skills/rafa-stretch-gap-log/SKILL.md +72 -0
  9. package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +77 -0
  10. package/dist/bundled/operators/skills/rafa-stretch-sweep/SKILL.md +111 -0
  11. package/dist/bundled/skills/dev-planner/SKILL.md +22 -4
  12. package/dist/bundled/skills/git-workflow/SKILL.md +1 -1
  13. package/dist/cli.js +4495 -1789
  14. package/dist/{describe-d31jy6dk.js → describe-5hqfwbjc.js} +3 -3
  15. package/dist/effort/store/index.js +24 -4
  16. package/dist/{index-mt6hpsry.js → index-3mzw3kzh.js} +2 -2
  17. package/dist/{index-qgayjcym.js → index-4b3m7s0z.js} +7148 -4603
  18. package/dist/{index-22stnzde.js → index-b8t7q5hc.js} +666 -1137
  19. package/dist/{index-wvm2s4pr.js → index-bvfbfa63.js} +699 -132
  20. package/dist/{index-rs79dq9e.js → index-fzhd3d4y.js} +22 -4
  21. package/dist/{index-5tftj69y.js → index-k6sd4ym5.js} +2 -2
  22. package/dist/{index-pbeyv281.js → index-v8d7c6sw.js} +2 -2
  23. package/dist/{index-9aph6ft9.js → index-vp0xghk2.js} +167 -5
  24. package/dist/index.js +27 -7
  25. package/dist/plan/index.js +3 -3
  26. package/dist/plan-prompt.md +12 -0
  27. package/package.json +5 -2
@@ -80,7 +80,8 @@ var DECLARATION_KEYS = [
80
80
  "effort",
81
81
  "budget",
82
82
  "tools",
83
- "skills"
83
+ "skills",
84
+ "tests"
84
85
  ];
85
86
  var GRANULAR_KEYS = ["model", "effort", "tools"];
86
87
  var AGENT_OWNED_KEYS = ["model", "tools"];
@@ -92,6 +93,8 @@ var EFFORT_LEVELS = [
92
93
  "xhigh",
93
94
  "max"
94
95
  ];
96
+ var TEST_SCOPES = ["affected", "module", "full"];
97
+ var DEFAULT_TEST_SCOPE = "affected";
95
98
  var DECLARATION_BLOCK = /\{([^{}]*)\}$/;
96
99
  var ENTRY_TOKEN = /^([A-Za-z_][A-Za-z0-9_-]*)=(.*)$/;
97
100
  var FULL_MODEL_NAME = /^claude-[a-z0-9][a-z0-9.-]*$/;
@@ -112,6 +115,12 @@ function parseBudgetUsd(value) {
112
115
  function isEffortLevel(value) {
113
116
  return EFFORT_LEVELS.includes(value);
114
117
  }
118
+ function isTestScope(value) {
119
+ return TEST_SCOPES.includes(value);
120
+ }
121
+ function readTestScope(declaration) {
122
+ return declaration?.tests ?? DEFAULT_TEST_SCOPE;
123
+ }
115
124
  function isModelValue(value) {
116
125
  if (MODEL_ALIASES.includes(value))
117
126
  return true;
@@ -166,6 +175,7 @@ function readBlock(raw, body) {
166
175
  let budget = null;
167
176
  let tools = null;
168
177
  let skills = null;
178
+ let tests = null;
169
179
  for (const token of tokenise(body)) {
170
180
  const match = token.match(ENTRY_TOKEN);
171
181
  const key = match?.[1];
@@ -222,6 +232,13 @@ function readBlock(raw, body) {
222
232
  tools = parsed;
223
233
  continue;
224
234
  }
235
+ if (key === "tests") {
236
+ if (isTestScope(value))
237
+ tests = value;
238
+ else
239
+ issues.push(unusableValue(key, token));
240
+ continue;
241
+ }
225
242
  const named = parseSkillList(value);
226
243
  if (named === null)
227
244
  issues.push(unusableValue(key, token));
@@ -240,7 +257,8 @@ function readBlock(raw, body) {
240
257
  effort,
241
258
  budget,
242
259
  tools,
243
- skills
260
+ skills,
261
+ tests
244
262
  };
245
263
  }
246
264
  function parseTaskDeclaration(taskText) {
@@ -315,7 +333,7 @@ var STORE_BACKENDS = ["sqlite", "ndjson"];
315
333
  var SYNC_STRATEGIES = ["local", "file", "git", "service", "p2p"];
316
334
  var BOARD_RELATIONSHIP_MODES = ["labels", "native"];
317
335
  var INJECT_MODES = ["full", "stage", "task"];
318
- var OUTPUT_MODES = ["text", "json"];
336
+ var OUTPUT_MODES = ["text", "json", "events"];
319
337
  var CLAUDE_SETTING_SOURCES = ["user", "project", "local"];
320
338
  var PR_PROVIDERS = ["gh", "none"];
321
339
  var RELEASE_AUTO = "auto";
@@ -425,4 +443,4 @@ function subsetOf(values) {
425
443
  };
426
444
  }
427
445
 
428
- 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, SYNC_STRATEGIES, BOARD_RELATIONSHIP_MODES, INJECT_MODES, OUTPUT_MODES, CLAUDE_SETTING_SOURCES, PR_PROVIDERS, RELEASE_AUTO, SKILL_RESOLVERS, CLAIMS_STALE_DISABLED, refused, refusedWith, mapReading, below, oneOf, text, flag, mergeMethod, usdAmount, issueNumber, dayCount, BUSY_TIMEOUT_MIN_MS, BUSY_TIMEOUT_MAX_MS, isBusyTimeoutMs, busyTimeoutMs, confidence, recurrenceCount, releaseEnabled, tierSwitch, tierPin, routeTarget, skillResolverName, lessonSwitch, claimDurationHours, claimsStaleAfter, claimsAhead, isGitHubLogin, githubLogin, listOf, subsetOf };
446
+ 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_VERSIONS, STORE_BACKENDS, SYNC_STRATEGIES, BOARD_RELATIONSHIP_MODES, INJECT_MODES, OUTPUT_MODES, CLAUDE_SETTING_SOURCES, PR_PROVIDERS, RELEASE_AUTO, SKILL_RESOLVERS, CLAIMS_STALE_DISABLED, refused, refusedWith, mapReading, below, oneOf, text, flag, mergeMethod, usdAmount, issueNumber, dayCount, BUSY_TIMEOUT_MIN_MS, BUSY_TIMEOUT_MAX_MS, isBusyTimeoutMs, busyTimeoutMs, confidence, recurrenceCount, releaseEnabled, tierSwitch, tierPin, routeTarget, skillResolverName, lessonSwitch, claimDurationHours, claimsStaleAfter, claimsAhead, isGitHubLogin, githubLogin, listOf, subsetOf };
@@ -4,10 +4,10 @@ import {
4
4
  commandSpelling,
5
5
  isRoutingWord,
6
6
  isTopLevel
7
- } from "./index-mt6hpsry.js";
7
+ } from "./index-3mzw3kzh.js";
8
8
  import {
9
9
  describeValue
10
- } from "./index-rs79dq9e.js";
10
+ } from "./index-fzhd3d4y.js";
11
11
 
12
12
  // src/cli/registry.ts
13
13
  var REFUSAL = "command registry";
@@ -3,11 +3,11 @@ import {
3
3
  activeOutput,
4
4
  isStampableStub,
5
5
  readRafaBlocks
6
- } from "./index-9aph6ft9.js";
6
+ } from "./index-vp0xghk2.js";
7
7
  import {
8
8
  messageOf,
9
9
  parseTaskDeclaration
10
- } from "./index-rs79dq9e.js";
10
+ } from "./index-fzhd3d4y.js";
11
11
  // src/preflight/prerequisites-md.ts
12
12
  import { basename, dirname, join } from "path";
13
13
  var SECTION_AUTO_RE = /\[auto\]/i;
@@ -39,7 +39,7 @@ import {
39
39
  tierPin,
40
40
  tierSwitch,
41
41
  usdAmount
42
- } from "./index-rs79dq9e.js";
42
+ } from "./index-fzhd3d4y.js";
43
43
 
44
44
  // src/config-items.ts
45
45
  var itemText = text("a non-empty string");
@@ -172,6 +172,61 @@ var fragmentsDirectory = (raw, at) => {
172
172
  return { value: undefined, problems: [problem], extras: [] };
173
173
  };
174
174
 
175
+ // src/config-schema-hub.ts
176
+ var HUB_TIMEOUT_MIN_SECONDS = 1;
177
+ var HUB_TIMEOUT_MAX_SECONDS = 30;
178
+ var MS_PER_SECOND = 1000;
179
+ var HUB_TIMEOUT = /^(\d+)s$/;
180
+ var HUB_URL_PROTOCOLS = Object.freeze(["http:", "https:"]);
181
+ var HUB_DEFAULTS = Object.freeze({
182
+ hubUrl: null,
183
+ hubTokenSecret: null,
184
+ hubTimeout: "3s"
185
+ });
186
+ function hubTimeoutMs(raw) {
187
+ const match = typeof raw === "string" ? HUB_TIMEOUT.exec(raw) : null;
188
+ if (match === null)
189
+ return null;
190
+ const seconds = Number(match[1]);
191
+ return seconds >= HUB_TIMEOUT_MIN_SECONDS && seconds <= HUB_TIMEOUT_MAX_SECONDS ? seconds * MS_PER_SECOND : null;
192
+ }
193
+ var hubTimeout = (raw, at) => hubTimeoutMs(raw) === null ? refused(at, raw, `a duration of whole seconds from ${String(HUB_TIMEOUT_MIN_SECONDS)}s to ${String(HUB_TIMEOUT_MAX_SECONDS)}s, such as 3s`) : { value: raw, problems: [], extras: [] };
194
+ function isHubUrl(raw) {
195
+ if (typeof raw !== "string" || raw.trim() !== raw)
196
+ return false;
197
+ const url = URL.parse(raw);
198
+ return url !== null && HUB_URL_PROTOCOLS.includes(url.protocol) && url.username === "" && url.password === "";
199
+ }
200
+ var hubUrl = (raw, at) => isHubUrl(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, "an http or https URL with no user name or password, such as https://hub.example.org");
201
+ var HUB_SETTINGS = {
202
+ hubUrl: { key: "hub.url", read: hubUrl, cli: false },
203
+ hubTokenSecret: { key: "hub.tokenSecret", read: text("a secret store name"), cli: false },
204
+ hubTimeout: { key: "hub.timeout", read: hubTimeout, cli: false }
205
+ };
206
+ var HUB_STRATEGY = "service";
207
+ function labelOf(input) {
208
+ const path = input.effortSyncSource === "user" ? input.paths.user : input.paths.file;
209
+ return path ?? input.effortSyncSource;
210
+ }
211
+ function hubUrlProblems(input) {
212
+ if (input.effortSync !== HUB_STRATEGY || input.hubUrl !== null)
213
+ return [];
214
+ return [
215
+ `${labelOf(input)}: effort.sync is ${describeValue(HUB_STRATEGY)} and no config file names hub.url;` + " expected hub.url, the address of the hub, such as https://hub.example.org"
216
+ ];
217
+ }
218
+ function hubContextOf(config) {
219
+ const url = config.hubUrl ?? null;
220
+ if (url === null)
221
+ return;
222
+ const timeout = config.hubTimeout ?? HUB_DEFAULTS.hubTimeout;
223
+ const timeoutMs = hubTimeoutMs(timeout);
224
+ if (timeoutMs === null) {
225
+ throw new TypeError(`hub.timeout is ${describeValue(timeout)}, which no config accepts`);
226
+ }
227
+ return Object.freeze({ url, tokenSecret: config.hubTokenSecret ?? null, timeoutMs });
228
+ }
229
+
175
230
  // src/config-schema-release.ts
176
231
  var PR_DEFAULTS = Object.freeze({
177
232
  prProvider: null,
@@ -240,6 +295,78 @@ var DANGEROUS_RELEASE_SETTINGS = {
240
295
  }
241
296
  };
242
297
 
298
+ // src/config-schema-tests.ts
299
+ import { isAbsolute as isAbsolute2 } from "path";
300
+ var GLOB_PATTERN = "a glob pattern relative to the repository root";
301
+ var repoGlob = (raw, at) => typeof raw === "string" && isAbsolute2(raw) ? refused(at, raw, GLOB_PATTERN) : text(GLOB_PATTERN)(raw, at);
302
+ var globList = listOf(repoGlob, "glob patterns");
303
+ var TESTS_DEFAULTS = Object.freeze({
304
+ testsFullSuiteTriggers: Object.freeze([
305
+ "bunfig.toml",
306
+ "tsconfig*.json",
307
+ "package.json",
308
+ "bun.lock",
309
+ "bun.lockb"
310
+ ]),
311
+ testsIntegration: Object.freeze([
312
+ "**/*-integration.test.ts",
313
+ "**/*.integration.test.ts",
314
+ "**/*-spawned*.test.ts",
315
+ "**/*-cli.test.ts"
316
+ ])
317
+ });
318
+ var TESTS_SETTINGS = {
319
+ testsFullSuiteTriggers: {
320
+ key: "tests.fullSuiteTriggers",
321
+ read: globList,
322
+ cli: false
323
+ },
324
+ testsIntegration: { key: "tests.integration", read: globList, cli: false }
325
+ };
326
+
327
+ // src/config-schema-triage.ts
328
+ var SIMILARITY_THRESHOLD_MAX = 1;
329
+ var SIMILARITY_CANDIDATES_MIN = 1;
330
+ var SIMILARITY_CANDIDATES_MAX = 10;
331
+ function isThreshold(raw) {
332
+ return typeof raw === "number" && Number.isFinite(raw) && raw > 0 && raw <= SIMILARITY_THRESHOLD_MAX;
333
+ }
334
+ function isCandidateCount(raw) {
335
+ return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= SIMILARITY_CANDIDATES_MIN && raw <= SIMILARITY_CANDIDATES_MAX;
336
+ }
337
+ var similarityThreshold = (raw, at) => raw === false || isThreshold(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, `false or a number above 0 and at most ${String(SIMILARITY_THRESHOLD_MAX)}`);
338
+ var similarityCandidates = (raw, at) => isCandidateCount(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, `a whole number from ${String(SIMILARITY_CANDIDATES_MIN)} to ${String(SIMILARITY_CANDIDATES_MAX)}`);
339
+ var TRIAGE_DEFAULTS = Object.freeze({
340
+ triageSimilarityThreshold: 0.3,
341
+ triageSimilarityCandidates: 3
342
+ });
343
+ var TRIAGE_SETTINGS = {
344
+ triageSimilarityThreshold: {
345
+ key: "triage.similarity.threshold",
346
+ read: similarityThreshold,
347
+ cli: false
348
+ },
349
+ triageSimilarityCandidates: {
350
+ key: "triage.similarity.candidates",
351
+ read: similarityCandidates,
352
+ cli: false
353
+ }
354
+ };
355
+
356
+ // src/config-schema-wrap-up.ts
357
+ var WRAP_UP_RETRIES_MIN = 1;
358
+ var WRAP_UP_RETRIES_MAX = 3;
359
+ function isRetryCount(raw) {
360
+ return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= WRAP_UP_RETRIES_MIN && raw <= WRAP_UP_RETRIES_MAX;
361
+ }
362
+ var wrapUpRetries = (raw, at) => raw === false || isRetryCount(raw) ? { value: raw, problems: [], extras: [] } : refused(at, raw, `false or a whole number from ${String(WRAP_UP_RETRIES_MIN)} to ${String(WRAP_UP_RETRIES_MAX)}`);
363
+ var WRAP_UP_DEFAULTS = Object.freeze({
364
+ loopWrapUpRetries: 1
365
+ });
366
+ var WRAP_UP_SETTINGS = {
367
+ loopWrapUpRetries: { key: "loop.wrapUp.retries", read: wrapUpRetries, cli: false }
368
+ };
369
+
243
370
  // src/tiers/resolve.ts
244
371
  import { readFileSync } from "fs";
245
372
  var VENDORED_HEADER = /^<!-- vendored by rafa from .* on \d{4}-\d{2}-\d{2} -->$/;
@@ -411,6 +538,7 @@ var CONFIG_DEFAULTS = Object.freeze({
411
538
  store: "sqlite",
412
539
  effortBusyTimeoutMs: 5000,
413
540
  effortSync: "local",
541
+ ...HUB_DEFAULTS,
414
542
  inject: "stage",
415
543
  planDir: join(".rafa", "plans"),
416
544
  specsDir: join(".rafa", "specs"),
@@ -430,12 +558,14 @@ var CONFIG_DEFAULTS = Object.freeze({
430
558
  allowList: Object.freeze([]),
431
559
  settingSources: Object.freeze(["project", "local"]),
432
560
  loopWorktreeDir: join(".rafa", "worktrees"),
561
+ ...WRAP_UP_DEFAULTS,
433
562
  ...PR_DEFAULTS,
434
563
  boardTrustedAuthors: Object.freeze([]),
435
564
  boardRelationships: "labels",
436
565
  roadmapIssue: null,
437
566
  claimsStaleAfter: "3d",
438
567
  claimsAhead: "off",
568
+ ...TRIAGE_DEFAULTS,
439
569
  ...RELEASE_DEFAULTS,
440
570
  cleanupStaleDays: 30,
441
571
  cleanupWorktreeIdleDays: 7,
@@ -449,13 +579,15 @@ var CONFIG_DEFAULTS = Object.freeze({
449
579
  tiersAgents: new Map,
450
580
  routing: DEFAULT_ROUTING,
451
581
  taskSkills: "planner",
452
- taskLessons: "on"
582
+ taskLessons: "on",
583
+ ...TESTS_DEFAULTS
453
584
  });
454
585
  var SETTINGS = {
455
586
  version: { key: "version", read: oneOf(CONFIG_VERSIONS), cli: false },
456
587
  store: { key: "store", read: oneOf(STORE_BACKENDS), cli: true },
457
588
  effortBusyTimeoutMs: { key: "effort.busyTimeoutMs", read: busyTimeoutMs, cli: false },
458
589
  effortSync: { key: "effort.sync", read: oneOf(SYNC_STRATEGIES), cli: false },
590
+ ...HUB_SETTINGS,
459
591
  inject: { key: "plan.inject", read: oneOf(INJECT_MODES), cli: true },
460
592
  planDir: { key: "plan.dir", read: directory, cli: true },
461
593
  specsDir: { key: "specs.dir", read: directory, cli: true },
@@ -506,6 +638,7 @@ var SETTINGS = {
506
638
  cli: true
507
639
  },
508
640
  loopWorktreeDir: { key: "loop.worktreeDir", read: directory, cli: false },
641
+ ...WRAP_UP_SETTINGS,
509
642
  ...PR_SETTINGS,
510
643
  boardTrustedAuthors: {
511
644
  key: "board.trustedAuthors",
@@ -520,6 +653,7 @@ var SETTINGS = {
520
653
  roadmapIssue: { key: "roadmap.issue", read: issueNumber, cli: false },
521
654
  claimsStaleAfter: { key: "claims.staleAfter", read: claimsStaleAfter, cli: false },
522
655
  claimsAhead: { key: "claims.ahead", read: claimsAhead, cli: false },
656
+ ...TRIAGE_SETTINGS,
523
657
  ...RELEASE_SETTINGS,
524
658
  cleanupStaleDays: { key: "cleanup.staleDays", read: dayCount, cli: false },
525
659
  cleanupWorktreeIdleDays: {
@@ -549,7 +683,8 @@ var SETTINGS = {
549
683
  tiersAgents: { key: "tiers.agents", read: tierPins, cli: false },
550
684
  routing: { key: "routing", read: routeTable, cli: false },
551
685
  taskSkills: { key: "task.skills", read: skillResolverName, cli: true },
552
- taskLessons: { key: "task.lessons", read: lessonSwitch, cli: false }
686
+ taskLessons: { key: "task.lessons", read: lessonSwitch, cli: false },
687
+ ...TESTS_SETTINGS
553
688
  };
554
689
  var SETTING_NAMES = Object.keys(SETTINGS);
555
690
  var SETTING_BY_KEY = new Map(SETTING_NAMES.map((setting) => [
@@ -621,6 +756,9 @@ function readLayer(rawOf, atOf) {
621
756
  store: read("store"),
622
757
  effortBusyTimeoutMs: read("effortBusyTimeoutMs"),
623
758
  effortSync: read("effortSync"),
759
+ hubUrl: read("hubUrl"),
760
+ hubTokenSecret: read("hubTokenSecret"),
761
+ hubTimeout: read("hubTimeout"),
624
762
  inject: read("inject"),
625
763
  planDir: read("planDir"),
626
764
  specsDir: read("specsDir"),
@@ -640,6 +778,7 @@ function readLayer(rawOf, atOf) {
640
778
  allowList: read("allowList"),
641
779
  settingSources: read("settingSources"),
642
780
  loopWorktreeDir: read("loopWorktreeDir"),
781
+ loopWrapUpRetries: read("loopWrapUpRetries"),
643
782
  prProvider: read("prProvider"),
644
783
  prMergeMethod: read("prMergeMethod"),
645
784
  prBase: read("prBase"),
@@ -650,6 +789,8 @@ function readLayer(rawOf, atOf) {
650
789
  roadmapIssue: read("roadmapIssue"),
651
790
  claimsStaleAfter: read("claimsStaleAfter"),
652
791
  claimsAhead: read("claimsAhead"),
792
+ triageSimilarityThreshold: read("triageSimilarityThreshold"),
793
+ triageSimilarityCandidates: read("triageSimilarityCandidates"),
653
794
  releaseEnabled: read("releaseEnabled"),
654
795
  releaseVersionFile: read("releaseVersionFile"),
655
796
  releaseChangelog: read("releaseChangelog"),
@@ -671,7 +812,9 @@ function readLayer(rawOf, atOf) {
671
812
  tiersAgents: read("tiersAgents"),
672
813
  routing: read("routing"),
673
814
  taskSkills: read("taskSkills"),
674
- taskLessons: read("taskLessons")
815
+ taskLessons: read("taskLessons"),
816
+ testsFullSuiteTriggers: read("testsFullSuiteTriggers"),
817
+ testsIntegration: read("testsIntegration")
675
818
  };
676
819
  return { layer, problems, extras };
677
820
  }
@@ -711,7 +854,14 @@ function sortKeys(document, path) {
711
854
  }
712
855
  return { named, extras, problems };
713
856
  }
857
+ 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`] : []);
860
+ }
714
861
  function parseYaml(text2, path) {
862
+ const tabProblems = tabIndentProblems(text2, path);
863
+ if (tabProblems.length > 0)
864
+ throw new ConfigError(tabProblems);
715
865
  try {
716
866
  return Bun.YAML.parse(text2);
717
867
  } catch (error) {
@@ -793,6 +943,15 @@ function resolveConfig(layers = {}) {
793
943
  return { value: CONFIG_DEFAULTS[setting], source: "default" };
794
944
  };
795
945
  const ranked = SETTING_NAMES.map((setting) => [setting, rank(setting)]);
946
+ const effortSync = rank("effortSync");
947
+ const hubProblems = hubUrlProblems({
948
+ effortSync: effortSync.value,
949
+ hubUrl: rank("hubUrl").value,
950
+ effortSyncSource: effortSync.source,
951
+ paths: { file: file?.path ?? null, user: user?.path ?? null }
952
+ });
953
+ if (hubProblems.length > 0)
954
+ throw new ConfigError(hubProblems);
796
955
  const rafaLoaded = ranked.find(([setting]) => setting === "tiersRafa")?.[1].value !== "off";
797
956
  const warnings = [user, file].flatMap((layer) => layer === null ? [] : [
798
957
  ...layer.extras.map((extra) => unknownKeyWarning(extra.key, layer.path)),
@@ -1222,6 +1381,9 @@ function createTextOutput({ verbosity, stream }) {
1222
1381
  writeLine(resultLine(event));
1223
1382
  return;
1224
1383
  }
1384
+ case "event": {
1385
+ return;
1386
+ }
1225
1387
  }
1226
1388
  };
1227
1389
  return Object.freeze({ info, warn, error, debug, emit, result });
@@ -1238,4 +1400,4 @@ function activeOutputMode() {
1238
1400
  return activeMode;
1239
1401
  }
1240
1402
 
1241
- export { 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 };
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 };
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  start,
11
11
  usage,
12
12
  validateManifest
13
- } from "./index-qgayjcym.js";
13
+ } from "./index-4b3m7s0z.js";
14
14
  import {
15
15
  PLAN_BLOCK_KINDS,
16
16
  PLAN_HEADER_FIELDS,
@@ -24,7 +24,7 @@ import {
24
24
  renderInjection,
25
25
  runPreflight,
26
26
  runShellProbe
27
- } from "./index-pbeyv281.js";
27
+ } from "./index-v8d7c6sw.js";
28
28
  import {
29
29
  CORE_ADAPTER_REGISTRY,
30
30
  DISK_FILE_SYSTEM,
@@ -33,9 +33,19 @@ import {
33
33
  PORT_VERSIONS,
34
34
  SCOPE_DIR,
35
35
  ScopeError,
36
+ TRUSTED_PERMISSIONS,
37
+ WIRE_FORMAT,
38
+ WIRE_VERSION,
39
+ WireExportRefusal,
40
+ WireFormatError,
36
41
  createAdapterRegistry,
42
+ decodeWirePayload,
43
+ encodeWirePayload,
44
+ exportWirePayload,
37
45
  initHint,
38
46
  loadConfig,
47
+ materialiseWirePayload,
48
+ mergeStore,
39
49
  openNdjsonStore,
40
50
  openSqliteStore,
41
51
  readConfigFile,
@@ -43,7 +53,7 @@ import {
43
53
  scopeAt,
44
54
  selectEffortStore,
45
55
  selfAndAncestors
46
- } from "./index-wvm2s4pr.js";
56
+ } from "./index-bvfbfa63.js";
47
57
  import {
48
58
  CONFIG_DEFAULTS,
49
59
  CONFIG_FILE,
@@ -60,10 +70,10 @@ import {
60
70
  parseReport,
61
71
  readRafaBlocks,
62
72
  resolveConfig
63
- } from "./index-9aph6ft9.js";
73
+ } from "./index-vp0xghk2.js";
64
74
  import"./index-d6d0942q.js";
65
- import"./index-5tftj69y.js";
66
- import"./index-mt6hpsry.js";
75
+ import"./index-k6sd4ym5.js";
76
+ import"./index-3mzw3kzh.js";
67
77
  import {
68
78
  BOARD_RELATIONSHIP_MODES,
69
79
  CLAUDE_SETTING_SOURCES,
@@ -74,7 +84,7 @@ import {
74
84
  RELEASE_AUTO,
75
85
  STORE_BACKENDS,
76
86
  SYNC_STRATEGIES
77
- } from "./index-rs79dq9e.js";
87
+ } from "./index-fzhd3d4y.js";
78
88
  import"./index-wp8c28fd.js";
79
89
  export {
80
90
  validateManifest,
@@ -99,15 +109,25 @@ export {
99
109
  parseConfigText,
100
110
  openSqliteStore,
101
111
  openNdjsonStore,
112
+ mergeStore,
102
113
  mergePlanPrerequisites,
114
+ materialiseWirePayload,
103
115
  loadPlanPrerequisites,
104
116
  loadConfig,
105
117
  isRafaBlockKind,
106
118
  initHint,
119
+ exportWirePayload,
120
+ encodeWirePayload,
107
121
  report as effortReportCommand,
108
122
  collect as effortCollectCommand,
123
+ decodeWirePayload,
109
124
  createAdapterRegistry,
110
125
  configFilePath,
126
+ WireFormatError,
127
+ WireExportRefusal,
128
+ WIRE_VERSION,
129
+ WIRE_FORMAT,
130
+ TRUSTED_PERMISSIONS,
111
131
  ScopeError,
112
132
  SYNC_STRATEGIES,
113
133
  STORE_BACKENDS,
@@ -12,7 +12,7 @@ import {
12
12
  renderInjection,
13
13
  runPreflight,
14
14
  runShellProbe
15
- } from "../index-pbeyv281.js";
15
+ } from "../index-v8d7c6sw.js";
16
16
  import {
17
17
  FINDING_KINDS,
18
18
  FINDING_SIGNALS,
@@ -21,10 +21,10 @@ import {
21
21
  isRafaBlockKind,
22
22
  parseReport,
23
23
  readRafaBlocks
24
- } from "../index-9aph6ft9.js";
24
+ } from "../index-vp0xghk2.js";
25
25
  import {
26
26
  INJECT_MODES
27
- } from "../index-rs79dq9e.js";
27
+ } from "../index-fzhd3d4y.js";
28
28
  import"../index-wp8c28fd.js";
29
29
  export {
30
30
  runShellProbe,
@@ -24,6 +24,18 @@ on the `open-tomato/rafa` board.
24
24
  `RafaCommand` — see the dev-planner skill's "Command-development rule" for
25
25
  guidance.
26
26
 
27
+ * Size each task's suite run with the `tests=` declaration key (the
28
+ dev-planner skill's `tests=` section). Leave it off where the task's
29
+ own diff reaches the tests that could break, which the `affected`
30
+ default covers. Write `tests=module` on a task whose change other
31
+ modules consume through their own tests: an integration or spawned
32
+ test task, a change to a shared type, a reader or a module many
33
+ callers import. Write `tests=full` on a task whose change can break a
34
+ test that imports none of its files: test preloads, `bunfig.toml`,
35
+ `tsconfig*.json`, `package.json` or the lockfile, global state or
36
+ environment every test inherits, and a stage's closing cross-module
37
+ test task.
38
+
27
39
  * Before planning, review the spec as written, and report that review at the
28
40
  END of your final message as a `rafa:spec-review` block carrying
29
41
  `verdict: ready` or `verdict: not-ready`, with empty `gaps:` for ready, or a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-tomato/rafa",
3
- "version": "0.32.0",
3
+ "version": "0.34.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": {
@@ -28,6 +28,9 @@
28
28
  "author": "Marcos Tomatti <marcos@opentomato.io>",
29
29
  "packageManager": "bun@1.3.14",
30
30
  "type": "module",
31
+ "workspaces": [
32
+ "packages/*"
33
+ ],
31
34
  "module": "./dist/index.js",
32
35
  "bin": {
33
36
  "rafa": "./dist/cli.js"
@@ -52,7 +55,7 @@
52
55
  "prepack": "bun run build",
53
56
  "test": "bun test",
54
57
  "lint": "eslint .",
55
- "check-types": "tsc --noEmit",
58
+ "check-types": "tsc --noEmit && bun run --filter './packages/*' check-types",
56
59
  "gate:control-bytes": "bun scripts/control-byte-gate/control-byte-gate.ts",
57
60
  "snapshot": "bun scripts/snapshot-runtime.ts"
58
61
  },