Skip to content

chore: address remaining code smell findings from review #15

@Jamie-BitFlight

Description

@Jamie-BitFlight

Overview

These findings were identified during a code smell review on 2026-03-13. Actionable, self-contained fixes (dead imports, FURB101 read_bytes patterns, the isinstance dict guard) have already been applied. The items below are deferred structural work, mypy type-narrowing, and LOW-priority observations.


Deferred Findings

auto_sync_manifests.py

Severity Location Finding
MEDIUM module level (lines 39–42) sys.stdout.reconfigure() runs at import time. Guard behind if __name__ == "__main__" or move to CLI entry-point function to avoid side effects when imported as a library.
LOW whole file File is 1300+ lines combining CLI parsing, git diff analysis, manifest CRUD, version bumping, and reconciliation. Consider decomposing into submodules: _version_bump.py, _reconcile.py, _git_helpers.py.

plugin_validator.py

Severity Location Finding
HIGH line 1981 data["hooks"] typed as YamlValue — mypy does not narrow through .get() guard on line 1979. Fix: assign hooks = data["hooks"] after the isinstance guard, or use an explicit cast.
HIGH line 3024 item.lstrip("./") where item is YamlValue (iterated from list[YamlValue]). Non-string items would raise AttributeError at runtime. Add if isinstance(item, str) guard.
HIGH line 4063 group.get("hooks", []) returns YamlValue which includes int | float | None — not always iterable. Add isinstance check before iterating.
MEDIUM line 2957 metadata["author"] = author assigns dict[str, str] to a slot typed as YamlValue. Technically compatible but mypy flags due to recursive type alias limitations. Consider narrowing metadata dict annotation.
MEDIUM module level (lines 28–31) sys.stdout.reconfigure() at import time — same concern as auto_sync_manifests.py.
MEDIUM line 85 _ADAPTERS dict built at module level via load_adapters() — triggers filesystem operations on import.
LOW whole file File is 4000+ lines. Consider extracting: HookValidator into its own module, CLI entry point (app, typer commands) into cli.py, auto-fix logic into _autofix.py, reporting/formatting into _reporting.py.
LOW multiple except blocks Where exceptions are re-raised, consider using e.add_note() (PEP 678) to attach context rather than wrapping in new exceptions.

adapters/claude_code/adapter.py

Severity Location Finding
MEDIUM line 66 self.get_schema("plugin") — verify that the schema contains a "plugin" entry in file_types, otherwise validate() always returns [] for JSON files.
LOW ClaudeCodeAdapter implements PlatformAdapter protocol but does not declare compliance. Consider explicit inheritance or a module-level type assertion: _: PlatformAdapter = ClaudeCodeAdapter()
LOW Add runtime protocol compliance assertion at module bottom to catch interface drift early.

_schema_loader.py

Severity Location Finding
LOW Return type is dict — could be dict[str, Any] for precision. No FileNotFoundError handling; consider a friendlier error message when a bundled schema file is missing.

tests/test_frontmatter_utils.py

Severity Location Finding
LOW lines 21, 30, 39, 49, 75 Imports of loads_frontmatter, dump_frontmatter, etc. inside every test method. Move to module level to reduce noise.

Acceptance Criteria

  • sys.stdout.reconfigure() guarded or moved to CLI entry point in both auto_sync_manifests.py and plugin_validator.py
  • Three HIGH mypy type-narrowing issues in plugin_validator.py resolved with explicit isinstance guards
  • _ADAPTERS initialization deferred away from module-level side effect
  • (Optional / separate PR) Module decomposition for files exceeding 1000 lines

https://claude.ai/code/session_01BevYUBWJm64cnqQ1E7U9uj

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions