Appendix B - 3. Component & zone model
The Structure of Component & zone model — its shape at a glance:
A typed registry names each component's zone once. Consumers read the registry instead of re-inferring from paths, and a reverse-mapping test walks the real tree and asserts parity in both directions.
flowchart LR
Reg[(Component registry)] --> Lints[Boundary lints]
Reg --> Dispatch[Dispatch]
Reg --> Inject[Context injection]
Tree[(Real directory tree)] --> RM{{Reverse-mapping test}}
Reg --> RM
Accessible description: a typed component registry feeds three consumers — boundary lints, dispatch, and context injection — so they read one answer. A reverse-mapping test compares the registry against the real directory tree and fails on divergence.
Projected from the catalogue entry system-models / Component & zone model.
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — A typed catalogue of every component's code zone (focus-dirs, tags, boundary kind, external seams, read surfaces), so "which component owns this file, and what may touch it" is a queried fact, not a guess.
Motivation
Governance constantly asks "which component owns this file? what zone is it in? what boundary kind, what seams?" Answered ad hoc, with a hardcoded path list here and a grep there, those answers drift the moment a component is added or a directory moves, and the tool keeps passing while reasoning about a stale map. It is also the map an agent needs to know where it is in a large codebase.
Applicability
- A typed component registry with the fields consumers need (zones, tags, boundary, seams).
- A reverse-mapping test so the model can't silently diverge from the tree.
- Consumers that read it (lints, dispatch, DCI) rather than hardcoding paths.
Structure
The Structure diagram appears at the top of this page.
Sample Code
A frozen record names each component's zone. Ownership is a lookup that finds the record whose directory prefixes the path, and a reverse-mapping check asserts every real directory maps back to exactly one component — the parity that stops the map staling as directories move.
from dataclasses import dataclass
import sys
@dataclass(frozen=True)
class Component:
name: str
focus_dir: str # the directory prefix this component owns
boundary: str # e.g. "leaf" / "group" / "external-seam"
REGISTRY = [
Component("editor", "src/editor/", "leaf"),
Component("worker", "src/worker/", "leaf"),
]
def owner_of(path: str) -> str | None:
for c in REGISTRY:
if path.startswith(c.focus_dir):
return c.name
return None
def reverse_map(real_dirs: set[str]) -> list[str]:
"""Every real top-level dir must map to exactly one component (no unmodeled zone)."""
owned = {c.focus_dir for c in REGISTRY}
return [f"'{d}' exists but no component owns it" for d in sorted(real_dirs - owned)]
if __name__ == "__main__":
# `list_real_dirs` enumerates the code tree's owned directories.
findings = reverse_map(list_real_dirs())
for f in findings:
print(f"UNMODELED-ZONE: {f}")
sys.exit(1 if findings else 0)
Consequences
- Add-a-component upkeep — a new component means a registry row + boundary/seam classification, or the reverse-mapping test fails (deliberately).
- Centralization blast radius — a wrong zone misroutes every consumer at once (the fix-once affordance's cost).
Example use within DocAble
- The component-registry (read by the lint fleet, dispatch, and audit surfaces).
- The boundary / seam / read-surface classifiers.
- The reverse-mapping-test (model↔tree parity).
Related Patterns
- Bridge — agents consume it (dynamic-context-injection slices constraints by component; role-typed-dispatch reads zones) ◀──▶ it governs the product (boundary/seam lints, focus-dir scoping).
- Counterpart — drift-parity-gates: the reverse-mapping test that keeps it honest.
- See also — meta-model-consumption (read it, don't hardcode) · query-surface (the repo-query
componentsubcommand).