first pass at the newspaper builder
Test / test (push) Has been cancelled

This commit is contained in:
2026-09-14 11:57:22 +10:00
commit bec1eaac87
497 changed files with 178953 additions and 0 deletions
@@ -0,0 +1,25 @@
**Collaborator:** aidlc-design-agent
## Contribution
Reviewing the personas and story draft for UX and persona fidelity.
- The two-persona split (P1 the couple, P2 the guest-as-constraint) is the right
call for a self-contained local tool — the reader is genuinely the printed
output, not an interface user. Keeping P2 as quality attributes on the P1
stories avoids inventing fake guest "tasks" that don't map to real usage.
- Strong points in the draft: US6 locks the classic broadsheet aesthetic as a
testable constraint; US3 gives the funnies first-class weight; US9 makes the
AI-review a first-class flow rather than a background detail.
- Design gap worth folding in: the stories don't yet capture a "no-content"
or "empty issue" authoring state — what the couple sees when they open the
generator with no content yet. A small, friendly empty-state story would
protect the first-run experience.
- Recommend a "first-run empty state" story (Won't/could) so the couple isn't
met with a blank page on first launch.
## Positions
- AGREE: two-persona model with guest as reader-constraint — honest to real usage.
- AGREE: US6 aesthetic-as-requirement — design intent is testable, not hand-wavy.
- OBJECT (minor): missing an empty-state / first-run experience story; consider
a small Could-Have story so first launch is friendly, not blank.
@@ -0,0 +1,36 @@
**Collaborator:** aidlc-developer-agent
## Contribution
Reviewing the personas and stories for implementability and story sizing.
- Story sizing at the FR-group level (Q2=B) reads correctly against this
project's surface area: US1 (multi-page), US3 (funnies), US8/US9 (AI+
review) are the meaty ones, and grouping them this way keeps each story
independently deliverable without splitting hairs.
- Dependencies are well-flagged (US7 feeds US2 for the masthead; US5 feeds
everything; US9 depends on US8). The dependency notes are accurate.
- Implementability notes worth locking:
- US3 (funnies) is the largest chunk — crossword building from user content,
word-search, comic placement, plus the xkcd fetch-and-embed. Consider
whether the crossword and the comics could be accepted as separate stories
if sizing gets tight, though the user's plan keeps them grouped; honoring
the current plan, I note it as a single Must-Have that is genuinely
composite.
- US5.AC5.1.3 (file-picker live load) needs the native file picker path —
this aligns with the affirmed practice and is known-possible, but it is
real work; calling it out so it isn't underestimated.
- US9 (per-article review) implies the AI draft output must be addressable
per article (a data model), not a single blob — the story's ACs already
capture this requirement implicitly; making the per-article boundary
explicit helps the implementer.
## Positions
- AGREE: FR-group story granularity is right for this scope — each US is
independently shippable.
- AGREE: dependency graph is accurate and useful.
- OBJECT (minor): US3 is composite (crossword + word-search + comics + xkcd
fetch/embed) and deserves an explicit note that it may need internal
splitting at Delivery Planning if the effort is large; and US5.3 / US9's
per-article boundary should be made explicit in the ACs so implementers
don't underestimate them.
@@ -0,0 +1,31 @@
**Collaborator:** aidlc-quality-agent
## Contribution
Reviewing the story draft for testability of the acceptance criteria.
- The BDD Given/When/Then acceptance criteria are generally well-formed and
each maps to a concrete verifiable outcome. US6, US1, and US5 are the most
testable — they map directly to observable print/layout behavior.
- Gaps in testability worth flagging:
- US2.AC2.1.3 and US7.AC7.1.2 (dynamic metadata) need a clear "observed
changed output" assertion — the criterion reads well but should explicitly
note that the change is verified by re-running generation with new values,
not by any code change.
- US3.AC3.1.4 ("genuine xkcd related to the occasion") is the weakest
criterion — "related" and "funny" are subjective. Recommend the story note
verification as a human-visible check (the couple judges the cartoon before
print) rather than an automated assertion, and keep the technical AC
(embedded locally, AC3.1.5) as the automated one.
- US9's per-article criteria (AC9.1.2–3) are strong — approving one and
revising another maps cleanly to a test.
- Recommend strengthening US3.AC3.1.4 by splitting the subjective "fits the
occasion" judgment to a human gate step, and keeping the verifiable
embed/local AC automated.
## Positions
- AGREE: most ACs are concrete and testable; the layout/print ones are best.
- AGREE: US9's per-article acceptance criteria are well-scoped.
- OBJECT (minor): US3.AC3.1.4 couples a subjective ("related/funny") judgment
with an objective (embedded local) assertion in one criterion; split them so
the human-visible check is separate from the machine-checkable one.
@@ -0,0 +1,16 @@
<!-- INVARIANT: examples are single-line HTML comments so a fresh template parses to total=0 (MEMORY_EMPTY). Do NOT un-comment or split across lines. t100 guards this. -->
> This file is kept up to date automatically while the stage runs. Add observations at the review step, not by editing here directly.
## Interpretations
<!-- example: 2026-05-29T10:14:32Z — chose REST over GraphQL; the consuming team only needs CRUD, revisit if subscriptions land -->
## Deviations
<!-- example: 2026-05-29T10:14:32Z — skipped the optional caching layer the stage prose suggested; the dataset is small enough that it adds risk -->
## Tradeoffs
<!-- example: 2026-05-29T10:14:32Z — picked TDD over BDD this run; the team is unit-first and the domain is well-understood -->
## Open questions
<!-- example: 2026-05-29T10:14:32Z — confirm the retention window with compliance before the next stage hardens the schema -->
2026-09-13T11:40:00Z — Interpretation — Plan: 2 personas, story-per-FR-group, editor-focus, dedicated AI-review group (user answers B,B,B,A)
2026-09-13T11:40:00Z — Tradeoff — Mob contributed 3 minors: designer (empty-state Could-Have), developer (US3 composite + per-article boundary), quality (split subjective/objective in AC3.1.4); all integrated, no mid-stage triage needed
@@ -0,0 +1,55 @@
# Personas
> Two personas affirmed for the wedding newspaper generator (Q1=B). Per the
> plan (Q3=B), the editor/generator flow drives the stories; the reader
> experience is a quality constraint, not a separate story set.
## P1 — The Couple (editor & publisher)
**Role**: The primary user. One (or both) of the newlyweds authors the content,
runs the generator, reviews the AI draft, and prints the newspaper.
**Goals**
- Produce a keepsake newspaper that captures the wedding day, their story, and
their guests' messages in one printed artifact.
- Make it feel like a real newspaper (classic broadsheet, masthead, funnies).
- Keep it private and fully local — nothing about their wedding leaves the machine.
- Generate a whole first pass quickly, then polish individual articles.
**Pain points**
- Time pressure around the wedding — wants drafting accelerated by AI, but
control over each article's final copy.
- Not a developer — needs a simple "drop content in, run, print" flow.
- The fun section (crosswords, comics) must feel hand-crafted for *them*, not
generic.
**Context**: Uses the local Ollama AI (granted `deepseek-v4-flash:cloud`) for
drafts; supplies markdown/txt content, optional photos, and dynamic masthead
metadata per issue.
## P2 — The Guest (reader)
**Role**: The person who receives/flips through the printed newspaper. Not a
user of the generator — a reader of its output. Represented as a quality
constraint on the editor flow (Q3=B).
**Goals**
- Enjoy reading it: clear layout, legible print, natural column flow, no clipped
articles.
- Recognize the couple and the occasion in the content and the cartoon.
- Be able to attempt the crossword and enjoy the comics.
**Pain points**
- Clipped text, broken page breaks, or unreadable small print would ruin the
keepsake.
- A cartoon or comic that feels unrelated to the couple would feel off.
**Context**: Receives the finished, printed A4 newspaper. Their experience is
locked in via print/readability acceptance criteria on the editor stories.
## Persona Relationships & Priority
- P1 (the couple) is the **primary** persona — all stories serve their authoring
flow. This is definitive for this project.
- P2 (the guest) is **secondary**, enforced as quality attributes (legibility,
clean page breaks, content fidelity) on the P1 stories, not as separate
guest-facing stories.
@@ -0,0 +1,181 @@
# User Stories — Wedding Newspaper Generator
> Two personas: **P1 The Couple (editor/publisher)**, **P2 The Guest (reader,
> quality constraint)**. Story-per-FR-group granularity (Q2=B), editor-flow
> focus (Q3=B), dedicated AI per-article-review group (Q4=A). INVEST-compliant,
> BDD acceptance criteria, MoSCoW priority.
## US1 — Multi-page newspaper output (FR1) — Must Have
**As** the couple (P1), **I want** the generator to flow my content across as
many A4 pages as it needs with clean automatic page breaks, **so that** my
newspaper can be as long as the content deserves and prints as a real
multi-page broadsheet.
- **AC1.1.1** — Given content that exceeds one A4 sheet, when I generate and print,
then the output continues onto subsequent sheets with a clean break between pages.
- **AC1.1.2** — Given a long article, when pagination runs, then the break falls at
a section/article boundary, never splitting a single article awkwardly mid-paragraph
unless unavoidable.
- **AC1.1.3** — Given a multi-page issue, when I print, then each page renders page
numbers and running headers/footers correctly and the masthead continues cleanly.
**Dependencies**: none. **INVEST**: Independent (self-contained), Small, Testable.
## US2 — Classic masthead (FR2) — Must Have
**As** the couple (P1), **I want** a classic newspaper masthead with title, date,
issue number, and volume line, **so that** the front page reads as an authentic
broadsheet.
- **AC2.1.1** — Given a generation run, when I supply dynamic masthead metadata
(title, couple names, date, issue, volume), then the front page renders the title
banner.
- **AC2.1.2** — Given the masthead metadata, when the page renders, then a date line,
issue number, and "Volume X" line all appear under the title.
- **AC2.1.3** — Given a new issue with different metadata, when I generate again, then
the masthead reflects the new values without any code change (dynamic, per FR7.5).
**Dependencies**: US7 (dynamic metadata). **INVEST**: Negotiable, Testable.
## US3 — The funnies: crosswords, word puzzles, and comics (FR4, FR5) — Must Have
**As** the couple (P1), **I want** the generator to build crosswords from content I
provide and to place funny comics (including an xkcd-style front-page cartoon tied
to the occasion), **so that** the fun section feels hand-crafted for our wedding,
not generic.
- **AC3.1.1** — Given content I supply (theme words and clues), when I generate, then
a crossword puzzle block renders with a grid, across/down clues, and a solution area.
- **AC3.1.2** — Given the fun section is requested, when I generate, then a word-search /
"find-a-word" puzzle also renders (FR4.4).
- **AC3.1.3** — Given a comic strip is requested, when I generate, then one or more
panels with art and dialogue render and print legibly on A4.
- **AC3.1.4** — Given the front page, when it renders, then a genuine xkcd cartoon
is placed and embedded locally (FR5, machine-checkable: the asset is local, not
a remote URL).
- **AC3.1.5** — Given the couple's review of the cartoon before print, then they
judge whether it fits the occasion and a comic in the fun section is funny before
final render (FR5.2, FR4.4 — human-visible check at the per-article/print review).
- **AC3.1.6** — Given an xkcd is sourced from the real site, when the page is built,
then it is embedded as a local asset so the delivered page remains self-contained
and print-capable offline (FR5.4, NFR4).
**Dependencies**: US1 (print), US7 (content/metadata). **INVEST**: Valuable, Testable.
## US4 — Photos embedded when supplied (FR6, FR7.4) — Must Have
**As** the couple (P1), **I want** photos I supply to be embedded and auto-balanced
into the newspaper columns, **so that** the layout looks natural and, if I supply no
photos, the paper still generates cleanly without them.
- **AC4.1.1** — Given I supply photo files, when I generate, then the photos embed in
the article layout and auto-balance into the column structure without overflowing
the A4 sheet.
- **AC4.1.2** — Given an embedded photo with a caption/credit, when the page renders,
then the caption and credit line render below it.
- **AC4.1.3** — Given I supply no photos, when I generate, then the newspaper renders
cleanly with **no** fabricated or placeholder images (FR7.4).
**Dependencies**: US1. **INVEST**: Independent, Testable.
## US5 — Content ingestion & self-contained output (FR7) — Must Have
**As** the couple (P1), **I want** to drop my markdown/text content in and have the
generator emit one self-contained `newspaper.html`, **so that** I can open it anywhere
from the local filesystem and print it with no server.
- **AC5.1.1** — Given markdown/text content files, when I run the generator, then a
single self-contained `newspaper.html` is produced.
- **AC5.1.2** — Given the generated page, when I open it from `file://` and print, then
it works with zero network requests and no server (NFR3, NFR4).
- **AC5.1.3** — Given the page open locally, when I want to swap in different content,
then I can load it via the native file picker / drag-and-drop without regenerating
(user-granted reads only, NFR5, FR7.3).
**Dependencies**: none. **INVEST**: Independent, Small, Testable.
## US6 — Classic broadsheet aesthetic (NFR8, NFR1, NFR2) — Must Have
**As** the couple (P1), **I want** the newspaper styled as classic broadsheet (black ink
on white/cream, serif headlines/body, column rules) that prints cleanly to A4, **so
that** the keepsake looks authentic and is legible on paper.
- **AC6.1.1** — Given the generated page, when I view it, then the theme is classic
broadsheet: black ink on white/cream, serif headlines and body, column rules (Q5=A).
- **AC6.1.2** — Given the page in the browser, when I choose Print → A4, then every
section, image, and puzzle stays inside the sheet with no clipping, orphaned columns,
or broken page breaks (NFR1, NFR2).
- **AC6.1.3** — Given the print CSS, when content is present, then margins render
correctly and the page uses sensible A4 print margins (NFR1).
**Dependencies**: US1. **INVEST**: Testable.
## US7 — Dynamic issue metadata (FR7.5, OQ3) — Must Have
**As** the couple (P1), **I want** issue metadata (title, couple names, date, issue
number, volume) to be supplied at generation time, **so that** each new issue is
produced without editing code.
- **AC7.1.1** — Given metadata supplied per issue, when I generate, then the masthead
and issue identity use those values.
- **AC7.1.2** — Given a second issue with different metadata, when I generate, then the
output reflects the new values with no code changes.
**Dependencies**: none. **INVEST**: Independent, Small, Testable.
## US8 — AI copy generation via local Ollama (FR8.1–3) — Must Have
**As** the couple (P1), **I want** the generator to draft newspaper copy using local
Ollama (`deepseek-v4-flash:cloud`), **so that** the initial article draft is
accelerated while all content stays on-machine.
- **AC8.1.1** — Given local Ollama is available, when I ask for a draft, then the
generator drafts the lead story and filler articles through the local model.
- **AC8.1.2** — Given a draft is produced, when it is used, then it flows through the
same layout pipeline exactly as hand-written content (FR8.2).
- **AC8.1.3** — Given generation, when AI runs, then **no** content is sent to an
external/cloud service (only local Ollama) (FR8.3, NFR9).
**Dependencies**: US5 (content pipeline). **INVEST**: Valuable, Testable.
## US9 — Per-article human review of AI drafts (FR8.4, OQ4) — Must Have
**As** the couple (P1), **I want** the generator to produce a whole first-pass
newspaper and then let me approve, edit, or replace any single article's copy,
**so that** I keep final control over what goes to print.
- **AC9.1.1** — Given a full first-pass AI newspaper, when generation completes, then
the run stops for per-article review.
- **AC9.1.2** — Given a reviewed article I approve, when it stays in, then its copy is
unchanged while others may still be revised.
- **AC9.1.3** — Given an article I want changed, when I request an edit, then only that
article's copy is revised and re-rendered; approved articles stay unchanged.
- **AC9.1.4** — Given an article I want replaced, when I supply new copy, then the new
content replaces the draft for that article while the rest of the paper is untouched.
- **AC9.1.5** — Given an AI draft was produced, when it is reviewed, then each
article is addressable as its own unit (an article-level data boundary), so any
single article can be approved, edited, or replaced independently (FR8.4).
**Dependencies**: US8 (AI drafts). **INVEST**: Independent, Negotiable, Valuable.
## US10 — Friendly first-run / empty state (design refinement) — Could Have
**As** the couple (P1), **I want** the generator to show a clear, friendly state
when I have no content yet, **so that** my first launch isn't a blank or broken page.
- **AC10.1.1** — Given no content provided, when I run/generate, then the page shows a
short, friendly empty-state message and guidance rather than a blank page.
- **AC10.1.2** — Given I then add content, when I generate again, then the full
newspaper renders normally.
**Dependencies**: US5. **INVEST**: Independent, Small, Testable.
## Won't Have (explicitly out)
- W1 — No remote deployment or hosting of the newspaper.
- W2 — No cloud/external AI.
- W3 — No dynamic server-side rendering service.
- W4 — No full WYSIWYG editor UI.
<!-- finalized-after-confirm -->
@@ -0,0 +1,23 @@
{
"stage": "user-stories",
"upstream_ids": ["FR1", "FR2", "FR3", "FR4", "FR5", "FR6", "FR7", "FR8", "NFR1", "NFR2", "NFR3", "NFR4", "NFR5", "NFR6", "NFR7", "NFR8", "NFR9"],
"coverage": [
{ "id": "FR1", "status": "OK", "target": "US1" },
{ "id": "FR2", "status": "OK", "target": "US2" },
{ "id": "FR3", "status": "OK", "target": "US5, US6" },
{ "id": "FR4", "status": "OK", "target": "US3" },
{ "id": "FR5", "status": "OK", "target": "US3" },
{ "id": "FR6", "status": "OK", "target": "US4" },
{ "id": "FR7", "status": "OK", "target": "US5, US7" },
{ "id": "FR8", "status": "OK", "target": "US8, US9" },
{ "id": "NFR1", "status": "OK", "target": "US6" },
{ "id": "NFR2", "status": "OK", "target": "US6" },
{ "id": "NFR3", "status": "OK", "target": "US5" },
{ "id": "NFR4", "status": "OK", "target": "US3, US5" },
{ "id": "NFR5", "status": "OK", "target": "US5" },
{ "id": "NFR6", "status": "OK", "target": "US5" },
{ "id": "NFR7", "status": "OK", "target": "US5" },
{ "id": "NFR8", "status": "OK", "target": "US6" },
{ "id": "NFR9", "status": "OK", "target": "US8" }
]
}
@@ -0,0 +1,34 @@
# User Stories Assessment
## Decision
**Execute**
## Rationale
User stories add clear value for the wedding newspaper generator. The tool has
multiple distinct user roles with different goals (the couple as editor/publisher,
guests reading/recalling, and the couple as the keepsake owners), user-facing
features throughout, and enough surface area — multi-page layout, the "funnies"
section, crosswords built from content, photo embedding, an AI draft-then-review
loop — that story-level framing improves both scope control and testability well
beyond the flat FR list.
## Factors Considered
- **Project type**: Greenfield user-facing application (a generator + printed artifact).
- **User-facing scope**: High — every feature is user-authored content rendered for a reader.
- **Complexity signals**: Multi-persona (couple/editor, guest reader), multi-page print
layout, puzzle generation from arbitrary content, optional AI pipeline with
per-article review. These need story-level acceptance criteria.
- **Cross-team work**: Internal (design/developer/quality alignment on the layout
and content flow); no external coordination but the mob adds value here.
## Key Areas Where Stories Add the Most Value
1. Authoring and content ingestion (markdown/txt → newspaper sections).
2. The multi-page print behaviour and A4 fidelity (the hardest acceptance surface).
3. The "funnies" section (crosswords built from user content, comics, xkcd cartoon).
4. Photo handling (embedded when supplied, clean when absent).
5. The optional AI draft + per-article human review loop.
6. Dynamic masthead metadata per issue.
## Alternative Coverage if Skipped
Not applicable — the requirements alone are insufficiently testable; this stage
provides the BDD Given/When/Then acceptance criteria that later stages need.
@@ -0,0 +1,77 @@
# User Stories — Story Plan & Questions
> Fill in each `[Answer]:` tag. Options A-E plus X (Other). The file is the
> authoritative record of your story-planning decisions.
## Story Plan Summary
- **Persona development approach**: draft three personas based on the
requirements (the couple-as-editor, the couple-as-keepsake-owners, and the
guest reader), refined here by your answer.
- **Story format**: INVEST (Independent, Negotiable, Valuable, Estimable,
Small, Testable), BDD Given/When/Then acceptance criteria, stable IDs.
- **Prioritization**: MoSCoW (Must / Should / Could / Won't Have) per story.
- **Breakdown approach**: by feature area with story groups aligned to the
FR groups in `requirements.md`.
## Q1: Persona depth
How thoroughly should we define the personas for this project?
A) Three personas (couple-as-editor, couple-as-keepsake-owner, guest reader), each with goals, pain points, and context (recommended)
B) Two personas (the couple, the guest) — keep it lean for a self-contained local tool
C) The couple is the only real persona; guests are implicit readers, not a separate persona
X) Other (please specify)
[Answer]: B
## Q2: Story granularity
How granular should the stories be?
A) Story per FR sub-requirement where meaningful (e.g. one story for "crossword built from user content", one for "xkcd front-page cartoon") — moderately fine-grained (recommended)
B) Story per FR group (fewer, larger stories — e.g. one story covering all of "the funnies")
C) Coarse — a handful of high-level epic stories, expanded later
X) Other (please specify)
[Answer]: B
## Q3: Guest-reader focus
How much weight should the guest-reading experience carry in story definition?
A) Treat guest-reader stories as first-class (printing legibility, nostalgia, easy flipping) alongside the editor flow (recommended)
B) Focus stories on the editor/generator flow; treat reader experience as a quality constraint, not separate stories
C) Reader experience is the whole point — lead with it, editor stories secondary
X) Other (please specify)
[Answer]: B
## Q4: AI-review loop story
The AI draft-then-per-article-review loop (FR8.4) is a notable piece of work. How should we represent it?
A) A dedicated Must-Have story group with an acceptance criterion per mechanism (approve / edit / replace per article) (recommended)
B) Fold it into the general AI-draft story as a Should-Have; the per-article review is a detail, not its own group
C) Keep it explicit but mark it Could-Have if time is tight
X) Other (please specify)
[Answer]: A
## Consolidated Summary Confirmation
> Summary of the four story-plan answers and the plan that follows, before the
> stories and personas artifacts are finalized:
>
> - Persona depth: **two personas** — the couple, and the guest-as-reader (Q1=B)
> - Story granularity: **story per FR group**, fewer larger stories (Q2=B)
> - Guest-reader focus: **editor/generator flow leads**; reader experience is a quality constraint (Q3=B)
> - AI per-article review loop: **dedicated Must-Have story group** (Q4=A)
> - Resulting plan: US1–US9 Must-Have (+ US10 Could-Have empty-state), BDD acceptance criteria, MoSCoW priority, full FR/NFR traceability
Does this all look correct before I finalize the stories and personas artifacts?
- Looks correct
- Request changes
[Answer]: Looks correct