@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
package/README.md
CHANGED
|
@@ -182,9 +182,11 @@ the next one, so you rarely have to remember it.
|
|
|
182
182
|
stored, one commit. A task that reports `blocked` is marked and the
|
|
183
183
|
run stops with the reason; fix what it names and start again, and the
|
|
184
184
|
blocked task goes first. After the last task a wrap-up session syncs
|
|
185
|
-
with the base
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
with the base and rewrites the release fragment's notes into changelog
|
|
186
|
+
lines, when the project has fragments. The loop writes the fragment
|
|
187
|
+
(the plan's level and notes) and commits it, pushes, opens the pull
|
|
188
|
+
request and waits for CI, spending repair sessions on a red one. The
|
|
189
|
+
version and the changelog are left to `rafa release settle`.
|
|
188
190
|
|
|
189
191
|
From another terminal: `rafa loop status`, `rafa loop pause` (after the
|
|
190
192
|
running task), `rafa loop stop` (now).
|
|
@@ -205,12 +207,12 @@ the next one, so you rarely have to remember it.
|
|
|
205
207
|
|
|
206
208
|
### Release fragments and settling
|
|
207
209
|
|
|
208
|
-
A branch no longer owns a version number. Instead, the wrap-up
|
|
209
|
-
release fragment (a small markdown file naming the
|
|
210
|
-
and `rafa release settle` assigns the version
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
under one version.
|
|
210
|
+
A branch no longer owns a version number. Instead, the loop's wrap-up
|
|
211
|
+
writes and commits a release fragment (a small markdown file naming the
|
|
212
|
+
plan, level and notes), and `rafa release settle` assigns the version and
|
|
213
|
+
folds the changelog on the base branch after merges. This lets several
|
|
214
|
+
branches merge in any order without a version collision: whichever
|
|
215
|
+
machine settles first releases all waiting fragments under one version.
|
|
214
216
|
|
|
215
217
|
The pull request shows a forecast of what version the branch would get if
|
|
216
218
|
merged now. The fragment is stored under `release.fragments` (default
|
|
@@ -218,10 +220,19 @@ merged now. The fragment is stored under `release.fragments` (default
|
|
|
218
220
|
waiting and suggests running settle. `rafa pr list` marks forecasts as
|
|
219
221
|
`(base moved)` if the base branch changed since the forecast was written.
|
|
220
222
|
|
|
223
|
+
A workspace package under `packages/` that is not `private: true` can release
|
|
224
|
+
on its own. A fragment names it with a fourth front-matter line,
|
|
225
|
+
`package: <name>` (the package's manifest `name`); a fragment without the line
|
|
226
|
+
is the root's. Settle then moves that package's version, changelog and tag
|
|
227
|
+
beside the root's, and `rafa release list` prints one row per unit that
|
|
228
|
+
releases: the root, then each publishable package, with its version, waiting
|
|
229
|
+
fragments and newest tag. `context/release.md` has the rules.
|
|
230
|
+
|
|
221
231
|
Every project starts with fragments settling to the base branch and tagging
|
|
222
232
|
by hand. You can configure settle to open a pending release pull request
|
|
223
233
|
instead (for protected base branches), and have settle tag the commit
|
|
224
|
-
automatically (for CI ownership of releases).
|
|
234
|
+
automatically (for CI ownership of releases). Every key is optional; the
|
|
235
|
+
examples below set `release.settle`, `release.tag` and `pr.versionCollision`:
|
|
225
236
|
|
|
226
237
|
```yaml
|
|
227
238
|
# Empty config: fragments in .changes/, semver-by-level, settle pushes, tags by hand
|
|
@@ -242,14 +253,74 @@ pr:
|
|
|
242
253
|
versionCollision: refuse
|
|
243
254
|
```
|
|
244
255
|
|
|
245
|
-
The keys are: `release.fragments` (path, default `.changes/`),
|
|
246
|
-
(fold strategy, default `semver-by-level`),
|
|
247
|
-
default `push`), `release.tag` (`manual` or
|
|
248
|
-
`release.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
`
|
|
252
|
-
`rafa release
|
|
256
|
+
The keys are: `release.fragments` (path, default `.changes/`),
|
|
257
|
+
`release.strategy` (fold strategy, default `semver-by-level`),
|
|
258
|
+
`release.settle` (`push` or `pr`, default `push`), `release.tag` (`manual` or
|
|
259
|
+
`settle`, default `manual`), `release.publish` (`manual` or `ci`, who publishes
|
|
260
|
+
a tagged version, default `manual`), `release.publishCommand` (the publish line
|
|
261
|
+
`rafa release tag` prints and `rafa release publish` runs in each tagged unit's
|
|
262
|
+
folder, default `npm publish`), `release.moveLock` (`true` has settle write
|
|
263
|
+
`rafa.lock` in its release commit, default `false`), and `pr.versionCollision`
|
|
264
|
+
(what happens when a merge would collide, default `report`). Read
|
|
265
|
+
`context/release.md` for the full design, `docs/ci-release-settle.md` for
|
|
266
|
+
automating settle in CI, and `rafa release settle --help` for the settle
|
|
267
|
+
command.
|
|
268
|
+
|
|
269
|
+
### The release ladder
|
|
270
|
+
|
|
271
|
+
The release keys step a project up a ladder, one level at a time, from nothing
|
|
272
|
+
on its own (0) to a release on every merge (4):
|
|
273
|
+
|
|
274
|
+
| Level | `release.settle` | `release.tag` | `release.publish` | Runs on its own |
|
|
275
|
+
|---|---|---|---|---|
|
|
276
|
+
| 0 Manual | any | `manual` | `manual` | nothing |
|
|
277
|
+
| 1 Settle tags | `push` | `settle` | `manual` | version, changelog and tag in one settle |
|
|
278
|
+
| 2 CI publishes | `push` | `manual` | `ci` | a pushed tag runs the gates and publishes with provenance |
|
|
279
|
+
| 3 Release PR | `pr` | `settle` | `ci` | every merge updates one release pull request; merging it tags and publishes |
|
|
280
|
+
| 4 Continuous | `push` | `settle` | `ci` | every push to the default branch settles, then publishes the release it tags |
|
|
281
|
+
|
|
282
|
+
`rafa doctor` prints the reading of the keys as its `Release ladder:` row, with
|
|
283
|
+
what the level still needs. The row never refuses a setting. The release order
|
|
284
|
+
across packages is parked until two publishable packages depend on each other.
|
|
285
|
+
|
|
286
|
+
To move to level 2, where a pushed tag publishes, take four steps:
|
|
287
|
+
|
|
288
|
+
1. Set the key in `.rafa/config.yaml`:
|
|
289
|
+
|
|
290
|
+
```yaml
|
|
291
|
+
release:
|
|
292
|
+
publish: ci
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
2. Run `rafa release workflows --write`. It writes
|
|
296
|
+
`.github/workflows/release-publish.yml` from the shipped template. A file
|
|
297
|
+
already at that path is left as it is.
|
|
298
|
+
3. On npmjs.com, add a trusted publisher for the package that names this
|
|
299
|
+
repository and `release-publish.yml`. Trusted publishing needs npm 11.5.1 or
|
|
300
|
+
newer.
|
|
301
|
+
4. In the repository's GitHub settings, open Settings > Secrets and variables >
|
|
302
|
+
Actions > Variables, and add the repository variable `RAFA_RELEASE_PUBLISH`
|
|
303
|
+
with the value `ci`. From a shell, the same is:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
gh variable set RAFA_RELEASE_PUBLISH --body ci
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Until the variable is `ci`, the publish job is skipped, and a skipped job is not
|
|
310
|
+
a failed run. Then `rafa release tag --push` tags the release and pushes the
|
|
311
|
+
tag, and the publish workflow runs the gates and publishes it with provenance.
|
|
312
|
+
|
|
313
|
+
The release commands beyond settle and tag:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
rafa release publish [--tag=<tag>] [--dry-run] # publishCommand in each unit tagged at HEAD
|
|
317
|
+
rafa release workflows [--write] # the ladder's workflow files
|
|
318
|
+
rafa release fragment --plan=<id> --level=<level> --title=<text> # a branch with no wrap-up
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
`rafa release publish` skips a version the registry already holds, so a rerun
|
|
322
|
+
after a publish that stopped halfway publishes only the units the registry
|
|
323
|
+
lacks.
|
|
253
324
|
|
|
254
325
|
### Tracking effort and learning from skills
|
|
255
326
|
|
|
@@ -263,8 +334,11 @@ rafa effort import <file> # merge another device's store into this one
|
|
|
263
334
|
```
|
|
264
335
|
|
|
265
336
|
`rafa effort report` shows the per-plan tables (sessions by status and
|
|
266
|
-
outcome), the task report tallies,
|
|
267
|
-
|
|
337
|
+
outcome), the task report tallies, any runs whose preflight halted,
|
|
338
|
+
how many of the filed bugs name only documentation, and per plan its
|
|
339
|
+
out-of-scope entries by the kind the loop routed them under, with the
|
|
340
|
+
share filed. To see which skills earned their place and which are
|
|
341
|
+
ignored:
|
|
268
342
|
|
|
269
343
|
```bash
|
|
270
344
|
rafa effort report --skills
|
|
@@ -403,7 +477,12 @@ writes it; you can change it.
|
|
|
403
477
|
`project` pin while a loaded user tier does; pin the tier the refusal
|
|
404
478
|
names, or delete or rename the copy it names. `loop start` refuses a
|
|
405
479
|
plan that names an agent or a skill it cannot resolve before any
|
|
406
|
-
session is paid for.
|
|
480
|
+
session is paid for. `rafa plan validate` names a plan whose task edits
|
|
481
|
+
an agent or a skill rafa bundles, with the pin that item needs, and
|
|
482
|
+
writes the pin as a `[human]` prerequisite of the plan, so a clone that
|
|
483
|
+
merges the plan sets the pin itself; that note is never a refusal. The
|
|
484
|
+
pin is not set at merge, since a pin is per clone and gitignored, and
|
|
485
|
+
one set unasked would hide the drift `doctor` shows.
|
|
407
486
|
- User-tier items are invisible unless `loop.settingSources` includes
|
|
408
487
|
`user`. `rafa agent list` shows what a run sees, `rafa agent vendor
|
|
409
488
|
<name>` copies one in or updates it, and `rafa skill check .claude/skills
|
|
@@ -515,16 +594,121 @@ rafa· no pr no open pull request for feat/rafa-485
|
|
|
515
594
|
|
|
516
595
|
## Configuration
|
|
517
596
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
project
|
|
521
|
-
|
|
522
|
-
|
|
597
|
+
rafa reads its settings from one file per scope. The project scope is
|
|
598
|
+
the repository's root; the user scope is `~/.rafa/`, read under every
|
|
599
|
+
project on the machine. In each scope the lookup takes the first of
|
|
600
|
+
three names that is a file, and the others are not read:
|
|
601
|
+
|
|
602
|
+
1. `rafa.config.ts`, a TypeScript module
|
|
603
|
+
2. `rafa.config.mjs`, a JavaScript module
|
|
604
|
+
3. `.rafa/config.yaml` in the project, `~/.rafa/config.yaml` for the user
|
|
605
|
+
|
|
606
|
+
The layers stack: rafa's defaults, under the user scope's file, under the
|
|
607
|
+
project's. A setting the project's file names outranks the same one in
|
|
608
|
+
the user's, key by key; a setting neither file names takes its default.
|
|
609
|
+
`rafa init` writes both YAML files with every setting commented out at
|
|
610
|
+
its default, so uncomment a line, with its section line, to change it.
|
|
523
611
|
|
|
524
612
|
Tab indentation in `.rafa/config.yaml` is refused with rafa's own error
|
|
525
613
|
on every Bun version, before the parser sees the file. The error names
|
|
526
614
|
the line that carries a tab; use spaces only.
|
|
527
615
|
|
|
616
|
+
### Which form to use
|
|
617
|
+
|
|
618
|
+
Pick the lightest form your situation needs:
|
|
619
|
+
|
|
620
|
+
- **No config at all.** rafa runs on its defaults, as it always has.
|
|
621
|
+
- **An older project on YAML.** Nothing changes; `.rafa/config.yaml` is
|
|
622
|
+
read as before.
|
|
623
|
+
- **A solo Python repository with rafa installed globally.** Write
|
|
624
|
+
`rafa.config.mjs` holding a plain list, or `rafa.config.ts` with only
|
|
625
|
+
an `import type`. The type import is erased before the file runs, so
|
|
626
|
+
nothing is needed at run time. A module that imports
|
|
627
|
+
`@open-tomato/rafa` at run time finds no such package here and is
|
|
628
|
+
refused, naming the file.
|
|
629
|
+
- **A JS or TS project that installs rafa as a dev dependency.** Write
|
|
630
|
+
`satisfies Config` or `defineConfig`, both from
|
|
631
|
+
`@open-tomato/rafa/config`, and your editor checks the entries.
|
|
632
|
+
- **A project moving from YAML to TypeScript.** For a while both files
|
|
633
|
+
sit side by side. The TypeScript file is read, and a warning names the
|
|
634
|
+
YAML file as not read; `rafa doctor` lists it until its keys have
|
|
635
|
+
moved, and then it can be removed.
|
|
636
|
+
|
|
637
|
+
The same setting in each form:
|
|
638
|
+
|
|
639
|
+
```yaml
|
|
640
|
+
# .rafa/config.yaml
|
|
641
|
+
naming:
|
|
642
|
+
branch: feat/{stub}
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
```js
|
|
646
|
+
// rafa.config.mjs
|
|
647
|
+
export default [{ naming: { branch: 'feat/{stub}' } }];
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
// rafa.config.ts
|
|
652
|
+
import type { Config } from '@open-tomato/rafa/config';
|
|
653
|
+
|
|
654
|
+
export default [{ naming: { branch: 'feat/{stub}' } }] satisfies Config;
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
```ts
|
|
658
|
+
// rafa.config.ts
|
|
659
|
+
import { defineConfig } from '@open-tomato/rafa/config';
|
|
660
|
+
|
|
661
|
+
export default defineConfig([{ dangerous: { selfUpdateDuringLoop: true } }]);
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
The import from `@open-tomato/rafa/config` is the one that needs the
|
|
665
|
+
package installed where the file runs. For this iteration it can be
|
|
666
|
+
solved with something simple attacking the type project specifically,
|
|
667
|
+
but the bigger issue remains.
|
|
668
|
+
|
|
669
|
+
Some routes were set aside, each for one reason. Merging both files of
|
|
670
|
+
one scope is not done: a scope reads one file, so one answer per key.
|
|
671
|
+
A Bun plugin redirecting the import does not resolve, as measured.
|
|
672
|
+
Setting `NODE_PATH` and starting rafa again is not done: it would start
|
|
673
|
+
a second process to load one file. Requiring a local install, as ESLint
|
|
674
|
+
and Vite do, is not done: it would refuse the global Python case above.
|
|
675
|
+
|
|
676
|
+
### Shadowed YAML and `rafa config show`
|
|
677
|
+
|
|
678
|
+
When a scope holds a module file and a YAML file, the YAML file is not
|
|
679
|
+
read, and every load says so:
|
|
680
|
+
|
|
681
|
+
```text
|
|
682
|
+
rafa config: /repo/.rafa/config.yaml is not read: /repo/rafa.config.ts holds the project scope's config, so move its keys into rafa.config.ts and remove it
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
`rafa config show` prints every setting with its merged value, nested
|
|
686
|
+
as a config file spells it. `rafa config show --sources` prints one line
|
|
687
|
+
per setting instead: its value, the layer that answered (`project`,
|
|
688
|
+
`user` or `default`) and, for a file, the file and the zero-based entry
|
|
689
|
+
that last set it; a YAML file is entry 0. `--output=json` carries the
|
|
690
|
+
same data for a script. The two views are refused together.
|
|
691
|
+
|
|
692
|
+
### Changing a key with `config set`
|
|
693
|
+
|
|
694
|
+
`rafa config set <key>=<value>` edits the project's `.rafa/config.yaml`
|
|
695
|
+
in place and keeps its comments. In a project whose config is
|
|
696
|
+
`rafa.config.ts` or `rafa.config.mjs`, it refuses with exit 1, naming
|
|
697
|
+
that file and writing nothing, because a module is code the command does
|
|
698
|
+
not rewrite. Edit the module by hand until #893 gives the command a file
|
|
699
|
+
to write.
|
|
700
|
+
|
|
701
|
+
### `dangerous.*` settings
|
|
702
|
+
|
|
703
|
+
A `dangerous.*` key is a person's consent, so rafa says what is in force:
|
|
704
|
+
once per run, before its work starts, every command that loads the
|
|
705
|
+
config prints one line for each `dangerous.*` key set off its default,
|
|
706
|
+
naming the file and entry that set it, such as:
|
|
707
|
+
|
|
708
|
+
```text
|
|
709
|
+
dangerous.selfUpdateDuringLoop: true (/repo/rafa.config.ts, entry 0)
|
|
710
|
+
```
|
|
711
|
+
|
|
528
712
|
### `effort`
|
|
529
713
|
|
|
530
714
|
One setting says how long a command waits for another rafa process that
|
|
@@ -690,6 +874,52 @@ dangerous:
|
|
|
690
874
|
selfUpdateDuringLoop: true # update the binary even while a loop runs
|
|
691
875
|
```
|
|
692
876
|
|
|
877
|
+
### `merge`
|
|
878
|
+
|
|
879
|
+
One setting says what a load does when one key is set twice in a file.
|
|
880
|
+
|
|
881
|
+
| Key | Default | What it sets |
|
|
882
|
+
|---|---|---|
|
|
883
|
+
| `merge.duplicates` | `warn` | `warn` prints each duplicate, `error` refuses the load with every one, `allow` drops them |
|
|
884
|
+
|
|
885
|
+
Two entries of one module file setting one key, or a YAML key given
|
|
886
|
+
twice, are duplicates. The project's file decides the level, over the
|
|
887
|
+
user's. `config set` refuses a key written twice in the same file, as
|
|
888
|
+
the same mistake.
|
|
889
|
+
|
|
890
|
+
```yaml
|
|
891
|
+
merge:
|
|
892
|
+
duplicates: error
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### `naming`
|
|
896
|
+
|
|
897
|
+
One setting names the branch `rafa loop start` creates for a plan.
|
|
898
|
+
|
|
899
|
+
| Key | Default | What it sets |
|
|
900
|
+
|---|---|---|
|
|
901
|
+
| `naming.branch` | `feat/{stub}` | the branch name; `{stub}` appears exactly once and stands for the plan's stub |
|
|
902
|
+
|
|
903
|
+
A template with no `{stub}`, or with it twice, is refused. The value is
|
|
904
|
+
kept as written.
|
|
905
|
+
|
|
906
|
+
```yaml
|
|
907
|
+
naming:
|
|
908
|
+
branch: feat/{stub}
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
### Config code and `pr triage --resolve`
|
|
912
|
+
|
|
913
|
+
A `rafa.config.ts` or `rafa.config.mjs` is a module rafa imports, so it
|
|
914
|
+
runs with your shell, credentials and remotes. `pr triage --resolve`
|
|
915
|
+
checks a pull request's branch out and starts a loop in it, and that loop
|
|
916
|
+
loads whatever config the branch carries. So under `--resolve`, a head
|
|
917
|
+
carrying a config module that `origin/<base>` does not hold as the same
|
|
918
|
+
file (compared byte for byte) is refused with exit 1, before the worktree
|
|
919
|
+
is added. Passing `--allow-local-config` runs it anyway and prints one
|
|
920
|
+
warning line naming what it let through. A YAML config is data and is not
|
|
921
|
+
checked this way.
|
|
922
|
+
|
|
693
923
|
## Specs, issues and the roadmap
|
|
694
924
|
|
|
695
925
|
You can plan from a local file and never touch a board. When you want
|
|
@@ -782,6 +1012,9 @@ The full guide, with the spec template explained, a prompt for drafting
|
|
|
782
1012
|
a spec, epics, boards and every gate in order, is
|
|
783
1013
|
[docs/specs-and-roadmap.md](docs/specs-and-roadmap.md).
|
|
784
1014
|
|
|
1015
|
+
The version policy, the bump levels, which package publishes and the
|
|
1016
|
+
`REFACTOR_NEEDED.md` rule are in [docs/versioning.md](docs/versioning.md).
|
|
1017
|
+
|
|
785
1018
|
## From a checkout
|
|
786
1019
|
|
|
787
1020
|
To install dependencies:
|
|
@@ -798,7 +1031,7 @@ bun src/rafa.ts loop start --plan=<file>
|
|
|
798
1031
|
|
|
799
1032
|
Every command but `init`, the help and `describe` runs inside a rafa
|
|
800
1033
|
project: the nearest directory at or above the working directory holding
|
|
801
|
-
`.rafa/config.yaml`. Outside one it prints the `rafa init` hint and exits
|
|
1034
|
+
`rafa.config.ts`, `rafa.config.mjs` or `.rafa/config.yaml`. Outside one it prints the `rafa init` hint and exits
|
|
802
1035
|
1; `bun src/rafa.ts init --yes` sets up the git toplevel as one.
|
|
803
1036
|
|
|
804
1037
|
`bun run build` writes `dist/`, which the `rafa` bin and the package's
|
|
@@ -819,16 +1052,20 @@ install the same way (`src/runtime/install.ts`). The bin is not in
|
|
|
819
1052
|
`~/.bun/bin`, where `bun link` in this checkout re-points `rafa` at the
|
|
820
1053
|
checkout's `dist/` with no message, so put `~/.rafa/bin` on `PATH` ahead
|
|
821
1054
|
of `~/.bun/bin`; both warn when it is not, and `rafa doctor` checks it.
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
`
|
|
1055
|
+
A plan tracker in `plan.dir` (`.rafa/plans` unless `.rafa/config.yaml`
|
|
1056
|
+
names another) that still holds an open or blocked task holds an install
|
|
1057
|
+
back only while a loop of the checkout is live: both then exit 1 before
|
|
1058
|
+
building anything and name every such tracker, unless `--force` is on
|
|
1059
|
+
the line. With no loop live they install, one warning naming each such
|
|
1060
|
+
tracker, so a plan stopped halfway no longer blocks an update.
|
|
1061
|
+
`rafa self-update` runs only inside a project, so `rafa init` the
|
|
1062
|
+
checkout first, and it also exits 1 while a loop of the project is live,
|
|
1063
|
+
naming each loop's branch and pid, unless
|
|
1064
|
+
`dangerous.selfUpdateDuringLoop` is true in the config; `--force` does
|
|
1065
|
+
not override that wait. They exit 2 when they could not run: a
|
|
1066
|
+
`package.json` that is not rafa's or cannot be read, a config, tracker
|
|
1067
|
+
or loop record they could not read, or a build, copy or link that
|
|
1068
|
+
failed.
|
|
832
1069
|
|
|
833
1070
|
A version is installed once. Both also exit 1, before building, when
|
|
834
1071
|
`~/.rafa/runtime/<version>/` is already there, naming that directory and
|
|
@@ -862,11 +1099,12 @@ takes `--yes`. The rest of `rafa update` (`self`, `project`, `board`,
|
|
|
862
1099
|
The build targets bun, and `engines` names `bun` alone: there is no
|
|
863
1100
|
`engines.node`, because no node version runs the binary. The package
|
|
864
1101
|
root, `./cli` and `./store` import `bun:sqlite`, which node's ESM loader
|
|
865
|
-
refuses before any module code runs, so only `./plan`, `./ports
|
|
866
|
-
`./learning` load under node at all. `module` points at
|
|
867
|
-
`./dist/index.js`, the same build the root of `exports` names.
|
|
868
|
-
`
|
|
869
|
-
`
|
|
1102
|
+
refuses before any module code runs, so only `./plan`, `./ports`,
|
|
1103
|
+
`./learning` and `./config` load under node at all. `module` points at
|
|
1104
|
+
`./dist/index.js`, the same build the root of `exports` names. Only
|
|
1105
|
+
`./config` ships type declarations, at `./dist/config/index.d.ts`, which
|
|
1106
|
+
its `exports` entry names as `types`. No other entry names `types`, and
|
|
1107
|
+
a TypeScript consumer importing one gets TS7016 under `strict`.
|
|
870
1108
|
|
|
871
1109
|
## Roadmap
|
|
872
1110
|
|
package/dist/PROMPT.md
CHANGED
|
@@ -4,7 +4,16 @@ Do not stage or commit anything: the loop owns staging and committing, and once
|
|
|
4
4
|
|
|
5
5
|
Run every command in the foreground, the full test suite included: never start a background command and never wait on a notification. This session is a single `claude -p` turn, so ending it to wait for something leaves no report and no commit; end the session only after your `rafa:report` block.
|
|
6
6
|
|
|
7
|
-
End your final message with exactly one `rafa:report` block shaped like the example below, and write nothing after it: the loop stores what it reads there, and a message without the block stores none of your findings. Write all
|
|
7
|
+
End your final message with exactly one `rafa:report` block shaped like the example below, and write nothing after it: the loop stores what it reads there, and a message without the block stores none of your findings. Write all eight fields, `status`, `feedback`, `findings`, `skills_used`, `blockers`, `out_of_scope_bugs`, `changes` and `stale_docs`, and write a list with nothing in it as `[]` rather than leaving its field out. `status` is `done` or `blocked`. `feedback` says what was done and how it went. `findings` is a list with one entry per distinct observation, never several merged into one; a finding's `kind` is one of `gotcha`, `pattern`, `location` or `skill-suggestion`, its `signal` is `loud` when it surfaced as a failure or `silent` when something passed while wrong, and its `artifact`, when there is one, is the exact string a recurrence would match on, such as an error message. A finding may also carry a `domain`, the area of work its lesson belongs to, one of `code-style`, `testing`, `git`, `debugging`, `workflow`, `security` or `general-best-practices`; leave it out when none fits. `skills_used` names each skill you invoked. `blockers` lists what stopped the task, each entry a `what` and, when there is one, an `artifact`, `out_of_scope_bugs` what you saw wrong outside it, each entry a `what`, an `artifact` when there is one, `security` set to `true` or `false`, a `kind` from the six listed after this paragraph, and the optional `module`, `action`, `reproduce` and `cause` keys, which may be left out, with `reproduce` and `cause` always double-quoted — a test type error that the task's base already held is part of the measured backlog and is not reported as a bug, and the type step's line names how many errors the base held — and `changes` is the changelog for your diff, each entry holding the required fields `level` (one of patch, minor, major, none) and `summary` (a quoted line the user would understand), plus optional `area` (the changelog section). `stale_docs` lists the documentation lines you saw that no longer match the code, each entry a `where` (the file, with the line when known, as one string such as "context/triage.md:12") and a `what` (what no longer matches). A doc line your own change falsified is not an entry: repair it in the same commit as the change. Any other stale doc line you come across goes into `stale_docs` and never into `out_of_scope_bugs`. Write those closed-set words, `security` and an entry's `kind` bare, as the example does, and double-quote every other value on one line: an unquoted value that opens with a backtick, `@`, `%` or `[` makes the whole block unreadable, and a `#` after a space silently cuts a value short.
|
|
8
|
+
|
|
9
|
+
An `out_of_scope_bugs` entry's `kind` is one of six, a different list from a finding's `kind`:
|
|
10
|
+
|
|
11
|
+
- `bug` applies when the code does the wrong thing and nothing this plan did caused it.
|
|
12
|
+
- `own-fallout` applies when an earlier task of this plan broke something, or left it stale, outside your task.
|
|
13
|
+
- `own-gap` applies when this plan built something and left it unfinished, short of what your task needs or the plan describes.
|
|
14
|
+
- `convention` applies when the code works but breaks a house rule, such as a file over the line ceiling or a name off the pattern.
|
|
15
|
+
- `docs` applies when the leftover is a documentation fault larger than one stale line, since a single stale doc line goes into `stale_docs` instead.
|
|
16
|
+
- `machine` applies when the fault lies in this machine or its setup, such as a missing tool or an unreachable service, rather than in the code.
|
|
8
17
|
|
|
9
18
|
```rafa:report
|
|
10
19
|
status: done
|
|
@@ -25,7 +34,15 @@ out_of_scope_bugs:
|
|
|
25
34
|
- what: "..."
|
|
26
35
|
artifact: "..."
|
|
27
36
|
security: false
|
|
37
|
+
kind: bug
|
|
38
|
+
module: "src/report"
|
|
39
|
+
action: "parse the entry"
|
|
40
|
+
reproduce: "run the report parser on an entry with the four keys"
|
|
41
|
+
cause: "the parser did not read the optional keys"
|
|
28
42
|
changes:
|
|
29
43
|
- level: patch
|
|
30
44
|
summary: "the loop waits for the running task's commit"
|
|
45
|
+
stale_docs:
|
|
46
|
+
- where: "context/triage.md:12"
|
|
47
|
+
what: "says triage has three channels"
|
|
31
48
|
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The logger's settings: what `logger.*` in the config says, held where
|
|
3
|
+
* every logger of the process can read it (#950).
|
|
4
|
+
*
|
|
5
|
+
* The dispatcher builds a command's logger before the project is found,
|
|
6
|
+
* and a command loads its config later. So the settings cannot be handed
|
|
7
|
+
* to the logger when it is made: `loadConfig`
|
|
8
|
+
* (`packages/rafa/src/core/config/config-load.ts`) calls core's load hook once a
|
|
9
|
+
* config is read, as it sets the effort store's settings, and the hook
|
|
10
|
+
* `src/config-registry.ts` sets hands the logger section's reading to
|
|
11
|
+
* this module. A logger reads them at each entry. Until then the default
|
|
12
|
+
* applies, with the invocation's verbosity beside it.
|
|
13
|
+
*
|
|
14
|
+
* This module imports types and `node:async_hooks` alone, so the
|
|
15
|
+
* registry can import it without pulling an adapter in.
|
|
16
|
+
*
|
|
17
|
+
* ## Where they are held
|
|
18
|
+
*
|
|
19
|
+
* In two places, and {@link activeLoggerSettings} and
|
|
20
|
+
* {@link setActiveLoggerSettings} both act on the first that applies:
|
|
21
|
+
*
|
|
22
|
+
* - **A scope.** {@link runWithLoggerSettings} runs a function with
|
|
23
|
+
* settings of its own in an async scope, an `AsyncLocalStorage`
|
|
24
|
+
* (`node:async_hooks`). Inside that function, and in everything it
|
|
25
|
+
* awaits or starts, the reader answers the scope's settings and the
|
|
26
|
+
* setter replaces them. Once the function ends, however it ends,
|
|
27
|
+
* nothing of them is left. The dispatcher runs every command this
|
|
28
|
+
* way, starting from the defaults (`src/cli/dispatch.ts`), so the
|
|
29
|
+
* config a command loads sets that invocation's settings alone.
|
|
30
|
+
* - **The module-level value.** Outside every scope the reader answers
|
|
31
|
+
* one module-level value and the setter replaces it, the defaults
|
|
32
|
+
* until something sets another. A config loaded outside every
|
|
33
|
+
* command sets it, as the module loader (`src/modules/load.ts`) and
|
|
34
|
+
* the command hook (`src/status/hook.ts`) load one around an
|
|
35
|
+
* invocation; no command reads it.
|
|
36
|
+
*
|
|
37
|
+
* A scope belongs to one run, so runs need not nest to stay apart. Two
|
|
38
|
+
* that overlap in one process, started together and awaited with
|
|
39
|
+
* `Promise.all`, each read and set their own whichever ends first. A
|
|
40
|
+
* scope opened inside another starts from the settings it is given,
|
|
41
|
+
* never from the outer one's, and the outer one reads its own again
|
|
42
|
+
* after it. A module-level value set and put back in a `finally` keeps
|
|
43
|
+
* overlapping runs apart only while they nest (#927).
|
|
44
|
+
*
|
|
45
|
+
* ## A set made inside a scope
|
|
46
|
+
*
|
|
47
|
+
* It replaces that scope's settings, and never the module-level value.
|
|
48
|
+
* This is where the settings differ from the active output
|
|
49
|
+
* (`packages/rafa/src/core/output/active.ts`), whose scope cannot be replaced from
|
|
50
|
+
* inside it: the config naming the settings is loaded inside the run
|
|
51
|
+
* that reads them, so the setter has to reach the run it is called in.
|
|
52
|
+
* The scope therefore holds a cell, and a set swaps the frozen settings
|
|
53
|
+
* the cell holds.
|
|
54
|
+
*
|
|
55
|
+
* ## What reads outside the scope
|
|
56
|
+
*
|
|
57
|
+
* A scope follows the awaits and the callbacks started inside it, by
|
|
58
|
+
* where the code runs and not by where it was written: a function made
|
|
59
|
+
* in one invocation and called from another reads the caller's. A
|
|
60
|
+
* callback the runtime calls from elsewhere does not carry it, and reads
|
|
61
|
+
* and sets the module-level value. Measured under bun 1.3.14, three
|
|
62
|
+
* listeners registered inside a scope read the module-level settings: a
|
|
63
|
+
* `process.on` signal listener when the signal arrived, an abort
|
|
64
|
+
* listener that handler fired, and an abort listener an
|
|
65
|
+
* `AbortSignal.timeout` fired. A timer, a microtask and the code after
|
|
66
|
+
* an await read the scope's, and so did a signal listener wrapped with
|
|
67
|
+
* `AsyncResource.bind` where it was registered.
|
|
68
|
+
*
|
|
69
|
+
* ## Which entries are on
|
|
70
|
+
*
|
|
71
|
+
* `error`, `warn` and `debug` are ordered, quietest first
|
|
72
|
+
* ({@link LOG_LEVELS}). An entry is on when its level is at or quieter
|
|
73
|
+
* than the threshold: the level its module has in `modules`, else
|
|
74
|
+
* `level`. `debug` is also on from verbosity {@link DEBUG_VERBOSITY}.
|
|
75
|
+
*
|
|
76
|
+
* `api` sits outside that order. It is on when `api` is true or from
|
|
77
|
+
* verbosity {@link API_VERBOSITY}, and nothing else turns it on: a
|
|
78
|
+
* level of `debug` asks for rafa's own reasoning, never for the traffic
|
|
79
|
+
* to a service.
|
|
80
|
+
*
|
|
81
|
+
* Bun runs every test file in one process and the module-level value is
|
|
82
|
+
* module state, so a case that sets settings outside a scope sets `null`
|
|
83
|
+
* after it.
|
|
84
|
+
*/
|
|
85
|
+
import type { LogLevel } from '@open-tomato/rafa/ports/log-level';
|
|
86
|
+
/** How a logger colours its lines. */
|
|
87
|
+
export type LoggerTheme = 'default' | 'plain';
|
|
88
|
+
/** The ordered levels, quietest first. `api` is not one of them. */
|
|
89
|
+
export declare const LOG_LEVELS: readonly LogLevel[];
|
|
90
|
+
/** Every theme, in the order a refusal names them. */
|
|
91
|
+
export declare const LOGGER_THEMES: readonly LoggerTheme[];
|
|
92
|
+
/** The adapter kind core ships. */
|
|
93
|
+
export declare const DEFAULT_LOGGER_KIND = "console";
|
|
94
|
+
/** The verbosity at and above which `debug` entries are on. */
|
|
95
|
+
export declare const DEBUG_VERBOSITY = 2;
|
|
96
|
+
/** The verbosity at and above which `api` entries are on. */
|
|
97
|
+
export declare const API_VERBOSITY = 3;
|
|
98
|
+
/** What a logger reads at each entry. */
|
|
99
|
+
export interface LoggerSettings {
|
|
100
|
+
/** The adapter kind. `logger.kind`. */
|
|
101
|
+
readonly kind: string;
|
|
102
|
+
/** The loudest ordered level written. `logger.level`. */
|
|
103
|
+
readonly level: LogLevel;
|
|
104
|
+
/** How lines are coloured. `logger.theme`. */
|
|
105
|
+
readonly theme: LoggerTheme;
|
|
106
|
+
/** A level per module, over `level`. `logger.modules.<module>.level`. */
|
|
107
|
+
readonly modules: ReadonlyMap<string, LogLevel>;
|
|
108
|
+
/** Whether a `debug` line names the file that wrote it. `logger.callSite`. */
|
|
109
|
+
readonly callSite: boolean;
|
|
110
|
+
/** Whether `api` entries are written. `logger.api`. */
|
|
111
|
+
readonly api: boolean;
|
|
112
|
+
}
|
|
113
|
+
/** The settings until a config is loaded. */
|
|
114
|
+
export declare const DEFAULT_LOGGER_SETTINGS: LoggerSettings;
|
|
115
|
+
/**
|
|
116
|
+
* Runs `run` with settings of its own in an async scope, starting from
|
|
117
|
+
* `settings`, the defaults for `null`, and answers what `run` answers.
|
|
118
|
+
* Inside `run` and whatever it awaits they are what is read and what a
|
|
119
|
+
* set replaces, and nothing of them is left after it; see the module
|
|
120
|
+
* note.
|
|
121
|
+
*/
|
|
122
|
+
export declare function runWithLoggerSettings<T>(settings: LoggerSettings | null, run: () => T): T;
|
|
123
|
+
/**
|
|
124
|
+
* Sets the settings every logger reads from here on: those of the scope
|
|
125
|
+
* this is called in, else the module-level ones. `null` puts the
|
|
126
|
+
* defaults back. See the module note.
|
|
127
|
+
*/
|
|
128
|
+
export declare function setActiveLoggerSettings(settings: LoggerSettings | null): void;
|
|
129
|
+
/** The settings a logger reads now: those of the scope this is read in, else the module-level ones. */
|
|
130
|
+
export declare function activeLoggerSettings(): LoggerSettings;
|
|
131
|
+
/** Whether an entry at `level` from `module` is written; see the module note. */
|
|
132
|
+
export declare function levelEnabled(level: LogLevel, module: string | undefined, settings: LoggerSettings, verbosity: number): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The names closest to a value a person typed (#951), for a refusal that
|
|
3
|
+
* says "closest: billing" beside the name it turns down.
|
|
4
|
+
*
|
|
5
|
+
* Names here are single words: a module, an action, a place. So the
|
|
6
|
+
* measure is edits between spellings ({@link editDistance}), never the
|
|
7
|
+
* shared words `src/errors/match.ts` counts for a cause written as a
|
|
8
|
+
* sentence. A name further than half the value's length, and further than
|
|
9
|
+
* {@link MIN_REACH} edits, is no suggestion: it is another word.
|
|
10
|
+
*/
|
|
11
|
+
/** How many names a refusal shows. */
|
|
12
|
+
export declare const CLOSEST_LIMIT = 3;
|
|
13
|
+
/** The single-character inserts, deletes and swaps that turn `a` into `b`. */
|
|
14
|
+
export declare function editDistance(a: string, b: string): number;
|
|
15
|
+
/**
|
|
16
|
+
* The `names` nearest `value` by edits, nearest first and by name where
|
|
17
|
+
* two tie, `limit` at most. See the module note for how far is too far.
|
|
18
|
+
*/
|
|
19
|
+
export declare function closestNames(value: string, names: readonly string[], limit?: number): readonly string[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fence a bug's free text is shown in, shared by the loop's own
|
|
3
|
+
* filing (`../triage/issue-text.ts`, which re-exports it) and the bug
|
|
4
|
+
* record (`./record.ts`). A leaf: it imports nothing, so either side
|
|
5
|
+
* reaches it without importing the other.
|
|
6
|
+
*/
|
|
7
|
+
/** A value in a fence one backtick longer than any run of backticks it holds. */
|
|
8
|
+
export declare function fenced(value: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The places a bug is seen in (#951): the ones every project has, and
|
|
3
|
+
* the one rafa suggests.
|
|
4
|
+
*
|
|
5
|
+
* A place names WHERE a bug showed: `local`, `ci`, `prod`, or one a
|
|
6
|
+
* project adds under `issues.environments`. What was running belongs to
|
|
7
|
+
* the record's `action` and `reproduce`.
|
|
8
|
+
*
|
|
9
|
+
* rafa suggests `ci` when the `CI` variable is set to anything but
|
|
10
|
+
* nothing, `0` or `false`, and `local` otherwise. A filer's `--env` wins
|
|
11
|
+
* over the suggestion.
|
|
12
|
+
*
|
|
13
|
+
* This module imports nothing, so the config schema
|
|
14
|
+
* (`src/config-schema-issues.ts`) reads the built-in places without
|
|
15
|
+
* reaching the modules that read the config.
|
|
16
|
+
*/
|
|
17
|
+
/** The places every project has, in the order a refusal lists them. */
|
|
18
|
+
export declare const BUILT_IN_ENVIRONMENTS: readonly ["local", "ci", "prod"];
|
|
19
|
+
/** The place rafa suggests for a run with the environment `env`; see the module note. */
|
|
20
|
+
export declare function suggestedEnvironment(env: Readonly<Record<string, string | undefined>>): 'ci' | 'local';
|