@open-tomato/rafa 0.31.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -6
- package/dist/bundled/agents/build-error-resolver.md +22 -14
- package/dist/bundled/agents/code-reviewer.md +22 -14
- package/dist/bundled/agents/loop-implementer.md +22 -8
- package/dist/bundled/agents/tdd-guide.md +23 -15
- package/dist/bundled/operators/agents/rafa-stretch-engineer.md +172 -0
- package/dist/bundled/operators/agents/rafa-stretch-watchtower.md +91 -0
- package/dist/bundled/operators/skills/rafa-stretch-gap-log/SKILL.md +72 -0
- package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +71 -0
- package/dist/bundled/operators/skills/rafa-stretch-sweep/SKILL.md +111 -0
- package/dist/bundled/skills/dev-planner/SKILL.md +19 -1
- package/dist/cli.js +21032 -14271
- package/dist/{describe-b2kfwphn.js → describe-5hqfwbjc.js} +3 -3
- package/dist/effort/store/index.js +24 -4
- package/dist/{index-b766n1aw.js → index-13caphhp.js} +2983 -2860
- package/dist/{index-e10rwa4g.js → index-3mzw3kzh.js} +2 -2
- package/dist/{index-t6q4k1tq.js → index-dv0ycmp8.js} +228 -13
- package/dist/{index-dnwcx1cs.js → index-fzhd3d4y.js} +36 -74
- package/dist/{index-p0njjkjj.js → index-k6sd4ym5.js} +2 -2
- package/dist/{index-13wzpgc1.js → index-kz7e4gtt.js} +593 -80
- package/dist/{index-szgyrz6j.js → index-w3vyb08t.js} +19792 -13920
- package/dist/{index-89j1m0f6.js → index-zn08ywsv.js} +2 -2
- package/dist/index.js +32 -10
- package/dist/plan/index.js +3 -3
- package/dist/plan-prompt.md +12 -0
- package/package.json +5 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
describeValue
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-fzhd3d4y.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/spends.ts
|
|
7
7
|
var SPENDS_GLYPH = "\uD83E\uDE99";
|
|
@@ -31,7 +31,7 @@ function spendsProblem(value) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// src/cli/command.ts
|
|
34
|
-
var COMMAND_OUTPUTS = ["text", "json", "tui"];
|
|
34
|
+
var COMMAND_OUTPUTS = ["text", "json", "events", "tui"];
|
|
35
35
|
var MAX_EXIT_CODE = 255;
|
|
36
36
|
|
|
37
37
|
class CommandExit extends Error {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
+
BOARD_RELATIONSHIP_MODES,
|
|
3
4
|
CLAUDE_SETTING_SOURCES,
|
|
4
5
|
CONFIG_VERSIONS,
|
|
5
6
|
INJECT_MODES,
|
|
6
|
-
MODULE_SOURCE_KEYS,
|
|
7
|
-
OPTIONAL_ITEM_KEYS,
|
|
8
7
|
OUTPUT_MODES,
|
|
9
8
|
PR_PROVIDERS,
|
|
10
9
|
RELEASE_AUTO,
|
|
11
|
-
REQUIRED_ITEM_KEYS,
|
|
12
10
|
SKILL_TIERS,
|
|
13
11
|
STORE_BACKENDS,
|
|
14
12
|
SYNC_STRATEGIES,
|
|
13
|
+
below,
|
|
15
14
|
busyTimeoutMs,
|
|
15
|
+
claimsAhead,
|
|
16
|
+
claimsStaleAfter,
|
|
16
17
|
confidence,
|
|
17
18
|
dayCount,
|
|
18
19
|
describeValue,
|
|
@@ -23,14 +24,14 @@ import {
|
|
|
23
24
|
issueNumber,
|
|
24
25
|
lessonSwitch,
|
|
25
26
|
listOf,
|
|
27
|
+
mapReading,
|
|
26
28
|
mergeMethod,
|
|
27
29
|
messageOf,
|
|
28
|
-
moduleSource,
|
|
29
30
|
oneOf,
|
|
30
|
-
optionalPrerequisite,
|
|
31
31
|
recurrenceCount,
|
|
32
|
+
refused,
|
|
33
|
+
refusedWith,
|
|
32
34
|
releaseEnabled,
|
|
33
|
-
requiredPrerequisite,
|
|
34
35
|
routeTarget,
|
|
35
36
|
skillResolverName,
|
|
36
37
|
subsetOf,
|
|
@@ -38,7 +39,79 @@ import {
|
|
|
38
39
|
tierPin,
|
|
39
40
|
tierSwitch,
|
|
40
41
|
usdAmount
|
|
41
|
-
} from "./index-
|
|
42
|
+
} from "./index-fzhd3d4y.js";
|
|
43
|
+
|
|
44
|
+
// src/config-items.ts
|
|
45
|
+
var itemText = text("a non-empty string");
|
|
46
|
+
function readKeyedItem(shape, raw, at) {
|
|
47
|
+
const choices = shape.kinds.join(", ");
|
|
48
|
+
if (!isMapping(raw))
|
|
49
|
+
return refused(at, raw, `a mapping naming one of: ${choices}`);
|
|
50
|
+
const entries = Object.entries(raw);
|
|
51
|
+
const kinds = shape.kinds.filter((kind2) => entries.some(([name]) => name === kind2));
|
|
52
|
+
const [kind] = kinds;
|
|
53
|
+
if (kind === undefined)
|
|
54
|
+
return refusedWith([`${at.label} names none of: ${choices}`]);
|
|
55
|
+
if (kinds.length > 1) {
|
|
56
|
+
const named2 = kinds.join(" and ");
|
|
57
|
+
return refusedWith([`${at.label} names ${named2}, expected exactly one of: ${choices}`]);
|
|
58
|
+
}
|
|
59
|
+
const optionalKeys = shape.optionalFor(kind);
|
|
60
|
+
const problems = [];
|
|
61
|
+
const extras = [];
|
|
62
|
+
const optional = new Map;
|
|
63
|
+
let named;
|
|
64
|
+
for (const [name, value] of entries) {
|
|
65
|
+
if (name !== kind && !optionalKeys.includes(name)) {
|
|
66
|
+
extras.push({ key: `${at.key}.${name}`, value });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (name !== kind && value === null)
|
|
70
|
+
continue;
|
|
71
|
+
const reading = itemText(value, below(at, `.${name}`));
|
|
72
|
+
problems.push(...reading.problems);
|
|
73
|
+
if (reading.value === undefined)
|
|
74
|
+
continue;
|
|
75
|
+
if (name === kind)
|
|
76
|
+
named = reading.value;
|
|
77
|
+
else
|
|
78
|
+
optional.set(name, reading.value);
|
|
79
|
+
}
|
|
80
|
+
return problems.length > 0 || named === undefined ? { value: undefined, problems, extras } : { value: { kind, named, optional }, problems, extras };
|
|
81
|
+
}
|
|
82
|
+
var PREREQUISITE_KINDS = ["tool", "env", "service", "lsp"];
|
|
83
|
+
var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS, "probe"];
|
|
84
|
+
var OPTIONAL_ITEM_KEYS = [...REQUIRED_ITEM_KEYS, "reason"];
|
|
85
|
+
var requiredPrerequisite = (raw, at) => {
|
|
86
|
+
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe"] };
|
|
87
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
88
|
+
kind: item.kind,
|
|
89
|
+
name: item.named,
|
|
90
|
+
probe: item.optional.get("probe") ?? null
|
|
91
|
+
}));
|
|
92
|
+
};
|
|
93
|
+
var optionalPrerequisite = (raw, at) => {
|
|
94
|
+
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe", "reason"] };
|
|
95
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
96
|
+
kind: item.kind,
|
|
97
|
+
name: item.named,
|
|
98
|
+
probe: item.optional.get("probe") ?? null,
|
|
99
|
+
reason: item.optional.get("reason") ?? null
|
|
100
|
+
}));
|
|
101
|
+
};
|
|
102
|
+
var MODULE_SOURCE_KINDS = ["npm", "github", "path"];
|
|
103
|
+
var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS, "ref"];
|
|
104
|
+
var moduleSource = (raw, at) => {
|
|
105
|
+
const shape = {
|
|
106
|
+
kinds: MODULE_SOURCE_KINDS,
|
|
107
|
+
optionalFor: (kind) => kind === "github" ? ["ref"] : []
|
|
108
|
+
};
|
|
109
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
110
|
+
kind: item.kind,
|
|
111
|
+
location: item.named,
|
|
112
|
+
ref: item.optional.get("ref") ?? null
|
|
113
|
+
}));
|
|
114
|
+
};
|
|
42
115
|
|
|
43
116
|
// src/config-schema.ts
|
|
44
117
|
import { join } from "path";
|
|
@@ -99,6 +172,61 @@ var fragmentsDirectory = (raw, at) => {
|
|
|
99
172
|
return { value: undefined, problems: [problem], extras: [] };
|
|
100
173
|
};
|
|
101
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
|
+
|
|
102
230
|
// src/config-schema-release.ts
|
|
103
231
|
var PR_DEFAULTS = Object.freeze({
|
|
104
232
|
prProvider: null,
|
|
@@ -115,7 +243,8 @@ var RELEASE_DEFAULTS = Object.freeze({
|
|
|
115
243
|
releaseFragments: ".changes",
|
|
116
244
|
releaseStrategy: "semver-by-level",
|
|
117
245
|
releaseSettle: "push",
|
|
118
|
-
releaseTag: "manual"
|
|
246
|
+
releaseTag: "manual",
|
|
247
|
+
releasePublishCommand: "npm publish"
|
|
119
248
|
});
|
|
120
249
|
var DANGEROUS_RELEASE_DEFAULTS = Object.freeze({
|
|
121
250
|
dangerousAcceptVersionCollision: false
|
|
@@ -151,7 +280,12 @@ var RELEASE_SETTINGS = {
|
|
|
151
280
|
},
|
|
152
281
|
releaseStrategy: { key: "release.strategy", read: releaseStrategy, cli: false },
|
|
153
282
|
releaseSettle: { key: "release.settle", read: releaseSettleMode, cli: false },
|
|
154
|
-
releaseTag: { key: "release.tag", read: releaseTagMode, cli: false }
|
|
283
|
+
releaseTag: { key: "release.tag", read: releaseTagMode, cli: false },
|
|
284
|
+
releasePublishCommand: {
|
|
285
|
+
key: "release.publishCommand",
|
|
286
|
+
read: text("a publish command"),
|
|
287
|
+
cli: false
|
|
288
|
+
}
|
|
155
289
|
};
|
|
156
290
|
var DANGEROUS_RELEASE_SETTINGS = {
|
|
157
291
|
dangerousAcceptVersionCollision: {
|
|
@@ -161,6 +295,49 @@ var DANGEROUS_RELEASE_SETTINGS = {
|
|
|
161
295
|
}
|
|
162
296
|
};
|
|
163
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-wrap-up.ts
|
|
328
|
+
var WRAP_UP_RETRIES_MIN = 1;
|
|
329
|
+
var WRAP_UP_RETRIES_MAX = 3;
|
|
330
|
+
function isRetryCount(raw) {
|
|
331
|
+
return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= WRAP_UP_RETRIES_MIN && raw <= WRAP_UP_RETRIES_MAX;
|
|
332
|
+
}
|
|
333
|
+
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)}`);
|
|
334
|
+
var WRAP_UP_DEFAULTS = Object.freeze({
|
|
335
|
+
loopWrapUpRetries: 1
|
|
336
|
+
});
|
|
337
|
+
var WRAP_UP_SETTINGS = {
|
|
338
|
+
loopWrapUpRetries: { key: "loop.wrapUp.retries", read: wrapUpRetries, cli: false }
|
|
339
|
+
};
|
|
340
|
+
|
|
164
341
|
// src/tiers/resolve.ts
|
|
165
342
|
import { readFileSync } from "fs";
|
|
166
343
|
var VENDORED_HEADER = /^<!-- vendored by rafa from .* on \d{4}-\d{2}-\d{2} -->$/;
|
|
@@ -332,6 +509,7 @@ var CONFIG_DEFAULTS = Object.freeze({
|
|
|
332
509
|
store: "sqlite",
|
|
333
510
|
effortBusyTimeoutMs: 5000,
|
|
334
511
|
effortSync: "local",
|
|
512
|
+
...HUB_DEFAULTS,
|
|
335
513
|
inject: "stage",
|
|
336
514
|
planDir: join(".rafa", "plans"),
|
|
337
515
|
specsDir: join(".rafa", "specs"),
|
|
@@ -351,9 +529,13 @@ var CONFIG_DEFAULTS = Object.freeze({
|
|
|
351
529
|
allowList: Object.freeze([]),
|
|
352
530
|
settingSources: Object.freeze(["project", "local"]),
|
|
353
531
|
loopWorktreeDir: join(".rafa", "worktrees"),
|
|
532
|
+
...WRAP_UP_DEFAULTS,
|
|
354
533
|
...PR_DEFAULTS,
|
|
355
534
|
boardTrustedAuthors: Object.freeze([]),
|
|
535
|
+
boardRelationships: "labels",
|
|
356
536
|
roadmapIssue: null,
|
|
537
|
+
claimsStaleAfter: "3d",
|
|
538
|
+
claimsAhead: "off",
|
|
357
539
|
...RELEASE_DEFAULTS,
|
|
358
540
|
cleanupStaleDays: 30,
|
|
359
541
|
cleanupWorktreeIdleDays: 7,
|
|
@@ -367,13 +549,15 @@ var CONFIG_DEFAULTS = Object.freeze({
|
|
|
367
549
|
tiersAgents: new Map,
|
|
368
550
|
routing: DEFAULT_ROUTING,
|
|
369
551
|
taskSkills: "planner",
|
|
370
|
-
taskLessons: "on"
|
|
552
|
+
taskLessons: "on",
|
|
553
|
+
...TESTS_DEFAULTS
|
|
371
554
|
});
|
|
372
555
|
var SETTINGS = {
|
|
373
556
|
version: { key: "version", read: oneOf(CONFIG_VERSIONS), cli: false },
|
|
374
557
|
store: { key: "store", read: oneOf(STORE_BACKENDS), cli: true },
|
|
375
558
|
effortBusyTimeoutMs: { key: "effort.busyTimeoutMs", read: busyTimeoutMs, cli: false },
|
|
376
559
|
effortSync: { key: "effort.sync", read: oneOf(SYNC_STRATEGIES), cli: false },
|
|
560
|
+
...HUB_SETTINGS,
|
|
377
561
|
inject: { key: "plan.inject", read: oneOf(INJECT_MODES), cli: true },
|
|
378
562
|
planDir: { key: "plan.dir", read: directory, cli: true },
|
|
379
563
|
specsDir: { key: "specs.dir", read: directory, cli: true },
|
|
@@ -424,13 +608,21 @@ var SETTINGS = {
|
|
|
424
608
|
cli: true
|
|
425
609
|
},
|
|
426
610
|
loopWorktreeDir: { key: "loop.worktreeDir", read: directory, cli: false },
|
|
611
|
+
...WRAP_UP_SETTINGS,
|
|
427
612
|
...PR_SETTINGS,
|
|
428
613
|
boardTrustedAuthors: {
|
|
429
614
|
key: "board.trustedAuthors",
|
|
430
615
|
read: listOf(githubLogin, "GitHub logins"),
|
|
431
616
|
cli: false
|
|
432
617
|
},
|
|
618
|
+
boardRelationships: {
|
|
619
|
+
key: "board.relationships",
|
|
620
|
+
read: oneOf(BOARD_RELATIONSHIP_MODES),
|
|
621
|
+
cli: false
|
|
622
|
+
},
|
|
433
623
|
roadmapIssue: { key: "roadmap.issue", read: issueNumber, cli: false },
|
|
624
|
+
claimsStaleAfter: { key: "claims.staleAfter", read: claimsStaleAfter, cli: false },
|
|
625
|
+
claimsAhead: { key: "claims.ahead", read: claimsAhead, cli: false },
|
|
434
626
|
...RELEASE_SETTINGS,
|
|
435
627
|
cleanupStaleDays: { key: "cleanup.staleDays", read: dayCount, cli: false },
|
|
436
628
|
cleanupWorktreeIdleDays: {
|
|
@@ -460,7 +652,8 @@ var SETTINGS = {
|
|
|
460
652
|
tiersAgents: { key: "tiers.agents", read: tierPins, cli: false },
|
|
461
653
|
routing: { key: "routing", read: routeTable, cli: false },
|
|
462
654
|
taskSkills: { key: "task.skills", read: skillResolverName, cli: true },
|
|
463
|
-
taskLessons: { key: "task.lessons", read: lessonSwitch, cli: false }
|
|
655
|
+
taskLessons: { key: "task.lessons", read: lessonSwitch, cli: false },
|
|
656
|
+
...TESTS_SETTINGS
|
|
464
657
|
};
|
|
465
658
|
var SETTING_NAMES = Object.keys(SETTINGS);
|
|
466
659
|
var SETTING_BY_KEY = new Map(SETTING_NAMES.map((setting) => [
|
|
@@ -532,6 +725,9 @@ function readLayer(rawOf, atOf) {
|
|
|
532
725
|
store: read("store"),
|
|
533
726
|
effortBusyTimeoutMs: read("effortBusyTimeoutMs"),
|
|
534
727
|
effortSync: read("effortSync"),
|
|
728
|
+
hubUrl: read("hubUrl"),
|
|
729
|
+
hubTokenSecret: read("hubTokenSecret"),
|
|
730
|
+
hubTimeout: read("hubTimeout"),
|
|
535
731
|
inject: read("inject"),
|
|
536
732
|
planDir: read("planDir"),
|
|
537
733
|
specsDir: read("specsDir"),
|
|
@@ -551,13 +747,17 @@ function readLayer(rawOf, atOf) {
|
|
|
551
747
|
allowList: read("allowList"),
|
|
552
748
|
settingSources: read("settingSources"),
|
|
553
749
|
loopWorktreeDir: read("loopWorktreeDir"),
|
|
750
|
+
loopWrapUpRetries: read("loopWrapUpRetries"),
|
|
554
751
|
prProvider: read("prProvider"),
|
|
555
752
|
prMergeMethod: read("prMergeMethod"),
|
|
556
753
|
prBase: read("prBase"),
|
|
557
754
|
prResolveBudget: read("prResolveBudget"),
|
|
558
755
|
prVersionCollision: read("prVersionCollision"),
|
|
559
756
|
boardTrustedAuthors: read("boardTrustedAuthors"),
|
|
757
|
+
boardRelationships: read("boardRelationships"),
|
|
560
758
|
roadmapIssue: read("roadmapIssue"),
|
|
759
|
+
claimsStaleAfter: read("claimsStaleAfter"),
|
|
760
|
+
claimsAhead: read("claimsAhead"),
|
|
561
761
|
releaseEnabled: read("releaseEnabled"),
|
|
562
762
|
releaseVersionFile: read("releaseVersionFile"),
|
|
563
763
|
releaseChangelog: read("releaseChangelog"),
|
|
@@ -566,6 +766,7 @@ function readLayer(rawOf, atOf) {
|
|
|
566
766
|
releaseStrategy: read("releaseStrategy"),
|
|
567
767
|
releaseSettle: read("releaseSettle"),
|
|
568
768
|
releaseTag: read("releaseTag"),
|
|
769
|
+
releasePublishCommand: read("releasePublishCommand"),
|
|
569
770
|
cleanupStaleDays: read("cleanupStaleDays"),
|
|
570
771
|
cleanupWorktreeIdleDays: read("cleanupWorktreeIdleDays"),
|
|
571
772
|
cleanupKeep: read("cleanupKeep"),
|
|
@@ -578,7 +779,9 @@ function readLayer(rawOf, atOf) {
|
|
|
578
779
|
tiersAgents: read("tiersAgents"),
|
|
579
780
|
routing: read("routing"),
|
|
580
781
|
taskSkills: read("taskSkills"),
|
|
581
|
-
taskLessons: read("taskLessons")
|
|
782
|
+
taskLessons: read("taskLessons"),
|
|
783
|
+
testsFullSuiteTriggers: read("testsFullSuiteTriggers"),
|
|
784
|
+
testsIntegration: read("testsIntegration")
|
|
582
785
|
};
|
|
583
786
|
return { layer, problems, extras };
|
|
584
787
|
}
|
|
@@ -700,6 +903,15 @@ function resolveConfig(layers = {}) {
|
|
|
700
903
|
return { value: CONFIG_DEFAULTS[setting], source: "default" };
|
|
701
904
|
};
|
|
702
905
|
const ranked = SETTING_NAMES.map((setting) => [setting, rank(setting)]);
|
|
906
|
+
const effortSync = rank("effortSync");
|
|
907
|
+
const hubProblems = hubUrlProblems({
|
|
908
|
+
effortSync: effortSync.value,
|
|
909
|
+
hubUrl: rank("hubUrl").value,
|
|
910
|
+
effortSyncSource: effortSync.source,
|
|
911
|
+
paths: { file: file?.path ?? null, user: user?.path ?? null }
|
|
912
|
+
});
|
|
913
|
+
if (hubProblems.length > 0)
|
|
914
|
+
throw new ConfigError(hubProblems);
|
|
703
915
|
const rafaLoaded = ranked.find(([setting]) => setting === "tiersRafa")?.[1].value !== "off";
|
|
704
916
|
const warnings = [user, file].flatMap((layer) => layer === null ? [] : [
|
|
705
917
|
...layer.extras.map((extra) => unknownKeyWarning(extra.key, layer.path)),
|
|
@@ -1129,6 +1341,9 @@ function createTextOutput({ verbosity, stream }) {
|
|
|
1129
1341
|
writeLine(resultLine(event));
|
|
1130
1342
|
return;
|
|
1131
1343
|
}
|
|
1344
|
+
case "event": {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1132
1347
|
}
|
|
1133
1348
|
};
|
|
1134
1349
|
return Object.freeze({ info, warn, error, debug, emit, result });
|
|
@@ -1145,4 +1360,4 @@ function activeOutputMode() {
|
|
|
1145
1360
|
return activeMode;
|
|
1146
1361
|
}
|
|
1147
1362
|
|
|
1148
|
-
export { 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 };
|
|
1363
|
+
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 };
|
|
@@ -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) {
|
|
@@ -313,14 +331,17 @@ function messageOf(error) {
|
|
|
313
331
|
var CONFIG_VERSIONS = [1];
|
|
314
332
|
var STORE_BACKENDS = ["sqlite", "ndjson"];
|
|
315
333
|
var SYNC_STRATEGIES = ["local", "file", "git", "service", "p2p"];
|
|
334
|
+
var BOARD_RELATIONSHIP_MODES = ["labels", "native"];
|
|
316
335
|
var INJECT_MODES = ["full", "stage", "task"];
|
|
317
|
-
var OUTPUT_MODES = ["text", "json"];
|
|
336
|
+
var OUTPUT_MODES = ["text", "json", "events"];
|
|
318
337
|
var CLAUDE_SETTING_SOURCES = ["user", "project", "local"];
|
|
319
338
|
var PR_PROVIDERS = ["gh", "none"];
|
|
320
339
|
var RELEASE_AUTO = "auto";
|
|
321
340
|
var TIER_SWITCHES = ["on", "off"];
|
|
322
341
|
var SKILL_RESOLVERS = ["planner", "tag", "none"];
|
|
323
342
|
var LESSON_SWITCHES = ["on", "off"];
|
|
343
|
+
var CLAIMS_STALE_DISABLED = "disabled";
|
|
344
|
+
var CLAIMS_AHEAD = ["off", "allow"];
|
|
324
345
|
function accepted(value) {
|
|
325
346
|
return { value, problems: [], extras: [] };
|
|
326
347
|
}
|
|
@@ -377,6 +398,17 @@ var tierPin = (raw, at) => {
|
|
|
377
398
|
var routeTarget = (raw, at) => raw === false || typeof raw === "string" && raw.trim() !== "" ? accepted(raw) : refused(at, raw, "false or an agent name");
|
|
378
399
|
var skillResolverName = oneOf(SKILL_RESOLVERS);
|
|
379
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);
|
|
380
412
|
var GITHUB_LOGIN = /^[A-Za-z0-9][A-Za-z0-9-]*(?:\[bot\])?$/;
|
|
381
413
|
function isGitHubLogin(value) {
|
|
382
414
|
return typeof value === "string" && GITHUB_LOGIN.test(value);
|
|
@@ -410,75 +442,5 @@ function subsetOf(values) {
|
|
|
410
442
|
return accepted(Object.freeze(named));
|
|
411
443
|
};
|
|
412
444
|
}
|
|
413
|
-
var itemText = text("a non-empty string");
|
|
414
|
-
function readKeyedItem(shape, raw, at) {
|
|
415
|
-
const choices = shape.kinds.join(", ");
|
|
416
|
-
if (!isMapping(raw))
|
|
417
|
-
return refused(at, raw, `a mapping naming one of: ${choices}`);
|
|
418
|
-
const entries = Object.entries(raw);
|
|
419
|
-
const kinds = shape.kinds.filter((kind2) => entries.some(([name]) => name === kind2));
|
|
420
|
-
const [kind] = kinds;
|
|
421
|
-
if (kind === undefined)
|
|
422
|
-
return refusedWith([`${at.label} names none of: ${choices}`]);
|
|
423
|
-
if (kinds.length > 1) {
|
|
424
|
-
const named2 = kinds.join(" and ");
|
|
425
|
-
return refusedWith([`${at.label} names ${named2}, expected exactly one of: ${choices}`]);
|
|
426
|
-
}
|
|
427
|
-
const optionalKeys = shape.optionalFor(kind);
|
|
428
|
-
const problems = [];
|
|
429
|
-
const extras = [];
|
|
430
|
-
const optional = new Map;
|
|
431
|
-
let named;
|
|
432
|
-
for (const [name, value] of entries) {
|
|
433
|
-
if (name !== kind && !optionalKeys.includes(name)) {
|
|
434
|
-
extras.push({ key: `${at.key}.${name}`, value });
|
|
435
|
-
continue;
|
|
436
|
-
}
|
|
437
|
-
if (name !== kind && value === null)
|
|
438
|
-
continue;
|
|
439
|
-
const reading = itemText(value, below(at, `.${name}`));
|
|
440
|
-
problems.push(...reading.problems);
|
|
441
|
-
if (reading.value === undefined)
|
|
442
|
-
continue;
|
|
443
|
-
if (name === kind)
|
|
444
|
-
named = reading.value;
|
|
445
|
-
else
|
|
446
|
-
optional.set(name, reading.value);
|
|
447
|
-
}
|
|
448
|
-
return problems.length > 0 || named === undefined ? { value: undefined, problems, extras } : { value: { kind, named, optional }, problems, extras };
|
|
449
|
-
}
|
|
450
|
-
var PREREQUISITE_KINDS = ["tool", "env", "service", "lsp"];
|
|
451
|
-
var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS, "probe"];
|
|
452
|
-
var OPTIONAL_ITEM_KEYS = [...REQUIRED_ITEM_KEYS, "reason"];
|
|
453
|
-
var requiredPrerequisite = (raw, at) => {
|
|
454
|
-
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe"] };
|
|
455
|
-
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
456
|
-
kind: item.kind,
|
|
457
|
-
name: item.named,
|
|
458
|
-
probe: item.optional.get("probe") ?? null
|
|
459
|
-
}));
|
|
460
|
-
};
|
|
461
|
-
var optionalPrerequisite = (raw, at) => {
|
|
462
|
-
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe", "reason"] };
|
|
463
|
-
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
464
|
-
kind: item.kind,
|
|
465
|
-
name: item.named,
|
|
466
|
-
probe: item.optional.get("probe") ?? null,
|
|
467
|
-
reason: item.optional.get("reason") ?? null
|
|
468
|
-
}));
|
|
469
|
-
};
|
|
470
|
-
var MODULE_SOURCE_KINDS = ["npm", "github", "path"];
|
|
471
|
-
var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS, "ref"];
|
|
472
|
-
var moduleSource = (raw, at) => {
|
|
473
|
-
const shape = {
|
|
474
|
-
kinds: MODULE_SOURCE_KINDS,
|
|
475
|
-
optionalFor: (kind) => kind === "github" ? ["ref"] : []
|
|
476
|
-
};
|
|
477
|
-
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
478
|
-
kind: item.kind,
|
|
479
|
-
location: item.named,
|
|
480
|
-
ref: item.optional.get("ref") ?? null
|
|
481
|
-
}));
|
|
482
|
-
};
|
|
483
445
|
|
|
484
|
-
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, INJECT_MODES, OUTPUT_MODES, CLAUDE_SETTING_SOURCES, PR_PROVIDERS, RELEASE_AUTO, SKILL_RESOLVERS, 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,
|
|
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-
|
|
7
|
+
} from "./index-3mzw3kzh.js";
|
|
8
8
|
import {
|
|
9
9
|
describeValue
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-fzhd3d4y.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/registry.ts
|
|
13
13
|
var REFUSAL = "command registry";
|