@theholocron/cli 3.54.0 → 3.55.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 +27 -0
- package/dist/cli.mjs +128 -44
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +20 -2
- package/dist/index.mjs +2 -26
- package/dist/plugin/capabilities.d.mts +43 -24
- package/dist/plugin/capabilities.mjs +2 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -168,6 +168,31 @@ holocron auth unset github.read # remove a stored token
|
|
|
168
168
|
holocron auth list # show all stored providers
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
+
## Logging
|
|
172
|
+
|
|
173
|
+
Operational output goes through [`@theholocron/logger`](../logger) — separate from
|
|
174
|
+
the user-facing `print` surface. Global flags:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
holocron doctor --verbose # log level → debug (full structured output)
|
|
178
|
+
holocron doctor --quiet # log level → error (suppress info + warn)
|
|
179
|
+
holocron doctor --debug # print "Run ID: <uuid>" at command end for Axiom lookup
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Level resolution (highest priority first): `--verbose` / `--quiet` →
|
|
183
|
+
`HOLOCRON_LOG_LEVEL` → `log.level` in `holocron.config` → `"info"`.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
export default defineConfig({
|
|
187
|
+
log: { level: "warn" },
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Axiom credentials (`HOLOCRON_AXIOM_TOKEN` / `AXIOM_TOKEN`,
|
|
192
|
+
`HOLOCRON_AXIOM_DATASET` / `AXIOM_DATASET`) come from env vars only.
|
|
193
|
+
`HOLOCRON_TELEMETRY=false` disables the Axiom transport (and Sentry). See the
|
|
194
|
+
[logging guide](https://docs.theholocron.dev/holocron/logging/).
|
|
195
|
+
|
|
171
196
|
## What's in here
|
|
172
197
|
|
|
173
198
|
- `src/capabilities/` — the 14 capability interfaces that providers
|
|
@@ -176,6 +201,8 @@ holocron auth list # show all stored providers
|
|
|
176
201
|
`CapabilityConfigPackage`
|
|
177
202
|
- `src/load-config.ts` — `loadConfig` — reads JSON/JS/TS config files
|
|
178
203
|
- `src/define-config.ts` — `defineConfig` typed pass-through
|
|
204
|
+
- `src/logger.ts` — CLI-side `@theholocron/logger` wiring (`buildCliLogger`,
|
|
205
|
+
`resolveLogLevel`)
|
|
179
206
|
- `src/loader.ts` — `PluginLoader` — dynamic-imports plugins, resolves
|
|
180
207
|
capability config packages, builds the capability registry
|
|
181
208
|
- `src/cli.ts` — yargs entry, dispatches subcommands
|
package/dist/cli.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import chalk from "chalk";
|
|
|
14
14
|
import { execFile, execFileSync, spawnSync } from "node:child_process";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { access, copyFile, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
17
|
+
import { createLogger, parseLogLevel } from "@theholocron/logger";
|
|
17
18
|
import { createHash } from "node:crypto";
|
|
18
19
|
import { generateReadme } from "@theholocron/components-doc/markdown";
|
|
19
20
|
import { getClients, getConfigs, getDocs, getPlugins, getSkills, getThemes, getUtils } from "@theholocron/registry-doc";
|
|
@@ -172,7 +173,8 @@ const CARDINALITY = {
|
|
|
172
173
|
tooling: "many",
|
|
173
174
|
notifications: "many",
|
|
174
175
|
analytics: "many",
|
|
175
|
-
|
|
176
|
+
errors: "single",
|
|
177
|
+
logs: "single",
|
|
176
178
|
wiki: "single",
|
|
177
179
|
workers: "single"
|
|
178
180
|
};
|
|
@@ -184,31 +186,6 @@ const CARDINALITY = {
|
|
|
184
186
|
const REQUIRED_CAPABILITIES = [];
|
|
185
187
|
//#endregion
|
|
186
188
|
//#region src/config/config.ts
|
|
187
|
-
/**
|
|
188
|
-
* `holocron.config.json` schema, parser, and provider resolution.
|
|
189
|
-
*
|
|
190
|
-
* ESLint-style entry forms:
|
|
191
|
-
*
|
|
192
|
-
* "source": "github" ← single, short
|
|
193
|
-
* "deployment": ["vercel", { team: "rando" }] ← single, with options
|
|
194
|
-
* "notifications": ["slack", "discord"] ← multi, short
|
|
195
|
-
* "notifications": [
|
|
196
|
-
* ["slack", { channel: "#ops" }],
|
|
197
|
-
* ["discord", { webhook: "env:HOOK" }]
|
|
198
|
-
* ] ← multi, with options
|
|
199
|
-
*
|
|
200
|
-
* Discriminator: an array entry is a `[provider, options]` tuple when
|
|
201
|
-
* the length is 2 AND element[1] is a non-array, non-null object.
|
|
202
|
-
* Otherwise it's a multi-provider list (string[] or tuple[]).
|
|
203
|
-
*
|
|
204
|
-
* Validation rules:
|
|
205
|
-
* - `vault` is REQUIRED (every project has secrets somewhere)
|
|
206
|
-
* - Entries for `'many'` capabilities are normalized to an array of
|
|
207
|
-
* normalized tuples; entries for `'single'` capabilities are
|
|
208
|
-
* normalized to one tuple
|
|
209
|
-
* - Tokens / secret values never appear in config — providers read
|
|
210
|
-
* them from env (or pull from `vault` at runtime)
|
|
211
|
-
*/
|
|
212
189
|
var ConfigError = class extends Error {
|
|
213
190
|
name = "ConfigError";
|
|
214
191
|
};
|
|
@@ -306,7 +283,8 @@ function resolveConfig(raw) {
|
|
|
306
283
|
agent: raw.agent,
|
|
307
284
|
skills: raw.skills,
|
|
308
285
|
docs,
|
|
309
|
-
env: raw.env
|
|
286
|
+
env: raw.env,
|
|
287
|
+
log: raw.log
|
|
310
288
|
};
|
|
311
289
|
}
|
|
312
290
|
//#endregion
|
|
@@ -986,6 +964,19 @@ async function smokeCheck(key, provider, impl) {
|
|
|
986
964
|
const desc = await impl.describe();
|
|
987
965
|
return mk(key, provider, "ok", `provider: ${desc.provider}; env keys: ${desc.envKeys.join(", ")}`);
|
|
988
966
|
}
|
|
967
|
+
case "errors": {
|
|
968
|
+
const desc = await impl.describe();
|
|
969
|
+
return mk(key, provider, "ok", `provider: ${desc.provider}; env keys: ${desc.envKeys.join(", ")}`);
|
|
970
|
+
}
|
|
971
|
+
case "logs": {
|
|
972
|
+
const logs = impl;
|
|
973
|
+
const desc = await logs.describe();
|
|
974
|
+
if (logs.whoami) {
|
|
975
|
+
const who = await logs.whoami();
|
|
976
|
+
return mk(key, provider, who.ok ? "ok" : "fail", `dataset: ${who.dataset}`);
|
|
977
|
+
}
|
|
978
|
+
return mk(key, provider, "ok", `provider: ${desc.provider}; env keys: ${desc.envKeys.join(", ")}`);
|
|
979
|
+
}
|
|
989
980
|
default: return mk(key, provider, "skip", "loaded (no smoke check defined for this capability)");
|
|
990
981
|
}
|
|
991
982
|
} catch (err) {
|
|
@@ -3121,6 +3112,59 @@ var dependabot_default = "version: 2\nupdates:\n - package-ecosystem: npm\n
|
|
|
3121
3112
|
//#region src/templates/labeler.yml
|
|
3122
3113
|
var labeler_default = "bug:\n - '^fix'\n\nchore:\n - '^chore(?!\\(deps)'\n\nci:\n - '^ci'\n\ndependencies:\n - '^chore\\(deps'\n\ndocumentation:\n - '^docs'\n\nenhancement:\n - '^feat'\n\nperformance:\n - '^perf'\n\nrefactor:\n - '^refactor'\n\ntest:\n - '^test'\n";
|
|
3123
3114
|
//#endregion
|
|
3115
|
+
//#region src/logger.ts
|
|
3116
|
+
/**
|
|
3117
|
+
* CLI-side wiring for `@theholocron/logger`.
|
|
3118
|
+
*
|
|
3119
|
+
* `logger` is the operational-output channel — internal state, debug
|
|
3120
|
+
* traces, errors, structured context that routes to Axiom. It runs in
|
|
3121
|
+
* parallel to `print` (user-facing UX output) and does not replace it.
|
|
3122
|
+
*/
|
|
3123
|
+
/**
|
|
3124
|
+
* Resolve the explicit level to hand to `createLogger`, in priority order:
|
|
3125
|
+
*
|
|
3126
|
+
* 1. `--verbose` → `"debug"` 2. `--quiet` → `"error"`
|
|
3127
|
+
* 3. `HOLOCRON_LOG_LEVEL` env var
|
|
3128
|
+
* 4. `holocron.config` `log.level` (`configLevel`)
|
|
3129
|
+
*
|
|
3130
|
+
* Returns `undefined` when nothing applies — `createLogger` then defaults
|
|
3131
|
+
* to `"info"`. Resolving the full chain here (rather than passing
|
|
3132
|
+
* `configLevel` straight through) keeps config below the env var.
|
|
3133
|
+
*/
|
|
3134
|
+
function resolveLogLevel(argv, configLevel) {
|
|
3135
|
+
if (argv.verbose) return "debug";
|
|
3136
|
+
if (argv.quiet) return "error";
|
|
3137
|
+
return parseLogLevel(env.get("HOLOCRON_LOG_LEVEL")) ?? configLevel;
|
|
3138
|
+
}
|
|
3139
|
+
let root;
|
|
3140
|
+
let rootLevel;
|
|
3141
|
+
/**
|
|
3142
|
+
* The process-wide root logger. Built once (from `cli.ts`'s middleware,
|
|
3143
|
+
* with flags + env only). Rebuilt at most once more when a command's
|
|
3144
|
+
* handler supplies its `holocron.config` `log.level` — a case the
|
|
3145
|
+
* flag/env-only first pass could not have known — as long as no
|
|
3146
|
+
* higher-priority `--verbose` / `--quiet` already fixed the level. That
|
|
3147
|
+
* rebuild generates a fresh `runId`, which is harmless: nothing logs
|
|
3148
|
+
* between the middleware and the handler.
|
|
3149
|
+
*/
|
|
3150
|
+
function buildCliLogger(argv, configLevel) {
|
|
3151
|
+
const level = resolveLogLevel(argv, configLevel);
|
|
3152
|
+
const rebuildForConfig = configLevel !== void 0 && level !== rootLevel && !argv.verbose && !argv.quiet;
|
|
3153
|
+
if (!root || rebuildForConfig) {
|
|
3154
|
+
root = createLogger(level ? { level } : {});
|
|
3155
|
+
rootLevel = level;
|
|
3156
|
+
}
|
|
3157
|
+
return root;
|
|
3158
|
+
}
|
|
3159
|
+
/** Lazily-memoized `Logger` for module-level call sites with no `argv` in scope. */
|
|
3160
|
+
function getLogger() {
|
|
3161
|
+
return (root ??= createLogger()).logger;
|
|
3162
|
+
}
|
|
3163
|
+
/** The current root logger's correlation id, if a root has been built. */
|
|
3164
|
+
function getRunId() {
|
|
3165
|
+
return root?.runId;
|
|
3166
|
+
}
|
|
3167
|
+
//#endregion
|
|
3124
3168
|
//#region src/commands/setup-workflows/index.ts
|
|
3125
3169
|
/**
|
|
3126
3170
|
* Thin workflow wrapper templates for `holocron setup`.
|
|
@@ -3210,7 +3254,7 @@ function generateThinCallerContent(name, withOverrides, additionalPaths) {
|
|
|
3210
3254
|
}
|
|
3211
3255
|
const withBlock = Object.entries(withOverrides).map(([k, v]) => fmt(k, v)).join("\n");
|
|
3212
3256
|
const injected = result.replace(/ {4}secrets: inherit\n$/, ` with:\n${withBlock}\n secrets: inherit\n`);
|
|
3213
|
-
if (injected === result)
|
|
3257
|
+
if (injected === result) getLogger().warn({ template: name }, "generateThinCallerContent: could not inject `with:` overrides");
|
|
3214
3258
|
return injected;
|
|
3215
3259
|
}
|
|
3216
3260
|
/**
|
|
@@ -4585,6 +4629,17 @@ async function runSetup(input) {
|
|
|
4585
4629
|
}
|
|
4586
4630
|
print(formatStep(steps[steps.length - 1]));
|
|
4587
4631
|
}
|
|
4632
|
+
if (loader.has("logs")) {
|
|
4633
|
+
const logs = loader.get("logs");
|
|
4634
|
+
print(style.step("logs"));
|
|
4635
|
+
if (logs.ensureDataset) for (const dataset of ["holocron-ci", "holocron-local"]) {
|
|
4636
|
+
steps.push(await runStep("logs", `ensureDataset ${dataset}`, dryRun, async () => {
|
|
4637
|
+
const result = await logs.ensureDataset(dataset);
|
|
4638
|
+
return `${dataset} ${result.alreadyExists ? "exists" : "created"}`;
|
|
4639
|
+
}));
|
|
4640
|
+
print(formatStep(steps[steps.length - 1]));
|
|
4641
|
+
}
|
|
4642
|
+
}
|
|
4588
4643
|
if (loader.has("tooling")) {
|
|
4589
4644
|
const tools = loader.get("tooling");
|
|
4590
4645
|
print(style.step("tooling"));
|
|
@@ -4724,13 +4779,14 @@ async function runSkillsInstall(input) {
|
|
|
4724
4779
|
function runSkillsRemove(input) {
|
|
4725
4780
|
const { dryRun, repoRoot } = input.context;
|
|
4726
4781
|
const exec = input.exec ?? defaultExec;
|
|
4782
|
+
const logger = input.logger ?? getLogger();
|
|
4727
4783
|
const args = [
|
|
4728
4784
|
"skills",
|
|
4729
4785
|
"remove",
|
|
4730
4786
|
...input.names ?? []
|
|
4731
4787
|
];
|
|
4732
4788
|
if (dryRun) {
|
|
4733
|
-
|
|
4789
|
+
logger.info({ argv: args }, `Would run: npx ${args.join(" ")}`);
|
|
4734
4790
|
return { status: "dry-run" };
|
|
4735
4791
|
}
|
|
4736
4792
|
const { exitCode } = exec("npx", args, { cwd: repoRoot });
|
|
@@ -4739,13 +4795,14 @@ function runSkillsRemove(input) {
|
|
|
4739
4795
|
function runSkillsUpdate(input) {
|
|
4740
4796
|
const { dryRun, repoRoot } = input.context;
|
|
4741
4797
|
const exec = input.exec ?? defaultExec;
|
|
4798
|
+
const logger = input.logger ?? getLogger();
|
|
4742
4799
|
const args = [
|
|
4743
4800
|
"skills",
|
|
4744
4801
|
"update",
|
|
4745
4802
|
...input.name ? [input.name] : []
|
|
4746
4803
|
];
|
|
4747
4804
|
if (dryRun) {
|
|
4748
|
-
|
|
4805
|
+
logger.info({ argv: args }, `Would run: npx ${args.join(" ")}`);
|
|
4749
4806
|
return { status: "dry-run" };
|
|
4750
4807
|
}
|
|
4751
4808
|
const { exitCode } = exec("npx", args, { cwd: repoRoot });
|
|
@@ -6109,7 +6166,7 @@ async function fileExists(path) {
|
|
|
6109
6166
|
//#region src/telemetry.ts
|
|
6110
6167
|
const DSN = "https://95cbb72ad5636c94e119a5405ee8f55f@o4508238154104832.ingest.us.sentry.io/4511810950791168";
|
|
6111
6168
|
function isEnabled() {
|
|
6112
|
-
return !env.get("NO_HOLOCRON_TELEMETRY") && true;
|
|
6169
|
+
return !(env.get("HOLOCRON_TELEMETRY") === "false" || Boolean(env.get("NO_HOLOCRON_TELEMETRY"))) && true;
|
|
6113
6170
|
}
|
|
6114
6171
|
function init(version) {
|
|
6115
6172
|
if (!isEnabled()) return;
|
|
@@ -6280,6 +6337,8 @@ const resolveSyncToken = createFeatureResolver({
|
|
|
6280
6337
|
keyringKey: "github.sync"
|
|
6281
6338
|
});
|
|
6282
6339
|
const { version: CLI_VERSION } = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
6340
|
+
/** Whether to print the correlation id at command end (`--debug` / `--verbose`). */
|
|
6341
|
+
let printRunId = false;
|
|
6283
6342
|
/**
|
|
6284
6343
|
* Resolves the active org in priority order:
|
|
6285
6344
|
* 1. `--org` CLI flag
|
|
@@ -6296,7 +6355,7 @@ function tokenContext(rawTokens) {
|
|
|
6296
6355
|
return parseTokenArgs(rawTokens);
|
|
6297
6356
|
} catch (err) {
|
|
6298
6357
|
if (err instanceof TokenParseError) {
|
|
6299
|
-
|
|
6358
|
+
getLogger().error(`--token: ${err.message}`);
|
|
6300
6359
|
process.exitCode = 1;
|
|
6301
6360
|
return null;
|
|
6302
6361
|
}
|
|
@@ -6307,9 +6366,7 @@ init(CLI_VERSION);
|
|
|
6307
6366
|
const updateCheckPromise = checkForUpdates(CLI_VERSION);
|
|
6308
6367
|
let finishCommand = () => {};
|
|
6309
6368
|
try {
|
|
6310
|
-
await yargs(hideBin(process.argv)).
|
|
6311
|
-
finishCommand = startCommand(argv._.slice(0, 2).join(" ") || "unknown");
|
|
6312
|
-
}).scriptName("").usage("holocron <command> [options]").option("dry-run", {
|
|
6369
|
+
await yargs(hideBin(process.argv)).scriptName("").usage("holocron <command> [options]").option("dry-run", {
|
|
6313
6370
|
type: "boolean",
|
|
6314
6371
|
default: false,
|
|
6315
6372
|
describe: "Print what would be mutated without calling capability mutators. Commands branch on this; read-only commands ignore it."
|
|
@@ -6324,6 +6381,22 @@ try {
|
|
|
6324
6381
|
type: "string",
|
|
6325
6382
|
default: process.cwd(),
|
|
6326
6383
|
describe: "Directory to search for holocron.config.json"
|
|
6384
|
+
}).option("verbose", {
|
|
6385
|
+
type: "boolean",
|
|
6386
|
+
default: false,
|
|
6387
|
+
describe: "Set the log level to debug — full structured operational output."
|
|
6388
|
+
}).option("debug", {
|
|
6389
|
+
type: "boolean",
|
|
6390
|
+
default: false,
|
|
6391
|
+
describe: "Print the run ID at command end for Axiom lookup. Does not change the log level."
|
|
6392
|
+
}).option("quiet", {
|
|
6393
|
+
type: "boolean",
|
|
6394
|
+
default: false,
|
|
6395
|
+
describe: "Set the log level to error — suppress info and warn."
|
|
6396
|
+
}).middleware((argv) => {
|
|
6397
|
+
finishCommand = startCommand(argv._.slice(0, 2).join(" ") || "unknown");
|
|
6398
|
+
printRunId = Boolean(argv.debug || argv.verbose);
|
|
6399
|
+
buildCliLogger(argv);
|
|
6327
6400
|
}).command("version", "Print the CLI version", () => {}, () => {
|
|
6328
6401
|
console.log(`holocron ${CLI_VERSION}`);
|
|
6329
6402
|
}).command("clone", "Clone all repos in a GitHub org as siblings under a single directory", (y) => y.option("org", {
|
|
@@ -6340,7 +6413,7 @@ try {
|
|
|
6340
6413
|
try {
|
|
6341
6414
|
token = resolveCloneToken({ cliToken: tokens.cliTokens?.["github"] ?? tokens.cliToken });
|
|
6342
6415
|
} catch (err) {
|
|
6343
|
-
|
|
6416
|
+
getLogger().error(`clone: ${err instanceof AuthError ? err.message : String(err)}`);
|
|
6344
6417
|
process.exitCode = 1;
|
|
6345
6418
|
return;
|
|
6346
6419
|
}
|
|
@@ -6357,6 +6430,7 @@ try {
|
|
|
6357
6430
|
const tokens = tokenContext(argv.token);
|
|
6358
6431
|
if (!tokens) return;
|
|
6359
6432
|
const loaded = await loadConfig(argv.cwd);
|
|
6433
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6360
6434
|
if ((await runDoctor({
|
|
6361
6435
|
loaded,
|
|
6362
6436
|
context: {
|
|
@@ -6374,6 +6448,7 @@ try {
|
|
|
6374
6448
|
const tokens = tokenContext(argv.token);
|
|
6375
6449
|
if (!tokens) return;
|
|
6376
6450
|
const loaded = await loadConfig(argv.cwd);
|
|
6451
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6377
6452
|
if ((await runSetup({
|
|
6378
6453
|
loaded,
|
|
6379
6454
|
context: {
|
|
@@ -6439,6 +6514,7 @@ try {
|
|
|
6439
6514
|
const scopeArg = argv.scope;
|
|
6440
6515
|
const scope = parseScope(scopeArg);
|
|
6441
6516
|
const loaded = await loadConfig(argv.cwd);
|
|
6517
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6442
6518
|
if ((await runSecretSet({
|
|
6443
6519
|
loaded,
|
|
6444
6520
|
context: {
|
|
@@ -6468,6 +6544,7 @@ try {
|
|
|
6468
6544
|
const tokens = tokenContext(argv.token);
|
|
6469
6545
|
if (!tokens) return;
|
|
6470
6546
|
const loaded = await loadConfig(argv.cwd);
|
|
6547
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6471
6548
|
if ((await runSecretsSync({
|
|
6472
6549
|
loaded,
|
|
6473
6550
|
context: {
|
|
@@ -6496,6 +6573,7 @@ try {
|
|
|
6496
6573
|
const tokens = tokenContext(argv.token);
|
|
6497
6574
|
if (!tokens) return;
|
|
6498
6575
|
const loaded = await loadConfig(argv.cwd);
|
|
6576
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6499
6577
|
if ((await runDeploy({
|
|
6500
6578
|
loaded,
|
|
6501
6579
|
context: {
|
|
@@ -6523,6 +6601,7 @@ try {
|
|
|
6523
6601
|
const tokens = tokenContext(argv.token);
|
|
6524
6602
|
if (!tokens) return;
|
|
6525
6603
|
const loaded = await loadConfig(argv.cwd);
|
|
6604
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6526
6605
|
if ((await runCleanupPreview({
|
|
6527
6606
|
loaded,
|
|
6528
6607
|
context: {
|
|
@@ -6570,6 +6649,7 @@ try {
|
|
|
6570
6649
|
const tokens = tokenContext(argv.token);
|
|
6571
6650
|
if (!tokens) return;
|
|
6572
6651
|
const loaded = await loadConfig(argv.cwd);
|
|
6652
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6573
6653
|
if ((await runSync({
|
|
6574
6654
|
loaded,
|
|
6575
6655
|
context: {
|
|
@@ -6607,7 +6687,7 @@ try {
|
|
|
6607
6687
|
else try {
|
|
6608
6688
|
token = resolveSyncToken({ cliToken: parsed.cliTokens?.["github"] ?? parsed.cliToken });
|
|
6609
6689
|
} catch (err) {
|
|
6610
|
-
|
|
6690
|
+
getLogger().error(`sync-github: ${err instanceof AuthError ? err.message : String(err)}`);
|
|
6611
6691
|
process.exitCode = 1;
|
|
6612
6692
|
return;
|
|
6613
6693
|
}
|
|
@@ -6625,8 +6705,10 @@ try {
|
|
|
6625
6705
|
describe: "Print what would change without writing",
|
|
6626
6706
|
default: false
|
|
6627
6707
|
}), async (argv) => {
|
|
6708
|
+
const loaded = await loadConfig(argv.cwd);
|
|
6709
|
+
buildCliLogger(argv, loaded.resolved.log?.level);
|
|
6628
6710
|
if ((await runSyncReadme({
|
|
6629
|
-
loaded
|
|
6711
|
+
loaded,
|
|
6630
6712
|
context: {
|
|
6631
6713
|
repoRoot: argv.cwd,
|
|
6632
6714
|
dryRun: argv.dryRun
|
|
@@ -6860,12 +6942,12 @@ try {
|
|
|
6860
6942
|
}) === "yes";
|
|
6861
6943
|
if (skills.length === 0) skills = parseTopics(await input({ message: "Agent skills (comma-separated, optional):" }));
|
|
6862
6944
|
if (!type) {
|
|
6863
|
-
|
|
6945
|
+
getLogger().error("new: template type is required");
|
|
6864
6946
|
process.exitCode = 1;
|
|
6865
6947
|
return;
|
|
6866
6948
|
}
|
|
6867
6949
|
if (!name) {
|
|
6868
|
-
|
|
6950
|
+
getLogger().error("new: repo name is required");
|
|
6869
6951
|
process.exitCode = 1;
|
|
6870
6952
|
return;
|
|
6871
6953
|
}
|
|
@@ -6894,7 +6976,7 @@ try {
|
|
|
6894
6976
|
})).status === "fail") process.exitCode = 1;
|
|
6895
6977
|
} catch (err) {
|
|
6896
6978
|
if (err instanceof NewError) {
|
|
6897
|
-
|
|
6979
|
+
getLogger().error(`new: ${err.message}`);
|
|
6898
6980
|
process.exitCode = 1;
|
|
6899
6981
|
return;
|
|
6900
6982
|
}
|
|
@@ -6910,7 +6992,7 @@ try {
|
|
|
6910
6992
|
describe: "Vendor display name (PascalCase)"
|
|
6911
6993
|
}).option("capability", {
|
|
6912
6994
|
type: "string",
|
|
6913
|
-
describe: "Capability key: source|ci|secrets|environments|issues|deployment|storage|auth|vault|dns|tooling|notifications|analytics|
|
|
6995
|
+
describe: "Capability key: source|ci|secrets|environments|issues|deployment|storage|auth|vault|dns|tooling|notifications|analytics|errors|logs|wiki|workers"
|
|
6914
6996
|
}).option("token-env", {
|
|
6915
6997
|
type: "string",
|
|
6916
6998
|
describe: "Holocron env var name (defaults to HOLOCRON_<VENDOR>_TOKEN)"
|
|
@@ -6955,7 +7037,7 @@ try {
|
|
|
6955
7037
|
}).status === "fail") process.exitCode = 1;
|
|
6956
7038
|
} catch (err) {
|
|
6957
7039
|
if (err instanceof PluginCreateError) {
|
|
6958
|
-
|
|
7040
|
+
getLogger().error(`plugin create: ${err.message}`);
|
|
6959
7041
|
process.exitCode = 1;
|
|
6960
7042
|
return;
|
|
6961
7043
|
}
|
|
@@ -6983,7 +7065,7 @@ try {
|
|
|
6983
7065
|
extra
|
|
6984
7066
|
});
|
|
6985
7067
|
if (report.status === "fail") {
|
|
6986
|
-
if (report.message)
|
|
7068
|
+
if (report.message) getLogger().error(`upgrade node: ${report.message}`);
|
|
6987
7069
|
process.exitCode = 1;
|
|
6988
7070
|
}
|
|
6989
7071
|
}).demandCommand(1, "Run `holocron upgrade --help` to see available upgrade subcommands."), () => {}).command("auth <subcommand>", "Manage bootstrap credentials in the OS keyring", (y) => y.command("set <provider> [value]", "Verify + store a bootstrap token for a provider", (yy) => yy.positional("provider", {
|
|
@@ -7017,6 +7099,8 @@ try {
|
|
|
7017
7099
|
}
|
|
7018
7100
|
finishCommand(!process.exitCode);
|
|
7019
7101
|
endSession();
|
|
7102
|
+
const rid = getRunId();
|
|
7103
|
+
if (printRunId && rid) console.log(`Run ID: ${rid}`);
|
|
7020
7104
|
(await updateCheckPromise)?.();
|
|
7021
7105
|
await flush();
|
|
7022
7106
|
/**
|