Implementation Plan: CLI Bug Sweep & Tool Surface Self-Registration
Branch: fix/cli-bug-sweep-tool-surface-self-registration | Date: 2026-06-15 | Spec: spec.md Input: Feature specification from kitty-specs/cli-bug-sweep-tool-surface-self-registration-01KV5AWE/spec.md
Summary
Six targeted fixes across four subsystems. The largest is a structural refactor of tool_surface/service.py into a self-registration model (IC-04). Three others are small: remove a stale test marker (IC-01), add a missing test case for branch naming (IC-02), and repair three interlocking charter validation defects (IC-03). IC-05 is two task-workflow DX fixes: correct map-requirements path resolution and improve finalize-tasks --validate-only error messaging. All five ICs can be implemented in parallel lanes; there are no cross-IC dependencies.
Technical Context
Language/Version: Python 3.11+ Primary Dependencies: typer, rich, ruamel.yaml, pytest, mypy (strict) Storage: N/A — no persistence layer changes Testing: pytest with --dist loadfile for parallel runs; mypy --strict zero errors; ruff zero issues; 90%+ branch coverage on new code; Directive-030 conformance test for IC-04 Target Platform: Linux, macOS, Windows 10+ (CLI tool) Project Type: Single Python CLI package (src/specify_cli/ + src/charter/) Performance Goals: N/A — no performance-sensitive paths affected Constraints: No pkgutil/filesystem scan in provider discovery (C-001); no new user-facing CLI surfaces (C-004); provider ordering deterministic via explicit integer field (FR-010); gitignore whitelist must not be changed (C-003) Scale/Scope: ~16 files modified or created; largest change is IC-04 at ~10 files
Charter Check
| Gate | Status | Notes |
|---|---|---|
| DIRECTIVE_003 — Decision documentation | Pass | SurfaceRegistration shape documented in research.md and data-model.md |
| DIRECTIVE_005 — Tests for new functionality | Pass | Each IC includes test coverage; IC-04 adds Directive-030 conformance test |
| DIRECTIVE_006 — mypy --strict | Pass | Enforced as part of NFR-001 |
| DIRECTIVE_010 — Spec fidelity | Pass | All FR/NFR/C mapped to specific ICs; no undocumented deviations |
| DIRECTIVE_010/011 — Identifier sanitization | N/A | No sanitizer changes in scope |
| DIRECTIVE_030 — No central provider literals | Pass | IC-04 conformance test asserts coordinator file has no central provider list |
| Complexity ceiling (15) | Pass | IC-04 introduces helper functions scoped to stay ≤15 |
No charter violations requiring justification.
Project Structure
Documentation (this mission)
kitty-specs/cli-bug-sweep-tool-surface-self-registration-01KV5AWE/
├── plan.md # This file
├── research.md # Debugger Debbie findings summary
├── data-model.md # SurfaceRegistration entity design
├── quickstart.md # Validation guide
└── tasks.md # Generated by /spec-kitty.tasks
Source Code (affected paths)
src/specify_cli/
├── lanes/
│ └── branch_naming.py # IC-02: docstring update only
├── tool_surface/
│ ├── service.py # IC-04: refactored to consume registry
│ └── providers/
│ ├── _registry.py # IC-04: NEW — SurfaceRegistration + registry
│ ├── _discovery.py # IC-04: NEW — explicit import tuple
│ ├── agent_profiles.py # IC-04: add registration call
│ ├── command_skills.py # IC-04: add registration call
│ ├── managed_skills.py # IC-04: add registration call
│ ├── native_config.py # IC-04: add registration call
│ ├── plugin_bundle.py # IC-04: add registration call
│ ├── session_presence.py # IC-04: add registration call
│ └── slash_commands.py # IC-04: add registration call
src/charter/
├── bundle.py # IC-03: built_in_only early-exit
└── synthesizer/
└── artifact_naming.py # IC-03: singular subdir names
tests/
├── adversarial/
│ └── test_distribution.py # IC-01: remove xfail decorator
├── core/
│ └── test_branch_naming_human_slug.py # IC-02: pathological case test
└── specify_cli/
├── charter/
│ └── test_bundle_validate.py # IC-03: built_in_only scenario test
└── tool_surface/
└── test_provider_registration.py # IC-04: NEW — conformance test
.kittify/charter/provenance/ # IC-03: git rm 7 stale sidecar files
src/specify_cli/
├── cli/commands/agent/tasks.py # IC-05a: map-requirements spec.md path resolution
└── ownership/
└── validation.py # IC-05b: create_intent hint for zero-match literal paths
Implementation Concern Map
> Implementation concerns are NOT work packages. /spec-kitty.tasks translates > these into executable WPs. Concerns may be parallelized — there are no > cross-IC dependencies in this mission.
IC-01 — Stale xfail removal
- Purpose: Remove the
@pytest.mark.xfail(strict=False)decorator onTestUpgradeWithAllMissions::test_upgrade_updates_templatesintests/adversarial/test_distribution.pyso the test provides real regression protection for init-with---ai. - Relevant requirements: FR-001
- Affected surfaces:
tests/adversarial/test_distribution.pylines 193–206 (decorator + comment block) - Sequencing/depends-on: none
- Risks: If
ensure_runtime()is flaky in CI after the marker is removed, that failure will be visible immediately. It is a pre-existing latent issue, not introduced here; file a new issue if it manifests rather than re-adding the xfail.
IC-02 — Branch naming pathological test and docstring
- Purpose: Add a test covering the pathological slug-contains-wrong-mid8 case to
tests/core/test_branch_naming_human_slug.py, and add an invariant docstring to_human_slug_for_mid8_branch()insrc/specify_cli/lanes/branch_naming.py. - Relevant requirements: FR-002
- Affected surfaces:
tests/core/test_branch_naming_human_slug.py(new parameterized case);src/specify_cli/lanes/branch_naming.py:134(docstring) - Sequencing/depends-on: none
- Risks: The test must assert the current behavior (double-append in the pathological case) as documented behavior — not as a bug to fix — so any future change is caught explicitly.
IC-03 — Charter bundle validation repair (three-part)
- Purpose: Restore
spec-kitty charter bundle validateto exit 0 on a fresh checkout by (A) removing 7 stale provenance sidecar files, (B) correctingdoctrine_kind_subdir()to use singular directory names matching the gitignore whitelist, and (C) adding abuilt_in_onlyearly-exit tovalidate_synthesis_state(). - Relevant requirements: FR-003, FR-004, FR-005
- Affected surfaces:
- Part A:
git rmon.kittify/charter/provenance/(7 files listed in spec) - Part B:
src/charter/synthesizer/artifact_naming.py→doctrine_kind_subdir()and all callers inwrite_pipeline.py - Part C:
src/charter/bundle.py→validate_synthesis_state(); add test intests/specify_cli/charter/ - Sequencing/depends-on: none; B and C can be done in any order after A
- Risks: Part B must audit all callers of
doctrine_kind_subdir()and any hardcoded plural-dir paths inwrite_pipeline.py(lines ~174, ~206, ~584 per Debugger Debbie). Missing a caller leaves a dangling plural path. Part C must not suppress validation for repos that have real synthesis state — the early-exit is gated onbuilt_in_only: true AND artifacts == [].
IC-04 — Tool surface self-registration seam
- Purpose: Eliminate the four-region centralized provider enrollment in
service.pyby introducing aSurfaceRegistrationdataclass and aSurfaceProviderRegistryclass store. Each provider module declares its own registration;service.pyderives all configuration from the registry. - Relevant requirements: FR-006, FR-007, FR-008, FR-009, FR-010
- Affected surfaces: See project structure — 2 new files, 7 provider modules modified,
service.pyrefactored, 1 new conformance test - Sequencing/depends-on: none; operates in an independent subsystem
- Risks:
session_presencecontributes 3 definitions (not 1):SurfaceRegistration.definitionsmust be a tuple, not a single field.plugin_bundleregisters under a synthetic key, not the per-tool-key fan-out:SurfaceRegistration.synthetic_key: str | Nonefield required.plugin_bundle.pyhas a lazy import ofbuild_plans_for_bundlesfromservice.pyto avoid a circular import. This workaround must be preserved unchanged after the refactor; do not attempt to resolve the cycle as part of this IC._discovery.pymust use an explicit tuple (not pkgutil) to satisfy the dead-symbol gate (C-001).SurfaceRegistration.ordermust be an explicit integer (not derived from import order) to satisfy FR-010.- The Directive-030 conformance test (
test_provider_registration.py) must assert two things: (1) every non-underscore module inproviders/has a corresponding registration, and (2)service.pycontains no central provider literal list patterns.
IC-05 — Task-workflow DX fixes (two-part)
- Purpose: Fix two workflow bugs discovered during this mission's own planning phase that block the documented
map-requirements→finalize-tasksflow and produce misleading error messages. - Relevant requirements: FR-011, FR-012
- Affected surfaces:
- Part A (
src/specify_cli/cli/commands/agent/tasks.py—map_requirementsfunction):map-requirementscallsresolve_feature_dir_for_mission(main_repo_root, mission_slug), which delegates tomission_runtime.resolve_action_context. The runtime's coord-worktree routing fires only whenmeta.jsoncarriescoordination_branch— absent for PR-bound missions. The runtime falls through to the primary checkout, wherekitty-specs/<mission>/may not exist if the mission's target branch is checked out in a coord worktree, causing the "spec.md not found" error. Fix (investigation-first — see WP05 T020 for the confirmed approach): Routemap_requirementsthroughresolve_feature_dir_for_slug(which calls_read_path_resolver.resolve_mission_read_pathdirectly and is already coord-topology-aware, bypassing thecoordination_branchgate). Confirm via source tracing before implementing — see WP05 T020 for detailed investigation guidance. - Part B (
src/specify_cli/ownership/validation.py—validate_glob_matches, around line 374): when a zero-match literalowned_filesentry has a nearest-match suggestion (_nearest_match_suggestionreturns non-None), the error message includes the "did you mean?" hint but omits thecreate_intentguidance. The two paths are mutually exclusive (if suggestion: msg += suggestion; else: msg += create_intent_hint). Fix: change toif suggestion: msg += suggestion; msg += create_intent_hintso both appear together when a nearest-match is found. - Sequencing/depends-on: none; both parts touch independent code surfaces
- Risks:
- Part A must not regress the case where the primary checkout IS on the target branch (no coord worktree). Test both paths.
- Part B's message change must be covered by an updated test in the existing ownership validation test suite. Changing error message text may break test assertions that compare against the old exact string — audit
tests/for affected assertions before merging.