# Phase 0 Research: Clean Release Compliance Subsystem Redesign

## Decision 1: The subsystem becomes API/CLI-first and TUI becomes a thin client

**Decision**  
Primary release operations are owned by application services and exposed through CLI and HTTP API first. TUI is retained only as a thin operator interface that reads state and triggers actions through the same facade.

**Rationale**  
The current implementation mixes UI state with preparation, manifest creation and compliance execution. This blocks automation and makes behavior depend on the interface used.

**Alternatives considered**  
- Keep TUI as primary orchestrator and add wrappers around it: rejected because it preserves hidden business logic inside the interface.  
- Remove TUI entirely: rejected because operators still need an interactive console flow in enterprise environments.

---

## Decision 2: Policy and registry are trusted snapshots, never runtime UI/env payloads

**Decision**  
Policy and source registry are resolved by a dedicated read-only resolution service from trusted stores, then frozen into immutable snapshots for each compliance run.

**Rationale**  
The redesign explicitly separates trusted and untrusted inputs. Candidate input, artifacts JSON and operator choices are not allowed to define policy contents or final report outcomes.

**Alternatives considered**  
- Continue using `.clean-release.yaml` and env bootstrap as policy source: rejected because it violates the new trust model.  
- Let TUI construct policy in demo and real mode differently: rejected because it breaks evidence integrity and reproducibility.

---

## Decision 3: Manifest, report and snapshots are immutable; run history is append-only

**Decision**  
`DistributionManifest`, `CleanPolicySnapshot`, `SourceRegistrySnapshot`, `ComplianceReport`, `ApprovalDecision` and `PublicationRecord` are immutable. `ComplianceRun`, `ComplianceStageRun`, `ComplianceViolation` and audit log are append-only once created; only non-terminal run fields may progress during execution.

**Rationale**  
The main value of the subsystem is evidence integrity. Mutable manifest/report records make audit and publication safety unverifiable.

**Alternatives considered**  
- Update manifest/report in place: rejected because historical evidence would be lost.  
- Allow deleting old runs to keep storage small: rejected because real mode must preserve evidence.

---

## Decision 4: Release lifecycle is modeled as an explicit state machine

**Decision**  
The candidate lifecycle is formalized as `DRAFT -> PREPARED -> MANIFEST_BUILT -> CHECK_PENDING -> CHECK_RUNNING -> CHECK_PASSED|CHECK_BLOCKED|CHECK_ERROR -> APPROVED -> PUBLISHED -> REVOKED`, with hard guards on forbidden transitions.

**Rationale**  
Current logic spreads status changes across TUI and orchestration code. A formal state machine makes approval/publication gating deterministic and testable.

**Alternatives considered**  
- Keep loose status updates per module: rejected because it produces hidden invalid states.  
- Collapse all states into a smaller set: rejected because manifest, check and approval stages need separate audit visibility.

---

## Decision 5: Compliance execution is a pluggable stage pipeline integrated with TaskManager

**Decision**  
Each compliance run becomes a `TaskManager` task. The run stores lifecycle metadata while stage logs are emitted as task logs or structured sub-events. The pipeline remains pluggable with stage-specific decisions and violations.

**Rationale**  
The repository already has a mature async task lifecycle and reporting patterns. Reusing it reduces duplicated orchestration infrastructure and aligns with repository constitution.

**Alternatives considered**  
- Keep synchronous orchestrator execution: rejected due to non-blocking API requirements.  
- Build a second custom task subsystem inside clean release: rejected as redundant and harder to observe.

---

## Decision 6: Interfaces are split into CLI, REST API and thin TUI over one facade

**Decision**  
A single `CleanReleaseFacade` exposes use cases for candidate overview, manifest build, compliance run, approval and publication. CLI, API and TUI all call the facade. Headless mode belongs to CLI/API only.

**Rationale**  
A facade keeps interface code thin and prevents re-implementing business rules per entrypoint.

**Alternatives considered**  
- Let each interface call lower-level services directly: rejected because state validation and DTO assembly would drift.  
- Keep a headless branch inside TUI: rejected because headless is not a UI concern.

---

## Decision 7: Repositories are decomposed by responsibility, even if exposed through one internal facade

**Decision**  
Persistence is split by bounded responsibility: candidate, artifacts, manifest, policy, compliance run, report, approval, publication and audit. A convenience facade may exist, but ownership remains explicit.

**Rationale**  
The current `CleanReleaseRepository` is too broad for the redesigned evidence model. Explicit repository boundaries make append-only and immutable behavior easier to enforce.

**Alternatives considered**  
- Keep one universal repository class: rejected because contracts stay ambiguous.  
- Persist everything only through TaskManager: rejected because domain entities need direct retrieval independently of task history.

---

## Decision 8: Demo mode is preserved but isolated by namespace

**Decision**  
Demo mode is handled by a dedicated demo service and isolated storage namespace. Demo runs, policies, candidates and reports never share identifiers or history with real mode.

**Rationale**  
Demo mode remains useful for operator training, but it must not contaminate real compliance evidence.

**Alternatives considered**  
- Simulate demo behavior inside real storage: rejected because it risks false evidence and operator confusion.  
- Drop demo mode entirely: rejected because it removes a safe training path.

---

## Decision 9: Migration proceeds incrementally, starting by extracting services out of TUI

**Decision**  
Migration starts by extracting build/run logic into new services/facade, then removes env-driven policy injection, then introduces immutable snapshots, then adds CLI/API contracts, and only after that thins the TUI.

**Rationale**  
The current codebase already has working routes, models and tests. A big-bang rewrite would create unnecessary integration risk.

**Alternatives considered**  
- Rewrite the whole subsystem at once: rejected because it is harder to validate incrementally.  
- Patch TUI only: rejected because it does not solve the architectural problem.
