ruff-sync 0.1.5.dev6__tar.gz → 0.1.6.dev2__tar.gz
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.
- ruff_sync-0.1.6.dev2/.agents/plans/issue-100-roadmap-plan.md +370 -0
- ruff_sync-0.1.6.dev2/.agents/plans/issue-116-config-validation.md +741 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mike/SKILL.md +32 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/SKILL.md +6 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/troubleshooting.md +20 -0
- ruff_sync-0.1.6.dev2/.agents/skills/warnings-control/SKILL.md +108 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/AGENTS.md +1 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/PKG-INFO +42 -13
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/README.md +41 -12
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/configuration.md +3 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/usage.md +35 -1
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/pyproject.toml +1 -1
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/scripts/generate_tui_screenshots.py +3 -4
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/__init__.py +2 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/cli.py +25 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/core.py +14 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/app.py +4 -2
- ruff_sync-0.1.6.dev2/src/ruff_sync/validation.py +223 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tasks.py +2 -2
- ruff_sync-0.1.6.dev2/tests/test_config_validation.py +657 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/uv.lock +4 -4
- ruff_sync-0.1.5.dev6/tests/test_config_validation.py +0 -125
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/DEPENDENCIES.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/TESTING.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/decisions/0001-type-refactoring-strategy.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/decisions/0002-tui-node-ast.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/decisions/README.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/doc-fix.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/formatters-architecture.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/gitlab-reports.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/issue-102-context.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/adr/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/references/common-matchers.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/references/toml-matching.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/trigger_eval.json +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/gh-issues/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mike/references/commands.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/examples.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/api-reference.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/getting-started.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/index.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/mkdocs.yml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/release-notes-generation/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/ci-integration.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/configuration.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/best-practices.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/evaluating-skills.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/optimizing-descriptions.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/quickstart.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/sources.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/using-scripts.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/scripts/scaffold_skill.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/examples/basic_app.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/examples/reactive_example.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/events.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/styling.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/testing.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/widgets.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/evals.json +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/advanced-narrowing.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/error-code-lookup.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/generics.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/naming.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/protocol-patterns.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/quickstart.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/refactoring-patterns.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/scripts/audit_types.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/tui_design.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/tui_requirements.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/tui_rule_browsing.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/tui_rule_browsing_design.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/workflows/add-test-case.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.agents/workflows/update-screenshots.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.git-blame-ignore-revs +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.github/dependabot.yml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.github/workflows/ci.yaml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.github/workflows/complexity.yaml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.gitignore +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.pre-commit-config.yaml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/.pre-commit-hooks.yaml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/CONTRIBUTING.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/LICENSE.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/codecov.yml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/configs/data-science-engineering/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/configs/fastapi/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/configs/kitchen-sink/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/agent-skill.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/favicon.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/github-job-summary.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/github-pr-annotation.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/inspect-main.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/inspect-search.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/logo.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/ruff_sync_banner.png +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/dashboard.svg +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/legend_help.svg +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/rule_details.svg +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/screenshot_sample.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/search_omnibox.svg +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/best-practices.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/ci-integration.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/contributing.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/examples/advanced-config.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/examples/basic-config.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/gen_ref_pages.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/index.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/inspect.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/installation.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/overrides/main.html +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/overrides/partials/version_warning.html +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/pre-commit.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/pre-defined-configs.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/troubleshooting.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/docs/url-resolution.md +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/mkdocs.yml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/scripts/check_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/scripts/gitclone_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/scripts/pull_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/skills-lock.json +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/__main__.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/config_io.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/constants.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/dependencies.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/formatters.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/pre_commit.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/system.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/__init__.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/constants.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/screens.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/themes.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/types_.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/widgets.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/src/ruff_sync/types_.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/__init__.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/conftest.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_up1.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_up2.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_final.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_initial.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_basic.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_check.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_ci_integration.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_ci_validation.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_config_io.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_constants.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_corner_cases.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_dependencies.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_deprecation.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_e2e.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_formatters.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_git_fetch.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_minimal_imports.sh +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_pre_commit.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_project.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_rule_logic.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_scaffold.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_serialization.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_system.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_toml_operations.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_url_handling.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/test_whitespace.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/tui/__init__.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/tui/conftest.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/tui/test_themes.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/tui/test_tui.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/tui/test_tui_types.py +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/w_ruff_sync_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/wo_ruff_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.5.dev6 → ruff_sync-0.1.6.dev2}/tests/wo_ruff_sync_cfg/pyproject.toml +0 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# Issue #100 — Feature Roadmap: Ecosystem-Inspired Improvements
|
|
2
|
+
|
|
3
|
+
> **Source issue**: [#100 Feature roadmap: ecosystem-inspired improvements for ruff-sync](https://github.com/Kilo59/ruff-sync/issues/100)
|
|
4
|
+
> **Status**: Planning / Pre-implementation
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Issue #100 surveyed how 8+ ecosystems (ESLint, Prettier, Stylelint, RuboCop, golangci-lint, Cargo/Rust, pre-commit, and Ruff's own `extend`) handle shared linter/formatter config. The result is a **10-item prioritized roadmap** grouped into three tiers:
|
|
11
|
+
|
|
12
|
+
| Tier | Theme | Items |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| 🟢 Tier 1 — High Impact, Natural Extensions | Core capabilities that directly complement the existing merge pipeline | #1 Config Layering, #2 Richer CI drift output, #3 Lock/pin versions |
|
|
15
|
+
| 🟡 Tier 2 — Valuable Additions | Ergonomic improvements and power-user features | #4 Dry-run mode, #5 Per-key merge strategies, #6 `status` command, #7 Monorepo support |
|
|
16
|
+
| 🔵 Tier 3 — Forward-Looking / Exploratory | Long-lived R&D; high value but high uncertainty | #8 Bidirectional sync/push, #9 Webhook/GitHub App, #10 Config validation |
|
|
17
|
+
|
|
18
|
+
**Supplemental item**: README ecosystem documentation (adding RuboCop, Stylelint, golangci-lint, Cargo `[workspace.lints]`, pre-commit to the survey table).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Current Architecture (Grounding)
|
|
23
|
+
|
|
24
|
+
Understanding the existing codebase is essential before proposing changes.
|
|
25
|
+
|
|
26
|
+
### Key modules
|
|
27
|
+
|
|
28
|
+
| File | Role |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `cli.py` | `ArgumentParser` wiring, `Arguments` (NamedTuple), resolution helpers (`_resolve_branch`, `_resolve_upstream`, …), `main()` |
|
|
31
|
+
| `core.py` | `fetch_upstream_config`, `merge_ruff_toml`, `_recursive_update`, `pull`, `check`, URL conversion |
|
|
32
|
+
| `constants.py` | `ConfKey` enum (TOML keys), `MissingType`/`MISSING` sentinel, `OutputFormat` enum, `resolve_defaults()` |
|
|
33
|
+
| `formatters.py` | `ResultFormatter` Protocol; `TextFormatter`, `GithubFormatter`, `JsonFormatter`, `GitlabFormatter`, `SarifFormatter` |
|
|
34
|
+
| `pre_commit.py` | Pre-commit hook version sync |
|
|
35
|
+
| `config_io.py` | `RuffConfigFileName`, `resolve_target_path`, `is_ruff_toml_file` |
|
|
36
|
+
|
|
37
|
+
### Configuration contract
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[tool.ruff-sync]
|
|
41
|
+
upstream = "https://github.com/org/repo" # or list[str]
|
|
42
|
+
branch = "main"
|
|
43
|
+
path = ""
|
|
44
|
+
exclude = ["lint.per-file-ignores"]
|
|
45
|
+
to = "."
|
|
46
|
+
output-format = "github"
|
|
47
|
+
pre-commit-version-sync = true
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Config is read by `get_config()` (cached), mapped via `ConfKey.get_canonical()`, and resolved in `_resolve_args()`. The `MISSING` sentinel from `constants.py` is the standard way to distinguish "not provided" from explicit defaults.
|
|
51
|
+
|
|
52
|
+
### CLI exit codes (current)
|
|
53
|
+
|
|
54
|
+
| Code | Meaning |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `0` | Success |
|
|
57
|
+
| `1` | Dependency / config error |
|
|
58
|
+
| `4` | One or more upstream fetch failures |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Tier 1 — High Impact, Natural Extensions
|
|
63
|
+
|
|
64
|
+
### 1 — Config Inheritance / Layering (ESLint flat config model)
|
|
65
|
+
|
|
66
|
+
**Goal**: Allow an ordered list of upstream sources where later entries override earlier ones.
|
|
67
|
+
|
|
68
|
+
**Current state**: Already partially implemented — `upstream` already accepts `list[str]` and `fetch_upstreams_concurrently` fetches them concurrently, then `_merge_multiple_upstreams` merges sequentially. The fundamental machinery exists.
|
|
69
|
+
|
|
70
|
+
**Remaining gap**: The original issue's example shows *named* layers with comments, but the existing `upstream = [...]` syntax covers this already. The real user-visible gap is **documentation and discoverability** — users don't know this is possible.
|
|
71
|
+
|
|
72
|
+
**Implementation notes**:
|
|
73
|
+
- No new CLI flags needed. `upstream` already accepts multiple values both via CLI (`ruff-sync pull URL1 URL2`) and config (`upstream = ["URL1", "URL2"]`).
|
|
74
|
+
- Verify and add a focused test in `test_e2e.py` that a 3-layer merge resolves precedence correctly (last URL wins on a conflict).
|
|
75
|
+
- Update the README and the `ruff-sync-usage` skill with a "layered upstreams" example.
|
|
76
|
+
|
|
77
|
+
**Scope**: Small — mostly docs + a test.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### 2 — Richer CI Drift Output (exit codes + structured formats)
|
|
82
|
+
|
|
83
|
+
**Goal**: Differentiate exit codes so CI pipelines can distinguish classes of failures. Extend `--output-format` to cover SARIF for code-scanning UIs.
|
|
84
|
+
|
|
85
|
+
**Current state**:
|
|
86
|
+
- `OutputFormat` enum already has `TEXT`, `JSON`, `GITHUB`, `GITLAB`, `SARIF`. Classes `GithubFormatter`, `SarifFormatter`, `GitlabFormatter` all exist in `formatters.py`.
|
|
87
|
+
- Exit codes 0, 1, 4 are defined but there is **no dedicated code for "out of sync"** — `check` currently returns `1` for drift.
|
|
88
|
+
|
|
89
|
+
**Proposed exit code table**:
|
|
90
|
+
|
|
91
|
+
| Code | Meaning |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `0` | In sync |
|
|
94
|
+
| `1` | Configuration / dependency error |
|
|
95
|
+
| `2` | Out of sync (drift detected) |
|
|
96
|
+
| `3` | Warning only (e.g. non-fatal upstream issue) |
|
|
97
|
+
| `4` | Upstream unreachable / fetch failure |
|
|
98
|
+
|
|
99
|
+
**Implementation notes**:
|
|
100
|
+
- Add `ExitCode` `IntEnum` to `constants.py` (e.g. `OK=0`, `CONFIG_ERROR=1`, `OUT_OF_SYNC=2`, `UPSTREAM_ERROR=4`).
|
|
101
|
+
- Update `core.check()` to return `ExitCode.OUT_OF_SYNC` (2) instead of `1` when drift is found.
|
|
102
|
+
- Update `main()` return values to use `ExitCode`.
|
|
103
|
+
- Update CI docs, `ruff-sync-usage` skill, and the `--output-format` help string.
|
|
104
|
+
- Tests: `test_check.py` will need updated expected exit code assertions.
|
|
105
|
+
|
|
106
|
+
> [!IMPORTANT]
|
|
107
|
+
> This is technically a **breaking change** for any CI script that checks `[ $? -eq 1 ]` for drift. Document the migration clearly in the changelog and consider a deprecation period where both `1` and `2` are valid for a release.
|
|
108
|
+
|
|
109
|
+
**Scope**: Medium — touches `constants.py`, `core.py`, `cli.py`, several tests.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### 3 — Lock / Pin Upstream Versions
|
|
114
|
+
|
|
115
|
+
**Goal**: Record the exact commit SHA fetched from an upstream so subsequent `check` runs can verify against the same snapshot.
|
|
116
|
+
|
|
117
|
+
**Inspiration**: `npm package-lock.json`, `go.sum`, pre-commit's `rev:` pinning.
|
|
118
|
+
|
|
119
|
+
**Proposed design**:
|
|
120
|
+
|
|
121
|
+
```toml
|
|
122
|
+
# Written by `ruff-sync pull --lock` or automatically with `save = true`
|
|
123
|
+
[tool.ruff-sync.lock]
|
|
124
|
+
"https://github.com/my-org/standards" = "abc1234def5678" # SHA resolved at pull time
|
|
125
|
+
pulled-at = "2026-03-10T14:30:00Z"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Or a standalone `ruff-sync.lock` file (simpler to gitignore independently).
|
|
129
|
+
|
|
130
|
+
**Implementation notes**:
|
|
131
|
+
- `fetch_upstream_config` returns a `FetchResult(buffer, resolved_upstream)`. Extend it with an optional `sha: str | None` field (add `sha` to the `NamedTuple`).
|
|
132
|
+
- For HTTP sources: resolve SHA via GitHub API (`/repos/{owner}/{repo}/commits?path=pyproject.toml&per_page=1`) if `GITHUB_TOKEN` is set; otherwise store the ETag.
|
|
133
|
+
- For git sources (`_fetch_via_git`): after `git clone --depth 1`, run `git rev-parse HEAD` to capture the exact SHA.
|
|
134
|
+
- Add `ruff-sync update` sub-command that bumps the lock to latest.
|
|
135
|
+
- `check` without a lock behaves as today; `check --locked` validates against the locked SHA.
|
|
136
|
+
|
|
137
|
+
> [!WARNING]
|
|
138
|
+
> HTTP ETag-based pinning is less reliable than SHA pinning. Make the limitation clear in docs. Recommend using git:// URLs for true reproducibility.
|
|
139
|
+
|
|
140
|
+
**Scope**: Large — new `FetchResult` field, new lock file I/O, new `update` subcommand, CI integration docs.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Tier 2 — Valuable Additions
|
|
145
|
+
|
|
146
|
+
### 4 — Dry-run / Preview Mode
|
|
147
|
+
|
|
148
|
+
**Goal**: `pull --dry-run` prints the fully merged TOML to stdout without writing it to disk.
|
|
149
|
+
|
|
150
|
+
**Current state**: `check --diff` shows a unified diff but doesn't print the full merged file. There is no `pull --dry-run`.
|
|
151
|
+
|
|
152
|
+
**Implementation notes**:
|
|
153
|
+
- Add `--dry-run` flag to the `pull` subparser in `cli.py`.
|
|
154
|
+
- In `core.pull()`, after computing `merged_doc`, if `args.dry_run` is `True`, write to stdout (`sys.stdout`) instead of the target file.
|
|
155
|
+
- The `Arguments` NamedTuple needs a `dry_run: bool = False` field.
|
|
156
|
+
- Add `ConfKey.DRY_RUN = "dry-run"` to `ConfKey` if it should be saveable to config (probably not — leave it CLI-only).
|
|
157
|
+
|
|
158
|
+
**Inspiration**: `terraform plan`, `npm pack --dry-run`.
|
|
159
|
+
|
|
160
|
+
**Scope**: Small-to-medium.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### 5 — Per-Key Merge Strategies
|
|
165
|
+
|
|
166
|
+
**Goal**: Support different merge behaviors per TOML key instead of the current "always overwrite" default.
|
|
167
|
+
|
|
168
|
+
**Proposed strategies**:
|
|
169
|
+
|
|
170
|
+
| Strategy | Behaviour |
|
|
171
|
+
|---|---|
|
|
172
|
+
| `replace` (default) | Upstream value completely replaces local value |
|
|
173
|
+
| `append` | For list values: append upstream items to local list (e.g. `lint.extend-select`) |
|
|
174
|
+
| `local-only` | Never touch this key (effectively an exclude per-key) |
|
|
175
|
+
| `local-first` | Use local value if present, otherwise use upstream |
|
|
176
|
+
|
|
177
|
+
**Config syntax proposal**:
|
|
178
|
+
|
|
179
|
+
```toml
|
|
180
|
+
[tool.ruff-sync.merge-strategy]
|
|
181
|
+
"lint.extend-select" = "append"
|
|
182
|
+
"target-version" = "local-only"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Implementation notes**:
|
|
186
|
+
- Add `merge_strategy: dict[str, str]` to `Config` TypedDict.
|
|
187
|
+
- Add `ConfKey.MERGE_STRATEGY = "merge-strategy"` to `ConfKey`.
|
|
188
|
+
- Create `MergeStrategy` enum in `constants.py`: `REPLACE`, `APPEND`, `LOCAL_ONLY`, `LOCAL_FIRST`.
|
|
189
|
+
- Modify `_recursive_update` (in `core.py`) to accept an optional `merge_strategies: Mapping[str, MergeStrategy]` parameter. The dotted key path (e.g. `lint.extend-select`) is used to look up the strategy.
|
|
190
|
+
- The `exclude` mechanism could be unified with `local-only` as a migration convenience.
|
|
191
|
+
|
|
192
|
+
**Scope**: Medium-to-large — changes the core merge algorithm, new `ConfKey`, new tests in `test_corner_cases.py`.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### 6 — `status` Command — Richer Sync Reporting
|
|
197
|
+
|
|
198
|
+
**Goal**: A human-readable summary of the current sync state, including upstream SHA, last-pulled time, and per-tool drift summary.
|
|
199
|
+
|
|
200
|
+
**Proposed output**:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
ruff-sync v0.2.0
|
|
204
|
+
upstream: https://github.com/my-org/standards (main @ abc1234)
|
|
205
|
+
target: pyproject.toml
|
|
206
|
+
ruff ✅ in sync (last pulled: 2026-03-10)
|
|
207
|
+
mypy ❌ out of sync (3 keys differ)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Implementation notes**:
|
|
211
|
+
- `status` is a new subcommand in `cli.py` (beside `pull`, `check`, `inspect`).
|
|
212
|
+
- Requires the lock file (Feature #3) to report the "last pulled" timestamp and pinned SHA.
|
|
213
|
+
- For the drift summary: run the same diff logic as `check` but in summary-only mode (count of differing keys, not full diff text).
|
|
214
|
+
- If no lock exists, report "unknown" for last-pulled but still show drift status.
|
|
215
|
+
|
|
216
|
+
**Scope**: Medium — depends on #3 for full value, but the drift-count part can be built independently.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### 7 — Monorepo Support
|
|
221
|
+
|
|
222
|
+
**Goal**: Allow a single `pyproject.toml` at the repo root to configure independent sync targets for multiple sub-packages.
|
|
223
|
+
|
|
224
|
+
**Proposed config**:
|
|
225
|
+
|
|
226
|
+
```toml
|
|
227
|
+
[[tool.ruff-sync.targets]]
|
|
228
|
+
to = "packages/api"
|
|
229
|
+
exclude = ["lint.per-file-ignores"]
|
|
230
|
+
|
|
231
|
+
[[tool.ruff-sync.targets]]
|
|
232
|
+
to = "packages/worker"
|
|
233
|
+
exclude = ["target-version"]
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Implementation notes**:
|
|
237
|
+
- Add support for `[[tool.ruff-sync.targets]]` TOML array of tables.
|
|
238
|
+
- Each target entry inherits top-level `upstream`, `branch`, etc. unless overridden.
|
|
239
|
+
- `cli.py`'s `get_config()` and `_resolve_args()` would need to expand into a list of `Arguments` objects when targets are present.
|
|
240
|
+
- `pull` and `check` would iterate over all targets.
|
|
241
|
+
- This is a significant schema change — design carefully for backward compatibility.
|
|
242
|
+
|
|
243
|
+
> [!IMPORTANT]
|
|
244
|
+
> This is the largest Tier 2 item. Consider making it an ADR before implementation.
|
|
245
|
+
|
|
246
|
+
**Scope**: Large.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Tier 3 — Forward-Looking / Exploratory
|
|
251
|
+
|
|
252
|
+
These are exploratory. Opening tracking issues is appropriate, but full implementation plans should come later.
|
|
253
|
+
|
|
254
|
+
### 8 — Bidirectional Sync / Push Command
|
|
255
|
+
|
|
256
|
+
Push local changes upstream as a GitHub/GitLab PR. Very high value for teams making downstream discoveries.
|
|
257
|
+
|
|
258
|
+
**Implementation notes sketch**:
|
|
259
|
+
- Requires authenticated GitHub API access (`GITHUB_TOKEN`).
|
|
260
|
+
- Would create a branch on the upstream repo with the locally changed `[tool.ruff]` section, then open a PR.
|
|
261
|
+
- Scope: Very Large. Dependencies: git auth, PR API, fork/branch strategy.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### 9 — Webhook / GitHub App for Automatic PRs
|
|
266
|
+
|
|
267
|
+
A hosted service (like Renovate or Dependabot) that watches upstream config repos and opens PRs downstream when upstream changes.
|
|
268
|
+
|
|
269
|
+
**Notes**: This is out of scope for the `ruff-sync` CLI itself — it's a service/infrastructure concern. Could be built as a separate GitHub App or Action. The CLI's `check` exit codes (#2 above) are a prerequisite.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### 10 — Config Validation
|
|
274
|
+
|
|
275
|
+
Before applying a merge, validate the merged result:
|
|
276
|
+
- Warn if upstream references deprecated Ruff rules (query `ruff rule --all` or maintain a list).
|
|
277
|
+
- Warn if `target-version` conflicts with local `requires-python`.
|
|
278
|
+
- Optionally run `ruff check --no-fix` against the merged config to catch syntax errors.
|
|
279
|
+
|
|
280
|
+
**Implementation notes sketch**:
|
|
281
|
+
- Add a `validate` step inside `pull()` (between merge and write).
|
|
282
|
+
- Integrate with `ruff` subprocess (similar to how `pre_commit.py` calls subprocess tools).
|
|
283
|
+
- This overlaps with the `ruff-inspect` TUI — the TUI already shows per-rule status.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Supplemental — README Ecosystem Documentation
|
|
288
|
+
|
|
289
|
+
Update the "How Other Ecosystems Solve This" README section to include:
|
|
290
|
+
|
|
291
|
+
| Tool | Mechanism | Notable feature |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| RuboCop (Ruby) | `inherit_from: <URL>` | Native remote URL — closest peer to ruff-sync |
|
|
294
|
+
| Stylelint (CSS) | `extends` via npm packages | Package-based distribution |
|
|
295
|
+
| golangci-lint (Go) | No native remote config | Teams use CI workarounds |
|
|
296
|
+
| Cargo/Rust | `[workspace.lints]` | Monorepo only, no remote |
|
|
297
|
+
| pre-commit | No `include`/`extends` | Repos must duplicate config |
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Recommended Sequencing
|
|
302
|
+
|
|
303
|
+
The items above are not all equal in effort or dependency. Here is a recommended order:
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
Phase 0 (docs/quick wins):
|
|
307
|
+
- #1 Layered Upstreams — docs + test only
|
|
308
|
+
- README ecosystem table
|
|
309
|
+
|
|
310
|
+
Phase 1 (CI hardening):
|
|
311
|
+
- #2 Exit code differentiation + ExitCode enum
|
|
312
|
+
|
|
313
|
+
Phase 2 (ergonomics):
|
|
314
|
+
- #4 Dry-run mode (small, high user value)
|
|
315
|
+
- #6 Status command (lite version without lock)
|
|
316
|
+
|
|
317
|
+
Phase 3 (advanced features):
|
|
318
|
+
- #3 Lock file + `update` subcommand
|
|
319
|
+
- #6 Status command (full version with lock)
|
|
320
|
+
- #5 Per-key merge strategies
|
|
321
|
+
|
|
322
|
+
Phase 4 (monorepo):
|
|
323
|
+
- #7 Monorepo targets — design ADR first
|
|
324
|
+
|
|
325
|
+
Phase 5 (exploratory / long-term):
|
|
326
|
+
- #10 Config validation
|
|
327
|
+
- #8 Bidirectional push
|
|
328
|
+
- #9 Webhook/GitHub App (external service)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Open Questions / Design Decisions
|
|
334
|
+
|
|
335
|
+
> [!IMPORTANT]
|
|
336
|
+
> These need answers before starting Phase 2–3 work.
|
|
337
|
+
|
|
338
|
+
1. **Lock file location**: `[tool.ruff-sync.lock]` (inside `pyproject.toml`) vs. a separate `ruff-sync.lock` file? A standalone file is easier to gitignore and diff-track, but adds a new file to every user's repo.
|
|
339
|
+
|
|
340
|
+
2. **Exit code migration**: Should drift remain `1` for one more release cycle (with a deprecation warning) before moving to `2`? This minimizes breakage for existing CI pipelines.
|
|
341
|
+
|
|
342
|
+
3. **`merge-strategy` syntax**: The dotted-key syntax (e.g. `"lint.extend-select" = "append"`) is readable but unusual for TOML. Alternative: an explicit array-of-tables with `key`, `strategy` fields. Which is more ergonomic?
|
|
343
|
+
|
|
344
|
+
4. **`status` without a lock**: Should `status` fail loudly if no lock exists, or silently omit the "last pulled" field?
|
|
345
|
+
|
|
346
|
+
5. **Monorepo schema backward compat**: The `[[tool.ruff-sync.targets]]` array-of-tables would coexist with top-level `upstream`, `to`, etc. What is the exact precedence rule? Should scalar `to` continue to work if `targets` is present?
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Testing Strategy (per feature)
|
|
351
|
+
|
|
352
|
+
| Feature | Primary test file(s) | Notes |
|
|
353
|
+
|---|---|---|
|
|
354
|
+
| #1 Layered upstreams | `test_e2e.py`, `test_corner_cases.py` | New lifecycle triple: base + domain → final |
|
|
355
|
+
| #2 Exit codes | `test_check.py`, `test_ci_integration.py` | Update expected return codes |
|
|
356
|
+
| #3 Lock file | New `test_lock.py` | `pyfakefs` for file I/O; `respx` for ETag mocking |
|
|
357
|
+
| #4 Dry-run | `test_basic.py`, `test_e2e.py` | Assert stdout contains merged TOML, file unchanged |
|
|
358
|
+
| #5 Merge strategies | `test_corner_cases.py` | `append`, `local-only`, `local-first` strategies |
|
|
359
|
+
| #6 Status | New `test_status.py` | Mocked upstream + lock file |
|
|
360
|
+
| #7 Monorepo | New `test_monorepo.py` | Multiple `pyfakefs` directories |
|
|
361
|
+
| #10 Config validation | New `test_validation.py` | Deprecated rule detection |
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Related Issues
|
|
366
|
+
|
|
367
|
+
- [#69](https://github.com/Kilo59/ruff-sync/issues/69) — Multi-tool config sync (overlaps with Tier 1 scope expansion)
|
|
368
|
+
- [#74](https://github.com/Kilo59/ruff-sync/issues/74) — Short CLI aliases (more useful if multi-tool lands)
|
|
369
|
+
- [#83](https://github.com/Kilo59/ruff-sync/issues/83) — Example Ruff configs for various domains (Tier 2)
|
|
370
|
+
- [#87](https://github.com/Kilo59/ruff-sync/issues/87) — Example config: Data Science / Data Engineering (Tier 2)
|