Skip to content

feat: add rulesync doctor command for config diagnostics - #2491

Merged
dyoshikawa merged 3 commits into
mainfrom
feature/doctor-command-2446
Jul 30, 2026
Merged

feat: add rulesync doctor command for config diagnostics#2491
dyoshikawa merged 3 commits into
mainfrom
feature/doctor-command-2446

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

First slice of #2446: adds a read-only rulesync doctor command that diagnoses the configuration files (rulesync.jsonc / rulesync.local.jsonc) and reports problems grouped by severity (error / warning / info).

Closes #2446 (config-file check group; input-tree and workspace check groups are follow-ups as noted in the issue).

Why

Today the only feedback channel for a broken setup is rulesync generate. Because ConfigFileSchema is non-strict, a misspelled key such as "target" instead of "targets" is silently swallowed and generation quietly falls back to defaults. doctor gives a single, fast, read-only answer to "is my configuration correct?" — usable both as a first troubleshooting step and as a CI guard.

What it checks

  • JSONC parse errors, with line/column
  • Unknown or misspelled top-level keys, with "did you mean" suggestions derived from ConfigFileSchema (no hard-coded key list)
  • Unknown tool targets / features (array and object forms), with nearest-name suggestions
  • Deprecated ignore feature (warning)
  • Object-form targets combined with features, including the case where the conflict only appears after merging base and local config files
  • Conflicting target pairs (reuses the exported CONFLICTING_TARGET_PAIRS)
  • $schema presence (info) and currency (warning)
  • Structural violations on other keys via ConfigFileSchema.safeParse
  • sources[].tokenEnv naming an unset environment variable (warning)
  • inputRoot pointing at a nonexistent directory (error)

UX

  • Exit code 1 when any error is present; --strict makes warnings fatal for CI
  • Honors the global -j, --json flag (diagnostics + severity summary as structured data)
  • -c, --config, -V, --verbose, -s, --silent wired like other commands
  • Never writes files

Example

$ rulesync doctor
✖ rulesync.jsonc [config/unknown-key] Unknown key 'target'. It is silently ignored by 'rulesync generate'.
    ↳ Did you mean 'targets'?
✖ rulesync.jsonc [config/unknown-target] Unknown tool target 'cursorr' in the 'targets' object.
    ↳ Did you mean 'cursor'?
⚠ rulesync.jsonc [config/deprecated-feature] Feature 'ignore' in 'features' is deprecated.
    ↳ Use the 'permissions' feature instead.
Doctor found problems: 2 error(s), 1 warning(s), 0 info(s).

Tests

  • Unit tests per check (40+ cases) plus command-level tests: clean-workspace happy path (exit 0, no diagnostics), broken fixtures per diagnostic code, --strict, --config, JSON capture, base+local merge conflict
  • pnpm cicheck passes

🤖 Generated with Claude Code

cm-dyoshikawa and others added 3 commits July 29, 2026 23:49
Adds a read-only 'rulesync doctor' command that diagnoses the configuration files (rulesync.jsonc / rulesync.local.jsonc) and reports problems grouped by severity. This is the first slice of #2446, covering the config-file checks:

- JSONC parse errors with line/column
- Unknown or misspelled top-level keys with did-you-mean suggestions (the config schema is non-strict, so these are otherwise silently ignored)
- Unknown tool targets and features with nearest-name suggestions
- Deprecated 'ignore' feature warning
- Object-form targets combined with features, including conflicts that only appear after merging base and local config files
- Conflicting target pairs
- $schema presence and currency
- Structural schema violations via ConfigFileSchema
- sources[].tokenEnv pointing at an unset environment variable
- inputRoot pointing at a nonexistent directory

Exit code is 1 when errors are present (or warnings with --strict); the global --json flag emits structured diagnostics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Scope test-fixture typo words to doctor.test.ts via cspell:ignore instead of the global cspell dictionary
- Add CLI-level e2e spec (e2e-doctor.spec.ts): clean-config exit 0, missing config, misspelled-key exit 1, --strict, --json success and failure documents
- Reuse GITIGNORE_DESTINATION_KEY exported from config.ts instead of hard-coding the per-feature extra key
- Derive deprecated-feature diagnostics from a new DEPRECATED_FEATURE_REPLACEMENTS map in features.ts
- Simplify collectMergedConfigDiagnostics: drop the unreachable assertTargetsFeaturesExclusive round-trip
- Read each config file once and share the content between per-file and merge checks
- Strip control characters from config-derived strings before terminal output
- Skip per-diagnostic logging in JSON mode so the error document keeps its DOCTOR_FAILED code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In JSON mode a failing doctor run previously kept only the summary string in error.message, dropping the structured diagnostics that CI and editors need most when something is wrong. CLIError now carries an optional structured details payload that JsonLogger.error propagates into error.details, and doctorCommand attaches the diagnostics and severity summary to the DOCTOR_FAILED error. The e2e failure-path test now pins the propagation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dyoshikawa
dyoshikawa merged commit a149067 into main Jul 30, 2026
9 checks passed
@dyoshikawa

Copy link
Copy Markdown
Owner Author

@dyoshikawa Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a rulesync doctor command that diagnoses config and input-file correctness

2 participants