4.5 KiB
4.5 KiB
Architecture Decision Records — Wedding Newspaper Generator
Durable ADR log for the significant design choices made in Domain Design.
ADR-001: Cohesive Generator component over fine-grained splitting
- Context — The generator is a single-purpose, fully-local tool. The team had to choose between one cohesive orchestrator with separated internal responsibilities (Q1=A) and several fine-grained independent components (ContentLoader, FunniesBuilder, LayoutEngine, Renderer).
- Decision — Adopt a single
Generatorcomponent that owns content parsing, the layout model, multi-page rendering, and emission, with its funnies and AI-draft concerns delegated to two distinct components (Funnies,AiDraft). - Consequences — (+) Simpler for a local tool; fewer moving parts; layout/print changes land in one place. (−) The Generator is larger; if the tool grows into a larger system this may need splitting later.
- Alternatives Rejected — Option B (fine-grained components): over-fragmented for this scope. Option C (minimal thin script): collapses concerns and loses testability.
ADR-002: Distinct optional AiDraft component (local Ollama only)
- Context — AI copy generation (US8/US9/FR8) uses local Ollama and must be fully optional and stay on-machine (NFR9). The team chose whether to isolate it.
- Decision — Model
AiDraftas a distinct, fully-optional component that talks only to local Ollama and owns the draft + per-article review contract. When--draftis absent it does nothing. - Consequences — (+) No-draft runs never touch AI; the AI integration is isolated and easier to test/disable; content stays local. (−) One more component boundary to document.
- Alternatives Rejected — Folding Ollama calls into the generator: couples the optional AI path into the core and makes "no AI" runs carry AI code.
ADR-003: Funnies generation owned by a distinct component
- Context — The funnies (crossword, find-a-word, comics, xkcd cartoon) are generated from the content itself (US3/FR4/Q5=X), which is non-trivial work.
- Decision — Give
Funniesits own component that derives theme words/context from content and produces the crossword/find-a-word grids and the embedded cartoon. It emits A4-printable, self-contained blocks. - Consequences — (+) Puzzle logic is isolated from layout so layout changes don't destabilize generation; content-derived puzzles feel hand-crafted. (−) The content→puzzle heuristic is genuinely complex and must handle a no-cartoon fallback (mockups R-02).
- Alternatives Rejected — Folding funnies into the generator: couples puzzle heuristics into layout; separate puzzle-gen and cartoon-fetch sub-components: over-split for now.
ADR-004: Draft bundle read via native file picker (no-server review handoff)
- Context — The per-article review page (US9/Q3=A) is a single
file://page, and the no-server/zero-network constraints (NFR3–NFR5) forbidfetch()of sibling files and forbid running a server during review (Q1=A / Q4=B). - Decision — The CLI writes the AI draft as a JSON
DraftBundle; the review page loads it through the native file picker (user-granted read, NFR5). This resolves the mockups R-01 finding. - Consequences — (+) Review works fully offline, no server, no CORS workaround (§12 of the empirical file:// research). (−) The couple must pick the draft bundle in the file dialog once per run.
- Alternatives Rejected — Serving a temporary localhost just during review (violates the no-server decision and adds a process to the flow); CLI prompt loop instead of an HTML review page (departs from confirmed Q3=A).
ADR-005: Lightweight plain-data entities, filesystem as store
- Context — The project is a local generator with no deployment; the entities are Issue, Article, MastheadConfig, Puzzle, DraftBundle.
- Decision — Model them as lightweight plain-data shapes owned by the
generator; the content
config.json+content/filesystem is the store. No database. - Consequences — (+) No infra to run; entities are trivially serializable (the DraftBundle JSON is one shape); fits the static-generator model. (−) No built-in indexing/querying — not needed at this scale.
- Alternatives Rejected — A formalized strict-schema data layer: unnecessary overhead for a static local tool. No explicit entity model: would make the review handoff and traceability harder to test.