fix: honor config-file silent and verbose in logger configuration#2316
Conversation
Config-file silent: true was a documented no-op: wrapCommand configured the logger from CLI flags only and Config.getSilent() had no call sites. - ConfigResolver.resolve now re-configures the supplied logger (and the shared fallbackLogger) from the resolved verbose/silent as soon as the config files are merged, so config-file settings apply to everything logged afterwards. CLI flags still win via the existing pick precedence. - Thread the command logger into ConfigResolver.resolve from the convert, install, and gitignore commands (generate and import already did). - Replace the unconfigured module-level ConsoleLogger fallbacks in the qwencode/augmentcode permission translators with a shared fallbackLogger that wrapCommand and ConfigResolver keep configured, and route warnWithFallback(undefined, ...) through it so those warn paths honor silent end to end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a wiring gap in Rulesync’s CLI logging: silent/verbose values from rulesync.jsonc were being resolved correctly but were not applied to the configured logger (so only CLI flags consistently affected output). The change centralizes logger re-configuration inside ConfigResolver.resolve, threads loggers into more command entrypoints, and introduces a shared fallback logger so “no-logger” warning paths also honor silent.
Changes:
- Re-configure the supplied logger (and a shared fallback logger) from resolved
silent/verboseearly inConfigResolver.resolve, so config-file values affect subsequent warnings and debug output. - Thread command loggers into
ConfigResolver.resolvefor additional CLI commands (convert,install,gitignore) so precedence (CLI > file) remains consistent. - Route
warnWithFallback(undefined, ...)and certain module-level permission translator warnings through a sharedfallbackLogger, with new/updated tests.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/logger.ts | Adds fallbackLogger and changes warnWithFallback to route through it. |
| src/utils/logger.test.ts | Adds unit tests validating warnWithFallback routing and fallback silent suppression. |
| src/features/permissions/qwencode-permissions.ts | Replaces a private module ConsoleLogger fallback with fallbackLogger so silent is honored. |
| src/features/permissions/augmentcode-permissions.ts | Same as above for AugmentCode permissions translator. |
| src/features/mcp/codexcli-mcp.test.ts | Updates tests to spy on fallbackLogger.warn instead of console.warn. |
| src/config/config-resolver.ts | Re-configures logger/fallback logger from resolved config silent/verbose early during resolution. |
| src/config/config-resolver.test.ts | Adds regression tests for resolver-driven logger reconfiguration and fallback behavior. |
| src/cli/wrap-command.ts | Configures fallbackLogger from CLI flags alongside the command logger. |
| src/cli/index.ts | Passes verbose/silent options through to gitignoreCommand. |
| src/cli/commands/install.ts | Threads { logger } into ConfigResolver.resolve. |
| src/cli/commands/gitignore.ts | Threads CLI verbose/silent and { logger } into ConfigResolver.resolve. |
| src/cli/commands/convert.ts | Threads { logger } into ConfigResolver.resolve. |
| src/cli/commands/convert.test.ts | Updates expectations to include { logger } passed to ConfigResolver.resolve. |
| /** | ||
| * Shared fallback logger for code paths that have no command logger threaded | ||
| * through (module-level translators, `warnWithFallback(undefined, ...)`). | ||
| * `wrapCommand` configures it from CLI flags and `ConfigResolver.resolve` | ||
| * re-configures it from the resolved config, so `silent`/`verbose` settings | ||
| * are honored even on paths where the command logger is not available. | ||
| */ | ||
| export const fallbackLogger: Logger = new ConsoleLogger(); |
| // Wire the resolved `verbose`/`silent` into the logger as soon as they are | ||
| // known, so config-file settings are honored by every message emitted from | ||
| // here on (including the warnings later in this resolution). CLI flags | ||
| // still win via `pick`. Only re-configure when the caller threaded a | ||
| // logger through — those call sites pass their CLI flags in the params, so | ||
| // precedence stays intact. The shared `fallbackLogger` is kept in sync for | ||
| // paths that have no logger threaded through. |
| targets: resolvedTargets ? [...resolvedTargets] : undefined, | ||
| features: cliFeatures, | ||
| verbose: (options as { verbose?: boolean }).verbose, | ||
| silent: (options as { silent?: boolean }).silent, | ||
| }); |
Address review findings: BaseLogger.configure no longer warns on verbose+silent — with the logger now re-configured from resolved config values, the warning fired up to four times, leaked raw console.warn into --json mode via the fallbackLogger, and mislabeled a config-file silent as a CLI flag conflict. The warning moved to warnOnConflictingFlags, called once in wrapCommand with JSON-mode suppression. Silent still always wins over verbose regardless of source. Also restore fallbackLogger state in tests and document the process-global caveat. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
src/config/config-resolver.ts:314
- When the supplied
loggeris aJsonLogger(logger.jsonMode === true), the sharedfallbackLoggerremains aConsoleLoggerand will emit plain-text warnings, which can corrupt JSON-mode output. Consider forcing the fallback into silent mode when the resolved logger is in JSON mode.
fallbackLogger.configure({ verbose: resolvedVerbose, silent: resolvedSilent });
src/cli/index.ts:85
resolveGitignoreTargets()callsConfigResolver.resolve({})without threading the commandloggeror CLIverbose/silent. That means warnings emitted during target resolution can bypass config-filesilent/verbosereconfiguration, undermining the goal of honoring config-file logging settings end-to-end.
await gitignoreCommand(logger, {
targets: resolvedTargets ? [...resolvedTargets] : undefined,
features: cliFeatures,
verbose: (options as { verbose?: boolean }).verbose,
silent: (options as { silent?: boolean }).silent,
| }; | ||
| warnOnConflictingFlags({ ...cliLoggerOptions, jsonMode: logger.jsonMode }); | ||
| logger.configure(cliLoggerOptions); | ||
| fallbackLogger.configure(cliLoggerOptions); |
|
Status: iteration-2 review round is clean (zero mid-or-above findings; the three iteration-1 mid findings around the conflicting-flags warning were fixed in 9fa06cb) and all 9 CI checks are green. Merge is blocked for this session's credentials (cm-dyoshikawa has write access only; the main ruleset requires approval from someone other than the last pusher, and self-approval is not possible). Ready for a one-click merge by the maintainer. |
|
@cm-dyoshikawa Thank you! |
Summary
Fixes the documented no-op reported in #2312:
silent: trueinrulesync.jsoncwas parsed and resolved correctly, but the logger was configured from CLI flags only (wrapCommand), andConfig.getSilent()had zero call sites — so only--silentworked.verbosehad the same wiring gap forlogger.debug.Changes
ConfigResolver.resolvenow re-configures the supplied logger from the resolvedverbose/silentas soon as the base and local config files are merged — before the resolver's own warnings fire — so config-file settings apply end to end. CLI flags still win through the existingpick(CLI > local > base > default) precedence. Re-configuration only happens when the caller threads a logger through, since those call sites also pass their CLI flags (keeping precedence intact).convert,install, andgitignorenow pass their logger (and, for gitignore, the CLIverbose/silentflags) intoConfigResolver.resolve;generateandimportalready did.fallbackLoggerinsrc/utils/logger.tsthatwrapCommandconfigures from CLI flags andConfigResolver.resolvekeeps in sync with the resolved config.warnWithFallback(undefined, ...)now routes through it instead of rawconsole.warn, and the unconfigured module-levelConsoleLoggerfallbacks in the qwencode/augmentcode permission translators now alias it — so those warn paths honorsilenttoo (issue items 1 and 2).verbose: truein the config file now enableslogger.debug(issue item 4).Tests
ConfigResolverre-configuration: config-file values applied, CLI flags winning, config-fileverboseenabling debug, and no fallback mutation when no logger is supplied.warnWithFallbackrouting and fallback silent suppression.resolvecalls or rawconsole.warnfallback.Closes #2312
🤖 Generated with Claude Code