@open-tomato/rafa 0.44.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.
- package/README.md +280 -42
- package/dist/PROMPT.md +18 -1
- package/dist/adapters/logger/settings.d.ts +132 -0
- package/dist/bugs/closest.d.ts +19 -0
- package/dist/bugs/fenced.d.ts +8 -0
- package/dist/bugs/places.d.ts +20 -0
- package/dist/bugs/record.d.ts +145 -0
- package/dist/bugs/title.d.ts +83 -0
- package/dist/bundled/agents/doc-updater.md +17 -3
- package/dist/bundled/agents/loop-implementer.md +14 -2
- package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +10 -3
- package/dist/bundled/operators/skills/rafa-stretch-sweep/SKILL.md +5 -0
- package/dist/bundled/skills/dev-planner/SKILL.md +120 -24
- package/dist/bundled/skills/documentation/SKILL.md +2 -12
- package/dist/cli.js +72387 -59411
- package/dist/config/entry.d.ts +119 -0
- package/dist/config/index.d.ts +36 -0
- package/dist/config/index.js +51 -0
- package/dist/config/shape.d.ts +232 -0
- package/dist/config-registry.d.ts +127 -0
- package/dist/config-schema-board-project.d.ts +157 -0
- package/dist/config-schema-bugs.d.ts +71 -0
- package/dist/config-schema-errors.d.ts +54 -0
- package/dist/config-schema-features.d.ts +64 -0
- package/dist/config-schema-hub.d.ts +150 -0
- package/dist/config-schema-issues.d.ts +95 -0
- package/dist/config-schema-logger.d.ts +91 -0
- package/dist/config-schema-loop-continue.d.ts +122 -0
- package/dist/config-schema-loop-retries.d.ts +94 -0
- package/dist/config-schema-release.d.ts +307 -0
- package/dist/config-schema-tests.d.ts +170 -0
- package/dist/config-schema-triage.d.ts +142 -0
- package/dist/config-schema-wrap-up.d.ts +96 -0
- package/dist/core/command/command.d.ts +228 -0
- package/dist/core/command/confirm.d.ts +67 -0
- package/dist/core/command/index.d.ts +112 -0
- package/dist/core/command/lazy.d.ts +54 -0
- package/dist/core/command/registry-types.d.ts +96 -0
- package/dist/core/command/running.d.ts +96 -0
- package/dist/core/command/spends.d.ts +39 -0
- package/dist/core/command/types.d.ts +92 -0
- package/dist/core/command/version.d.ts +4 -0
- package/dist/core/config/branch-template.d.ts +20 -0
- package/dist/core/config/config-items.d.ts +86 -0
- package/dist/core/config/config-load.d.ts +47 -0
- package/dist/core/config/config-origins.d.ts +57 -0
- package/dist/core/config/config-readers.d.ts +167 -0
- package/dist/core/config/config-schema.d.ts +207 -0
- package/dist/core/config/config-sections.d.ts +493 -0
- package/dist/core/config/config.d.ts +320 -0
- package/dist/core/config/core-section.d.ts +39 -0
- package/dist/core/config/dangerous.d.ts +58 -0
- package/dist/core/config/default-routing.d.ts +16 -0
- package/dist/core/config/index.d.ts +141 -0
- package/dist/core/config/scope.d.ts +42 -0
- package/dist/core/config/section.d.ts +206 -0
- package/dist/core/config/sections.d.ts +45 -0
- package/dist/core/config/standard-schema.d.ts +27 -0
- package/dist/core/git/commit.d.ts +232 -0
- package/dist/core/git/gh-runner.d.ts +24 -0
- package/dist/core/git/git.d.ts +22 -0
- package/dist/core/git/index.d.ts +85 -0
- package/dist/core/loop/claude.d.ts +388 -0
- package/dist/core/loop/hop-record.d.ts +52 -0
- package/dist/core/loop/index.d.ts +179 -0
- package/dist/core/loop/session-env.d.ts +20 -0
- package/dist/core/loop/session-record-parse.d.ts +63 -0
- package/dist/core/loop/sessions.d.ts +408 -0
- package/dist/core/loop/suite-failure.d.ts +25 -0
- package/dist/core/output/active.d.ts +100 -0
- package/dist/core/output/stream.d.ts +20 -0
- package/dist/core/output/text.d.ts +55 -0
- package/dist/core/plan/block-reader.d.ts +46 -0
- package/dist/core/plan/blocks.d.ts +139 -0
- package/dist/core/plan/declaration.d.ts +366 -0
- package/dist/core/plan/plan-stamp.d.ts +75 -0
- package/dist/core/runtime/identity.d.ts +21 -0
- package/dist/core/runtime/index.d.ts +46 -0
- package/dist/effort/store/bring-forward.d.ts +131 -0
- package/dist/effort/store/check-rows.d.ts +31 -0
- package/dist/effort/store/commit-stats.d.ts +42 -0
- package/dist/effort/store/copy.d.ts +35 -0
- package/dist/effort/store/development-build.d.ts +105 -0
- package/dist/effort/store/effort-levels.d.ts +13 -0
- package/dist/effort/store/findings.d.ts +214 -0
- package/dist/effort/store/fix-schema.d.ts +184 -0
- package/dist/effort/store/index.js +10 -7
- package/dist/effort/store/location.d.ts +44 -0
- package/dist/effort/store/merge-commit-gaps.d.ts +68 -0
- package/dist/effort/store/merge-conflicts.d.ts +91 -0
- package/dist/effort/store/merge-rules.d.ts +82 -0
- package/dist/effort/store/merge-store.d.ts +211 -0
- package/dist/effort/store/merge-union.d.ts +92 -0
- package/dist/effort/store/migrate.d.ts +146 -0
- package/dist/effort/store/migrations.d.ts +92 -0
- package/dist/effort/store/ndjson-files.d.ts +114 -0
- package/dist/effort/store/origins.d.ts +116 -0
- package/dist/effort/store/plan-stubs.d.ts +79 -0
- package/dist/effort/store/rebuild-aside.d.ts +172 -0
- package/dist/effort/store/schema-plan.d.ts +102 -0
- package/dist/effort/store/session-row-types.d.ts +64 -0
- package/dist/effort/store/settings.d.ts +13 -0
- package/dist/effort/store/sqlite.d.ts +340 -0
- package/dist/effort/store/store-generation.d.ts +17 -0
- package/dist/effort/store/store-identity.d.ts +220 -0
- package/dist/effort/store/store-meta.d.ts +305 -0
- package/dist/effort/store/store-replaced.d.ts +72 -0
- package/dist/effort/store/types.d.ts +223 -0
- package/dist/errors/codes.d.ts +56 -0
- package/dist/errors/rafa-codes.d.ts +36 -0
- package/dist/index-2a7nb3an.js +125 -0
- package/dist/{index-57mmzkcn.js → index-39kbcw68.js} +516 -217
- package/dist/{index-nv34ptht.js → index-77ajfffn.js} +14 -9
- package/dist/index-cy98y87p.js +2597 -0
- package/dist/index-gqz4jn6j.js +13447 -0
- package/dist/index-gvek4r8m.js +710 -0
- package/dist/index-j4k2vdz3.js +1125 -0
- package/dist/index-jh1r4kcn.js +1067 -0
- package/dist/index-ykggr043.js +540 -0
- package/dist/index-z1w83f81.js +4 -0
- package/dist/index.js +16091 -22798
- package/dist/learning/index.js +5 -6
- package/dist/plan/index.js +12 -11
- package/dist/plan-prompt.md +11 -2
- package/dist/ports/index.d.ts +732 -0
- package/dist/ports/learning.d.ts +101 -0
- package/dist/ports/log-level.d.ts +13 -0
- package/dist/ports/spec-review.d.ts +66 -0
- package/dist/pr/checks.d.ts +133 -0
- package/dist/pr/types.d.ts +422 -0
- package/dist/ready-4f8edezt.js +2016 -0
- package/dist/release-templates/release-bot-fragment.yml +153 -0
- package/dist/release-templates/release-publish.yml +110 -0
- package/dist/release-templates/release-settle.yml +122 -0
- package/dist/release-templates/release-tag.yml +102 -0
- package/dist/report/parse.d.ts +415 -0
- package/dist/schema/project-id.d.ts +79 -0
- package/dist/schema/tiers.d.ts +107 -0
- package/package.json +42 -4
- package/dist/index-6q30dtgm.js +0 -6342
- package/dist/index-cknayrpc.js +0 -2414
- package/dist/index-hf2k497d.js +0 -16
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One config entry and the list of them a config module exports:
|
|
3
|
+
* {@link ConfigEntry}, rafa's own deep partial of the nested file shape
|
|
4
|
+
* `ConfigShape` (`shape.ts`), {@link Config}, {@link defineConfig}, and
|
|
5
|
+
* {@link entryOf}, which nests dotted keys into an entry.
|
|
6
|
+
*
|
|
7
|
+
* ## What an entry may hold
|
|
8
|
+
*
|
|
9
|
+
* An entry holds any part of the shape, every key at every depth
|
|
10
|
+
* optional, and two more forms the merge reads:
|
|
11
|
+
*
|
|
12
|
+
* - `false` at an id of a keyed map (`routing`, `tiers.skills`,
|
|
13
|
+
* `tiers.agents`, `logger.modules`) overrides what an earlier entry
|
|
14
|
+
* gave that id, so `{ logger: { modules: { board: false } } }` drops
|
|
15
|
+
* what an earlier entry gave `board`. Where the map takes `false` as a
|
|
16
|
+
* value (`routing`, the `tiers` pins) the loader keeps it as one, so it
|
|
17
|
+
* also shadows a lower layer's row, as in a YAML file; where it does
|
|
18
|
+
* not (`logger.modules`) the id is removed (`config-load.ts` in
|
|
19
|
+
* `packages/rafa/src/core/config/`). A named key takes `false` only where its own
|
|
20
|
+
* value does (`loop.retries`), never to remove it.
|
|
21
|
+
* - `{ $replace: true, …rest }` at any mapping below the top replaces
|
|
22
|
+
* that mapping whole with `rest`, discarding what earlier entries put
|
|
23
|
+
* there. On a scalar or a list it is a type error, since a later
|
|
24
|
+
* entry's list replaces an earlier one whole already. Inside `rest`
|
|
25
|
+
* neither form is read again: `rest` is a plain deep partial.
|
|
26
|
+
*
|
|
27
|
+
* These are the rules `@open-tomato/define-config`'s `merge` reads and
|
|
28
|
+
* its own `ConfigEntry` types. The type is declared here rather than
|
|
29
|
+
* imported so the `./config` subpath's declaration names nothing outside
|
|
30
|
+
* rafa. Its shapes follow that package's: one mapped type over every key
|
|
31
|
+
* with `$replace` beside them, never the named keys intersected with a
|
|
32
|
+
* keyed map's index signature, which that package's notes give as
|
|
33
|
+
* letting a stray `true` past at a map id.
|
|
34
|
+
*
|
|
35
|
+
* ## Values
|
|
36
|
+
*
|
|
37
|
+
* {@link defineConfig} is the identity: it answers the very list it is
|
|
38
|
+
* given and exists for its parameter type, so an editor flags a wrong
|
|
39
|
+
* key or value as the file is written. {@link entryOf} builds an entry
|
|
40
|
+
* from dotted keys, as `index.ts`'s `defaults` is built.
|
|
41
|
+
*/
|
|
42
|
+
import type { ConfigShape } from './shape.js';
|
|
43
|
+
/** A value an entry never descends into: a scalar, or a list, which replaces whole. */
|
|
44
|
+
type EntryLeaf = string | number | boolean | bigint | symbol | null | undefined | readonly unknown[];
|
|
45
|
+
/** True when `K` is an index signature's key, an id of a keyed map, rather than a named key. */
|
|
46
|
+
type IsMapId<K> = string extends K ? true : number extends K ? true : false;
|
|
47
|
+
/** The value type of `T`'s string index signature, or `never` when it has none. */
|
|
48
|
+
type MapValue<T> = string extends keyof T ? T extends {
|
|
49
|
+
readonly [id: string]: infer V;
|
|
50
|
+
} ? V : never : never;
|
|
51
|
+
/** Every key of `T`, optional, its index signature included: the skeleton the shapes below map over. */
|
|
52
|
+
type Keys<T> = {
|
|
53
|
+
[K in keyof T]?: 0;
|
|
54
|
+
};
|
|
55
|
+
/** `T` with every key at every depth optional, leaves whole: what `rest` of a `$replace` holds. */
|
|
56
|
+
type PartialOf<T> = T extends EntryLeaf ? T : T extends object ? {
|
|
57
|
+
[K in keyof T]?: PartialOf<T[K]>;
|
|
58
|
+
} : T;
|
|
59
|
+
/** Maps skeleton `S` to a replacing mapping: `$replace` itself, then a deep partial of each key. */
|
|
60
|
+
type ReplaceShape<S, T> = {
|
|
61
|
+
[K in keyof S]: K extends '$replace' ? true : IsMapId<K> extends true ? PartialOf<MapValue<T>> | true | undefined : PartialOf<T[K & keyof T]>;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* `{ $replace: true, …rest }` standing in for a mapping of type `T`;
|
|
65
|
+
* `never` for a leaf, so a `$replace` on a scalar or a list is refused.
|
|
66
|
+
* Over a keyed map the index signature admits `true` beside each id's
|
|
67
|
+
* value, since `$replace` is checked against it too.
|
|
68
|
+
*/
|
|
69
|
+
type Replace<T> = T extends EntryLeaf ? never : T extends object ? ReplaceShape<{
|
|
70
|
+
$replace: 0;
|
|
71
|
+
} & Keys<T>, T> : never;
|
|
72
|
+
/** What an entry may set at key `K` of a mapping of type `T`. */
|
|
73
|
+
type EntryAt<T, K> = IsMapId<K> extends true ? EntryOf<MapValue<T>> | Replace<MapValue<T>> | false | undefined : EntryOf<T[K & keyof T]> | Replace<T[K & keyof T]>;
|
|
74
|
+
/** Maps skeleton `S`, with its modifiers, to the values an entry sets. */
|
|
75
|
+
type EntryShape<S, T> = {
|
|
76
|
+
[K in keyof S]: EntryAt<T, K>;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* An entry for a value of type `T`: a leaf whole, a mapping key by key
|
|
80
|
+
* with `false` at a map id and `$replace` below it; see the module note.
|
|
81
|
+
*
|
|
82
|
+
* @typeParam T - The shape, or any part of it.
|
|
83
|
+
*/
|
|
84
|
+
export type EntryOf<T> = T extends EntryLeaf ? T : T extends object ? EntryShape<Keys<T>, T> : T;
|
|
85
|
+
/** One config entry: a deep partial of {@link ConfigShape}; see the module note. */
|
|
86
|
+
export type ConfigEntry = EntryOf<ConfigShape>;
|
|
87
|
+
/** A config module's default export: its entries, applied in order over rafa's defaults. */
|
|
88
|
+
export type Config = readonly ConfigEntry[];
|
|
89
|
+
/**
|
|
90
|
+
* Declares a config's entries. At run time the identity: it answers the
|
|
91
|
+
* very list it is given, unchanged.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* export default defineConfig([{ naming: { branch: 'work/{stub}' } }]);
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @param entries - The entries, in the order they apply.
|
|
99
|
+
* @returns `entries`, the same list.
|
|
100
|
+
*/
|
|
101
|
+
export declare function defineConfig(entries: Config): Config;
|
|
102
|
+
/**
|
|
103
|
+
* Nests dotted keys into one entry: `[['plan.inject', 'task']]` into
|
|
104
|
+
* `{ plan: { inject: 'task' } }`, every mapping frozen, keys in the
|
|
105
|
+
* order first named. The values are taken as given, already in the
|
|
106
|
+
* file's spelling. Throws on an empty key or segment, on a key given
|
|
107
|
+
* twice, and on a key that is both a value and a mapping (`a` beside
|
|
108
|
+
* `a.b`).
|
|
109
|
+
*
|
|
110
|
+
* The answer is typed {@link ConfigEntry} on the caller's word:
|
|
111
|
+
* nothing here checks a key against the shape. `index.ts`'s `defaults`
|
|
112
|
+
* is built from the registry's own keys, and `index.test.ts` reads each
|
|
113
|
+
* value back through its setting's reader.
|
|
114
|
+
*
|
|
115
|
+
* @param pairs - Each dotted key with its value.
|
|
116
|
+
* @returns A new frozen entry.
|
|
117
|
+
*/
|
|
118
|
+
export declare function entryOf(pairs: readonly (readonly [key: string, value: unknown])[]): ConfigEntry;
|
|
119
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `./config` subpath, `@open-tomato/rafa/config`: what a
|
|
3
|
+
* `rafa.config.ts` or `rafa.config.mjs` imports to type its entries.
|
|
4
|
+
*
|
|
5
|
+
* - `Config`, the list of entries a config module exports, each a
|
|
6
|
+
* `ConfigEntry`, rafa's deep partial of the nested file shape
|
|
7
|
+
* `ConfigShape` (`entry.ts`, `shape.ts`).
|
|
8
|
+
* - `defineConfig`, the identity, typed for its parameter.
|
|
9
|
+
* - {@link defaults}, the one entry holding every setting's default.
|
|
10
|
+
*
|
|
11
|
+
* ## The defaults entry
|
|
12
|
+
*
|
|
13
|
+
* {@link defaults} is built from the registry (`src/config-registry.ts`):
|
|
14
|
+
* each setting's file key, nested, holding its value from
|
|
15
|
+
* `CONFIG_DEFAULTS` in the file's spelling ({@link fileValueOf}). A
|
|
16
|
+
* setting whose default is null (`pr.base`, `hub.url`) is left out: no
|
|
17
|
+
* reader accepts null, and an absent key is what null stands for.
|
|
18
|
+
* `index.test.ts` reads every value back through its setting's reader
|
|
19
|
+
* to the default it came from.
|
|
20
|
+
*
|
|
21
|
+
* Importing this module imports the registry, so the sections are
|
|
22
|
+
* registered with core as `src/rafa.ts` and `src/index.ts` register
|
|
23
|
+
* them. `ConfigShape` does not lean on that import for its keys:
|
|
24
|
+
* `shape.ts` composes it from each section's exported interface by
|
|
25
|
+
* `import type`, so the declaration emitted for `shape.ts` imports every
|
|
26
|
+
* section's emitted `.d.ts` and `ConfigShape` names every section's keys
|
|
27
|
+
* in the published declarations as in a program built from source
|
|
28
|
+
* (`shape.test.ts` reads `ConfigShape['hub']['url']` as `string` from
|
|
29
|
+
* declarations emitted over this file).
|
|
30
|
+
*/
|
|
31
|
+
import type { ConfigEntry } from './entry.js';
|
|
32
|
+
export type { Config, ConfigEntry } from './entry.js';
|
|
33
|
+
export type { ConfigShape } from './shape.js';
|
|
34
|
+
export { defineConfig } from './entry.js';
|
|
35
|
+
/** Every setting's default, as one entry; see the module note. */
|
|
36
|
+
export declare const defaults: ConfigEntry;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
CONFIG_DEFAULTS,
|
|
4
|
+
SETTINGS,
|
|
5
|
+
SETTING_NAMES
|
|
6
|
+
} from "../index-j4k2vdz3.js";
|
|
7
|
+
import"../index-gvek4r8m.js";
|
|
8
|
+
import"../index-ykggr043.js";
|
|
9
|
+
import"../index-z1w83f81.js";
|
|
10
|
+
|
|
11
|
+
// src/config/entry.ts
|
|
12
|
+
function defineConfig(entries) {
|
|
13
|
+
return entries;
|
|
14
|
+
}
|
|
15
|
+
function nest(placed, above) {
|
|
16
|
+
const heads = [...new Set(placed.map(([[head]]) => head ?? ""))];
|
|
17
|
+
return Object.freeze(Object.fromEntries(heads.map((head) => {
|
|
18
|
+
const key = above === "" ? head : `${above}.${head}`;
|
|
19
|
+
const under = placed.filter(([[first]]) => first === head);
|
|
20
|
+
const [leaf, ...more] = under.filter(([path]) => path.length === 1);
|
|
21
|
+
if (leaf === undefined)
|
|
22
|
+
return [head, nest(under.map(([path, value]) => [path.slice(1), value]), key)];
|
|
23
|
+
if (more.length > 0 || under.length > 1)
|
|
24
|
+
throw new Error(`rafa config: ${key} is given twice, or as a value and a mapping`);
|
|
25
|
+
return [head, leaf[1]];
|
|
26
|
+
})));
|
|
27
|
+
}
|
|
28
|
+
function entryOf(pairs) {
|
|
29
|
+
const placed = pairs.map(([key, value]) => {
|
|
30
|
+
const path = key.split(".");
|
|
31
|
+
if (path.some((segment) => segment === ""))
|
|
32
|
+
throw new Error(`rafa config: ${JSON.stringify(key)} is no dotted key`);
|
|
33
|
+
return [path, value];
|
|
34
|
+
});
|
|
35
|
+
return nest(placed, "");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/config/index.ts
|
|
39
|
+
var COMMA_SEPARATED = new Set(["settingSources"]);
|
|
40
|
+
function fileValueOf(setting, value) {
|
|
41
|
+
if (value instanceof Map)
|
|
42
|
+
return Object.freeze(Object.fromEntries(value));
|
|
43
|
+
if (COMMA_SEPARATED.has(setting) && Array.isArray(value))
|
|
44
|
+
return value.join(",");
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
var defaults = entryOf(SETTING_NAMES.filter((setting) => CONFIG_DEFAULTS[setting] !== null).map((setting) => [SETTINGS[setting].key, fileValueOf(setting, CONFIG_DEFAULTS[setting])]));
|
|
48
|
+
export {
|
|
49
|
+
defineConfig,
|
|
50
|
+
defaults
|
|
51
|
+
};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nested file shape: {@link ConfigShape}, every key a config file
|
|
3
|
+
* writes, nested as the file nests it (`plan: { inject: 'stage' }` for
|
|
4
|
+
* `plan.inject`), each leaf typed as the file spells it. It is the type a
|
|
5
|
+
* `rafa.config.ts` entry is a deep partial of (`entry.ts`), and the
|
|
6
|
+
* `./config` subpath (`index.ts`) publishes it.
|
|
7
|
+
*
|
|
8
|
+
* ## The file's spelling, not the resolved value
|
|
9
|
+
*
|
|
10
|
+
* A leaf holds what the setting's reader accepts, which is not always
|
|
11
|
+
* what `RafaConfig` resolves it to. A map (`routing`, `tiers.skills`,
|
|
12
|
+
* `tiers.agents`, `logger.modules`) is a plain object here and a
|
|
13
|
+
* `ReadonlyMap` there; `loop.settingSources` is the comma-separated
|
|
14
|
+
* string the file writes (`project,local`) and a list there; an item of
|
|
15
|
+
* `prerequisites.required` or `modules` names its kind by its key
|
|
16
|
+
* (`{ tool: 'bun' }`, `{ npm: 'rafa-board' }`) where the resolved item
|
|
17
|
+
* carries `kind` and `name`; and a setting whose default is null
|
|
18
|
+
* (`pr.base`, `hub.url`) takes no null, since no reader accepts one.
|
|
19
|
+
*
|
|
20
|
+
* ## Who declares what
|
|
21
|
+
*
|
|
22
|
+
* This module declares core's own top-level keys, the keys of
|
|
23
|
+
* `packages/rafa/src/core/config/core-section.ts`, and composes {@link ConfigShape}
|
|
24
|
+
* from them and the interface each of the thirteen section files
|
|
25
|
+
* (`src/config-schema-*.ts`) exports for the keys it writes: `HubShape`
|
|
26
|
+
* for `hub`, `ReleaseShape` for `pr` and `release`, and so on, each
|
|
27
|
+
* extended by {@link ConfigShape}. A namespace two packages share is a
|
|
28
|
+
* named interface here holding core's keys and extending the part each
|
|
29
|
+
* section exports as an interface of its own: {@link LoopShape} extends
|
|
30
|
+
* `LoopRetriesShape`, `LoopContinueShape` and `WrapUpShape`,
|
|
31
|
+
* {@link BoardProjectShape} extends `BoardProjectLimitsShape`, and
|
|
32
|
+
* {@link DangerousShape} extends `ReleaseDangerousShape`.
|
|
33
|
+
*
|
|
34
|
+
* The composition is written out, not merged into this file by a
|
|
35
|
+
* section's `declare module`, so the declaration emitted for this file
|
|
36
|
+
* imports each section's emitted declaration and a reader of the
|
|
37
|
+
* `./config` subpath's `.d.ts` files alone sees every key.
|
|
38
|
+
* `shape.test.ts` emits the declarations in memory over
|
|
39
|
+
* `src/config/index.ts` and reads `ConfigShape['hub']['url']` as
|
|
40
|
+
* `string` from them.
|
|
41
|
+
*
|
|
42
|
+
* `shape.test.ts` reads every leaf back as a setting's key and every
|
|
43
|
+
* setting's key as a leaf, so a key added to a section without its leaf
|
|
44
|
+
* here, or the other way round, fails there.
|
|
45
|
+
*
|
|
46
|
+
* Every type is `import type`, so this module loads nothing.
|
|
47
|
+
*/
|
|
48
|
+
import type { BoardProjectLimitsShape } from '../config-schema-board-project.js';
|
|
49
|
+
import type { BugsShape } from '../config-schema-bugs.js';
|
|
50
|
+
import type { ErrorsShape } from '../config-schema-errors.js';
|
|
51
|
+
import type { FeaturesShape } from '../config-schema-features.js';
|
|
52
|
+
import type { HubShape } from '../config-schema-hub.js';
|
|
53
|
+
import type { IssuesShape } from '../config-schema-issues.js';
|
|
54
|
+
import type { LoggerShape } from '../config-schema-logger.js';
|
|
55
|
+
import type { LoopContinueShape } from '../config-schema-loop-continue.js';
|
|
56
|
+
import type { LoopRetriesShape } from '../config-schema-loop-retries.js';
|
|
57
|
+
import type { ReleaseDangerousShape, ReleaseShape } from '../config-schema-release.js';
|
|
58
|
+
import type { TestsShape } from '../config-schema-tests.js';
|
|
59
|
+
import type { TriageShape } from '../config-schema-triage.js';
|
|
60
|
+
import type { WrapUpShape } from '../config-schema-wrap-up.js';
|
|
61
|
+
import type { ModuleSourceKind, PrerequisiteKind } from '@open-tomato/rafa/core/config';
|
|
62
|
+
import type { BoardRelationshipMode, ClaimsAhead, ClaimsStaleAfter, ConfigVersion, DuplicatesLevel, InjectMode, LessonSwitch, OutputMode, RouteTarget, SkillResolverName, StoreBackend, SyncStrategy, TierPin, TierSwitch } from '@open-tomato/rafa/core/config/sections';
|
|
63
|
+
/**
|
|
64
|
+
* An item keyed by its kind: one of `K` as its key, naming the item.
|
|
65
|
+
* `KindKeyed<'tool' | 'env'>` is `{ tool: string } | { env: string }`.
|
|
66
|
+
*/
|
|
67
|
+
type KindKeyed<K extends string> = {
|
|
68
|
+
readonly [P in K]: {
|
|
69
|
+
readonly [Q in P]: string;
|
|
70
|
+
};
|
|
71
|
+
}[K];
|
|
72
|
+
/** One `prerequisites.required` item as a file writes it: `{ tool: 'bun', probe: 'bun --version' }`. */
|
|
73
|
+
export type PrerequisiteFileItem = KindKeyed<PrerequisiteKind> & {
|
|
74
|
+
/** The command that proves the item; left out or null to check presence alone. */
|
|
75
|
+
readonly probe?: string | null;
|
|
76
|
+
};
|
|
77
|
+
/** One `prerequisites.optional` item as a file writes it: a required item's keys and `reason`. */
|
|
78
|
+
export type OptionalPrerequisiteFileItem = PrerequisiteFileItem & {
|
|
79
|
+
/** Why the item helps, for the line naming it missing. */
|
|
80
|
+
readonly reason?: string | null;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* One `modules` entry as a file writes it: `{ npm: 'rafa-board' }`,
|
|
84
|
+
* `{ path: '../board' }`, or `{ github: 'owner/repo', ref: 'v1' }`.
|
|
85
|
+
*/
|
|
86
|
+
export type ModuleFileItem = KindKeyed<Exclude<ModuleSourceKind, 'github'>> | {
|
|
87
|
+
/** The `owner/repo` the module is cloned from. */
|
|
88
|
+
readonly github: string;
|
|
89
|
+
/** The git ref to check out; left out or null for the default branch. */
|
|
90
|
+
readonly ref?: string | null;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* The `loop` namespace: core's two keys, and the keys the
|
|
94
|
+
* `loop-retries`, `loop-continue` and `wrap-up` sections write.
|
|
95
|
+
*/
|
|
96
|
+
export interface LoopShape extends LoopRetriesShape, LoopContinueShape, WrapUpShape {
|
|
97
|
+
/** `loop.settingSources`: a comma-separated subset of `user`, `project`, `local`. */
|
|
98
|
+
readonly settingSources: string;
|
|
99
|
+
/** `loop.worktreeDir`: where the loop's worktrees are made. */
|
|
100
|
+
readonly worktreeDir: string;
|
|
101
|
+
}
|
|
102
|
+
/** The `board.project` namespace: core's two keys and the `board-project` section's limits. */
|
|
103
|
+
export interface BoardProjectShape extends BoardProjectLimitsShape {
|
|
104
|
+
/** `board.project.template`: the project board copied for a new board. */
|
|
105
|
+
readonly template: string;
|
|
106
|
+
/** `board.project.number`: the project board this repository's issues go on. */
|
|
107
|
+
readonly number: number;
|
|
108
|
+
}
|
|
109
|
+
/** The `board` namespace, core's, with the shared {@link BoardProjectShape} under `project`. */
|
|
110
|
+
export interface BoardShape {
|
|
111
|
+
/** `board.trustedAuthors`: the GitHub logins whose board items are read without a prompt. */
|
|
112
|
+
readonly trustedAuthors: readonly string[];
|
|
113
|
+
/** `board.relationships`: how a parent and its children are linked. */
|
|
114
|
+
readonly relationships: BoardRelationshipMode;
|
|
115
|
+
/** The `board.project` keys. */
|
|
116
|
+
readonly project: BoardProjectShape;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The `dangerous` namespace: each key a person's consent to a step rafa
|
|
120
|
+
* otherwise refuses. Core's two, and the one the `release` section writes.
|
|
121
|
+
*/
|
|
122
|
+
export interface DangerousShape extends ReleaseDangerousShape {
|
|
123
|
+
/** `dangerous.acceptStaleRefs`. */
|
|
124
|
+
readonly acceptStaleRefs: boolean;
|
|
125
|
+
/** `dangerous.selfUpdateDuringLoop`. */
|
|
126
|
+
readonly selfUpdateDuringLoop: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** The nested file shape: core's keys, and each section's; see the module note. */
|
|
129
|
+
export interface ConfigShape extends BugsShape, ErrorsShape, FeaturesShape, HubShape, IssuesShape, LoggerShape, ReleaseShape, TestsShape, TriageShape {
|
|
130
|
+
/** `version`: the config format's version. */
|
|
131
|
+
readonly version: ConfigVersion;
|
|
132
|
+
/** `store`: the effort store's backend. */
|
|
133
|
+
readonly store: StoreBackend;
|
|
134
|
+
/** The `effort` keys. */
|
|
135
|
+
readonly effort: {
|
|
136
|
+
readonly busyTimeoutMs: number;
|
|
137
|
+
readonly sync: SyncStrategy;
|
|
138
|
+
};
|
|
139
|
+
/** The `plan` keys. */
|
|
140
|
+
readonly plan: {
|
|
141
|
+
readonly inject: InjectMode;
|
|
142
|
+
readonly dir: string;
|
|
143
|
+
};
|
|
144
|
+
/** The `specs` keys. */
|
|
145
|
+
readonly specs: {
|
|
146
|
+
readonly dir: string;
|
|
147
|
+
};
|
|
148
|
+
/** The `tracker` keys. */
|
|
149
|
+
readonly tracker: {
|
|
150
|
+
readonly default: string;
|
|
151
|
+
readonly fallback: readonly string[];
|
|
152
|
+
};
|
|
153
|
+
/** The `learning` keys. */
|
|
154
|
+
readonly learning: {
|
|
155
|
+
readonly adapter: string;
|
|
156
|
+
readonly bless: {
|
|
157
|
+
readonly minConfidence: number;
|
|
158
|
+
};
|
|
159
|
+
readonly promote: {
|
|
160
|
+
readonly after: number;
|
|
161
|
+
readonly minConfidence: number;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
/** The `output` keys. */
|
|
165
|
+
readonly output: {
|
|
166
|
+
readonly mode: OutputMode;
|
|
167
|
+
};
|
|
168
|
+
/** The `prerequisites` keys. */
|
|
169
|
+
readonly prerequisites: {
|
|
170
|
+
readonly required: readonly PrerequisiteFileItem[];
|
|
171
|
+
readonly optional: readonly OptionalPrerequisiteFileItem[];
|
|
172
|
+
};
|
|
173
|
+
/** The `tracking` keys. */
|
|
174
|
+
readonly tracking: {
|
|
175
|
+
readonly specs: boolean;
|
|
176
|
+
readonly plans: boolean;
|
|
177
|
+
readonly all: boolean;
|
|
178
|
+
};
|
|
179
|
+
/** `modules`: where each module is installed from. */
|
|
180
|
+
readonly modules: readonly ModuleFileItem[];
|
|
181
|
+
/** `allowList`. */
|
|
182
|
+
readonly allowList: readonly string[];
|
|
183
|
+
/** The `loop` keys. */
|
|
184
|
+
readonly loop: LoopShape;
|
|
185
|
+
/** The `board` keys. */
|
|
186
|
+
readonly board: BoardShape;
|
|
187
|
+
/** The `roadmap` keys. */
|
|
188
|
+
readonly roadmap: {
|
|
189
|
+
readonly issue: number;
|
|
190
|
+
};
|
|
191
|
+
/** The `claims` keys. */
|
|
192
|
+
readonly claims: {
|
|
193
|
+
readonly staleAfter: ClaimsStaleAfter;
|
|
194
|
+
readonly ahead: ClaimsAhead;
|
|
195
|
+
};
|
|
196
|
+
/** The `cleanup` keys. */
|
|
197
|
+
readonly cleanup: {
|
|
198
|
+
readonly staleDays: number;
|
|
199
|
+
readonly worktreeIdleDays: number;
|
|
200
|
+
readonly keep: readonly string[];
|
|
201
|
+
};
|
|
202
|
+
/** The `dangerous` keys. */
|
|
203
|
+
readonly dangerous: DangerousShape;
|
|
204
|
+
/** The `status` keys. */
|
|
205
|
+
readonly status: {
|
|
206
|
+
readonly notice: boolean;
|
|
207
|
+
};
|
|
208
|
+
/** The `tiers` keys, each map a name to `false` or a tier. */
|
|
209
|
+
readonly tiers: {
|
|
210
|
+
readonly rafa: TierSwitch;
|
|
211
|
+
readonly skills: Readonly<Record<string, TierPin>>;
|
|
212
|
+
readonly agents: Readonly<Record<string, TierPin>>;
|
|
213
|
+
};
|
|
214
|
+
/** `routing`: a task shape to an agent, or `false`. */
|
|
215
|
+
readonly routing: Readonly<Record<string, RouteTarget>>;
|
|
216
|
+
/** The `task` keys. */
|
|
217
|
+
readonly task: {
|
|
218
|
+
readonly skills: SkillResolverName;
|
|
219
|
+
readonly lessons: LessonSwitch;
|
|
220
|
+
};
|
|
221
|
+
/** The `merge` keys. */
|
|
222
|
+
readonly merge: {
|
|
223
|
+
/** `merge.duplicates`: how two entries of one file setting one key are reported. */
|
|
224
|
+
readonly duplicates: DuplicatesLevel;
|
|
225
|
+
};
|
|
226
|
+
/** The `naming` keys. */
|
|
227
|
+
readonly naming: {
|
|
228
|
+
/** `naming.branch`: the template the branch `loop start` creates is named from, holding `{stub}` once. */
|
|
229
|
+
readonly branch: string;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registry: the fourteen sections of the config schema, handed to
|
|
3
|
+
* core when {@link registerCoreConfigSections} is called, and the merged schema read off
|
|
4
|
+
* them, {@link SETTINGS}, {@link CONFIG_DEFAULTS}, {@link SETTING_NAMES},
|
|
5
|
+
* {@link SETTING_BY_KEY}, {@link SECTIONS} and {@link knownKeysAbove}.
|
|
6
|
+
*
|
|
7
|
+
* Core declares the section contract (`packages/rafa/src/core/config/section.ts`) and
|
|
8
|
+
* names no section. This module, outside `packages/rafa/src/core/`, is the one place
|
|
9
|
+
* the fourteen are listed, {@link CONFIG_SECTIONS}: core's own
|
|
10
|
+
* (`CORE_SECTION`) and the thirteen files `src/config-schema-*.ts` that
|
|
11
|
+
* each export one.
|
|
12
|
+
*
|
|
13
|
+
* Importing it registers nothing. {@link registerCoreConfigSections}
|
|
14
|
+
* calls `registerConfigSections` once, with that list cut into the runs
|
|
15
|
+
* {@link SETTINGS} holds (see the order below), so `activeSettings()`
|
|
16
|
+
* and `activeDefaults()` answer every setting; a registration core
|
|
17
|
+
* refuses throws from the call, naming what it refused. The root is
|
|
18
|
+
* called, never imported for its effect: under `"sideEffects": false`
|
|
19
|
+
* in a manifest, `bun build` drops an import kept for its effect alone.
|
|
20
|
+
* The root manifest declares no such field today, since bun 1.3.14's
|
|
21
|
+
* split build breaks under it (#1213).
|
|
22
|
+
* `src/rafa.ts` and `src/index.ts` call it as they load, after their
|
|
23
|
+
* imports, ahead of `registerCoreAdapters` and before anything that
|
|
24
|
+
* loads a config; core never imports this module. Until something calls
|
|
25
|
+
* it, `loadConfig` refuses, naming this module. `bun test` calls it once
|
|
26
|
+
* for the test process, from `src/tests/preload.ts`; a child process a
|
|
27
|
+
* test spawns runs no preload, and calls the root itself. A second call
|
|
28
|
+
* finds every setting registered already and registers nothing.
|
|
29
|
+
*
|
|
30
|
+
* The call also sets core's load hook (`setConfigLoadHook` in
|
|
31
|
+
* `packages/rafa/src/core/config/section.ts`) to {@link handConfigToLogger}, so every
|
|
32
|
+
* config `loadConfig` resolves hands the logger its `logger` settings
|
|
33
|
+
* without core importing the logger's section file.
|
|
34
|
+
*
|
|
35
|
+
* ## The order
|
|
36
|
+
*
|
|
37
|
+
* {@link SETTINGS} keeps the order the schema has always reported
|
|
38
|
+
* problems in, which is not the order of the list: core's settings are
|
|
39
|
+
* taken in runs, and each section's settings are spread whole between
|
|
40
|
+
* two of them, so `hub.url` follows `effort.sync` and the `board.project`
|
|
41
|
+
* limits follow `board.project.number`. The `release` section is spread
|
|
42
|
+
* in three parts, its `pr`, `release` and `dangerous.` keys, each where
|
|
43
|
+
* its keys have always stood.
|
|
44
|
+
*
|
|
45
|
+
* Core reads every setting in the order it was registered: a layer, a
|
|
46
|
+
* resolution, and the keys a warning about an unknown key lists. So the
|
|
47
|
+
* sections are registered cut into the runs {@link SETTINGS} holds them
|
|
48
|
+
* in (`inSettingOrder`), each cut under its section's package and a
|
|
49
|
+
* section's checks on its first cut, and core's registry holds every
|
|
50
|
+
* setting in this order. Registering the list whole would put core's
|
|
51
|
+
* forty-two first, and the warning recorded in
|
|
52
|
+
* `src/tests/fixtures/config-parity/` would list `hub` after `task`.
|
|
53
|
+
* `config-registry.test.ts` holds that the registry holds the same
|
|
54
|
+
* settings, in the same order, as the same specs, and the same defaults,
|
|
55
|
+
* as the same values.
|
|
56
|
+
*
|
|
57
|
+
* ## The closed set
|
|
58
|
+
*
|
|
59
|
+
* {@link SETTINGS} is a mapped record over `ConfigSetting` built from
|
|
60
|
+
* each section file's typed settings, so a field added to `RafaConfig`
|
|
61
|
+
* without a spec in some section does not compile. The indexes are all
|
|
62
|
+
* read off it. Keys are looked up in a `Map`, never with `in` or an
|
|
63
|
+
* object index: `Bun.YAML.parse` returns a key spelled `constructor` or
|
|
64
|
+
* `__proto__` as an ordinary own key, and an object lookup would match
|
|
65
|
+
* it against `Object.prototype` instead.
|
|
66
|
+
*
|
|
67
|
+
* ## Beside core
|
|
68
|
+
*
|
|
69
|
+
* This module is the one place the six names are built: the core barrel
|
|
70
|
+
* `packages/rafa/src/core/config/index.ts` exports none of them, and a file outside
|
|
71
|
+
* `packages/rafa/src/core/` imports them from here. Core reads the registered
|
|
72
|
+
* settings and defaults through `activeSettings()` and
|
|
73
|
+
* `activeDefaults()`, and the key indexes through `activeSettingByKey()`,
|
|
74
|
+
* `activeSectionPaths()` and `activeKnownKeysAbove()`, all in
|
|
75
|
+
* `packages/rafa/src/core/config/section.ts`. Those follow registration order, which
|
|
76
|
+
* is the order here, so they answer what {@link SETTING_BY_KEY},
|
|
77
|
+
* {@link SECTIONS} and {@link knownKeysAbove} answer.
|
|
78
|
+
* `src/index.ts` publishes this module's {@link CONFIG_DEFAULTS}.
|
|
79
|
+
*/
|
|
80
|
+
import type { ConfigSection, ConfigSetting, RafaConfig, SettingSpec } from '@open-tomato/rafa/core/config';
|
|
81
|
+
/** The fourteen sections, core's first, in the order they are registered. */
|
|
82
|
+
export declare const CONFIG_SECTIONS: readonly ConfigSection[];
|
|
83
|
+
/**
|
|
84
|
+
* The hook `loadConfig` calls with every config it resolves: it hands
|
|
85
|
+
* the logger its `logger` settings, read through the logger section's
|
|
86
|
+
* `loggerSettingsOf`. Set by {@link registerCoreConfigSections}, beside
|
|
87
|
+
* the registration.
|
|
88
|
+
*/
|
|
89
|
+
export declare function handConfigToLogger(config: Readonly<RafaConfig>): void;
|
|
90
|
+
/** What every setting resolves to when no layer names it. */
|
|
91
|
+
export declare const CONFIG_DEFAULTS: Readonly<RafaConfig>;
|
|
92
|
+
/**
|
|
93
|
+
* Every setting, by name, in the order problems are reported.
|
|
94
|
+
*
|
|
95
|
+
* A mapped record rather than a list so the set is closed: a field
|
|
96
|
+
* added to `RafaConfig` without an entry here does not compile.
|
|
97
|
+
*/
|
|
98
|
+
export declare const SETTINGS: {
|
|
99
|
+
readonly [K in ConfigSetting]: SettingSpec<K>;
|
|
100
|
+
};
|
|
101
|
+
/** Every setting name, read off the closed record above. */
|
|
102
|
+
export declare const SETTING_NAMES: readonly ConfigSetting[];
|
|
103
|
+
/**
|
|
104
|
+
* Registers {@link CONFIG_SECTIONS} with core, cut into the runs
|
|
105
|
+
* {@link SETTINGS} holds them in, and sets core's load hook to
|
|
106
|
+
* {@link handConfigToLogger}.
|
|
107
|
+
*
|
|
108
|
+
* When core's registry holds every setting already, each as the same
|
|
109
|
+
* spec, it registers nothing and leaves the load hook as it is, so the
|
|
110
|
+
* preload and an entry may both call it in one process. Throws what
|
|
111
|
+
* `registerConfigSections` throws on a section core refuses, such as a
|
|
112
|
+
* setting another package registered first, leaving the registry and
|
|
113
|
+
* the load hook as they were.
|
|
114
|
+
*/
|
|
115
|
+
export declare function registerCoreConfigSections(): void;
|
|
116
|
+
/** Setting names by the dotted key the file spells them with. */
|
|
117
|
+
export declare const SETTING_BY_KEY: ReadonlyMap<string, ConfigSetting>;
|
|
118
|
+
/** Every dotted prefix a setting sits under: the sections a file opens. */
|
|
119
|
+
export declare const SECTIONS: ReadonlySet<string>;
|
|
120
|
+
/**
|
|
121
|
+
* The nearest path above `key` with known keys, and those keys. An
|
|
122
|
+
* item path such as `modules[0]` looks up `modules[]`.
|
|
123
|
+
*
|
|
124
|
+
* @param key - A dotted key a file spelled, `modules[0].kind` included.
|
|
125
|
+
* @returns The path the keys sit under, `''` for the top, and the keys.
|
|
126
|
+
*/
|
|
127
|
+
export declare function knownKeysAbove(key: string): [string, readonly string[]];
|