@theholocron/cli 5.0.0-alpha.19 → 5.0.0-alpha.190

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 CHANGED
@@ -17,33 +17,101 @@ holocron --help
17
17
  ## Interactive mode
18
18
 
19
19
  Run `holocron` with no command, a parent command with no subcommand
20
- (`holocron auth`, `holocron skills`, `holocron upgrade`), or a leaf command
21
- missing a required positional (`holocron deploy`, `holocron secret set`), and
22
- you get a prompt instead of a `--help` dead end:
20
+ (`holocron auth`, `holocron repo`, `holocron repo upgrade`, …), or a leaf command
21
+ missing a required positional (`holocron deploy`, `holocron secrets set`), and
22
+ you get a prompt instead of a `--help` dead end.
23
+
24
+ The menu mirrors the command tree: each level shows only the next word, and a
25
+ group (marked `›`) opens its own submenu, as deep as the commands nest. Nothing
26
+ is shown as a `<command> <subcommand>` path — `config show` is `config ›` then
27
+ `show`. Every submenu has a `← back` item, and a command that is also a group
28
+ (`repo sync`, `deploy`) has a `(run it)` item at the top of its submenu. Typing
29
+ searches the whole tree — `upgrade` at the top finds the `repo` group — with
30
+ name matches ranked above description matches.
31
+
32
+ ```console
33
+ $ holocron
34
+ ? What would you like to do? › repo
35
+ ❯ repo ›
36
+ ? repo — choose a subcommand: › upgrade
37
+ ? repo upgrade — choose a subcommand: › node
38
+ ? Target Node.js major version: › 24
39
+ ```
40
+
41
+ For a command that declares options (so far: `package publish` — more are
42
+ rolled out one command group at a time), it also offers those: any required
43
+ option is prompted like a positional, and everything else goes through one
44
+ "Set any options?" checkbox, prompting only what you picked:
23
45
 
46
+ ```console
47
+ ? Set any options? (space to select, enter to skip) › ◉ npm dist-tag ◯ One-time password (2FA)
48
+ ? npm dist-tag (blank = latest): › beta
24
49
  ```
25
- $ holocron
26
- ? What would you like to do? › dep
27
- ────────────────────────────────────────────────
28
- ❯ deploy Trigger a deployment via the configured `deployment` capability
29
50
 
30
- ? Branch to deploy: › main
51
+ `package publish` specifically has three workflows that don't mix — a
52
+ steady-state publish, a one-shot `--initial` bootstrap, and a `--sync-trust`
53
+ maintenance run — so it asks which one first, then only offers that
54
+ workflow's own options; nothing from a different workflow is ever shown:
55
+
56
+ ```console
57
+ ? What would you like to do? › Initial publish (--initial)
58
+ ? Set any options? (space to select, enter to skip) › ◉ One-time password (2FA)
59
+ ...dry-run output...
60
+ ? Dry run complete — proceed with the real run? › yes
61
+ ? One-time password (2FA), if npm requires it for this publish: › ***
31
62
  ```
32
63
 
64
+ Each workflow's label ends with its real flag in parentheses when it has
65
+ one, and a longer caveat ("use only for a package's very first publish")
66
+ shows as helper text under the highlighted choice rather than bloating the
67
+ label itself.
68
+
69
+ A secret option (`--otp`) is masked as you type and delivered to the spawned
70
+ command through its environment, never its argv — `ps` and shell history
71
+ both expose a child's argv, never its env. A time-sensitive one like `--otp`
72
+ is checked off early but not actually typed until right before the real run
73
+ — after the dry-run preview and the "proceed?" question, never before —
74
+ since a dry run never checks it anyway and a code typed any earlier risks
75
+ going stale while something else is still being answered.
76
+
77
+ Whether an option is _checkbox-optional vs. always included_ and _collected
78
+ upfront vs. collected last_ are independent choices. `package publish`'s
79
+ `--otp` is always collected last, but whether it's checkbox-optional depends
80
+ on `HOLOCRON_NPM_ENFORCE_2FA`: unset (the default), it's opt-in like any other
81
+ checkbox pick; set in your own shell profile (never checked into the repo),
82
+ it's always included — for an operator whose own npm account enforces 2FA
83
+ on every publish, so the box doesn't need re-checking every single run.
84
+ Setting it has no effect on anyone else publishing from the same repo.
85
+
33
86
  The picked command spawns as a normal `holocron <command> …` invocation —
34
87
  `--token`, `--org`, `--cwd`, and `--dry-run` on the original invocation carry
35
88
  through. A non-interactive shell (CI, a script, a pipe) gets the old
36
89
  hard-failure message instead of hanging on a prompt.
37
90
 
91
+ For a command whose handler honours `--dry-run` (most of them — everything
92
+ except `auth *` and `config show`), the menu always previews it first — a
93
+ dry run doesn't mutate anything, so there's nothing to ask permission for —
94
+ then asks the one real decision:
95
+
96
+ ```console
97
+ ...dry-run output...
98
+ ? Dry run complete — proceed with the real run? › yes
99
+ ```
100
+
101
+ A preview that reports nothing would actually change (e.g. `clone` finding
102
+ every repo already cloned) skips that question too — there'd be nothing for
103
+ the real run to do either. `--skip-dry-run` opts out of the preview
104
+ entirely, straight to the real run, for when you already know what you want.
105
+
38
106
  ## Execution contexts
39
107
 
40
108
  Every command is tagged with how much of a repo it needs:
41
109
 
42
- | Context | Needs | Examples |
43
- | ------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
44
- | `global` | just the CLI binary | `version`, `clone`, `new`, `upgrade node`, `auth set` / `check`, `plugin create`, `skills …` |
45
- | `repo-aware` | `./holocron.config` in cwd, no plugins | `run`, `ci`, `config show`, `sync-readme` |
46
- | `workspace` | the `@theholocron/holocron-plugin-*` packages resolvable | `doctor`, `setup`, `sync`, `secrets sync`, `deploy` |
110
+ | Context | Needs | Examples |
111
+ | ------------ | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
112
+ | `global` | the CLI binary alone | `version`, `clone`, `new repo` / `plugin`, `repo upgrade …`, `auth set` / `check`, `package …`, `run lint commit-msg`, `skills …` |
113
+ | `repo-aware` | `./holocron.config`, walking up from cwd, no plugins | `run`, `run ci`, `config show`, `repo sync readme`, `deploy on-release` |
114
+ | `workspace` | the `@theholocron/holocron-plugin-*` packages resolvable | `doctor`, `repo setup`, `repo sync`, `secrets …`, `deploy`, `sync github` |
47
115
 
48
116
  A `workspace` command run from a bare global install (no plugins next to the
49
117
  CLI) fails with one actionable line — install the plugins as devDependencies or
@@ -51,6 +119,21 @@ use `pnpm exec holocron <cmd>`. `auth check` degrades to "token present,
51
119
  verification skipped" instead. `holocron --help` prints the grouping; see
52
120
  [Execution Contexts](https://theholocron.github.io/holocron/execution-contexts).
53
121
 
122
+ ### Viewing the resolved config
123
+
124
+ `holocron config show` prints the resolved config. On a TTY it opens a foldable
125
+ tree by default; piped or redirected, it always emits plain, valid JSON
126
+ (`holocron config show | jq`).
127
+
128
+ ```console
129
+ holocron config show # TTY: foldable tree (↑↓ move, →/⏎ expand, ← collapse, E/C all, q quit)
130
+ holocron config show --depth 2 # static coloured tree, anything nested deeper than 2 levels collapsed
131
+ holocron config show --no-interactive # static coloured tree, fully expanded
132
+ ```
133
+
134
+ Passing `--interactive` explicitly needs a TTY on stdin and stdout and fails
135
+ with a one-line message otherwise; the default falls back to static output. It has no extra dependencies — nothing to install.
136
+
54
137
  ## Config file
55
138
 
56
139
  Holocron reads `holocron.config.{json,js,ts}` from the project root
@@ -103,18 +186,18 @@ A minimal config — for repos with a `package.json` and a GitHub remote
103
186
 
104
187
  ### repo options
105
188
 
106
- Additional `repo` fields recognised by `holocron setup`:
189
+ Additional `repo` fields recognised by `holocron repo setup`:
107
190
 
108
- | Field | Type | Description |
109
- | ----------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
110
- | `repo.teams` | `Array<string \| { slug, permission }>` | GitHub teams granted repo access. String shorthand defaults to `push` (Write). `holocron setup` also writes `.github/CODEOWNERS` for teams with `push`/`maintain`/`admin`. |
111
- | `repo.topics` | `string[]` | GitHub topics set on the repository. |
112
- | `repo.protection` | `"balanced" \| "strict" \| "none"` | Branch-protection preset applied by `holocron setup`. For `"strict"`, the required status checks are derived from the task manifest — see below. |
113
- | `repo.properties` | `RepoProperties` | Org-level custom property values synced to the GitHub dashboard. |
191
+ | Field | Type | Description |
192
+ | ----------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
193
+ | `repo.teams` | `Array<string \| { slug, permission }>` | GitHub teams granted repo access. String shorthand defaults to `push` (Write). `holocron repo setup` also writes `.github/CODEOWNERS` for teams with `push`/`maintain`/`admin`. |
194
+ | `repo.topics` | `string[]` | GitHub topics set on the repository. |
195
+ | `repo.protection` | `"balanced" \| "strict" \| "none"` | Branch-protection preset applied by `holocron repo setup`. For `"strict"`, the required status checks are derived from the task manifest — see below. |
196
+ | `repo.properties` | `RepoProperties` | Org-level custom property values synced to the GitHub dashboard. |
114
197
 
115
198
  ### Custom properties synced to GitHub
116
199
 
117
- `holocron setup` and `holocron sync` both call `syncProperties()` with two
200
+ `holocron repo setup` and `holocron repo sync` both call `syncProperties()` with two
118
201
  kinds of fields — always one-way (`holocron.config.ts` → resolved →
119
202
  properties; properties are never a second editable source of truth):
120
203
 
@@ -160,7 +243,7 @@ posts, instead of reporting pass/fail.
160
243
 
161
244
  ### Required status checks (`protection: "strict"`)
162
245
 
163
- `holocron setup` builds the branch-protection required-check list from the
246
+ `holocron repo setup` builds the branch-protection required-check list from the
164
247
  manifest, not a hand-maintained array:
165
248
 
166
249
  - `"DCO"` (hard-prepended), then
@@ -186,12 +269,32 @@ The generated ruleset also sets `require_extra_approval_for_unattributed_changes
186
269
  false` — with `required_approving_review_count: 0` and a single maintainer, the
187
270
  GitHub default (`true`) is an unsatisfiable block on any PR with an
188
271
  unverified/unattributed commit. Repository-admin bypass still covers the real
189
- risk. And the `codecov.yml` `holocron setup` writes carries `if_not_found:
272
+ risk. And the `codecov.yml` `holocron repo setup` writes carries `if_not_found:
190
273
  success` on every status default, so an infra-only PR (dep bump, config,
191
274
  lockfile — no coverable change) passes instead of hanging on a `codecov/*`
192
- required check that never posts. A re-run of `holocron setup` backfills both into
275
+ required check that never posts. A re-run of `holocron repo setup` backfills both into
193
276
  an existing repo.
194
277
 
278
+ ### Default branch (`repo.defaultBranch`)
279
+
280
+ ```ts
281
+ export default defineConfig({
282
+ repo: { protection: "strict", defaultBranch: "alpha" },
283
+ providers: { source: "github" },
284
+ });
285
+ ```
286
+
287
+ `holocron repo setup` syncs GitHub's repo-level default branch (`HEAD`) — what a
288
+ fresh clone checks out, what `gh pr create`/the compare UI target by default,
289
+ and what Sentinel's `validateConfig()` reads (it only ever reads config from
290
+ the repo's default branch, never a PR ref — a deliberate security boundary).
291
+ Omit this field to leave GitHub's current setting untouched; most repos never
292
+ need it. It exists for a repo using a `main`/`alpha` prerelease-channel split
293
+ where active development happens on a non-`main` branch: set this to that
294
+ branch so Sentinel validates against what's actually being developed, then
295
+ change it back once that branch merges to `main` for a stable cut and stops
296
+ being the active branch.
297
+
195
298
  ### Git hooks
196
299
 
197
300
  ```ts
@@ -202,7 +305,7 @@ export default defineConfig({
202
305
  });
203
306
  ```
204
307
 
205
- `holocron setup` writes `.husky/pre-push` (runs `holocron ci` before every
308
+ `holocron repo setup` writes `.husky/pre-push` (runs `holocron run ci` before every
206
309
  push) and `.husky/pre-commit` (runs `gitleaks protect --staged` + `lint-staged`
207
310
  before every commit — scoped to staged changes, not the whole history, so a
208
311
  past false positive can't permanently block future commits) and sets
@@ -213,7 +316,7 @@ setup --hooks` / `--no-hooks` override per run. Bypass one push with `git push
213
316
 
214
317
  ### Task scripts
215
318
 
216
- `holocron sync` reconciles `package.json#scripts` from the `tasks` manifest
319
+ `holocron repo sync` reconciles `package.json#scripts` from the `tasks` manifest
217
320
  (merge, never clobber — only the managed keys are touched):
218
321
 
219
322
  ```ts
@@ -248,8 +351,8 @@ export default defineConfig({
248
351
  `@theholocron/astromech`'s `loadTasksConfig` merges it over
249
352
  `holocron.config`'s `tasks` — **task arrays concatenate**
250
353
  (`holocron.config` first), the dedicated file **wins on scalars**,
251
- `extraRequiredChecks` concatenate. `holocron run` / `holocron ci` /
252
- `holocron setup` / `holocron sync` all read the merged result, so the
354
+ `extraRequiredChecks` concatenate. `holocron run` / `holocron run ci` /
355
+ `holocron repo setup` / `holocron repo sync` all read the merged result, so the
253
356
  split is transparent. Useful for keeping the capability/provider config
254
357
  and the "what this repo runs" manifest in separate files (this repo does).
255
358
 
@@ -276,10 +379,27 @@ job execute the same thing — at a turbo root both are
276
379
  `turbo run test -- --coverage` (the registry's org-default flags flow through
277
380
  turbo's `--`).
278
381
 
279
- ### `holocron ci`
382
+ ### `holocron deploy on-release`
280
383
 
281
384
  ```bash
282
- holocron ci [--all] [--filter <pkg>] [--dry-run]
385
+ holocron deploy on-release [--channel <alpha|main>] [--from <commit>] [--to <commit>] [--dry-run]
386
+ ```
387
+
388
+ Deploys every workspace package whose own `holocron.config` declares
389
+ `{ name: "delivery.deploy", with: { on: "release" } }` (holocron#930), when the
390
+ release (`--channel`: its prerelease identifier, or `main`/empty for a stable
391
+ release) is on the task's `channel` (default `main`, the stable release) and changes the package or one of its
392
+ `workspace:*` dependencies between `--from` (the previous release's commit,
393
+ omitted when there is none) and `--to` (default `HEAD`). It waits for npm to
394
+ serve the release's new dependency versions, then runs `pnpm --filter <pkg>
395
+ delivery.deploy`. A package that doesn't apply is skipped; a deploy that
396
+ doesn't succeed exits non-zero. The shared `delivery.publish` workflow runs it as its own
397
+ `deploy` job after the release job (opt in with `deploy-on-release: true`).
398
+
399
+ ### `holocron run ci`
400
+
401
+ ```bash
402
+ holocron run ci [--all] [--filter <pkg>] [--dry-run]
283
403
  ```
284
404
 
285
405
  Runs the merge-gating checks locally, in CI order, exiting non-zero on the
@@ -293,6 +413,46 @@ Order comes from the `CI_ORDER` constant in `@theholocron/astromech`
293
413
  expands into its sub-jobs (each under its own `audit / …` check context)
294
414
  unless the repo ships its own `"audit"` script.
295
415
 
416
+ ### `holocron deploy`
417
+
418
+ `holocron deploy <branch>` (a Git-linked deployment) and `holocron deploy
419
+ --files <dir>` (a directory of build output, no linked repo) both trigger a
420
+ deployment through the configured `deployment` capability, then **wait for
421
+ it to finish**. The command reports success, exit code 0, only when the
422
+ deployment reaches `ready`. A deployment that ends `error` or `cancelled`,
423
+ or is still building after 10 minutes, is a failure: the exit code is
424
+ non-zero and the output includes the provider's own reason
425
+ (`DeploymentRecord.errorMessage`, e.g. Vercel's `Command "npm install"
426
+ exited with 1`). Providers build asynchronously, so accepting a deployment
427
+ isn't the same as it going live (holocron#911).
428
+
429
+ Provider plugins support this through the `Deployment` capability's
430
+ existing `getDeployment(id)`. They should set `errorMessage` on the
431
+ returned `DeploymentRecord` whenever the provider exposes one.
432
+
433
+ ### `holocron monitoring check <url>`
434
+
435
+ Runs every configured `monitoring` check against `<url>` instead of each
436
+ check's own configured `url` — no vendor API call, only a plain HTTP
437
+ request evaluated locally against the exact same `assertions` already in
438
+ `holocron.config.ts`. Built for CI: the `delivery.previewCheck` task runs
439
+ this against a PR's Vercel preview deployment (triggered by
440
+ `deployment_status`, not `push`/`pull_request`), reusing the production
441
+ check definitions to catch a breaking change before merge instead of
442
+ after (holocron#1010).
443
+
444
+ ```ts
445
+ export default defineConfig({
446
+ tasks: ["delivery.previewCheck"],
447
+ providers: {
448
+ monitoring: ["checkly", { accountId: "...", checks: [/* ... */] }],
449
+ },
450
+ });
451
+ ```
452
+
453
+ Exits non-zero if any check fails — the job's own pass/fail is what
454
+ posts as the GitHub check, no separate reporting step needed.
455
+
296
456
  ### Lint parity
297
457
 
298
458
  The `lint` task takes an optional `linters` array — one list that drives
@@ -310,7 +470,7 @@ export default defineConfig({
310
470
 
311
471
  ### Skills installer
312
472
 
313
- `holocron setup` can install shared skills from `@theholocron/skills` into the local repo:
473
+ `holocron repo setup` can install shared skills from `@theholocron/skills` into the local repo:
314
474
 
315
475
  ```ts
316
476
  export default defineConfig({
@@ -373,16 +533,16 @@ export default acmeConfig;
373
533
 
374
534
  ## Upgrading
375
535
 
376
- - **`holocron upgrade node <to>`** — patches every Node.js version pin
536
+ - **`holocron repo upgrade node <to>`** — patches every Node.js version pin
377
537
  (`engines.node`, `.nvmrc`, `.node-version`, `.github/workflows/*`,
378
538
  `Dockerfile`, `.tool-versions`) to a new major.
379
- - **`holocron upgrade deps`** — bumps every `@theholocron/*` pin in
539
+ - **`holocron repo upgrade deps`** — bumps every `@theholocron/*` pin in
380
540
  `pnpm-workspace.yaml` (`catalog:` and every named `catalogs.*`) to its latest
381
541
  published version, then migrates `holocron.config.ts` from the 7.x preset
382
542
  shape (`const { repo, workflows } = node()` + `repo.requiredChecks` +
383
543
  `workflows:`) to the current composed-preset API (`const preset = node()` +
384
544
  `...preset` + `tasks:` + `extraRequiredChecks:`). Mechanical transforms only —
385
- review the result, then `pnpm install && holocron ci`. `--pins-only` skips
545
+ review the result, then `pnpm install && holocron run ci`. `--pins-only` skips
386
546
  the config migration; `--dry-run` prints without writing.
387
547
 
388
548
  ## Auth — fine-grained tokens
@@ -401,7 +561,7 @@ holocron auth set github.admin ghp_xxx # setup, secrets, environments
401
561
 
402
562
  The resolution chain per capability is:
403
563
 
404
- ```
564
+ ```text
405
565
  --token flag → HOLOCRON_<FEATURE>_TOKEN env var → keyring("github.<feature>")
406
566
  ```
407
567
 
@@ -418,16 +578,21 @@ holocron auth list # show all stored providers
418
578
  ## Logging
419
579
 
420
580
  Operational output goes through `@theholocron/observability/logger` — separate
421
- from the user-facing `print` surface. Global flags:
581
+ from the user-facing `print` surface. Local/interactive runs are quiet by
582
+ default: no colorized or raw structured console output, regardless of the
583
+ resolved level (Axiom shipping, when configured, is unaffected). CI is
584
+ untouched — its existing stdout output still appears. Global flags:
422
585
 
423
586
  ```sh
424
- holocron doctor --verbose # log level → debug (full structured output)
425
- holocron doctor --quiet # log level → error (suppress info + warn)
587
+ holocron doctor --log debug # show console output at this level (opt back in)
588
+ holocron doctor --verbose # log level → debug, and shows console output
589
+ holocron doctor --quiet # log level → error, and shows console output
426
590
  holocron doctor --debug # print "Run ID: <uuid>" at command end for Axiom lookup
427
591
  ```
428
592
 
429
- Level resolution (highest priority first): `--verbose` / `--quiet` →
430
- `HOLOCRON_LOG_LEVEL` → `log.level` in `holocron.config` → `"info"`.
593
+ Level resolution (highest priority first): `--log <level>` → `--verbose` /
594
+ `--quiet` → `HOLOCRON_LOG_LEVEL` → `log.level` in `holocron.config` →
595
+ `"info"`.
431
596
 
432
597
  ```ts
433
598
  export default defineConfig({
@@ -439,7 +604,16 @@ Axiom shipping activates when a token (`HOLOCRON_AXIOM_TOKEN` / `AXIOM_TOKEN`
439
604
  → OS keyring `axiom.<org>` → `axiom`) **and** a dataset
440
605
  (`HOLOCRON_AXIOM_DATASET` / `AXIOM_DATASET` → `log.axiom.dataset` in
441
606
  `holocron.config`) both resolve; env vars win. The token is never read from a
442
- config file. See the [logging guide](https://docs.theholocron.dev/holocron/logging/).
607
+ config file.
608
+
609
+ The dataset side of that resolution is **execution-context-aware** (ADR-0012):
610
+ a `global`-context command (`clone`, `new`, `auth set`, `upgrade node`, `plugin
611
+ create`, …) always ships to holocron's own dataset regardless of `$PWD` — it
612
+ isn't "about" any repo, so routing it through whichever repo's `.envrc`
613
+ happens to be active would be wrong. `repo-aware` / `workspace` commands
614
+ (`doctor`, `deploy`, `sync`, …) keep the env-var/config chain above, so a
615
+ per-repo `HOLOCRON_AXIOM_DATASET` — e.g. via a `.envrc` + `direnv` — separates
616
+ each consuming repo's logs. See the [logging guide](https://docs.theholocron.dev/holocron/logging/).
443
617
 
444
618
  ### Telemetry
445
619
 
@@ -468,38 +642,67 @@ export default defineConfig({
468
642
 
469
643
  Each SDK sits behind an interface from `@theholocron/observability` —
470
644
  `ErrorSink` (Sentry) / `AnalyticsSink` (PostHog); the adapters, and the only
471
- `@sentry/node` / `posthog-node` imports, live in that package. `telemetry.ts`
645
+ `@sentry/node` / `posthog-node` imports, live in that package. `observability/telemetry.ts`
472
646
  holds the orchestration + the Holocron-specific credential resolution
473
- (`telemetry/resolve.ts`). See the
647
+ (`observability/resolve-telemetry.ts`). See the
474
648
  [telemetry guide](https://docs.theholocron.dev/holocron/telemetry/).
475
649
 
650
+ ### ESLint bundle options
651
+
652
+ Most repos need nothing here — `@theholocron/eslint-config`'s `library()`
653
+ bundle resolves with zero committed file (Bucket A: `eslint --config
654
+ <shared path>`, no per-repo `eslint.config.ts` needed). A package with a
655
+ genuine, deliberate exception — e.g. Web Crypto globals a Node-targeted
656
+ package still needs, exempted via `library()`'s own `browserPackages`
657
+ option in that package's own `eslint.config.ts` — should also declare the
658
+ same paths in `holocron.config`'s `eslint.browserPackages`:
659
+
660
+ ```ts
661
+ export default defineConfig({
662
+ eslint: {
663
+ browserPackages: ["packages/github-client/src/app-auth"],
664
+ },
665
+ });
666
+ ```
667
+
668
+ This doesn't replace the package's own `eslint.config.ts` (local/CI linting
669
+ still resolves that file directly) — it's the signal Sentinel's centralized
670
+ static-analysis check (holocron#849/#858) reads instead, since that check
671
+ never reads a PR's own committed config files. Without it, Sentinel flags a
672
+ false-positive `eslint-plugin-n` node-builtins finding on exactly the files
673
+ the local override exists to exempt.
674
+
476
675
  ## What's in here
477
676
 
478
- - `src/capabilities/` — the 14 capability interfaces that providers
479
- implement
677
+ - `src/plugin/capabilities.ts` — the 18 capability interfaces that
678
+ providers implement
480
679
  - `src/config.ts` — config schema, `defineConfig`, `resolveConfig`,
481
680
  `CapabilityConfigPackage`
482
681
  - `src/config/load-config.ts` — `loadConfig` — reads `holocron.config.*`
483
682
  (file discovery via [`@theholocron/datapad`](../datapad))
484
683
  - `src/define-config.ts` — `defineConfig` typed pass-through
485
- - `src/logger.ts` — CLI-side `@theholocron/observability/logger` wiring
684
+ - `src/observability/logger.ts` — CLI-side `@theholocron/observability/logger` wiring
486
685
  (`buildCliLogger`, `resolveLogLevel`)
487
686
  - `src/loader.ts` — `PluginLoader` — dynamic-imports plugins, resolves
488
687
  capability config packages, builds the capability registry
489
688
  - `src/cli.ts` — yargs entry, dispatches subcommands. `holocron run` / `ci` are
490
689
  delegated to [`@theholocron/astromech`](../astromech) (`createAstromech`).
491
- `holocron sync` / `holocron setup` write each repo's `.github/workflows/*.yml`
492
- thin callers from `astromech.thinCallers()`; `holocron sync-github` pushes the
690
+ `holocron repo sync` / `holocron repo setup` write each repo's `.github/workflows/*.yml`
691
+ thin callers from `astromech.thinCallers()`; `holocron sync github` pushes the
493
692
  reusable `workflow_call` implementations + composite actions from
494
693
  `astromech.reusableTemplates()` to `theholocron/.github` (a pure sync target —
495
694
  never hand-edit its `.github/workflows/*`).
496
- - `src/commands/` — `setup`, `sync`, `doctor`, `deploy`, `secret set`,
497
- `secrets sync`, `publish`, `bump-versions`, `sync-github`, `upgrade node`,
498
- `upgrade deps`, `plugin create`, `auth`
499
- - `src/interactive-menu.ts` — the interactive fallback: `COMMAND_REGISTRY`,
500
- `launchMenu` (Layers 1–2, picks + spawns a fresh `holocron <command>`),
501
- `promptForPositionals` (Layer 3, called inline from each leaf command's
502
- `cli.ts` handler)
695
+ - `src/commands/` — `repo setup`, `repo sync`, `doctor`, `deploy`,
696
+ `monitoring check`, `secrets set`, `secrets sync`, `package publish`,
697
+ `package bump-versions`, `sync github`, `repo upgrade node`,
698
+ `repo upgrade deps`, `new plugin`, `auth`
699
+ - `src/interactive-menu/` — the interactive fallback: `command-registry`
700
+ (`COMMAND_REGISTRY`, each entry's `positionals`/`options`), `launch-menu`
701
+ (Layers 1–2, picks + spawns a fresh `holocron <command>`), `child-argv`
702
+ (builds the spawned argv + secret env), `menu-items`, `run-menu-entries`.
703
+ The generic prompting pieces it calls — `promptForPositionals`,
704
+ `promptForOptions` (Layer 3) — live in `src/ui/`, which has no knowledge
705
+ of commands.
503
706
 
504
707
  ## Status
505
708