Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/reference/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ See also:
- [Module Contracts](module-contracts.md)
- [Module Security](module-security.md)

### Core vs modules-repo ownership boundary

After module extraction and core slimming (module-migration-02, migration-03), the ownership boundary is:

- **specfact-cli (core)**: Owns runtime, lifecycle, bootstrap, registry, adapters, shared models (`ProjectBundle`, `PlanBundle`, etc.), and the three permanent core modules (`init`, `module_registry`, `upgrade`). Core must **not** import from bundle packages (`backlog_core`, `bundle_mapper`, etc.).
- **specfact-cli-modules (bundles)**: Owns bundle implementations (backlog-core, bundle-mapper, etc.). Bundles import from `specfact_cli` (adapters, models, utils, registry, contracts) as pip dependencies. Core provides interfaces; bundles implement and consume them.

Boundary regression tests (`test_core_does_not_import_from_bundle_packages`) enforce that core remains decoupled from bundle implementation details.

## Operational Modes

Mode detection currently exists via `src/specfact_cli/modes/detector.py` and CLI flags.
Expand Down
2 changes: 1 addition & 1 deletion openspec/CHANGE_ORDER.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ These are derived extensions of the same 2026-02-15 plan and are required to ope
| module-migration | 02 | module-migration-02-bundle-extraction | [#316](https://github.com/nold-ai/specfact-cli/issues/316) | module-migration-01 ✅ |
| module-migration | 03 | module-migration-03-core-slimming | [#317](https://github.com/nold-ai/specfact-cli/issues/317) | module-migration-02; migration-05 sections 18-22 (tests, decoupling, docs, pipeline/config) must precede deletion |
| module-migration | 04 | module-migration-04-remove-flat-shims | [#330](https://github.com/nold-ai/specfact-cli/issues/330) | module-migration-01; shim-removal scope only (no broad legacy test migration) |
| module-migration | 06 | module-migration-06-core-decoupling-cleanup | [#338](https://github.com/nold-ai/specfact-cli/issues/338) | module-migration-03; migration-05 bundle-parity baseline (remove remaining non-core coupling in specfact-cli core) |
| module-migration | 06 | module-migration-06-core-decoupling-cleanup (in progress) | [#338](https://github.com/nold-ai/specfact-cli/issues/338) | module-migration-03; migration-05 bundle-parity baseline |
| module-migration | 07 | module-migration-07-test-migration-cleanup | [#339](https://github.com/nold-ai/specfact-cli/issues/339) | migration-03 phase 20 handoff; migration-04 and migration-05 residual specfact-cli test debt |
| backlog-auth | 01 | backlog-auth-01-backlog-auth-commands | TBD | module-migration-03 (central auth interface in core; auth removed from core) |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Core Decoupling Inventory

## Classification: keep / move / interface

Analysis date: 2026-03-04

### Summary

- **Core import boundary**: Core (`src/specfact_cli/`) does NOT import from bundle packages (`backlog_core`, `bundle_mapper`). Boundary test enforces this.
- **Bundle dependencies on core**: Bundles import from `specfact_cli.adapters`, `specfact_cli.models`, `specfact_cli.utils`, `specfact_cli.registry`, `specfact_cli.contracts`, `specfact_cli.modules` — all shared infrastructure used by core commands and validators.

### Candidate components

| Component | Classification | Rationale |
|-----------|----------------|-----------|
| `specfact_cli.models.backlog_item` | **KEEP** | Used by core (versioning, validators) and bundles. Shared model. |
| `specfact_cli.models.plan` | **KEEP** | Used by core (validators, sync, utils) and bundles. Shared model. |
| `specfact_cli.models.project` | **KEEP** | Used by core (versioning, utils, bundle_loader) and bundles. Shared model. |
| `specfact_cli.models.dor_config` | **KEEP** | Used by backlog-core add command; core validators may use. Shared. |
| `specfact_cli.adapters.registry` | **KEEP** | Core infrastructure for adapter resolution. Bundles use for backlog adapters. |
| `specfact_cli.adapters.ado`, `github` | **KEEP** | Core adapters. Bundles use via registry and protocol. |
| `specfact_cli.utils.prompts` | **KEEP** | Used by core and backlog-core commands. Shared utility. |
| `specfact_cli.registry.bridge_registry` | **KEEP** | Protocol registry. Core and bundles use. |
| `specfact_cli.contracts.module_interface` | **KEEP (interface)** | Already an interface contract. Bundles implement. |
| `specfact_cli.modules.module_io_shim` | **KEEP (interface)** | Shim for bundle I/O. Core provides; bundles use. |

### Move candidates (extended scope per #338)

| Component | Status | Notes |
|-----------|--------|-------|
| `templates.bridge_templates` | **REMOVED** | Dead code; only tests used it. specfact-project has sync_runtime. |
| `tests/unit/sync/*` | **MIGRATED** | Moved to modules repo: `tests/unit/specfact_project/sync_runtime/` (2026-03-05). |
| `sync`, `agents`, `analyzers`, `backlog`, etc. | **PLANNED** | See `MIGRATION_REMOVAL_PLAN.md`. Migration-05 moved to specfact-cli-modules; code removal from core is phased. |

### Enforcement

- `test_core_modules_do_not_import_migrate_tier` — core modules (init, module_registry, upgrade) must not import MIGRATE-tier paths.
- `test_core_repo_does_not_host_sync_runtime_unit_tests` — core repo must not keep sync-runtime unit tests after migration.

### Interface contracts (already in place)

- `ModuleIOContract` — bundles implement; core consumes via `module_io_shim`
- `AdapterRegistry` — core provides; bundles use for backlog adapters
- `BRIDGE_PROTOCOL_REGISTRY` — protocol registration; bundles register `BacklogGraphProtocol`

### Boundary enforcement

- **Test**: `test_core_does_not_import_from_bundle_packages` — fails if any file under `src/specfact_cli/` imports from `backlog_core` or `bundle_mapper`
- **Status**: Passes. No residual core→bundle coupling.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Migration Removal Plan: specfact-cli Core Decoupling

## Context

- **Migration-05** completed: All MIGRATE-tier code was copied to specfact-cli-modules. Bundles (specfact-project, specfact-backlog, specfact-codebase, specfact-spec, specfact-govern) have local copies. `check-bundle-imports` gate passes; bundles only use CORE/SHARED imports.
- **Migration-06 scope**: Remove residual MIGRATE-tier code from specfact-cli so core owns only runtime/lifecycle/bootstrap. Package-specific artifacts must live in specfact-cli-modules.

## Current State

specfact-cli still contains MIGRATE-tier subsystems that bundles no longer import:

| Subsystem | Target bundle | Core usage blocker |
|-----------|---------------|-------------------|
| `agents` | specfact-project | `modes.router` uses `get_agent` for Copilot routing |
| `analyzers` | specfact-codebase | `sync.repository_sync` uses `CodeAnalyzer`; `importers` uses `ConstitutionEvidenceExtractor` |
| `backlog` | specfact-backlog | `adapters` (github, ado) use backlog mappers/converters for issue conversion |
| `comparators` | specfact-codebase | `sync.repository_sync` uses `PlanComparator` |
| `enrichers` | specfact-project/spec | Used by generators, importers |
| `generators` | specfact-project/spec | `utils.structure` uses `PlanGenerator` for `update_plan_summary`; `importers`, `migrations` |
| `importers` | specfact-project | `adapters.speckit` uses `SpecKitConverter`, `SpecKitScanner` |
| `merge` | specfact-project | Used by generators/enrichers |
| `migrations` | specfact-spec | Used by `generators`, `analyzers`, `agents` |
| `parsers` | specfact-codebase | Used by `validators.agile_validation` |
| `sync` | specfact-project | `templates.bridge_templates` uses `BridgeProbe`; only tests use bridge_templates |
| `templates.registry` | specfact-backlog | Used by `backlog` |
| `validators.sidecar`, `repro_checker` | specfact-codebase | Used by validate/repro commands (bundle) |
| `utils.*` (MIGRATE subset) | specfact-project | Various; `structure` uses `PlanGenerator` |

## Removal Phases

### Phase 1: Zero-core-usage removal (immediate)

Components with **no** imports from core (cli, init, module_registry, upgrade, registry, bootstrap, adapters, models, runtime, telemetry, allowed utils):

- **`templates.bridge_templates`**: Only used by tests. `BridgeProbe` is in sync (MIGRATE). → Migrate tests to specfact-cli-modules; remove `bridge_templates.py`.
- **`sync`** (after bridge_templates): Only used by bridge_templates and tests. specfact-project has `sync_runtime`. → Remove after bridge_templates; migrate sync tests.

Phase 1 progress (2026-03-05):
- `templates.bridge_templates` removed from core (completed earlier).
- Legacy unit tests under `specfact-cli/tests/unit/sync/` migrated to `specfact-cli-modules/tests/unit/specfact_project/sync_runtime/` (102 tests passing in modules worktree).
- Core now enforces this via `test_core_repo_does_not_host_sync_runtime_unit_tests`.

### Phase 2: Interface extraction (core keeps interface, impl moves)

- **`utils.structure.update_plan_summary`**: Uses `PlanGenerator`. Extract to interface or delegate to bundle via `module_io_shim`. Minimal stub in core that raises "use bundle" or delegates.
- **`modes.router`**: Uses `agents.registry`. Replace with bundle-loaded agent resolution (router asks registry for agent by command; agent comes from loaded bundle).

### Phase 3: Adapter decoupling (larger refactor)

- **`adapters` (github, ado)**: Use `backlog` mappers/converters. Options: (a) Inline conversion in adapters, (b) Move conversion to specfact-backlog and expose via protocol, (c) Keep minimal backlog interface in core.
- **`adapters.speckit`**: Uses `importers`. Move speckit-specific import logic to specfact-project or create adapter-internal implementation.

### Phase 4: Full MIGRATE removal

After Phases 1–3, remove: `agents`, `analyzers`, `backlog`, `comparators`, `enrichers`, `generators`, `importers`, `merge`, `migrations`, `parsers`, `sync`, `validators.sidecar`, `validators.repro_checker`, `templates.registry`, MIGRATE `utils.*`. Migrate associated tests to specfact-cli-modules.

## Execution Order (Phase 1)

1. Add `test_core_migrate_tier_allowlist` — fail if new MIGRATE-tier paths are added to core.
2. Remove `templates.bridge_templates` (and its test) — move test to specfact-cli-modules or delete if covered there.
3. Remove `sync` package — specfact-project has `sync_runtime`. Update `sync/__init__.py` to raise `ImportError` with migration message, or delete and fix any remaining imports. (Unit test migration completed; source package removal pending.)
4. Fix `utils.structure` — replace `PlanGenerator` usage with minimal implementation or interface.
5. Run quality gates.

## References

- `openspec/changes/archive/2026-03-03-module-migration-02-bundle-extraction/IMPORT_DEPENDENCY_ANALYSIS.md`
- `openspec/changes/archive/2026-03-04-module-migration-05-modules-repo-quality/tasks.md` (section 19)
- specfact-cli-modules `ALLOWED_IMPORTS.md`, `scripts/check-bundle-imports.py`
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# TDD Evidence: module-migration-06-core-decoupling-cleanup

## Task 2: Spec and tests first (TDD)

### 2.2 Boundary test: core must not import from bundle packages

**Test:** `tests/unit/specfact_cli/test_module_boundary_imports.py::test_core_does_not_import_from_bundle_packages`

#### Pre-implementation (failing) evidence

Temporary violation added to `src/specfact_cli/registry/bootstrap.py`:
```python
from backlog_core.main import backlog_app # noqa: F401
```

**Command:** `hatch run pytest tests/unit/specfact_cli/test_module_boundary_imports.py::test_core_does_not_import_from_bundle_packages -v`

**Result:** FAILED
```
AssertionError: Core must not import from bundle packages (backlog_core, bundle_mapper).
- src/specfact_cli/registry/bootstrap.py: from backlog_core.main import
```

**Timestamp:** 2026-03-04

#### Post-implementation (passing) evidence

Temporary violation removed. Core has no imports from `backlog_core` or `bundle_mapper`.

**Command:** `hatch run pytest tests/unit/specfact_cli/test_module_boundary_imports.py -v`

**Result:** 3 passed (including `test_core_does_not_import_from_bundle_packages`)

**Timestamp:** 2026-03-04

### Task 3.4 Post-decoupling (passing) evidence

**Command:** `hatch run pytest tests/unit/specfact_cli/test_module_boundary_imports.py tests/unit/backlog/ tests/unit/validators/test_bundle_dependency_install.py -v`

**Result:** 172 passed (including boundary tests)

**Timestamp:** 2026-03-04

Inventory confirmed no move candidates; core already decoupled. Boundary test prevents future coupling.

### Extended scope (Phase 1) — 2026-03-04

**Removed:** `templates.bridge_templates`, `tests/unit/templates/test_bridge_templates.py` (dead code; only tests used it).

**Added:** `test_core_modules_do_not_import_migrate_tier` — core modules must not import MIGRATE-tier paths.

**Command:** `hatch run pytest tests/unit/sync/ tests/unit/templates/ tests/unit/specfact_cli/test_module_boundary_imports.py -v`

**Result:** 127 passed

### Extended scope continuation (sync-runtime unit test migration) — 2026-03-05

#### Pre-implementation (failing) evidence

Added boundary test: `test_core_repo_does_not_host_sync_runtime_unit_tests`.

**Command:** `hatch run pytest tests/unit/specfact_cli/test_module_boundary_imports.py::test_core_repo_does_not_host_sync_runtime_unit_tests -v`

**Result:** FAILED
```
AssertionError: Sync runtime unit tests must be migrated out of specfact-cli into specfact-cli-modules.
- tests/unit/sync/test_bridge_probe.py
- tests/unit/sync/test_bridge_sync.py
- tests/unit/sync/test_bridge_watch.py
- tests/unit/sync/test_drift_detector.py
- tests/unit/sync/test_repository_sync.py
- tests/unit/sync/test_watcher_enhanced.py
```

**Timestamp:** 2026-03-05 08:21:57Z

#### Post-implementation (passing) evidence

Migrated legacy core sync-runtime unit tests from:
- `specfact-cli/tests/unit/sync/test_*.py`

To modules repo:
- `specfact-cli-modules/tests/unit/specfact_project/sync_runtime/test_*.py`

Then removed migrated tests from `specfact-cli` core.

**Core command:** `hatch run pytest tests/unit/specfact_cli/test_module_boundary_imports.py::test_core_repo_does_not_host_sync_runtime_unit_tests -v`

**Core result:** PASSED (1 passed)

**Modules command:** `hatch run pytest tests/unit/specfact_project/sync_runtime -v`

**Modules result:** PASSED (102 passed)
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,35 @@ The `specfact-cli` core package SHALL include only components required for perma
- **GIVEN** internal decoupling refactors are applied
- **WHEN** users run supported core and installed-bundle commands
- **THEN** observable command behavior remains compatible with current migration topology.

### Requirement: Core Must Not Import From Bundle Packages

The `specfact-cli` core (`src/specfact_cli/`) SHALL NOT import from bundle packages (`backlog_core`, `bundle_mapper`, or other extracted bundle namespaces). Core modules (init, module_registry, upgrade) and shared infrastructure (models, utils, adapters, registry) must remain decoupled from bundle implementation details.

#### Scenario: Core import boundary is enforced by regression tests

- **GIVEN** core and bundle packages coexist in the repository
- **WHEN** boundary tests run
- **THEN** any file under `src/specfact_cli/` that imports from `backlog_core` or `bundle_mapper` causes the test to fail.

### Migration Acceptance Criteria

- [x] Inventory of candidate core components (keep/move/interface) produced and documented
- [x] No core file imports from `backlog_core` or `bundle_mapper`
- [x] Boundary regression tests pass
- [ ] Quality gates (format, type-check, lint, contract-test, smart-test) pass
- [x] docs/architecture updated with core vs modules-repo ownership boundary

### Requirement: MIGRATE-Tier Enforcement

Core modules (init, module_registry, upgrade) SHALL NOT import from MIGRATE-tier paths. MIGRATE-tier code (agents, analyzers, backlog, sync, etc.) lives in specfact-cli-modules. Regression test `test_core_modules_do_not_import_migrate_tier` enforces this.

### Requirement: Package-Specific Artifact Removal

Package-specific artifacts not required by CLI core SHALL be removed from specfact-cli and live in respective packages (specfact-cli-modules). `MIGRATION_REMOVAL_PLAN.md` documents phased removal. Phase 1: remove dead code (e.g. `templates.bridge_templates`).

#### Scenario: Sync-runtime unit tests are owned by modules repo

- **GIVEN** `sync_runtime` implementation is owned by `specfact-project` in specfact-cli-modules
- **WHEN** decoupling migration updates test ownership
- **THEN** legacy core tests under `specfact-cli/tests/unit/sync/` are migrated to `specfact-cli-modules/tests/unit/specfact_project/sync_runtime/` and core boundary test `test_core_repo_does_not_host_sync_runtime_unit_tests` enforces this.
Loading
Loading