Package boundaries (a2c-workflow)
Normative ownership and dependency rules for the three Python packages in the a2c-workflow repository. Builds on accepted architecture (overview.md, ADR-0006).
Repository: a2c-workflow
Primary Python packages: a2c_core, a2c_cli, a2c_tui
Status: Implementation specification — M1 scaffold complete; does not change accepted ADRs.
Ownership matrix
| Package | Owns | Must not own | Depends on |
|---|---|---|---|
a2c_core | Domain logic; metadata read/write; schema validation; repository artifact contracts; decomposition orchestration hooks; AI workflow orchestration and evaluation; shared result/error types | CLI argument parsing; stdout/stderr formatting; Textual screens/widgets; editor or host-specific code | Lowest-level third-party libs only (e.g. pydantic, pyyaml, pathlib stdlib) — never a2c_cli or a2c_tui |
a2c_cli | Command tree; argument parsing; exit codes; human-readable tables/text; JSON command output for automation and extension | Core business rules; schema definitions; AI prompt content; Textual UI | a2c_core only |
a2c_tui | Textual App structure; navigation; forms and diagnostic screens; calling core services for display | Core business rules; CLI parsing semantics; duplicate validation logic | a2c_core only — not a2c_cli (see TUI interaction model) |
Allowed dependency directions
| From | To | Allowed |
|---|---|---|
a2c_cli | a2c_core | Yes |
a2c_tui | a2c_core | Yes |
a2c_core | a2c_cli | No |
a2c_core | a2c_tui | No |
a2c_tui | a2c_cli | No — TUI calls core services directly |
a2c_cli | a2c_tui | No |
Rationale: CLI and TUI are peer presentation layers. TUI must not shell out to CLI (avoids subprocess overhead, divergent error paths, and circular packaging). The VS Code extension does invoke CLI — that is an external host concern (ADR-0007).
Forbidden imports (enforced by convention + lint)
| Package | Must never import |
|---|---|
a2c_core | a2c_cli, a2c_tui, textual, click/typer (if used in CLI only) |
a2c_cli | a2c_tui, textual |
a2c_tui | a2c_cli |
Add an import-linter or ruff banned-module rule in Phase 0 when the a2c-workflow scaffold exists.
Shared types and service boundaries
All cross-surface contracts live in a2c_core:
| Module area (intended) | Contents |
|---|---|
a2c_core.schemas | Pydantic/dataclass models for metadata files, config, CLI result envelope |
a2c_core.contracts | Repository artifact expectations (paths, required files) |
a2c_core.services | Validation, metadata CRUD, decomposition orchestration entrypoints |
a2c_core.workflows | AI workflow runners, prompt assembly, approval gates |
a2c_core.errors | Typed exceptions → mapped to CLI exit codes / TUI messages / JSON error field |
Presentation packages map core outcomes to their surface — they do not redefine domain types.
Cross-cutting concerns
| Concern | Owner | Notes |
|---|---|---|
| Config loading | a2c_core | Single loader; CLI/TUI pass paths or use defaults |
| Logging | a2c_core | Structured logger factory; CLI/TUI attach handlers for verbosity |
| Paths / repo discovery | a2c_core | Find A2C metadata root, docs/adr/, etc. |
| Version string | a2c_core | __version__ or shared VERSION reader — CLI a2c version reads from core |
| Human-in-control gates | a2c_core.workflows | Approval checkpoints before mutating writes; CLI/TUI only render prompts |
AI workflow interaction
| Rule | Detail |
|---|---|
Orchestration lives in a2c_core.workflows | Prompt templates may load from packaged rules/ / prompts/ assets |
| No UI in workflow modules | Workflows return structured plans/results — never Textual widgets or ANSI formatting |
| CLI exposes workflows | a2c_cli commands call a2c_core.workflows and serialize via result envelope |
| TUI exposes workflows | Screens call same core APIs; optional human approval UI in TUI layer only |
| Evaluation fixtures | Under tests/fixtures/ — assert core workflow outputs, not CLI ANSI snapshots |
Anti-patterns
- Duplicating validation in CLI “for convenience”
- TUI subprocess calling
a2cCLI for every button action - Putting schema models in
a2c_cli.modelsbecause “CLI needs them first” - AI prompt strings hard-coded in
a2c_tuiscreens - Extension-oriented JSON shapes defined only in extension TypeScript — CLI JSON contract is owned by
a2c_core+a2c_cli
Still open (implementation)
- Exact internal module names under
a2c_core - Whether
a2c_tuiuses async Textual with core sync services via thread pool - Plugin/hook extension points in core (future ADR if needed)
Related
- implementation-plan.md — phased build order
- initial-contracts.md — contracts to define before broad coding
- repository-anatomy.md — repository tree
- ADR-0006