Skip to content

Commit 7894b7d

Browse files
author
clanker
committed
close(DE-114): god-file structural splits complete
5 god files (8,371 lines) split into ~30 focused modules. All 4,585 tests pass. Delta completed.
1 parent 3a162a0 commit 7894b7d

33 files changed

Lines changed: 11540 additions & 11923 deletions

File tree

.spec-driver/deltas/DE-114-god_file_structural_splits_list_py_common_py_requirements_registry_py_creation_py_workflow_metadata_py/DE-114.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ id: DE-114
33
slug: god_file_structural_splits_list_py_common_py_requirements_registry_py_creation_py_workflow_metadata_py
44
name: "Delta - God-file structural splits: list.py, common.py, requirements/registry.py, creation.py, workflow_metadata.py"
55
created: "2026-03-22"
6-
updated: "2026-03-22"
7-
status: in-progress
6+
updated: "2026-03-23"
7+
status: completed
88
kind: delta
99
aliases: []
1010
relations: []

.spec-driver/deltas/DE-125-enforce_explicit_module_boundaries_and_coupling_constraints/DE-125.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Before executing symptomatic refactorings, we must define the structural bluepri
6666
- Define strict, one-way architectural layers (Core, Models, Domain/Registry, Orchestration, Presentation).
6767
- Draft and approve POL-003 to formalize coupling constraints (a layer may only import from itself or layers below it).
6868
- Re-home and rename the obfuscatory `supekku/scripts/lib` paths into an explicit, layer-aligned package structure (e.g., `spec_driver/core/`, `spec_driver/domain/`).
69+
- Separate fast unit tests (sitting alongside their target code) from slow integration tests (re-homed to `tests/integration/` and invoked via a separate command).
6970
- **Operational Constraints**:
7071
- The refactoring must be mechanically verifiable (e.g., via `import-linter` or explicit CI checks).
7172
- Must not change the external CLI behaviour or workflow artifact schemas.
@@ -81,7 +82,7 @@ Before executing symptomatic refactorings, we must define the structural bluepri
8182
## 5. Approach Overview
8283

8384
- **Phase 1: Blueprint & Policy**: Thrash out the layer definitions in DR-125 and ratify POL-003.
84-
- **Phase 2: Establish API Shell & Boundaries**: Create the `spec_driver/__init__.py` and `spec_driver/workflow/__init__.py` public APIs. Re-import necessary types/functions from `supekku` to immediately unblock `autobahn` (DE-124). Establish explicit `__all__` exports in `spec_driver` internal layers.
85+
- **Phase 2: Establish API Shell & Boundaries**: Create the `spec_driver/__init__.py` and `spec_driver/orchestration/__init__.py` public APIs. Re-import necessary types/functions from `supekku` to immediately unblock `autobahn` (DE-124). Establish explicit `__all__` exports in `spec_driver` internal layers.
8586
- **Phase 3: Enforcement**: Configure `import-linter` in `pyproject.toml` to rigidly enforce the layers for `spec_driver/`. Set `pylint` to aggressively fail for `spec_driver/` while remaining lenient on `supekku/`.
8687
- **Phase 4: The Strangler Fig Move**: Move individual files from `supekku/` to `spec_driver/` one by one. Fix their import graphs as they move, utilizing the strict internal boundaries.
8788
- **Phase 5: Cleanup**: Eradicate `supekku/` once empty. This naturally resolves the god-init problem (DE-114).

.spec-driver/deltas/DE-125-enforce_explicit_module_boundaries_and_coupling_constraints/DR-125.md

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,29 +98,63 @@ We are shifting from an implicit, flat module graph to an explicit, layered arch
9898
* **Responsibility:** Reading models from disk, maintaining the in-memory entity graph, resolving cross-artifact relations, tracking drift logic.
9999
* **Coupling Rules:** May import from `models/` and `core/`. Must **never** import orchestration/workflow logic or presentation concerns.
100100

101-
#### 4. Orchestration / Workflow Layer
102-
* **Target Path:** `spec_driver/workflow/` (and potentially `spec_driver/sync/`, `spec_driver/validation/`)
101+
#### 4. Orchestration Layer
102+
* **Target Path:** `spec_driver/orchestration/`
103103
* **Contents:** State machines, staleness evaluation, sync routines, phase sheet generation, cross-artifact validation passes.
104104
* **Responsibility:** The "verbs" of the system. Coordinating multi-step state transitions, executing syncs across the registry, evaluating operational readiness.
105105
* **Coupling Rules:** May import from all layers below. Must **not** import from the presentation layer. This layer represents the boundary for the Public API Facade (DE-124).
106106

107107
#### 5. Presentation Layer
108-
* **Target Path:** `spec_driver/cli/`, `spec_driver/tui/`
108+
* **Target Path:** `spec_driver/presentation/cli/`, `spec_driver/presentation/tui/`
109109
* **Contents:** Typer CLI commands, Textual TUI applications.
110110
* **Responsibility:** Argument parsing, user interaction, formatting terminal output, rendering UIs.
111111
* **Coupling Rules:** May import from any layer below. Must **never** contain inline business logic or state transitions (enforces the Skinny CLI pattern).
112112

113+
### Intra-Layer Coupling (Isolation & Sub-layers)
114+
115+
To prevent large layers (like the 5,000+ LOC TUI) from becoming internal hairballs, we apply secondary constraints within the layers:
116+
117+
1. **Independence Contracts (Isolation):** Sibling packages that have no reason to talk to each other must be explicitly isolated. For example, `spec_driver.presentation.cli` and `spec_driver.presentation.tui` must be declared independent (neither may import the other).
118+
2. **Sub-layering:** Large packages get their own internal `layers` contract. The TUI, for example, will be structured as:
119+
* `spec_driver.presentation.tui.app` (top-level assembly)
120+
* `spec_driver.presentation.tui.views` (composed screens)
121+
* `spec_driver.presentation.tui.widgets` (reusable components)
122+
* `spec_driver.presentation.tui.search` / `.core` (internal state/logic)
123+
124+
### Test Architecture (Unit vs. Integration)
125+
126+
A secondary goal of this refactoring is to dramatically improve the feedback loop by separating fast unit tests from slow integration tests.
127+
128+
* **Unit Tests:** Must sit alongside the code they test (e.g., `spec_driver/core/file_ops_test.py`). They must be fast, isolated, and free of slow I/O or full-system initialization. **Import Constraint:** Unit tests are strictly bound by the same layer constraints as their target code. A test in `spec_driver.domain` may mock an orchestration component, but it may not import it.
129+
* **Integration Tests:** Must be re-homed to a dedicated `tests/integration/` directory at the repository root. These tests exercise the composed layers (e.g., CLI-to-disk workflows) and can be executed via a separate runner command (e.g., `just test-integration`), keeping the primary `just test` suite lightning fast. **Import Constraint:** Because they reside outside the `spec_driver` namespace, integration tests are exempt from the internal layer constraints and act as top-level consumers.
130+
113131
## 4. Re-homing & Renaming Strategy
114132

115133
The `supekku` package name and `scripts/lib` path prefix are legacy cruft. The new package root will be `spec_driver/`.
116134

135+
### Layer Assignment Heuristics & Borderline Cases
136+
137+
When moving files, use the following heuristics to resolve ambiguity, especially for modules that currently conflate multiple responsibilities:
138+
139+
* **Heuristic 1: Does it enforce a domain rule or execute a multi-step process?**
140+
* *Example:* `validation/validator.py` cross-checks multiple registries to ensure relations are valid. Because it coordinates across registries but does not mutate disk state or perform side-effects, it belongs in `spec_driver/domain/validation/`.
141+
* *Example:* `sync/` adapters pull external states (like code comments) and create requirements. Because this involves I/O, network (potentially), and mutation of the workspace, it belongs in `spec_driver/orchestration/sync/`.
142+
* **Heuristic 2: Is it the definition of a state, or the act of transitioning?**
143+
* *Example:* `workflow/state_machine.py` defines the valid states and the matrix of allowed transitions. This is a pure domain rule. It belongs in `spec_driver/domain/workflow/state_machine.py` (or even `spec_driver/models/workflow.py` if reduced to pure Enums).
144+
* *Example:* `workflow/review_io.py` and the execution of `prime_review` perform I/O, evaluate staleness, and mutate the artifact's state. This belongs in `spec_driver/orchestration/review.py`.
145+
* **Heuristic 3: Does it represent the physical constraints of the repo, or the domain concepts?**
146+
* *Example:* `workspace.py` knows about `.spec-driver/registry/` and the repo root. It is foundational I/O context. It belongs in `spec_driver/core/workspace.py`.
147+
117148
**Mapping Examples:**
118149
* `supekku/scripts/lib/core/``spec_driver/core/`
119150
* `supekku/scripts/lib/file_ops.py``spec_driver/core/file_ops.py`
120151
* `supekku/scripts/lib/specs/models.py``spec_driver/models/specs.py`
121152
* `supekku/scripts/lib/registry_v2.py``spec_driver/domain/registry.py`
122-
* `supekku/scripts/lib/workflow/state_machine.py``spec_driver/workflow/state_machine.py`
123-
* `supekku/cli/``spec_driver/cli/`
153+
* `supekku/scripts/lib/workflow/state_machine.py``spec_driver/domain/workflow/state_machine.py`
154+
* `supekku/scripts/lib/sync/``spec_driver/orchestration/sync/`
155+
* `supekku/scripts/lib/validation/``spec_driver/domain/validation/`
156+
* `supekku/cli/``spec_driver/presentation/cli/`
157+
* `supekku/tui/``spec_driver/presentation/tui/`
124158

125159
## 5. Automated Enforcement (import-linter)
126160

@@ -135,26 +169,44 @@ root_package = "spec_driver"
135169
name = "Architectural Layers"
136170
type = "layers"
137171
layers = [
138-
"spec_driver.cli | spec_driver.tui",
139-
"spec_driver.workflow",
172+
"spec_driver.presentation",
173+
"spec_driver.orchestration",
140174
"spec_driver.domain",
141175
"spec_driver.models",
142176
"spec_driver.core",
143177
]
178+
179+
[[tool.importlinter.contracts]]
180+
name = "Presentation Layer Isolation"
181+
type = "independence"
182+
modules = [
183+
"spec_driver.presentation.cli",
184+
"spec_driver.presentation.tui",
185+
]
186+
187+
[[tool.importlinter.contracts]]
188+
name = "TUI Internal Layering"
189+
type = "layers"
190+
layers = [
191+
"spec_driver.presentation.tui.app",
192+
"spec_driver.presentation.tui.views",
193+
"spec_driver.presentation.tui.widgets",
194+
"spec_driver.presentation.tui.search",
195+
"spec_driver.presentation.tui.core",
196+
]
144197
```
145198
This contract explicitly bans upward imports, causing the CI pipeline to fail if an orchestration module accidentally imports a CLI formatter, or if a model imports a registry.
146199

147200
## 6. Rollout & Sequence
148201

149202
1. **Blueprint & Policy**: Finalize and ratify **DR-125** and **POL-003**.
150203
2. **Setup Enforcer**: Add `import-linter` to `pyproject.toml` and configure the initial contracts. Tune the linter and `pylint` for aggressive failure for the new `spec_driver/` package (while maintaining the existing threshold for `supekku/`).
151-
3. **Establish API Shell**: Create the `spec_driver/__init__.py` and `spec_driver/workflow/__init__.py` skeleton. Temporarily re-import the necessary functions/types from `supekku/*` to fulfill the Public API Facade (DE-124) without moving the underlying code yet.
204+
3. **Establish API Shell**: Create the `spec_driver/__init__.py` and `spec_driver/orchestration/__init__.py` skeleton. Temporarily re-import the necessary functions/types from `supekku/*` to fulfill the Public API Facade (DE-124) without moving the underlying code yet.
152205
4. **Establish Internal Boundaries**: Create internal boundary APIs within `spec_driver/` (e.g. `spec_driver.domain`) that strictly re-export a reduced set of functions and types.
153206
5. **The Strangler Fig Move**: Move individual files from `supekku/scripts/lib/` to `spec_driver/` one at a time. As each file is moved, fix its import graph so it strictly relies on the new `spec_driver` boundary APIs. The aggressive linter rules will validate each moved file.
154207
6. **Decouple & Cleanup**: Eradicate `supekku/scripts/lib` entirely once the strangler fig migration is complete. This will naturally resolve the god-init problem (DE-114).
155208

156-
## 7. Open Questions
209+
## 7. Open Questions / Decisions
157210

158-
- **OQ-125-001**: Should `autobahn` remain a separate top-level Python package alongside `spec_driver`, or be pulled inside the `spec_driver` namespace (e.g. `spec_driver.autobahn`)?
159-
- **OQ-125-002**: Are there specific modules in `supekku/scripts/lib` whose layer assignment is ambiguous (e.g., formatters)?
160-
_Proposed Answer: Formatters belong in the Presentation layer, or a dedicated `spec_driver/presentation/formatters/` package if shared between CLI and TUI._
211+
- **DEC-125-005 (autobahn):** `autobahn` will remain a separate top-level Python package (and repository, currently). This strictly enforces the architectural boundary: `autobahn` is a downstream consumer of `spec_driver.orchestration` and cannot accidentally bypass the facade to import internal models or domain logic. Dogfooding the public API via a completely separate package proves the API's completeness (DE-124).
212+
- **DEC-125-006 (formatters):** Formatters will be split based on their purity and dependencies. Pure string manipulation or data-to-string formatters that do not depend on presentation libraries (like `rich` or `textual`) or orchestration logic belong in `spec_driver/core/formatters/` or `spec_driver/models/formatters/`. Formatters that are inherently tied to terminal presentation (e.g., rendering `rich` Tables or `textual` widgets) belong in `spec_driver/presentation/formatters/`. This ensures pure formatting logic is reusable across the entire stack while keeping presentation dependencies isolated at the top.

.spec-driver/policies/POL-003-module-boundaries.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ The `spec-driver` codebase must adhere to a strict, one-way layered architecture
3737
* **Responsibility**: Entity registries, cross-artifact graph navigation, relation resolution, and in-memory artifact state management.
3838
* **Constraint**: May import from `models` and `core`. Must **never** import workflow orchestration or presentation logic.
3939

40-
4. **Orchestration / Workflow (`spec_driver.workflow`)**
40+
4. **Orchestration (`spec_driver.orchestration`)**
4141
* **Responsibility**: High-level operations, state machines, transition logic, sync coordination, and multi-artifact validation passes.
4242
* **Constraint**: Represents the "Public API" boundary. May import from all layers below. Must **not** import from the presentation layer.
4343

44-
5. **Presentation (`spec_driver.cli`, `spec_driver.tui`)**
44+
5. **Presentation (`spec_driver.presentation.cli`, `spec_driver.presentation.tui`)**
4545
* **Responsibility**: Argument parsing, formatting, terminal interaction, and user interface.
4646
* **Constraint**: Must follow the "Skinny CLI" pattern. May import from any layer below. Must **never** contain domain logic or state transitions.
4747

@@ -51,7 +51,12 @@ Without explicit boundaries, internal dependencies become cyclic and untraceable
5151

5252
## Scope
5353

54-
Applies to all production Python code in the `spec-driver` repository. Existing legacy code in `supekku/` must be migrated to the `spec_driver/` package structure and aligned with these layers via DE-125.
54+
Applies to all production Python code in the `spec-driver` repository, including unit tests.
55+
56+
* **Unit Tests:** Must reside within the `spec_driver/` package alongside the code they test (e.g., `spec_driver/core/file_ops_test.py`) and are strictly bound by the identical layer constraints as their targets. For instance, a domain test may not import orchestration modules to set up its fixtures.
57+
* **Integration Tests:** Must be located in a top-level `tests/integration/` directory outside the `spec_driver/` package. Because they sit outside the enforced package, they act as top-level consumers and are exempt from internal layer constraints.
58+
59+
Existing legacy code in `supekku/` must be migrated to the `spec_driver/` package structure and aligned with these layers via DE-125.
5560

5661
## Verification
5762

0 commit comments

Comments
 (0)