@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.
- package/README.md +255 -23
- 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 +101 -18
- package/dist/cli.js +74726 -62960
- 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-r28fzsvc.js → index-39kbcw68.js} +350 -165
- 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-mgh2s9bj.js → index-ykggr043.js} +58 -455
- package/dist/index-z1w83f81.js +4 -0
- package/dist/index.js +14715 -21516
- package/dist/learning/index.js +5 -6
- package/dist/plan/index.js +12 -11
- package/dist/plan-prompt.md +3 -1
- 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 +41 -3
- package/dist/index-hf2k497d.js +0 -16
- package/dist/index-nsr78ct2.js +0 -8219
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The section contract: how a slice of the config schema is handed to
|
|
3
|
+
* core, and the registry core reads the merged slices from.
|
|
4
|
+
*
|
|
5
|
+
* A {@link ConfigSection} is one package's part of the schema: its
|
|
6
|
+
* `settings` (each setting's file key, reader and command-line flag, as
|
|
7
|
+
* a partial of the record of every setting, {@link SettingsRecord}), its
|
|
8
|
+
* `defaults` (a partial of {@link RafaConfig}), and the cross-key
|
|
9
|
+
* `checks` run over the resolved config. {@link registerConfigSections}
|
|
10
|
+
* merges sections into the active registry, which {@link activeSettings},
|
|
11
|
+
* {@link activeDefaults} and {@link activeChecks} answer, and the key
|
|
12
|
+
* indexes below are read off. Core names no section here: the list of
|
|
13
|
+
* sections lives outside `packages/rafa/src/core/`, in `src/config-registry.ts`, the
|
|
14
|
+
* module that calls {@link registerConfigSections}.
|
|
15
|
+
*
|
|
16
|
+
* This file imports types alone, so it loads first in any order and can
|
|
17
|
+
* be imported by value from the loader and from every section file
|
|
18
|
+
* without closing a runtime cycle.
|
|
19
|
+
*
|
|
20
|
+
* ## The refusals
|
|
21
|
+
*
|
|
22
|
+
* A registration that breaks one of four rules throws a
|
|
23
|
+
* {@link ConfigSectionError} listing every problem it found, one
|
|
24
|
+
* sentence each, and leaves the active registry as it was:
|
|
25
|
+
*
|
|
26
|
+
* - A setting name registered by one section and again by another, in
|
|
27
|
+
* this call or an earlier one. The sentence names both packages, the
|
|
28
|
+
* one holding the name first.
|
|
29
|
+
* - A file key defined by one section and again by another under a
|
|
30
|
+
* different setting name. Two settings read off one key would
|
|
31
|
+
* answer one value under two names, so the sentence names both
|
|
32
|
+
* packages and both setting names, the one holding the key first.
|
|
33
|
+
* - A file key opening with `dangerous.` defined by one section and
|
|
34
|
+
* again by another under the same setting name. A `dangerous.*` key
|
|
35
|
+
* is a person's consent to a risk, so a second package defining it
|
|
36
|
+
* could widen what that consent was given for; the sentence names
|
|
37
|
+
* both packages, and the setting-name sentence is read beside it.
|
|
38
|
+
* Any other key redefined under the same name reads the setting-name
|
|
39
|
+
* sentence alone.
|
|
40
|
+
* - A {@link RafaConfig} field no section defines: a default given for
|
|
41
|
+
* a field no registered section has a setting for, or a setting no
|
|
42
|
+
* registered section gives a default for. The sentence names the
|
|
43
|
+
* package that gave the half it has. Types are erased at runtime, so
|
|
44
|
+
* a field declared on {@link RafaConfig} that no section mentions at
|
|
45
|
+
* all is out of this module's reach; the module that lists the
|
|
46
|
+
* sections is where a complete set is held.
|
|
47
|
+
*
|
|
48
|
+
* The completeness rule reads the registry as it would stand after the
|
|
49
|
+
* call, so a section whose setting and default come in two calls is
|
|
50
|
+
* refused at the first. A section's package must be a non-empty string,
|
|
51
|
+
* since every refusal names one.
|
|
52
|
+
*
|
|
53
|
+
* The key rules compare one section with the sections before it, in
|
|
54
|
+
* this call or an earlier one; two setting names one section gives the
|
|
55
|
+
* same key are not compared with each other.
|
|
56
|
+
*
|
|
57
|
+
* ## A registry is a value
|
|
58
|
+
*
|
|
59
|
+
* {@link mergeConfigSections} answers a new {@link ConfigSectionRegistry}
|
|
60
|
+
* and leaves the one it was handed unchanged; each section is copied and
|
|
61
|
+
* frozen as it is accepted, so editing a section object afterwards
|
|
62
|
+
* changes nothing registered. The active registry is the one
|
|
63
|
+
* module-level value: {@link registerConfigSections} replaces it with a
|
|
64
|
+
* merge and answers the one it replaced, and
|
|
65
|
+
* {@link restoreConfigSections} puts one back. Bun runs every test file
|
|
66
|
+
* in one process, so a case that registers puts the previous registry
|
|
67
|
+
* back in a `finally`, or every file bun runs later reads its sections.
|
|
68
|
+
* {@link EMPTY_CONFIG_REGISTRY} is the registry before any registration.
|
|
69
|
+
*
|
|
70
|
+
* ## The key indexes
|
|
71
|
+
*
|
|
72
|
+
* `config.ts` sorts a file's keys through three indexes of the active
|
|
73
|
+
* registry's settings: {@link activeSettingByKey}, the setting each
|
|
74
|
+
* dotted file key names; {@link activeSectionPaths}, every dotted prefix
|
|
75
|
+
* a setting sits under, which are the sections a file may open; and
|
|
76
|
+
* {@link activeKnownKeysAbove}, the keys a warning about an unknown key
|
|
77
|
+
* lists. Each is built on first read and kept per registry, so a
|
|
78
|
+
* registration or a restore is read at once and a registry is indexed
|
|
79
|
+
* once. Keys are looked up in a `Map` and a `Set`, never with `in` or an
|
|
80
|
+
* object index: `Bun.YAML.parse` returns a key spelled `constructor`,
|
|
81
|
+
* `toString` or `__proto__` as an ordinary own key, and an object lookup
|
|
82
|
+
* would match it against `Object.prototype` instead.
|
|
83
|
+
*
|
|
84
|
+
* The indexes follow registration order: the keys under a path are
|
|
85
|
+
* listed in the order their settings were registered. The registry
|
|
86
|
+
* registers its sections cut into the order the schema has always
|
|
87
|
+
* reported problems in, so a warning lists the keys it always listed;
|
|
88
|
+
* `src/config-registry.test.ts` holds the indexes to the registry's own.
|
|
89
|
+
*
|
|
90
|
+
* ## The load hook
|
|
91
|
+
*
|
|
92
|
+
* A setting core resolves can be read by a module outside `packages/rafa/src/core/`
|
|
93
|
+
* that core must not import: the logger's settings are read through
|
|
94
|
+
* `loggerSettingsOf` in `src/config-schema-logger.ts`. So the module that
|
|
95
|
+
* lists the sections also hands core one {@link ConfigLoadHook} with
|
|
96
|
+
* {@link setConfigLoadHook}, and `loadConfig` (`config-load.ts`) calls
|
|
97
|
+
* {@link activeConfigLoadHook} with every config it resolves, before it
|
|
98
|
+
* prints the config's warnings. The hook is a module-level value of its
|
|
99
|
+
* own, beside the registry rather than in it: restoring a registry
|
|
100
|
+
* leaves the hook as it was, and a case that sets one puts the previous
|
|
101
|
+
* hook back in a `finally`, as a case that registers does.
|
|
102
|
+
*/
|
|
103
|
+
import type { ConfigSetting, RafaConfig, SettingSpec } from './config-schema.js';
|
|
104
|
+
import type { ConfigSource } from './config.js';
|
|
105
|
+
/** Every setting's spec, by name: the record a section hands a part of. */
|
|
106
|
+
export type SettingsRecord = {
|
|
107
|
+
readonly [K in ConfigSetting]: SettingSpec<K>;
|
|
108
|
+
};
|
|
109
|
+
/** What a section's check reads: the resolved values, their layers and the files read. */
|
|
110
|
+
export interface ConfigCheckInput {
|
|
111
|
+
/** The value each setting resolved to. */
|
|
112
|
+
readonly config: Readonly<RafaConfig>;
|
|
113
|
+
/** The layer that answered each setting. */
|
|
114
|
+
readonly sources: Readonly<Record<ConfigSetting, ConfigSource>>;
|
|
115
|
+
/** The project's file consulted, or null when there was none. */
|
|
116
|
+
readonly path: string | null;
|
|
117
|
+
/** The user scope's file consulted, or null when there was none. */
|
|
118
|
+
readonly userPath: string | null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A cross-key refusal: the problems the resolved config holds, one
|
|
122
|
+
* sentence each, or an empty list when it holds none.
|
|
123
|
+
*/
|
|
124
|
+
export type ConfigCheck = (input: ConfigCheckInput) => readonly string[];
|
|
125
|
+
/** One package's slice of the config schema. */
|
|
126
|
+
export interface ConfigSection {
|
|
127
|
+
/** The package the section belongs to, named by every refusal. */
|
|
128
|
+
readonly package: string;
|
|
129
|
+
/** The specs of the settings the section defines. */
|
|
130
|
+
readonly settings: Partial<SettingsRecord>;
|
|
131
|
+
/** The default of each setting the section defines. */
|
|
132
|
+
readonly defaults: Partial<RafaConfig>;
|
|
133
|
+
/** The cross-key refusals run over the resolved config. */
|
|
134
|
+
readonly checks?: readonly ConfigCheck[];
|
|
135
|
+
}
|
|
136
|
+
/** The sections merged so far, and what core reads off them. */
|
|
137
|
+
export interface ConfigSectionRegistry {
|
|
138
|
+
/** Every section accepted, copied and frozen, in registration order. */
|
|
139
|
+
readonly sections: readonly ConfigSection[];
|
|
140
|
+
/** Every setting's spec, in registration order. */
|
|
141
|
+
readonly settings: Readonly<Partial<SettingsRecord>>;
|
|
142
|
+
/** Every setting's default. */
|
|
143
|
+
readonly defaults: Readonly<Partial<RafaConfig>>;
|
|
144
|
+
/** Every section's checks, in registration order. */
|
|
145
|
+
readonly checks: readonly ConfigCheck[];
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A registration refused: a setting name defined twice, a file key two
|
|
149
|
+
* sections define under two setting names or a `dangerous.` key under
|
|
150
|
+
* one, a field no section defines, or a section with no package name.
|
|
151
|
+
*/
|
|
152
|
+
export declare class ConfigSectionError extends Error {
|
|
153
|
+
/** Every problem found, one sentence each. */
|
|
154
|
+
readonly problems: readonly string[];
|
|
155
|
+
constructor(problems: readonly string[]);
|
|
156
|
+
}
|
|
157
|
+
/** The registry before any registration: no section, setting, default or check. */
|
|
158
|
+
export declare const EMPTY_CONFIG_REGISTRY: ConfigSectionRegistry;
|
|
159
|
+
/**
|
|
160
|
+
* A new registry holding `registry`'s sections and then `sections`, or a
|
|
161
|
+
* {@link ConfigSectionError} listing every problem found; see the module
|
|
162
|
+
* note. `registry` is left unchanged either way.
|
|
163
|
+
*/
|
|
164
|
+
export declare function mergeConfigSections(registry: ConfigSectionRegistry, sections: readonly ConfigSection[]): ConfigSectionRegistry;
|
|
165
|
+
/**
|
|
166
|
+
* Merges `sections` into the active registry, or throws a
|
|
167
|
+
* {@link ConfigSectionError} and leaves it unchanged. Answers the
|
|
168
|
+
* registry it replaced, for {@link restoreConfigSections}.
|
|
169
|
+
*/
|
|
170
|
+
export declare function registerConfigSections(sections: readonly ConfigSection[]): ConfigSectionRegistry;
|
|
171
|
+
/** Makes `registry` the active one: what {@link registerConfigSections} answered, or {@link EMPTY_CONFIG_REGISTRY}. */
|
|
172
|
+
export declare function restoreConfigSections(registry: ConfigSectionRegistry): void;
|
|
173
|
+
/** Every registered section, in registration order. */
|
|
174
|
+
export declare function activeSections(): readonly ConfigSection[];
|
|
175
|
+
/** Every registered setting's spec, in registration order. */
|
|
176
|
+
export declare function activeSettings(): Readonly<Partial<SettingsRecord>>;
|
|
177
|
+
/** Every registered setting's default. */
|
|
178
|
+
export declare function activeDefaults(): Readonly<Partial<RafaConfig>>;
|
|
179
|
+
/** Every registered section's checks, in registration order. */
|
|
180
|
+
export declare function activeChecks(): readonly ConfigCheck[];
|
|
181
|
+
/** Every registered setting's name, by the dotted key a file spells it with. */
|
|
182
|
+
export declare function activeSettingByKey(): ReadonlyMap<string, ConfigSetting>;
|
|
183
|
+
/** Every dotted prefix a registered setting sits under: the sections a file opens. */
|
|
184
|
+
export declare function activeSectionPaths(): ReadonlySet<string>;
|
|
185
|
+
/**
|
|
186
|
+
* The nearest path above `key` with registered keys, and those keys, in
|
|
187
|
+
* registration order. An item path such as `modules[0]` looks up the
|
|
188
|
+
* item keys of `modules`.
|
|
189
|
+
*
|
|
190
|
+
* @param key - A dotted key a file spelled, `modules[0].kind` included.
|
|
191
|
+
* @returns The path the keys sit under, `''` for the top, and the keys.
|
|
192
|
+
*/
|
|
193
|
+
export declare function activeKnownKeysAbove(key: string): [string, readonly string[]];
|
|
194
|
+
/**
|
|
195
|
+
* What `loadConfig` hands every config it resolves to, before printing
|
|
196
|
+
* its warnings: the reading of settings a module outside `packages/rafa/src/core/`
|
|
197
|
+
* acts on. See the module note.
|
|
198
|
+
*/
|
|
199
|
+
export type ConfigLoadHook = (config: Readonly<RafaConfig>) => void;
|
|
200
|
+
/**
|
|
201
|
+
* Makes `hook` the one `loadConfig` calls, or clears it with null.
|
|
202
|
+
* Answers the hook it replaced, for a caller to put back.
|
|
203
|
+
*/
|
|
204
|
+
export declare function setConfigLoadHook(hook: ConfigLoadHook | null): ConfigLoadHook | null;
|
|
205
|
+
/** The hook `loadConfig` calls with every config it resolves, or null when none is set. */
|
|
206
|
+
export declare function activeConfigLoadHook(): ConfigLoadHook | null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The barrel over the config's value readers: every name
|
|
3
|
+
* `config-sections.ts`, `config-readers.ts` and `branch-template.ts`
|
|
4
|
+
* export, and nothing else.
|
|
5
|
+
*
|
|
6
|
+
* A file outside `packages/rafa/src/core/` imports this file and never the three behind
|
|
7
|
+
* it (`scripts/survey/core-barrels.ts` measures that, and
|
|
8
|
+
* `src/tests/core-barrels.sweep.test.ts` holds it against the tree). A
|
|
9
|
+
* file inside `packages/rafa/src/core/` imports the three directly and never this file.
|
|
10
|
+
*
|
|
11
|
+
* ## Why the pair has a barrel of its own
|
|
12
|
+
*
|
|
13
|
+
* `packages/rafa/src/core/config/` has three barrels, all listed under `CORE_BARRELS`
|
|
14
|
+
* in `scripts/survey/core-moves.ts`. This one holds the leaf pair: the
|
|
15
|
+
* two files import each other one way (`config-readers.ts` reads
|
|
16
|
+
* `config-sections.ts`), `node:path`, and four modules that import none
|
|
17
|
+
* of the config back. The schema's section files (`src/config-schema-*.ts`)
|
|
18
|
+
* import the pair by value. While `config-merged.ts` imported them by
|
|
19
|
+
* value in turn, one barrel over the pair and the schema would have made
|
|
20
|
+
* every section file import a barrel that imports it back: a runtime
|
|
21
|
+
* cycle that fails as a `ReferenceError` at load, in one import order
|
|
22
|
+
* only. That file is retired, and measured since, no value import of a
|
|
23
|
+
* file behind `index.ts` reaches a section file, so that cycle is no
|
|
24
|
+
* longer what keeps the two barrels apart; they stay as the move left
|
|
25
|
+
* them, a name with one barrel to be learned from.
|
|
26
|
+
*
|
|
27
|
+
* `branch-template.ts` joined the pair with the readers of a branch name
|
|
28
|
+
* through the `naming.branch` template, `branchGlob` and `stubOfBranch`.
|
|
29
|
+
* It imports `config-readers.ts` alone, so it is a leaf as the pair is,
|
|
30
|
+
* and it sits beside `branchFromTemplate`, the writer it reads back.
|
|
31
|
+
*
|
|
32
|
+
* ## What it exports
|
|
33
|
+
*
|
|
34
|
+
* Each name is spelled, types apart from values, as the entries
|
|
35
|
+
* `src/index.ts` and `src/plan/index.ts` spell theirs.
|
|
36
|
+
*
|
|
37
|
+
* `sections.test.ts` holds the list to the three files: every name any
|
|
38
|
+
* of them exports is here once, as the same binding, and no name is here
|
|
39
|
+
* that none of them exports.
|
|
40
|
+
*/
|
|
41
|
+
export type { ReleasePublishMode, ReleaseSettleMode, ReleaseStrategy, ReleaseTagMode, VersionCollisionMode, } from './config-readers.js';
|
|
42
|
+
export type { BoardRelationshipMode, ClaimsAhead, ClaimsStaleAfter, ClaudeSettingSource, ConfigExtra, ConfigVersion, DuplicatesLevel, InjectMode, LessonSwitch, Mapping, OutputMode, PrProvider, Reader, Reading, ReleaseEnabled, RouteTarget, SkillResolverName, StoreBackend, SyncStrategy, TierPin, TierSwitch, ValueAt, } from './config-sections.js';
|
|
43
|
+
export { branchGlob, stubOfBranch } from './branch-template.js';
|
|
44
|
+
export { BRANCH_STUB, branchFromTemplate, branchTemplate, DEFAULT_BRANCH_TEMPLATE, directory, fragmentsDirectory, isBranchTemplate, mapOf, RELEASE_PUBLISH_MODES, RELEASE_SETTLE_MODES, RELEASE_STRATEGIES, RELEASE_TAG_MODES, releaseFile, releasePublishMode, releaseSettleMode, releaseStrategy, releaseTagMode, routeTable, tierPins, trackerKind, VERSION_COLLISION_MODES, versionCollisionMode, } from './config-readers.js';
|
|
45
|
+
export { below, BOARD_PROJECT_TEMPLATE_DEFAULT, BOARD_RELATIONSHIP_MODES, BUSY_TIMEOUT_MAX_MS, BUSY_TIMEOUT_MIN_MS, busyTimeoutMs, claimDurationHours, CLAIMS_AHEAD, CLAIMS_STALE_DISABLED, claimsAhead, claimsStaleAfter, CLAUDE_SETTING_SOURCES, confidence, CONFIDENCE_MAX, CONFIDENCE_MIN, CONFIG_VERSIONS, dayCount, describeValue, DUPLICATE_LEVELS, duplicatesLevel, flag, githubLogin, INJECT_MODES, isBusyTimeoutMs, isGitHubLogin, isMapping, issueNumber, LESSON_SWITCHES, lessonSwitch, listOf, mapReading, messageOf, oneOf, OUTPUT_MODES, PR_PROVIDERS, projectNumber, projectUrl, recurrenceCount, refused, refusedWith, RELEASE_AUTO, releaseEnabled, routeTarget, SKILL_RESOLVERS, skillResolverName, STORE_BACKENDS, subsetOf, SYNC_STRATEGIES, text, TIER_SWITCHES, tierPin, tierSwitch, usdAmount, } from './config-sections.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ConfigSection } from './section.js';
|
|
2
|
+
import type { StandardSchemaV1 } from '@open-tomato/define-config';
|
|
3
|
+
/** The vendor every schema built here names. */
|
|
4
|
+
export declare const SCHEMA_VENDOR = "rafa";
|
|
5
|
+
/**
|
|
6
|
+
* One pair of `createLoader`'s `schema` list: the key path of the
|
|
7
|
+
* subtree, outermost key first, and the schema that subtree must
|
|
8
|
+
* satisfy. The empty path names the whole value.
|
|
9
|
+
*/
|
|
10
|
+
export type ConfigSchemaSection = readonly [path: readonly string[], schema: StandardSchemaV1];
|
|
11
|
+
/**
|
|
12
|
+
* A Standard Schema V1 schema whose `validate` runs `section`'s readers
|
|
13
|
+
* over the merged mapping and answers one issue per refusal at the
|
|
14
|
+
* refused key's path; see the module note.
|
|
15
|
+
*
|
|
16
|
+
* @param section - The section whose settings' readers judge the value.
|
|
17
|
+
* @returns A schema validating synchronously, vendor {@link SCHEMA_VENDOR}.
|
|
18
|
+
*/
|
|
19
|
+
export declare function schemaOf(section: ConfigSection): StandardSchemaV1;
|
|
20
|
+
/**
|
|
21
|
+
* The `[path, schema]` list `createLoader`'s `schema` option takes: one
|
|
22
|
+
* pair per section, in the order given, each at the empty path.
|
|
23
|
+
*
|
|
24
|
+
* @param sections - The sections to validate the merged config with.
|
|
25
|
+
* @returns One frozen pair per section.
|
|
26
|
+
*/
|
|
27
|
+
export declare function schemaSectionsOf(sections: readonly ConfigSection[]): readonly ConfigSchemaSection[];
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conventional type of a derived subject.
|
|
3
|
+
*
|
|
4
|
+
* Exactly the six {@link COMMIT_TYPE_RULES} can select, one of which
|
|
5
|
+
* is also {@link DEFAULT_COMMIT_TYPE}. `ci` and `perf` are legal in
|
|
6
|
+
* this repo's history and are absent here on purpose: no rule selects
|
|
7
|
+
* them, and a member the inference can never answer would be a column
|
|
8
|
+
* that always reads empty.
|
|
9
|
+
*/
|
|
10
|
+
export type CommitType = 'chore' | 'docs' | 'feat' | 'fix' | 'refactor' | 'test';
|
|
11
|
+
/** What a task text is labelled when no rule matches it. */
|
|
12
|
+
export declare const DEFAULT_COMMIT_TYPE: CommitType;
|
|
13
|
+
/** One inference rule. The first whose pattern matches wins. */
|
|
14
|
+
export interface CommitTypeRule {
|
|
15
|
+
/** Type this rule selects. */
|
|
16
|
+
type: CommitType;
|
|
17
|
+
/** Matched against the normalised, still-capitalised task text. */
|
|
18
|
+
pattern: RegExp;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The inference table, in priority order.
|
|
22
|
+
*
|
|
23
|
+
* It is a LABEL and not a classification: a wrong type costs a
|
|
24
|
+
* slightly-off word at the front of a subject whose body carries the
|
|
25
|
+
* whole task text, so the rules are kept few and readable rather
|
|
26
|
+
* than exhaustive. Two orderings in it are load-bearing.
|
|
27
|
+
*
|
|
28
|
+
* `test` runs first because a test task is the one shape whose verb
|
|
29
|
+
* is indistinguishable from a feature's — both begin `Add` — and only
|
|
30
|
+
* the noun separates them.
|
|
31
|
+
*
|
|
32
|
+
* `docs` runs before every verb rule because a documentation task's
|
|
33
|
+
* verb is whatever the edit happens to be (`Remove the four commit
|
|
34
|
+
* instructions from PROMPT.md`, `Rewrite the root AGENTS.md`,
|
|
35
|
+
* `Split packages/service/AGENTS.md`), while the thing it names is
|
|
36
|
+
* reliably a markdown file. The known cost of that order is a real
|
|
37
|
+
* code task that merely mentions a `.md` path, which is labelled
|
|
38
|
+
* `docs`; the body still says what it did.
|
|
39
|
+
*/
|
|
40
|
+
export declare const COMMIT_TYPE_RULES: readonly CommitTypeRule[];
|
|
41
|
+
/**
|
|
42
|
+
* Longest subject this module will produce, including the type
|
|
43
|
+
* prefix. Git's own convention, and the ceiling GitHub renders
|
|
44
|
+
* without eliding.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MAX_SUBJECT_LENGTH = 72;
|
|
47
|
+
/** Description used when the task text carries no words at all. */
|
|
48
|
+
export declare const FALLBACK_DESCRIPTION = "complete the scoped task";
|
|
49
|
+
/**
|
|
50
|
+
* Characters of a failed git invocation kept on the result.
|
|
51
|
+
*
|
|
52
|
+
* A rejected hook can print a finding per staged file, and the loop
|
|
53
|
+
* echoes this to a console a human is scrolling. Truncation is
|
|
54
|
+
* marked, so a caller can tell a short message from a cut one.
|
|
55
|
+
*/
|
|
56
|
+
export declare const MAX_MESSAGE_CHARS = 4000;
|
|
57
|
+
/** Collapses every whitespace run, newlines included, to one space. */
|
|
58
|
+
export declare function normaliseTaskText(taskText: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Picks the conventional type for a task text.
|
|
61
|
+
*
|
|
62
|
+
* Falls back to {@link DEFAULT_COMMIT_TYPE}, which is what an
|
|
63
|
+
* unrecognised verb gets rather than an exception: the loop must
|
|
64
|
+
* still be able to commit a task whose wording nobody anticipated.
|
|
65
|
+
*/
|
|
66
|
+
export declare function inferCommitType(taskText: string): CommitType;
|
|
67
|
+
/**
|
|
68
|
+
* The task text up to its first comma, colon or parenthesis outside a
|
|
69
|
+
* code span, trailing whitespace dropped. The whole text when nothing
|
|
70
|
+
* ends it, and the empty string when the text opens on an ending.
|
|
71
|
+
*
|
|
72
|
+
* A subject quotes the first clause rather than the first 72
|
|
73
|
+
* characters because a width cut stops wherever the width falls: the
|
|
74
|
+
* 2026-09-14 cutover run committed a subject ending `(under 60 lines)
|
|
75
|
+
* stating that the loop`, mid-sentence, where the clause before the
|
|
76
|
+
* parenthesis was the whole of what it needed to say.
|
|
77
|
+
*
|
|
78
|
+
* The code-span exception is what makes the rule usable on a plan,
|
|
79
|
+
* which names identifiers in backticks: the comma in `run(a, b)` is
|
|
80
|
+
* part of a name, never the end of a clause. A backtick run that
|
|
81
|
+
* nothing closes opens no span, as CommonMark reads it, so it is
|
|
82
|
+
* literal text and the endings after it still count.
|
|
83
|
+
*/
|
|
84
|
+
export declare function firstClause(text: string): string;
|
|
85
|
+
/** How a subject is built. */
|
|
86
|
+
export interface SubjectOptions {
|
|
87
|
+
/** Conventional scope, rendered as `type(scope):`. Optional. */
|
|
88
|
+
scope?: string;
|
|
89
|
+
/** Cap including the prefix. Defaults to {@link MAX_SUBJECT_LENGTH}. */
|
|
90
|
+
maxLength?: number;
|
|
91
|
+
}
|
|
92
|
+
/** A derived subject and what deriving it decided. */
|
|
93
|
+
export interface DerivedSubject {
|
|
94
|
+
/** The whole subject line, prefix included. */
|
|
95
|
+
subject: string;
|
|
96
|
+
/** Type the rules selected. */
|
|
97
|
+
type: CommitType;
|
|
98
|
+
/**
|
|
99
|
+
* True when the description was cut to fit the cap. Ending at the
|
|
100
|
+
* first clause is not a cut: a clause that fits answers false
|
|
101
|
+
* however much task text follows it.
|
|
102
|
+
*/
|
|
103
|
+
truncated: boolean;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Derives a conventional-commit subject from a task's text.
|
|
107
|
+
*
|
|
108
|
+
* The description is the text's {@link firstClause}, cut at a word
|
|
109
|
+
* boundary when that clause alone is longer than the cap leaves room
|
|
110
|
+
* for. The TYPE is still inferred from the whole text, since a clause
|
|
111
|
+
* can end before the path or the noun the rules read. Whatever the
|
|
112
|
+
* subject leaves out, the body {@link buildCommitMessage} writes
|
|
113
|
+
* carries.
|
|
114
|
+
*
|
|
115
|
+
* Deterministic over its input: the same task text answers the same
|
|
116
|
+
* subject on every machine and every run, which is what lets the
|
|
117
|
+
* loop's commits be predicted by a test instead of inspected by a
|
|
118
|
+
* human.
|
|
119
|
+
*/
|
|
120
|
+
export declare function deriveCommitSubject(taskText: string, options?: SubjectOptions): DerivedSubject;
|
|
121
|
+
/** A subject with the body that carries the whole task line. */
|
|
122
|
+
export interface CommitMessage extends DerivedSubject {
|
|
123
|
+
/**
|
|
124
|
+
* The whole normalised task text, written whatever the subject kept
|
|
125
|
+
* of it. The empty string only for a task text with no words, which
|
|
126
|
+
* has no line to carry.
|
|
127
|
+
*/
|
|
128
|
+
body: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Builds the message a task's commit is made with.
|
|
132
|
+
*
|
|
133
|
+
* The body is the whole task line on every commit. The subject holds
|
|
134
|
+
* one clause at most, so it seldom carries the sentence, and a body
|
|
135
|
+
* written only when the subject lost words would leave a reader of
|
|
136
|
+
* `git log` checking, commit by commit, which of the two holds it. The
|
|
137
|
+
* sentence is the only record of what the commit was asked to do, so
|
|
138
|
+
* it sits in the same place every time, even where that repeats a
|
|
139
|
+
* subject that already says all of it.
|
|
140
|
+
*/
|
|
141
|
+
export declare function buildCommitMessage(taskText: string, options?: SubjectOptions): CommitMessage;
|
|
142
|
+
/** Argv that stages the whole worktree. */
|
|
143
|
+
export declare function stageAllArgs(): string[];
|
|
144
|
+
/**
|
|
145
|
+
* Argv that answers whether anything is staged: exit 0 for nothing,
|
|
146
|
+
* exit 1 for something. Exported so a caller reading the exit code
|
|
147
|
+
* can see which command produced it.
|
|
148
|
+
*/
|
|
149
|
+
export declare function stagedChangesArgs(): string[];
|
|
150
|
+
/**
|
|
151
|
+
* Argv that makes the commit.
|
|
152
|
+
*
|
|
153
|
+
* `--cleanup=whitespace` is spelled out because strip DELETES every
|
|
154
|
+
* line beginning with `#`, and a task text is free to open on a shell
|
|
155
|
+
* comment or a markdown heading. It is NOT defending against git's
|
|
156
|
+
* default: for a `-m` message the default already behaves as
|
|
157
|
+
* whitespace, strip being the default only when the message is to be
|
|
158
|
+
* edited. What it defends against is a `commit.cleanup=strip`
|
|
159
|
+
* CONFIGURATION, which a machine's global git config is free to set
|
|
160
|
+
* (measured, git 2.50.1). Since {@link buildCommitMessage} collapses
|
|
161
|
+
* the task text to one line, the whole reachable difference is a task
|
|
162
|
+
* text that OPENS on a hash.
|
|
163
|
+
*
|
|
164
|
+
* Two `-m` arguments rather than one joined string: git inserts the
|
|
165
|
+
* blank line between subject and body itself, so the separator
|
|
166
|
+
* cannot drift.
|
|
167
|
+
*/
|
|
168
|
+
export declare function commitArgs(subject: string, body?: string): string[];
|
|
169
|
+
/** Argv that reads the sha the commit just produced. */
|
|
170
|
+
export declare function headShaArgs(): string[];
|
|
171
|
+
/** One git invocation's result, as the runner reports it. */
|
|
172
|
+
export interface GitRunResult {
|
|
173
|
+
/** Exit code, or null when the process was killed or never ran. */
|
|
174
|
+
status: number | null;
|
|
175
|
+
stdout: string;
|
|
176
|
+
stderr: string;
|
|
177
|
+
}
|
|
178
|
+
/** Runs git with the given argv. The seam every test drives. */
|
|
179
|
+
export type GitRunner = (args: string[]) => GitRunResult;
|
|
180
|
+
/** Which invocation a failure came from. */
|
|
181
|
+
export type CommitStep = 'stage' | 'inspect' | 'commit';
|
|
182
|
+
/** What one attempt did. */
|
|
183
|
+
export type CommitOutcome = 'committed' | 'nothing-to-commit' | 'failed';
|
|
184
|
+
/** The whole result of one attempt. */
|
|
185
|
+
export interface CommitAttempt {
|
|
186
|
+
outcome: CommitOutcome;
|
|
187
|
+
/** Subject the commit was made with, derived either way. */
|
|
188
|
+
subject: string;
|
|
189
|
+
/** Sha of the new commit, or null when none was made. */
|
|
190
|
+
sha: string | null;
|
|
191
|
+
/** Invocation that failed, or null when none did. */
|
|
192
|
+
failedStep: CommitStep | null;
|
|
193
|
+
/** That invocation's exit code, or null. */
|
|
194
|
+
exitCode: number | null;
|
|
195
|
+
/** Its stderr and stdout, capped. Empty when nothing failed. */
|
|
196
|
+
message: string;
|
|
197
|
+
}
|
|
198
|
+
/** How an attempt is made. */
|
|
199
|
+
export interface CommitOptions {
|
|
200
|
+
/** The task's text, which the subject is derived from. */
|
|
201
|
+
taskText: string;
|
|
202
|
+
/** Directory git runs in. Defaults to the current one. */
|
|
203
|
+
cwd?: string;
|
|
204
|
+
/** Conventional scope for the subject. Optional. */
|
|
205
|
+
scope?: string;
|
|
206
|
+
/** Cap for the subject. Defaults to {@link MAX_SUBJECT_LENGTH}. */
|
|
207
|
+
maxLength?: number;
|
|
208
|
+
/** Runner override. Defaults to a real `git` spawn in `cwd`. */
|
|
209
|
+
runGit?: GitRunner;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The default runner: a real `git` in `cwd`.
|
|
213
|
+
*
|
|
214
|
+
* `spawnSync` and not `execFileSync`, because two of the three
|
|
215
|
+
* invocations use their exit code as an ANSWER rather than as an
|
|
216
|
+
* error — `git diff --cached --quiet` exits 1 to say a commit is
|
|
217
|
+
* warranted, and a thrown exception there would turn the ordinary
|
|
218
|
+
* case into the failure path.
|
|
219
|
+
*/
|
|
220
|
+
export declare function spawnGit(cwd: string): GitRunner;
|
|
221
|
+
/**
|
|
222
|
+
* Stages the worktree and commits it under a subject derived from
|
|
223
|
+
* the task's text.
|
|
224
|
+
*
|
|
225
|
+
* The three invocations run in a fixed order and each one's failure
|
|
226
|
+
* stops the attempt, so a caller never sees a `committed` result
|
|
227
|
+
* whose commit did not happen. The fourth read — the sha — is the
|
|
228
|
+
* exception: it runs AFTER the commit succeeded, so a failure there
|
|
229
|
+
* leaves the outcome `committed` with a null sha rather than
|
|
230
|
+
* retracting a commit that is already in the history.
|
|
231
|
+
*/
|
|
232
|
+
export declare function commitTaskWork(options: CommitOptions): CommitAttempt;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam every `gh` command goes through: the runner's type and what
|
|
3
|
+
* one command answers.
|
|
4
|
+
*
|
|
5
|
+
* Declared here, below the `github` tracker that spawns `gh`, so the
|
|
6
|
+
* adapter registry types its `gh` option without importing the tracker.
|
|
7
|
+
* `src/adapters/tracker/github.ts` imports both names from this file
|
|
8
|
+
* and re-exports them under the same names, so none of its importers
|
|
9
|
+
* changes.
|
|
10
|
+
*/
|
|
11
|
+
/** What one `gh` command answered. */
|
|
12
|
+
export interface GhResult {
|
|
13
|
+
/** True when `gh` exited 0. */
|
|
14
|
+
readonly ok: boolean;
|
|
15
|
+
readonly stdout: string;
|
|
16
|
+
readonly stderr: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Runs `gh` with the arguments after its name. A command that fails,
|
|
20
|
+
* or could not be run, answers `ok` false rather than rejecting.
|
|
21
|
+
* `stdin`, when given, is the whole of what `gh` reads on its standard
|
|
22
|
+
* input; left out, `gh` reads a closed one.
|
|
23
|
+
*/
|
|
24
|
+
export type GhRunner = (args: readonly string[], stdin?: string) => Promise<GhResult>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** What one git command answered. Never a throw; see the module note. */
|
|
2
|
+
export interface GitResult {
|
|
3
|
+
/** True when git exited 0. */
|
|
4
|
+
readonly ok: boolean;
|
|
5
|
+
/** Its standard output, empty when it wrote none. */
|
|
6
|
+
readonly stdout: string;
|
|
7
|
+
/** Its standard error, empty when it wrote none. */
|
|
8
|
+
readonly stderr: string;
|
|
9
|
+
}
|
|
10
|
+
/** Runs git with the arguments after its name, in the directory it was made for. */
|
|
11
|
+
export type GitRunner = (args: readonly string[]) => GitResult;
|
|
12
|
+
/**
|
|
13
|
+
* Makes the runner that spawns `git` in `cwd`, under `LC_ALL=C`, with
|
|
14
|
+
* its output read as UTF-8. It never throws; see the module note.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createGitRunner(cwd: string): GitRunner;
|
|
17
|
+
/**
|
|
18
|
+
* What git said, its standard error first, since that is where it
|
|
19
|
+
* writes its refusals and its progress. Empty when it said nothing at
|
|
20
|
+
* all, which a successful `git switch` does.
|
|
21
|
+
*/
|
|
22
|
+
export declare function gitSaid(result: GitResult): string;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The barrel over git: every name `git.ts`, `commit.ts` and
|
|
3
|
+
* `gh-runner.ts` export but one, and nothing else.
|
|
4
|
+
*
|
|
5
|
+
* A file outside `packages/rafa/src/core/` imports this file and never the two behind
|
|
6
|
+
* it (`scripts/survey/core-barrels.ts` measures that, and
|
|
7
|
+
* `src/tests/core-barrels.sweep.test.ts` holds it against the tree). A
|
|
8
|
+
* file inside `packages/rafa/src/core/` imports the two directly and never this file.
|
|
9
|
+
* None does today.
|
|
10
|
+
*
|
|
11
|
+
* ## What sits behind it
|
|
12
|
+
*
|
|
13
|
+
* - `git.ts`: the runner that spawns `git` in a directory and answers
|
|
14
|
+
* what git said instead of throwing, with the reader of that answer;
|
|
15
|
+
* - `commit.ts`: staging and committing one task's work on the loop's
|
|
16
|
+
* behalf, the subject derived from the task text, and the argv of
|
|
17
|
+
* each step;
|
|
18
|
+
* - `gh-runner.ts`: the type of the runner every `gh` command goes
|
|
19
|
+
* through and what one command answers, types alone, imported by
|
|
20
|
+
* nothing.
|
|
21
|
+
*
|
|
22
|
+
* ## The one name the two files share
|
|
23
|
+
*
|
|
24
|
+
* Both files export a type named `GitRunner`, and they are two types.
|
|
25
|
+
* `git.ts` declares `(args: readonly string[]) => GitResult`, the seam
|
|
26
|
+
* the callers of this barrel stub. `commit.ts` declares
|
|
27
|
+
* `(args: string[]) => GitRunResult`, the runner `CommitOptions.runGit`
|
|
28
|
+
* takes, which carries an exit status where the first carries `ok`.
|
|
29
|
+
*
|
|
30
|
+
* One barrel exports one binding under a name, so `GitRunner` here is
|
|
31
|
+
* the one `git.ts` declares, and the one of `commit.ts` is not exported
|
|
32
|
+
* from this file. The move changed paths and no logic, so neither type
|
|
33
|
+
* was renamed, and the barrel coins no second name for the one it
|
|
34
|
+
* leaves out.
|
|
35
|
+
*
|
|
36
|
+
* Measured when the two moved: 138 files under `src/` imported
|
|
37
|
+
* `git.ts`, and 107 of them took its `GitRunner`. Eleven imported
|
|
38
|
+
* `commit.ts`, and one of those took its `GitRunner`:
|
|
39
|
+
* `commit.test.ts`, which moved with it and imports it directly. A
|
|
40
|
+
* caller outside `packages/rafa/src/core/` that stubs the commit runner types it
|
|
41
|
+
* through `CommitOptions['runGit']`, and `GitRunResult` is exported for
|
|
42
|
+
* what it answers.
|
|
43
|
+
*
|
|
44
|
+
* ## Why one barrel can hold both
|
|
45
|
+
*
|
|
46
|
+
* A barrel that groups a file with a file outside `packages/rafa/src/core/` that
|
|
47
|
+
* imports the barrel back by value is a runtime cycle. `commit.ts`
|
|
48
|
+
* imports `node:child_process` and no file. `git.ts` imports one file by
|
|
49
|
+
* value: `packages/rafa/src/core/config/config-sections.ts`, for `messageOf`. That
|
|
50
|
+
* file imports one file outside `packages/rafa/src/core/` by value,
|
|
51
|
+
* `packages/rafa/src/schema/tiers.ts`, and it does not reach this barrel.
|
|
52
|
+
*
|
|
53
|
+
* `src/pr/index.ts`, the `pr` subject's barrel, re-exports the four
|
|
54
|
+
* names of `git.ts` from this file, as it re-exported them from
|
|
55
|
+
* `git.ts` before the move. `config-sections.ts` imports
|
|
56
|
+
* `src/pr/types.ts` directly and not that barrel, which is why the edge
|
|
57
|
+
* closes nothing.
|
|
58
|
+
*
|
|
59
|
+
* Measured when the two moved: the value imports of the non-test files
|
|
60
|
+
* under `src/` and `packages/` held six cycles before the move and the
|
|
61
|
+
* same six after it, none through a file of this folder. The control,
|
|
62
|
+
* the same tree with `src/pr/types.ts` taking one value (`gitSaid`) from
|
|
63
|
+
* this barrel, held a seventh: that file, `config-sections.ts`, `git.ts`
|
|
64
|
+
* and this one. No load order of the control was run.
|
|
65
|
+
*
|
|
66
|
+
* `docs/survey/cluster-map.json` places `git.ts` and `commit.ts` in two
|
|
67
|
+
* clusters, and this file, which it does not name, lands by its folder
|
|
68
|
+
* in the cluster of `git.ts`. `src/tests/import-cycle.sweep.test.ts`
|
|
69
|
+
* reads cycles and this file is in none.
|
|
70
|
+
*
|
|
71
|
+
* ## What it exports
|
|
72
|
+
*
|
|
73
|
+
* Each name is spelled, types apart from values, as the other core
|
|
74
|
+
* barrels spell theirs. No name here is part of the published surface:
|
|
75
|
+
* `src/index.ts` re-exports nothing from this file.
|
|
76
|
+
*
|
|
77
|
+
* `index.test.ts` holds the list to the two files: every name either
|
|
78
|
+
* exports is here once, as the same binding, `GitRunner` as the type
|
|
79
|
+
* `git.ts` declares, and no other name is here.
|
|
80
|
+
*/
|
|
81
|
+
export type { GhResult, GhRunner } from './gh-runner.js';
|
|
82
|
+
export type { GitResult, GitRunner } from './git.js';
|
|
83
|
+
export type { CommitAttempt, CommitMessage, CommitOptions, CommitOutcome, CommitStep, CommitType, CommitTypeRule, DerivedSubject, GitRunResult, SubjectOptions, } from './commit.js';
|
|
84
|
+
export { createGitRunner, gitSaid } from './git.js';
|
|
85
|
+
export { buildCommitMessage, COMMIT_TYPE_RULES, commitArgs, commitTaskWork, DEFAULT_COMMIT_TYPE, deriveCommitSubject, FALLBACK_DESCRIPTION, firstClause, headShaArgs, inferCommitType, MAX_MESSAGE_CHARS, MAX_SUBJECT_LENGTH, normaliseTaskText, spawnGit, stageAllArgs, stagedChangesArgs, } from './commit.js';
|