@open-tomato/rafa 0.45.0 → 0.46.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 (140) hide show
  1. package/README.md +255 -23
  2. package/dist/PROMPT.md +18 -1
  3. package/dist/adapters/logger/settings.d.ts +132 -0
  4. package/dist/bugs/closest.d.ts +19 -0
  5. package/dist/bugs/fenced.d.ts +8 -0
  6. package/dist/bugs/places.d.ts +20 -0
  7. package/dist/bugs/record.d.ts +145 -0
  8. package/dist/bugs/title.d.ts +83 -0
  9. package/dist/bundled/agents/doc-updater.md +17 -3
  10. package/dist/bundled/agents/loop-implementer.md +14 -2
  11. package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +10 -3
  12. package/dist/bundled/operators/skills/rafa-stretch-sweep/SKILL.md +5 -0
  13. package/dist/bundled/skills/dev-planner/SKILL.md +101 -18
  14. package/dist/cli.js +74726 -62960
  15. package/dist/config/entry.d.ts +119 -0
  16. package/dist/config/index.d.ts +36 -0
  17. package/dist/config/index.js +51 -0
  18. package/dist/config/shape.d.ts +232 -0
  19. package/dist/config-registry.d.ts +127 -0
  20. package/dist/config-schema-board-project.d.ts +157 -0
  21. package/dist/config-schema-bugs.d.ts +71 -0
  22. package/dist/config-schema-errors.d.ts +54 -0
  23. package/dist/config-schema-features.d.ts +64 -0
  24. package/dist/config-schema-hub.d.ts +150 -0
  25. package/dist/config-schema-issues.d.ts +95 -0
  26. package/dist/config-schema-logger.d.ts +91 -0
  27. package/dist/config-schema-loop-continue.d.ts +122 -0
  28. package/dist/config-schema-loop-retries.d.ts +94 -0
  29. package/dist/config-schema-release.d.ts +307 -0
  30. package/dist/config-schema-tests.d.ts +170 -0
  31. package/dist/config-schema-triage.d.ts +142 -0
  32. package/dist/config-schema-wrap-up.d.ts +96 -0
  33. package/dist/core/command/command.d.ts +228 -0
  34. package/dist/core/command/confirm.d.ts +67 -0
  35. package/dist/core/command/index.d.ts +112 -0
  36. package/dist/core/command/lazy.d.ts +54 -0
  37. package/dist/core/command/registry-types.d.ts +96 -0
  38. package/dist/core/command/running.d.ts +96 -0
  39. package/dist/core/command/spends.d.ts +39 -0
  40. package/dist/core/command/types.d.ts +92 -0
  41. package/dist/core/command/version.d.ts +4 -0
  42. package/dist/core/config/branch-template.d.ts +20 -0
  43. package/dist/core/config/config-items.d.ts +86 -0
  44. package/dist/core/config/config-load.d.ts +47 -0
  45. package/dist/core/config/config-origins.d.ts +57 -0
  46. package/dist/core/config/config-readers.d.ts +167 -0
  47. package/dist/core/config/config-schema.d.ts +207 -0
  48. package/dist/core/config/config-sections.d.ts +493 -0
  49. package/dist/core/config/config.d.ts +320 -0
  50. package/dist/core/config/core-section.d.ts +39 -0
  51. package/dist/core/config/dangerous.d.ts +58 -0
  52. package/dist/core/config/default-routing.d.ts +16 -0
  53. package/dist/core/config/index.d.ts +141 -0
  54. package/dist/core/config/scope.d.ts +42 -0
  55. package/dist/core/config/section.d.ts +206 -0
  56. package/dist/core/config/sections.d.ts +45 -0
  57. package/dist/core/config/standard-schema.d.ts +27 -0
  58. package/dist/core/git/commit.d.ts +232 -0
  59. package/dist/core/git/gh-runner.d.ts +24 -0
  60. package/dist/core/git/git.d.ts +22 -0
  61. package/dist/core/git/index.d.ts +85 -0
  62. package/dist/core/loop/claude.d.ts +388 -0
  63. package/dist/core/loop/hop-record.d.ts +52 -0
  64. package/dist/core/loop/index.d.ts +179 -0
  65. package/dist/core/loop/session-env.d.ts +20 -0
  66. package/dist/core/loop/session-record-parse.d.ts +63 -0
  67. package/dist/core/loop/sessions.d.ts +408 -0
  68. package/dist/core/loop/suite-failure.d.ts +25 -0
  69. package/dist/core/output/active.d.ts +100 -0
  70. package/dist/core/output/stream.d.ts +20 -0
  71. package/dist/core/output/text.d.ts +55 -0
  72. package/dist/core/plan/block-reader.d.ts +46 -0
  73. package/dist/core/plan/blocks.d.ts +139 -0
  74. package/dist/core/plan/declaration.d.ts +366 -0
  75. package/dist/core/plan/plan-stamp.d.ts +75 -0
  76. package/dist/core/runtime/identity.d.ts +21 -0
  77. package/dist/core/runtime/index.d.ts +46 -0
  78. package/dist/effort/store/bring-forward.d.ts +131 -0
  79. package/dist/effort/store/check-rows.d.ts +31 -0
  80. package/dist/effort/store/commit-stats.d.ts +42 -0
  81. package/dist/effort/store/copy.d.ts +35 -0
  82. package/dist/effort/store/development-build.d.ts +105 -0
  83. package/dist/effort/store/effort-levels.d.ts +13 -0
  84. package/dist/effort/store/findings.d.ts +214 -0
  85. package/dist/effort/store/fix-schema.d.ts +184 -0
  86. package/dist/effort/store/index.js +10 -7
  87. package/dist/effort/store/location.d.ts +44 -0
  88. package/dist/effort/store/merge-commit-gaps.d.ts +68 -0
  89. package/dist/effort/store/merge-conflicts.d.ts +91 -0
  90. package/dist/effort/store/merge-rules.d.ts +82 -0
  91. package/dist/effort/store/merge-store.d.ts +211 -0
  92. package/dist/effort/store/merge-union.d.ts +92 -0
  93. package/dist/effort/store/migrate.d.ts +146 -0
  94. package/dist/effort/store/migrations.d.ts +92 -0
  95. package/dist/effort/store/ndjson-files.d.ts +114 -0
  96. package/dist/effort/store/origins.d.ts +116 -0
  97. package/dist/effort/store/plan-stubs.d.ts +79 -0
  98. package/dist/effort/store/rebuild-aside.d.ts +172 -0
  99. package/dist/effort/store/schema-plan.d.ts +102 -0
  100. package/dist/effort/store/session-row-types.d.ts +64 -0
  101. package/dist/effort/store/settings.d.ts +13 -0
  102. package/dist/effort/store/sqlite.d.ts +340 -0
  103. package/dist/effort/store/store-generation.d.ts +17 -0
  104. package/dist/effort/store/store-identity.d.ts +220 -0
  105. package/dist/effort/store/store-meta.d.ts +305 -0
  106. package/dist/effort/store/store-replaced.d.ts +72 -0
  107. package/dist/effort/store/types.d.ts +223 -0
  108. package/dist/errors/codes.d.ts +56 -0
  109. package/dist/errors/rafa-codes.d.ts +36 -0
  110. package/dist/index-2a7nb3an.js +125 -0
  111. package/dist/{index-r28fzsvc.js → index-39kbcw68.js} +350 -165
  112. package/dist/{index-nv34ptht.js → index-77ajfffn.js} +14 -9
  113. package/dist/index-cy98y87p.js +2597 -0
  114. package/dist/index-gqz4jn6j.js +13447 -0
  115. package/dist/index-gvek4r8m.js +710 -0
  116. package/dist/index-j4k2vdz3.js +1125 -0
  117. package/dist/index-jh1r4kcn.js +1067 -0
  118. package/dist/{index-mgh2s9bj.js → index-ykggr043.js} +58 -455
  119. package/dist/index-z1w83f81.js +4 -0
  120. package/dist/index.js +14715 -21516
  121. package/dist/learning/index.js +5 -6
  122. package/dist/plan/index.js +12 -11
  123. package/dist/plan-prompt.md +3 -1
  124. package/dist/ports/index.d.ts +732 -0
  125. package/dist/ports/learning.d.ts +101 -0
  126. package/dist/ports/log-level.d.ts +13 -0
  127. package/dist/ports/spec-review.d.ts +66 -0
  128. package/dist/pr/checks.d.ts +133 -0
  129. package/dist/pr/types.d.ts +422 -0
  130. package/dist/ready-4f8edezt.js +2016 -0
  131. package/dist/release-templates/release-bot-fragment.yml +153 -0
  132. package/dist/release-templates/release-publish.yml +110 -0
  133. package/dist/release-templates/release-settle.yml +122 -0
  134. package/dist/release-templates/release-tag.yml +102 -0
  135. package/dist/report/parse.d.ts +415 -0
  136. package/dist/schema/project-id.d.ts +79 -0
  137. package/dist/schema/tiers.d.ts +107 -0
  138. package/package.json +41 -3
  139. package/dist/index-hf2k497d.js +0 -16
  140. package/dist/index-nsr78ct2.js +0 -8219
@@ -0,0 +1,710 @@
1
+ // @bun
2
+ import {
3
+ BOARD_PROJECT_TEMPLATE_DEFAULT,
4
+ BOARD_RELATIONSHIP_MODES,
5
+ CLAUDE_SETTING_SOURCES,
6
+ CONFIG_VERSIONS,
7
+ DEFAULT_BRANCH_TEMPLATE,
8
+ INJECT_MODES,
9
+ OUTPUT_MODES,
10
+ STORE_BACKENDS,
11
+ SYNC_STRATEGIES,
12
+ below,
13
+ branchTemplate,
14
+ busyTimeoutMs,
15
+ claimsAhead,
16
+ claimsStaleAfter,
17
+ confidence,
18
+ dayCount,
19
+ describeValue,
20
+ directory,
21
+ duplicatesLevel,
22
+ flag,
23
+ githubLogin,
24
+ isMapping,
25
+ issueNumber,
26
+ lessonSwitch,
27
+ listOf,
28
+ mapReading,
29
+ messageOf,
30
+ oneOf,
31
+ projectNumber,
32
+ projectUrl,
33
+ recurrenceCount,
34
+ refused,
35
+ refusedWith,
36
+ routeTable,
37
+ skillResolverName,
38
+ subsetOf,
39
+ text,
40
+ tierPins,
41
+ tierSwitch,
42
+ trackerKind
43
+ } from "./index-ykggr043.js";
44
+
45
+ // packages/rafa/src/core/config/config-items.ts
46
+ var itemText = text("a non-empty string");
47
+ function readKeyedItem(shape, raw, at) {
48
+ const choices = shape.kinds.join(", ");
49
+ if (!isMapping(raw))
50
+ return refused(at, raw, `a mapping naming one of: ${choices}`);
51
+ const entries = Object.entries(raw);
52
+ const kinds = shape.kinds.filter((kind2) => entries.some(([name]) => name === kind2));
53
+ const [kind] = kinds;
54
+ if (kind === undefined)
55
+ return refusedWith([`${at.label} names none of: ${choices}`]);
56
+ if (kinds.length > 1) {
57
+ const named2 = kinds.join(" and ");
58
+ return refusedWith([`${at.label} names ${named2}, expected exactly one of: ${choices}`]);
59
+ }
60
+ const optionalKeys = shape.optionalFor(kind);
61
+ const problems = [];
62
+ const extras = [];
63
+ const optional = new Map;
64
+ let named;
65
+ for (const [name, value] of entries) {
66
+ if (name !== kind && !optionalKeys.includes(name)) {
67
+ extras.push({ key: `${at.key}.${name}`, value });
68
+ continue;
69
+ }
70
+ if (name !== kind && value === null)
71
+ continue;
72
+ const reading = itemText(value, below(at, `.${name}`));
73
+ problems.push(...reading.problems);
74
+ if (reading.value === undefined)
75
+ continue;
76
+ if (name === kind)
77
+ named = reading.value;
78
+ else
79
+ optional.set(name, reading.value);
80
+ }
81
+ return problems.length > 0 || named === undefined ? { value: undefined, problems, extras } : { value: { kind, named, optional }, problems, extras };
82
+ }
83
+ var PREREQUISITE_KINDS = ["tool", "env", "service", "lsp"];
84
+ var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS, "probe"];
85
+ var OPTIONAL_ITEM_KEYS = [...REQUIRED_ITEM_KEYS, "reason"];
86
+ var requiredPrerequisite = (raw, at) => {
87
+ const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe"] };
88
+ return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
89
+ kind: item.kind,
90
+ name: item.named,
91
+ probe: item.optional.get("probe") ?? null
92
+ }));
93
+ };
94
+ var optionalPrerequisite = (raw, at) => {
95
+ const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe", "reason"] };
96
+ return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
97
+ kind: item.kind,
98
+ name: item.named,
99
+ probe: item.optional.get("probe") ?? null,
100
+ reason: item.optional.get("reason") ?? null
101
+ }));
102
+ };
103
+ var MODULE_SOURCE_KINDS = ["npm", "github", "path"];
104
+ var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS, "ref"];
105
+ var moduleSource = (raw, at) => {
106
+ const shape = {
107
+ kinds: MODULE_SOURCE_KINDS,
108
+ optionalFor: (kind) => kind === "github" ? ["ref"] : []
109
+ };
110
+ return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
111
+ kind: item.kind,
112
+ location: item.named,
113
+ ref: item.optional.get("ref") ?? null
114
+ }));
115
+ };
116
+
117
+ // packages/rafa/src/core/config/core-section.ts
118
+ import { dirname, join } from "path";
119
+
120
+ // packages/rafa/src/core/config/default-routing.ts
121
+ var DEFAULT_ROUTES = Object.freeze([
122
+ Object.freeze(["prose", "doc-updater"]),
123
+ Object.freeze(["tests", "tdd-guide"]),
124
+ Object.freeze(["repair", "build-error-resolver"]),
125
+ Object.freeze(["review", "code-reviewer"]),
126
+ Object.freeze(["implementation", "loop-implementer"])
127
+ ]);
128
+ var DEFAULT_ROUTING = new Map(DEFAULT_ROUTES);
129
+
130
+ // packages/rafa/src/core/config/core-section.ts
131
+ var CONFIG_FILE = join(".rafa", "config.yaml");
132
+ var SCOPE_DIR = dirname(CONFIG_FILE);
133
+ var CORE_PACKAGE = "core";
134
+ var CORE_SPECS = {
135
+ version: { key: "version", read: oneOf(CONFIG_VERSIONS), cli: false },
136
+ store: { key: "store", read: oneOf(STORE_BACKENDS), cli: true },
137
+ effortBusyTimeoutMs: { key: "effort.busyTimeoutMs", read: busyTimeoutMs, cli: false },
138
+ effortSync: { key: "effort.sync", read: oneOf(SYNC_STRATEGIES), cli: false },
139
+ inject: { key: "plan.inject", read: oneOf(INJECT_MODES), cli: true },
140
+ planDir: { key: "plan.dir", read: directory, cli: true },
141
+ specsDir: { key: "specs.dir", read: directory, cli: true },
142
+ trackerDefault: { key: "tracker.default", read: trackerKind, cli: true },
143
+ trackerFallback: {
144
+ key: "tracker.fallback",
145
+ read: listOf(trackerKind, "tracker kind names"),
146
+ cli: false
147
+ },
148
+ learningAdapter: {
149
+ key: "learning.adapter",
150
+ read: text("a learning adapter name"),
151
+ cli: true
152
+ },
153
+ learningBlessMinConfidence: { key: "learning.bless.minConfidence", read: confidence, cli: false },
154
+ learningPromoteAfter: { key: "learning.promote.after", read: recurrenceCount, cli: false },
155
+ learningPromoteMinConfidence: { key: "learning.promote.minConfidence", read: confidence, cli: false },
156
+ outputMode: { key: "output.mode", read: oneOf(OUTPUT_MODES), cli: true },
157
+ prerequisitesRequired: {
158
+ key: "prerequisites.required",
159
+ read: listOf(requiredPrerequisite, "prerequisite items"),
160
+ cli: false,
161
+ itemKeys: REQUIRED_ITEM_KEYS
162
+ },
163
+ prerequisitesOptional: {
164
+ key: "prerequisites.optional",
165
+ read: listOf(optionalPrerequisite, "prerequisite items"),
166
+ cli: false,
167
+ itemKeys: OPTIONAL_ITEM_KEYS
168
+ },
169
+ trackingSpecs: { key: "tracking.specs", read: flag, cli: false },
170
+ trackingPlans: { key: "tracking.plans", read: flag, cli: false },
171
+ trackingAll: { key: "tracking.all", read: flag, cli: false },
172
+ modules: {
173
+ key: "modules",
174
+ read: listOf(moduleSource, "module sources"),
175
+ cli: false,
176
+ itemKeys: MODULE_SOURCE_KEYS
177
+ },
178
+ allowList: {
179
+ key: "allowList",
180
+ read: listOf(text("a module name"), "module names"),
181
+ cli: false
182
+ },
183
+ settingSources: {
184
+ key: "loop.settingSources",
185
+ read: subsetOf(CLAUDE_SETTING_SOURCES),
186
+ cli: true
187
+ },
188
+ loopWorktreeDir: { key: "loop.worktreeDir", read: directory, cli: false },
189
+ boardTrustedAuthors: {
190
+ key: "board.trustedAuthors",
191
+ read: listOf(githubLogin, "GitHub logins"),
192
+ cli: false
193
+ },
194
+ boardRelationships: {
195
+ key: "board.relationships",
196
+ read: oneOf(BOARD_RELATIONSHIP_MODES),
197
+ cli: false
198
+ },
199
+ boardProjectTemplate: { key: "board.project.template", read: projectUrl, cli: false },
200
+ boardProjectNumber: { key: "board.project.number", read: projectNumber, cli: false },
201
+ roadmapIssue: { key: "roadmap.issue", read: issueNumber, cli: false },
202
+ claimsStaleAfter: { key: "claims.staleAfter", read: claimsStaleAfter, cli: false },
203
+ claimsAhead: { key: "claims.ahead", read: claimsAhead, cli: false },
204
+ cleanupStaleDays: { key: "cleanup.staleDays", read: dayCount, cli: false },
205
+ cleanupWorktreeIdleDays: {
206
+ key: "cleanup.worktreeIdleDays",
207
+ read: dayCount,
208
+ cli: false
209
+ },
210
+ cleanupKeep: {
211
+ key: "cleanup.keep",
212
+ read: listOf(text("a glob pattern"), "glob patterns"),
213
+ cli: false
214
+ },
215
+ dangerousAcceptStaleRefs: {
216
+ key: "dangerous.acceptStaleRefs",
217
+ read: flag,
218
+ cli: false
219
+ },
220
+ dangerousSelfUpdateDuringLoop: {
221
+ key: "dangerous.selfUpdateDuringLoop",
222
+ read: flag,
223
+ cli: false
224
+ },
225
+ statusNotice: { key: "status.notice", read: flag, cli: false },
226
+ tiersRafa: { key: "tiers.rafa", read: tierSwitch, cli: false },
227
+ tiersSkills: { key: "tiers.skills", read: tierPins, cli: false, map: true },
228
+ tiersAgents: { key: "tiers.agents", read: tierPins, cli: false, map: true },
229
+ routing: { key: "routing", read: routeTable, cli: false, map: true },
230
+ taskSkills: { key: "task.skills", read: skillResolverName, cli: true },
231
+ taskLessons: { key: "task.lessons", read: lessonSwitch, cli: false },
232
+ mergeDuplicates: { key: "merge.duplicates", read: duplicatesLevel, cli: false },
233
+ namingBranch: { key: "naming.branch", read: branchTemplate, cli: false }
234
+ };
235
+ var CORE_DEFAULTS = Object.freeze({
236
+ version: 1,
237
+ store: "sqlite",
238
+ effortBusyTimeoutMs: 5000,
239
+ effortSync: "local",
240
+ inject: "stage",
241
+ planDir: join(".rafa", "plans"),
242
+ specsDir: join(".rafa", "specs"),
243
+ trackerDefault: "github",
244
+ trackerFallback: Object.freeze(["local"]),
245
+ learningAdapter: "local",
246
+ learningBlessMinConfidence: 0.5,
247
+ learningPromoteAfter: 3,
248
+ learningPromoteMinConfidence: 0.7,
249
+ outputMode: "text",
250
+ prerequisitesRequired: Object.freeze([]),
251
+ prerequisitesOptional: Object.freeze([]),
252
+ trackingSpecs: false,
253
+ trackingPlans: false,
254
+ trackingAll: false,
255
+ modules: Object.freeze([]),
256
+ allowList: Object.freeze([]),
257
+ settingSources: Object.freeze(["project", "local"]),
258
+ loopWorktreeDir: join(".rafa", "worktrees"),
259
+ boardTrustedAuthors: Object.freeze([]),
260
+ boardRelationships: "labels",
261
+ boardProjectTemplate: BOARD_PROJECT_TEMPLATE_DEFAULT,
262
+ boardProjectNumber: null,
263
+ roadmapIssue: null,
264
+ claimsStaleAfter: "3d",
265
+ claimsAhead: "off",
266
+ cleanupStaleDays: 30,
267
+ cleanupWorktreeIdleDays: 7,
268
+ cleanupKeep: Object.freeze([]),
269
+ dangerousAcceptStaleRefs: false,
270
+ dangerousSelfUpdateDuringLoop: false,
271
+ statusNotice: true,
272
+ tiersRafa: "on",
273
+ tiersSkills: new Map,
274
+ tiersAgents: new Map,
275
+ routing: DEFAULT_ROUTING,
276
+ taskSkills: "planner",
277
+ taskLessons: "on",
278
+ mergeDuplicates: "warn",
279
+ namingBranch: DEFAULT_BRANCH_TEMPLATE
280
+ });
281
+ var CORE_SECTION = Object.freeze({
282
+ package: CORE_PACKAGE,
283
+ settings: Object.freeze(CORE_SPECS),
284
+ defaults: CORE_DEFAULTS
285
+ });
286
+
287
+ // packages/rafa/src/core/config/config.ts
288
+ import { join as join2 } from "path";
289
+
290
+ // packages/rafa/src/core/config/config-origins.ts
291
+ function originOf(source, setting, file, user) {
292
+ const layer = source === "file" ? file : source === "user" ? user : null;
293
+ if (layer === null)
294
+ return null;
295
+ return Object.freeze({ file: layer.path, entry: layer.entries?.get(setting) ?? 0 });
296
+ }
297
+
298
+ // packages/rafa/src/core/config/section.ts
299
+ class ConfigSectionError extends Error {
300
+ problems;
301
+ constructor(problems) {
302
+ super(`rafa config sections: ${problems.join("; ")}`);
303
+ this.name = "ConfigSectionError";
304
+ this.problems = problems;
305
+ }
306
+ }
307
+ var EMPTY_CONFIG_REGISTRY = Object.freeze({
308
+ sections: Object.freeze([]),
309
+ settings: Object.freeze({}),
310
+ defaults: Object.freeze({}),
311
+ checks: Object.freeze([])
312
+ });
313
+ var DANGEROUS_PREFIX = "dangerous.";
314
+ function quoted(value) {
315
+ return JSON.stringify(value) ?? String(value);
316
+ }
317
+ function frozenCopy(section) {
318
+ return Object.freeze({
319
+ package: section.package,
320
+ settings: Object.freeze({ ...section.settings }),
321
+ defaults: Object.freeze({ ...section.defaults }),
322
+ checks: Object.freeze([...section.checks ?? []])
323
+ });
324
+ }
325
+ function recordOwners(owners, section) {
326
+ for (const [name, spec] of Object.entries(section.settings)) {
327
+ if (!owners.names.has(name))
328
+ owners.names.set(name, section.package);
329
+ const key = spec?.key;
330
+ if (key !== undefined && !owners.keys.has(key)) {
331
+ owners.keys.set(key, { package: section.package, name });
332
+ }
333
+ }
334
+ }
335
+ function keyCollisionOf(owner, key, name, section) {
336
+ if (owner.name !== name) {
337
+ return `file key ${key} is defined by package ${quoted(owner.package)} under setting ${owner.name}` + ` and again by package ${quoted(section.package)} under setting ${name}`;
338
+ }
339
+ if (key.startsWith(DANGEROUS_PREFIX)) {
340
+ return `${key} is defined by package ${quoted(owner.package)} and again by package ${quoted(section.package)};` + " a dangerous. key is a person's consent and one package defines it";
341
+ }
342
+ return null;
343
+ }
344
+ function collisionsOf(owners, section) {
345
+ return Object.entries(section.settings).flatMap(([name, spec]) => {
346
+ const problems = [];
347
+ const nameOwner = owners.names.get(name);
348
+ if (nameOwner !== undefined) {
349
+ problems.push(`setting ${name} is registered by package ${quoted(nameOwner)}` + ` and again by package ${quoted(section.package)}`);
350
+ }
351
+ const key = spec?.key;
352
+ const keyOwner = key === undefined ? undefined : owners.keys.get(key);
353
+ const keyProblem = key === undefined || keyOwner === undefined ? null : keyCollisionOf(keyOwner, key, name, section);
354
+ if (keyProblem !== null)
355
+ problems.push(keyProblem);
356
+ return problems;
357
+ });
358
+ }
359
+ function unpairedOf(sections) {
360
+ const specified = new Set(sections.flatMap((section) => Object.keys(section.settings)));
361
+ const defaulted = new Set(sections.flatMap((section) => Object.keys(section.defaults)));
362
+ return sections.flatMap((section) => [
363
+ ...Object.keys(section.defaults).filter((name) => !specified.has(name)).map((name) => `package ${quoted(section.package)} gives a default for ${name},` + " a RafaConfig field no section defines a setting for"),
364
+ ...Object.keys(section.settings).filter((name) => !defaulted.has(name)).map((name) => `package ${quoted(section.package)} defines setting ${name},` + " a RafaConfig field no section gives a default for")
365
+ ]);
366
+ }
367
+ function mergeConfigSections(registry, sections) {
368
+ const owners = { names: new Map, keys: new Map };
369
+ for (const section of registry.sections)
370
+ recordOwners(owners, section);
371
+ const problems = [];
372
+ const accepted = [];
373
+ for (const section of sections) {
374
+ if (typeof section.package !== "string" || section.package === "") {
375
+ problems.push(`a section's package is ${quoted(section.package)}; expected a non-empty package name`);
376
+ }
377
+ const copy = frozenCopy(section);
378
+ problems.push(...collisionsOf(owners, copy));
379
+ recordOwners(owners, copy);
380
+ accepted.push(copy);
381
+ }
382
+ const merged = [...registry.sections, ...accepted];
383
+ problems.push(...unpairedOf(merged));
384
+ if (problems.length > 0)
385
+ throw new ConfigSectionError(problems);
386
+ return Object.freeze({
387
+ sections: Object.freeze(merged),
388
+ settings: Object.freeze(merged.reduce((all, section) => ({ ...all, ...section.settings }), {})),
389
+ defaults: Object.freeze(merged.reduce((all, section) => ({ ...all, ...section.defaults }), {})),
390
+ checks: Object.freeze(merged.flatMap((section) => section.checks ?? []))
391
+ });
392
+ }
393
+ var active = EMPTY_CONFIG_REGISTRY;
394
+ function registerConfigSections(sections) {
395
+ const previous = active;
396
+ active = mergeConfigSections(previous, sections);
397
+ return previous;
398
+ }
399
+ function activeSections() {
400
+ return active.sections;
401
+ }
402
+ function activeSettings() {
403
+ return active.settings;
404
+ }
405
+ function activeDefaults() {
406
+ return active.defaults;
407
+ }
408
+ function activeChecks() {
409
+ return active.checks;
410
+ }
411
+ function prefixesOf(key) {
412
+ const parts = key.split(".");
413
+ return parts.slice(1).map((_, index) => parts.slice(0, index + 1).join("."));
414
+ }
415
+ function keyIndexOf(registry) {
416
+ const settingByKey = new Map;
417
+ const knownUnder = new Map;
418
+ const add = (parent, name) => {
419
+ const names = knownUnder.get(parent) ?? [];
420
+ if (!names.includes(name))
421
+ knownUnder.set(parent, [...names, name]);
422
+ };
423
+ for (const [name, spec] of Object.entries(registry.settings)) {
424
+ if (spec === undefined)
425
+ continue;
426
+ settingByKey.set(spec.key, name);
427
+ const parts = spec.key.split(".");
428
+ parts.forEach((part, index) => add(parts.slice(0, index).join("."), part));
429
+ for (const item of spec.itemKeys ?? [])
430
+ add(`${spec.key}[]`, item);
431
+ }
432
+ const sectionPaths = new Set([...settingByKey.keys()].flatMap(prefixesOf));
433
+ return { settingByKey, sectionPaths, knownUnder };
434
+ }
435
+ var keyIndexes = new WeakMap;
436
+ function activeKeyIndex() {
437
+ const cached = keyIndexes.get(active);
438
+ if (cached !== undefined)
439
+ return cached;
440
+ const built = keyIndexOf(active);
441
+ keyIndexes.set(active, built);
442
+ return built;
443
+ }
444
+ function activeSettingByKey() {
445
+ return activeKeyIndex().settingByKey;
446
+ }
447
+ function activeSectionPaths() {
448
+ return activeKeyIndex().sectionPaths;
449
+ }
450
+ function parentOf(key) {
451
+ const cut = key.lastIndexOf(".");
452
+ return cut < 0 ? "" : key.slice(0, cut);
453
+ }
454
+ var TRAILING_INDEX = /\[\d+\]$/;
455
+ function activeKnownKeysAbove(key) {
456
+ const { knownUnder } = activeKeyIndex();
457
+ for (let parent = parentOf(key);parent !== ""; parent = parentOf(parent)) {
458
+ const names = knownUnder.get(parent.replace(TRAILING_INDEX, "[]"));
459
+ if (names !== undefined)
460
+ return [parent, names];
461
+ }
462
+ return ["", knownUnder.get("") ?? []];
463
+ }
464
+ var loadHook = null;
465
+ function setConfigLoadHook(hook) {
466
+ const previous = loadHook;
467
+ loadHook = hook;
468
+ return previous;
469
+ }
470
+ function activeConfigLoadHook() {
471
+ return loadHook;
472
+ }
473
+
474
+ // packages/rafa/src/core/config/config.ts
475
+ class ConfigError extends Error {
476
+ problems;
477
+ constructor(problems, options) {
478
+ super(`rafa config: ${problems.join("; ")}`, options);
479
+ this.name = "ConfigError";
480
+ this.problems = problems;
481
+ }
482
+ }
483
+ function registeredNames() {
484
+ return Object.keys(activeSettings());
485
+ }
486
+ function specOf(setting) {
487
+ const spec = activeSettings()[setting];
488
+ if (spec === undefined)
489
+ throw new Error(`rafa config: setting ${setting} is not registered`);
490
+ return spec;
491
+ }
492
+ function isCommandLineSetting(setting) {
493
+ return specOf(setting).cli;
494
+ }
495
+ function readLayer(rawOf, atOf) {
496
+ const problems = [];
497
+ const extras = [];
498
+ const entries = registeredNames().map((setting) => {
499
+ const raw = rawOf(setting);
500
+ if (raw === undefined)
501
+ return [setting, undefined];
502
+ const reading = specOf(setting).read(raw, atOf(setting));
503
+ problems.push(...reading.problems);
504
+ extras.push(...reading.extras);
505
+ return [setting, reading.value];
506
+ });
507
+ const layer = Object.fromEntries(entries);
508
+ return { layer, problems, extras };
509
+ }
510
+ function* entriesOf(mapping, prefix) {
511
+ const sectionPaths = activeSectionPaths();
512
+ for (const [name, value] of Object.entries(mapping)) {
513
+ const key = prefix === "" ? name : `${prefix}.${name}`;
514
+ if (sectionPaths.has(key) && isMapping(value))
515
+ yield* entriesOf(value, key);
516
+ else
517
+ yield { key, value };
518
+ }
519
+ }
520
+ function sortKeys(document, path) {
521
+ const named = new Map;
522
+ const seen = new Set;
523
+ const extras = [];
524
+ const problems = [];
525
+ const settingByKey = activeSettingByKey();
526
+ const sectionPaths = activeSectionPaths();
527
+ for (const entry of entriesOf(document, "")) {
528
+ const setting = settingByKey.get(entry.key);
529
+ if (setting !== undefined) {
530
+ if (seen.has(setting)) {
531
+ problems.push(`${path}: ${entry.key} is given more than once`);
532
+ } else if (entry.value !== null) {
533
+ named.set(setting, entry.value);
534
+ }
535
+ seen.add(setting);
536
+ continue;
537
+ }
538
+ if (!sectionPaths.has(entry.key)) {
539
+ extras.push(entry);
540
+ continue;
541
+ }
542
+ if (entry.value !== null) {
543
+ const found = describeValue(entry.value);
544
+ problems.push(`${path}: ${entry.key} must be a mapping, found ${found}`);
545
+ }
546
+ }
547
+ return { named, extras, problems };
548
+ }
549
+ var TAB_INDENTED_LINE = /^[ \t]*\t[ \t]*[^\s#]/;
550
+ function tabIndentProblems(text2, path) {
551
+ 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`] : []);
552
+ }
553
+ function parseConfigDocument(text2, path) {
554
+ const tabProblems = tabIndentProblems(text2, path);
555
+ if (tabProblems.length > 0)
556
+ throw new ConfigError(tabProblems);
557
+ try {
558
+ return Bun.YAML.parse(text2);
559
+ } catch (error) {
560
+ const problem = `${path}: not valid YAML (${messageOf(error)})`;
561
+ throw new ConfigError([problem], { cause: error });
562
+ }
563
+ }
564
+ function configFilePath(root) {
565
+ return join2(root, CONFIG_FILE);
566
+ }
567
+ function parseConfigText(text2, path) {
568
+ return readConfigDocument(parseConfigDocument(text2, path), path);
569
+ }
570
+ function readConfigDocument(parsed, path) {
571
+ const document = parsed ?? {};
572
+ if (!isMapping(document)) {
573
+ const found = describeValue(document);
574
+ throw new ConfigError([
575
+ `${path}: expected a mapping at the top level, found ${found}`
576
+ ]);
577
+ }
578
+ const sorted = sortKeys(document, path);
579
+ const read = readLayer((setting) => sorted.named.get(setting), (setting) => ({
580
+ label: `${path}: ${specOf(setting).key}`,
581
+ key: specOf(setting).key
582
+ }));
583
+ const all = [...sorted.problems, ...read.problems];
584
+ if (all.length > 0)
585
+ throw new ConfigError(all);
586
+ return { path, values: read.layer, extras: [...sorted.extras, ...read.extras] };
587
+ }
588
+ function isMapSetting(setting) {
589
+ return specOf(setting).map === true;
590
+ }
591
+ function mergeMaps(...layers) {
592
+ const merged = new Map;
593
+ for (const layer of layers) {
594
+ if (!(layer instanceof Map))
595
+ continue;
596
+ for (const [name, value] of layer)
597
+ merged.set(name, value);
598
+ }
599
+ return merged;
600
+ }
601
+ function unloadedPinWarnings(layer) {
602
+ const pins = [
603
+ ["tiers.skills", layer.values.tiersSkills],
604
+ ["tiers.agents", layer.values.tiersAgents]
605
+ ];
606
+ return pins.flatMap(([key, map]) => [...map ?? []].filter(([, pin]) => pin === "rafa").map(([name]) => `rafa config: ${key}.${name} in ${layer.path} pins the rafa tier, ` + "which is not loaded (tiers.rafa is off), so the pin has no effect"));
607
+ }
608
+ function unknownKeyWarning(key, path) {
609
+ const quoted2 = JSON.stringify(key);
610
+ const [under, names] = activeKnownKeysAbove(key);
611
+ const where = under === "" ? "" : ` under ${under}`;
612
+ return `rafa config: unknown key ${quoted2} in ${path} has no effect ` + `in this version (known keys${where}: ${names.join(", ")})`;
613
+ }
614
+ function resolveConfig(layers = {}) {
615
+ const file = layers.file ?? null;
616
+ const user = layers.user ?? null;
617
+ const overrides = layers.cli ?? {};
618
+ const { layer: cli, problems } = readLayer((setting) => isCommandLineSetting(setting) ? overrides[setting] : undefined, (setting) => ({ label: `command line: ${setting}`, key: setting }));
619
+ if (problems.length > 0)
620
+ throw new ConfigError(problems);
621
+ const defaults = activeDefaults();
622
+ const rank = (setting) => {
623
+ const fromCli = cli[setting];
624
+ if (fromCli !== undefined)
625
+ return { value: fromCli, source: "cli" };
626
+ const fromFile = file?.values[setting];
627
+ const fromUser = user?.values[setting];
628
+ if (isMapSetting(setting)) {
629
+ const merged = mergeMaps(defaults[setting], fromUser, fromFile);
630
+ const source = fromFile !== undefined ? "file" : fromUser !== undefined ? "user" : "default";
631
+ return { value: merged, source };
632
+ }
633
+ if (fromFile !== undefined)
634
+ return { value: fromFile, source: "file" };
635
+ if (fromUser !== undefined)
636
+ return { value: fromUser, source: "user" };
637
+ return { value: defaults[setting], source: "default" };
638
+ };
639
+ const ranked = registeredNames().map((setting) => [setting, rank(setting)]);
640
+ const config = Object.fromEntries(ranked.map(([setting, { value }]) => [setting, value]));
641
+ const sources = Object.fromEntries(ranked.map(([setting, { source }]) => [setting, source]));
642
+ const provenance = Object.fromEntries(ranked.map(([setting, { source }]) => [setting, originOf(source, setting, file, user)]));
643
+ const path = file?.path ?? null;
644
+ const userPath = user?.path ?? null;
645
+ const checkProblems = activeChecks().flatMap((check) => check({ config, sources, path, userPath }));
646
+ if (checkProblems.length > 0)
647
+ throw new ConfigError(checkProblems);
648
+ const rafaLoaded = ranked.find(([setting]) => setting === "tiersRafa")?.[1].value !== "off";
649
+ const warnings = [user, file].flatMap((layer) => layer === null ? [] : [
650
+ ...layer.extras.map((extra) => unknownKeyWarning(extra.key, layer.path)),
651
+ ...rafaLoaded ? [] : unloadedPinWarnings(layer)
652
+ ]);
653
+ return {
654
+ config,
655
+ sources,
656
+ path,
657
+ userPath,
658
+ extras: file?.extras ?? [],
659
+ userExtras: user?.extras ?? [],
660
+ warnings,
661
+ provenance,
662
+ shadowed: []
663
+ };
664
+ }
665
+
666
+ // packages/rafa/src/core/config/scope.ts
667
+ import { join as join3 } from "path";
668
+ function scopeAt(base, file = configFilePath(base)) {
669
+ return { dir: join3(base, SCOPE_DIR), configFile: file };
670
+ }
671
+ // packages/rafa/src/core/config/dangerous.ts
672
+ import { AsyncLocalStorage } from "async_hooks";
673
+ var DANGEROUS_PREFIX2 = "dangerous.";
674
+ var NO_PHRASES = Object.freeze({});
675
+ var phraseScopes = new AsyncLocalStorage;
676
+ var modulePhrases = NO_PHRASES;
677
+ function dangerousPhrases() {
678
+ return phraseScopes.getStore() ?? modulePhrases;
679
+ }
680
+ var written = new WeakMap;
681
+ function dangerousSettings() {
682
+ return Object.entries(activeSettings()).flatMap(([setting, spec]) => spec?.key.startsWith(DANGEROUS_PREFIX2) ? [{ setting, key: spec.key }] : []);
683
+ }
684
+ function sameValue(first, second) {
685
+ return Object.is(first, second) || JSON.stringify(first) === JSON.stringify(second);
686
+ }
687
+ function dangerousPassLines(resolved) {
688
+ const defaults = activeDefaults();
689
+ const phrases = dangerousPhrases();
690
+ return dangerousSettings().flatMap(({ setting, key }) => {
691
+ const value = resolved.config[setting];
692
+ if (sameValue(value, defaults[setting]))
693
+ return [];
694
+ const origin = resolved.provenance[setting] ?? null;
695
+ const where = origin === null ? "command line" : `${origin.file}, entry ${origin.entry}`;
696
+ const phrase = Object.hasOwn(phrases, key) ? `; ${phrases[key]}` : "";
697
+ return [`${key}: ${describeValue(value)} (${where})${phrase}`];
698
+ });
699
+ }
700
+ function writeDangerousPassLines(resolved, warn, invocation) {
701
+ const seen = written.get(invocation) ?? new Set;
702
+ written.set(invocation, seen);
703
+ for (const line of dangerousPassLines(resolved)) {
704
+ if (seen.has(line))
705
+ continue;
706
+ seen.add(line);
707
+ warn(line);
708
+ }
709
+ }
710
+ export { PREREQUISITE_KINDS, requiredPrerequisite, optionalPrerequisite, MODULE_SOURCE_KINDS, DEFAULT_ROUTING, CONFIG_FILE, SCOPE_DIR, CORE_SECTION, registerConfigSections, activeSections, activeSettings, activeDefaults, activeSettingByKey, setConfigLoadHook, activeConfigLoadHook, ConfigError, parseConfigDocument, configFilePath, parseConfigText, readConfigDocument, resolveConfig, writeDangerousPassLines, scopeAt };