This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
<!-- 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-13T12:10:00Z — Interpretation — Confirmed decomposition (all A, self-guided + user pre-approved continuation): one coarse unit per component (generator/ai-draft/funnies), defined interfaces (DraftBundle JSON handoff), embedded/static single deliverable
|
||||
2026-09-13T12:10:00Z — Interpretation — DAG: generator depends on ai-draft + funnies; ai-draft and funnies are independent (parallel buildable); acyclic
|
||||
2026-09-13T12:15:00Z — Interpretation — Human ruling on review R-01: U1 is a library-backed one-shot local tool, never a service/server. Retagged U1 kind service→library in unit-of-work.md + dependency edge block.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"stage": "units-generation",
|
||||
"upstream_ids": ["US1", "US2", "US3", "US4", "US5", "US6", "US7", "US8", "US9", "US10"],
|
||||
"coverage": [
|
||||
{ "id": "US1", "status": "OK", "target": "U1" },
|
||||
{ "id": "US2", "status": "OK", "target": "U1" },
|
||||
{ "id": "US3", "status": "OK", "target": "U3" },
|
||||
{ "id": "US4", "status": "OK", "target": "U1" },
|
||||
{ "id": "US5", "status": "OK", "target": "U1" },
|
||||
{ "id": "US6", "status": "OK", "target": "U1" },
|
||||
{ "id": "US7", "status": "OK", "target": "U1" },
|
||||
{ "id": "US8", "status": "OK", "target": "U2" },
|
||||
{ "id": "US9", "status": "OK", "target": "U2, U1" },
|
||||
{ "id": "US10", "status": "OK", "target": "U1" }
|
||||
]
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# Units Generation — Unit Dependency DAG
|
||||
|
||||
> Topology only. Describes what can depend on what; the economic build path
|
||||
> (Bolt sequence) is decided in Delivery Planning (Stage 2.9).
|
||||
|
||||
## Dependency Graph
|
||||
|
||||
```
|
||||
generator ──depends on──▶ ai-draft (optional AI draft, invoked by the CLI)
|
||||
generator ──depends on──▶ funnies (funnies output, invoked during layout)
|
||||
ai-draft (no dependencies)
|
||||
funnies (no dependencies)
|
||||
```
|
||||
|
||||
U2 and U3 are independent libraries the U1 CLI orchestrates. There is no
|
||||
dependency edge between U2 and U3; they never call each other. The graph is acyclic.
|
||||
|
||||
## Integration Points
|
||||
|
||||
| From | To | Integration | Style |
|
||||
|---|---|---|---|
|
||||
| generator | ai-draft | CLI invokes optional Ollama draft (`--draft`); receives DraftBundle article set | sync |
|
||||
| generator | funnies | CLI asks for crossword/find-a-word/cartoon built from content theme words + context | sync |
|
||||
| generator → review page | — | writes DraftBundle JSON; review page reads it via native file picker (ADR-004, NFR5) — data artifact, not a call | file |
|
||||
|
||||
## Parallel Development Opportunities
|
||||
|
||||
U2 and U3 are fully independent of each other (no dependency edge), so they can
|
||||
be built (and reviewed) in parallel. U1 depends on both and can be built in
|
||||
parallel with them up to the integration seams; the DAG admits multiple valid
|
||||
topological orders. The economic choice of which Bolt ships first is Delivery
|
||||
Planning's call, not this stage's.
|
||||
|
||||
## Machine-readable edge block
|
||||
|
||||
```yaml
|
||||
units:
|
||||
- name: "generator"
|
||||
kind: library
|
||||
depends_on: ["ai-draft", "funnies"]
|
||||
- name: "ai-draft"
|
||||
kind: library
|
||||
depends_on: []
|
||||
- name: "funnies"
|
||||
kind: library
|
||||
depends_on: []
|
||||
```
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
# Units Generation — Unit-of-Work Story Map
|
||||
|
||||
> Every user story mapped to the unit that implements it. Cross-cutting stories
|
||||
> are flagged. Coverage: every story assigned; every unit has stories.
|
||||
|
||||
## Story → Unit Map
|
||||
|
||||
| Story | Unit | Unit Directory | Notes |
|
||||
|---|---|---|---|
|
||||
| US1 — Multi-page newspaper output | U1 generator | u1-generator | layout + pagination |
|
||||
| US2 — Classic masthead | U1 generator | u1-generator | masthead render |
|
||||
| US3 — Funnies (crossword/comics/xkcd) | U3 funnies | u3-funnies | puzzle + cartoon build |
|
||||
| US4 — Photos embedded | U1 generator | u1-generator | photo embed + auto-balance |
|
||||
| US5 — Content ingestion & self-contained output | U1 generator | u1-generator | content parse + emit |
|
||||
| US6 — Classic broadsheet aesthetic | U1 generator | u1-generator | print CSS/theme |
|
||||
| US7 — Dynamic issue metadata | U1 generator | u1-generator | MastheadConfig/Issue |
|
||||
| US8 — AI copy via local Ollama | U2 ai-draft | u2-ai-draft | local draft |
|
||||
| US9 — Per-article human review of AI drafts | U2 ai-draft (DraftBundle) + U1 generator (review handoff/file-picker) | u2-ai-draft, u1-generator | cross-cutting: draft data + review page handoff |
|
||||
| US10 — Friendly first-run / empty state | U1 generator | u1-generator | empty-state |
|
||||
|
||||
## Cross-cutting stories
|
||||
|
||||
- **US9** spans U2 (produces the DraftBundle) and U1 (writes + hand off the
|
||||
bundle to the review page via the native file picker). The per-article
|
||||
review contract lives with U2; the file-picker read handoff lives with U1.
|
||||
|
||||
## Story implementation order (within each unit)
|
||||
|
||||
- **U1 generator** (natural build order): US7 (metadata) → US2 (masthead) →
|
||||
US5 (ingestion/emit) → US6 (aesthetic) → US1 (multi-page) → US4 (photos) →
|
||||
US10 (empty state) → US9-handoff (review page data path).
|
||||
- **U2 ai-draft**: US8 (local Ollama draft) → US9 (DraftBundle + per-article
|
||||
review contract).
|
||||
- **U3 funnies**: US3 (crossword → find-a-word → comics → cartoon embed).
|
||||
|
||||
> Implementation *ordering* shown here is a suggested construction sequence
|
||||
> within each unit; the economic Bolt order across units is Delivery Planning's
|
||||
> decision (2.9).
|
||||
|
||||
## Coverage verification
|
||||
|
||||
- Every story (US1–US10) is assigned to one or more units.
|
||||
- Every unit has at least one story: U1 → US1,2,4,5,6,7,9(handoff),10; U2 →
|
||||
US8,9; U3 → US3.
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
# Units Generation — Unit of Work
|
||||
|
||||
> Unit decomposition per confirmed answers (Q1–Q4 = A): one coarse unit per
|
||||
> component (`generator`, `ai-draft`, `funnies`), defined internal interface
|
||||
> boundaries (DraftBundle JSON as the review handoff), embedded/static single
|
||||
> local deliverable. This stage produces the dependency DAG (topology) only;
|
||||
> economic build ordering is decided in Delivery Planning.
|
||||
|
||||
## Unit Definitions
|
||||
|
||||
| Unit ID | Directory | Unit | Kind | Complexity |
|
||||
|---|---|---|---|---|
|
||||
| U1 | `u1-generator` | Generator | library (one-shot local CLI tool, not a deployable/server) | L |
|
||||
| U2 | `u2-ai-draft` | AiDraft | library (optional, no standalone runtime) | M |
|
||||
| U3 | `u3-funnies` | Funnies | library (no standalone runtime) | M |
|
||||
|
||||
**Deployment model per unit:** embedded/static — one `newspaper` command plus
|
||||
templates, all bundled into a single local deliverable. U2 and U3 are libraries
|
||||
the U1 CLI invokes; there is no separate deployable. Per the human ruling on
|
||||
architecture-review R-01 (2026-09-13): U1 is a **library-backed one-shot local
|
||||
tool**, never run as a service or server.
|
||||
|
||||
## Unit Responsibilities
|
||||
|
||||
### U1 — generator (kind: library)
|
||||
|
||||
- Owns the `newspaper` CLI entry point and the full build orchestrator.
|
||||
- Is a one-shot local library-backed tool — never run as a service or server
|
||||
(human ruling on review R-01).
|
||||
- Reads + validates `config.json` (masthead metadata) and the `content/` folder.
|
||||
- Parses markdown/txt into `Article` entities; owns the classic broadsheet
|
||||
layout model, multi-page A4 pagination with clean page breaks, article/section
|
||||
placement, and masthead rendering (US1, US2, US4, US5, US6, US7, US10).
|
||||
- Assembles the funnies section output produced by U3.
|
||||
- Writes the AI-draft `DraftBundle` JSON for the review page handoff (US9).
|
||||
- Emits the self-contained zero-network `newspaper.html`, openable via
|
||||
`file://` and printable to A4.
|
||||
- Owns entities: Issue, Article, MastheadConfig, DraftBundle.
|
||||
|
||||
### U2 — ai-draft (kind: library)
|
||||
|
||||
- Optional local-Ollama copy drafting (US8, US9).
|
||||
- Talks only to local Ollama (granted model `deepseek-v4-flash:cloud`); never
|
||||
contacts any external/cloud service; content stays on-machine (NFR9).
|
||||
- Produces the `DraftBundle` (article set) for per-article review.
|
||||
- Fully optional — when `--draft` is absent it does nothing.
|
||||
|
||||
### U3 — funnies (kind: library)
|
||||
|
||||
- Builds the "fun" section from the content itself (US3, FR4, Q5=X).
|
||||
- Derives theme words + context from content; produces the crossword grid +
|
||||
across/down clues, a find-a-word grid, and selects/embeds an xkcd-style cartoon
|
||||
using content-derived context. A build-time network fetch to enrich content is
|
||||
allowed (human ruling 2026-09-13); the EMITTED page makes zero network
|
||||
requests. Falls back to a tasteful content-derived strip if no cartoon found.
|
||||
- Emits A4-printable, self-contained puzzle/comic blocks.
|
||||
- Owns entity: Puzzle.
|
||||
|
||||
## Implementation Notes / Constraints per Unit
|
||||
|
||||
- **U1**: must keep the emitted page file://-printable and zero-network
|
||||
(NFR1–NFR6). Review-page handoff: the per-article review page reads the
|
||||
DraftBundle via the native file picker (not fetch of siblings) (NFR5, ADR-004).
|
||||
- **U2**: local-only; must never leak content off-machine (NFR9, ADR-002). The
|
||||
granted model is `deepseek-v4-flash:cloud`.
|
||||
- **U3**: puzzle heuristics handle a no-cartoon fallback deterministically
|
||||
(mockups R-02 / domain-design R-01 resolution). A build-time internet fetch to
|
||||
enrich content is fine; the shipped page stays self-contained (human ruling).
|
||||
|
||||
## Deployment Model
|
||||
|
||||
Embedded/static (Q4=A): all three units bundle into single local deliverable
|
||||
(`newspaper` CLI + templates). No servers, no independent deploys, never
|
||||
published beyond localhost.
|
||||
|
||||
<!-- units-after-confirm -->
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Units Generation — Questions
|
||||
|
||||
> Fill in each `[Answer]:` tag. Options A-E plus X (Other). The file is the
|
||||
> authoritative record of your unit-decomposition decisions.
|
||||
|
||||
## Q1: Unit boundary strategy
|
||||
|
||||
How should the build units be drawn from the three components (Generator, AiDraft, Funnies)?
|
||||
|
||||
A) One unit per component: `generator`, `ai-draft`, `funnies` — each is a separately buildable piece (recommended; clean mapping to Domain Design)
|
||||
B) One single unit containing all three components (coarse — simplest, one deliverable)
|
||||
C) Split finer: e.g. `layout`, `render`, `content-loader`, `puzzle-gen`, `cartoon` sub-units
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]: A
|
||||
|
||||
## Q2: Unit granularity
|
||||
|
||||
How fine-grained should the units be at build time?
|
||||
|
||||
A) Coarse — a handful of units corresponding to the components (3 units) (recommended for a small local tool)
|
||||
B) Fine-grained — split each component into smaller buildable pieces for maximum reuse/testing granularity
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]: A
|
||||
|
||||
## Q3: Integration points / contracts
|
||||
|
||||
How should the units share data and integrate (the contracts between them)?
|
||||
|
||||
A) A shared internal interface/module boundary per component (Generator calls AiDraft and Funnies via defined entry points; the DraftBundle JSON is the review handoff contract) (recommended)
|
||||
B) Loose — units communicate only through files on disk, no shared code interface
|
||||
C) A package-manager-style library dependency (one unit imports another as a package)
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]: A
|
||||
|
||||
## Q4: Deployment model
|
||||
|
||||
For this fully-local tool, what deployment shape should the units take?
|
||||
|
||||
A) Embedded/static — one `newspaper` command + templates, all bundled; single local deliverable (recommended, matches CLI-first file-only posture)
|
||||
B) Split executables that each run independently (no benefit here, but if preferred)
|
||||
C) Library + thin CLI wrapper (the generator logic as a reusable library, plus a thin `newspaper` script)
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]: A
|
||||
|
||||
## Consolidated Summary Confirmation
|
||||
|
||||
> Summary of your four decomposition answers before the unit artifacts are generated:
|
||||
>
|
||||
> - Boundary strategy: **one unit per component** — `generator`, `ai-draft`, `funnies` (Q1=A)
|
||||
> - Granularity: **coarse** — 3 units corresponding to the components (Q2=A)
|
||||
> - Integration/contracts: **defined internal interface boundaries**; the DraftBundle JSON is the review handoff contract (Q3=A)
|
||||
> - Deployment: **embedded/static** — one `newspaper` command + templates, single local deliverable (Q4=A)
|
||||
>
|
||||
> Plan approval: the human pre-approved the decomposition plan (answers recorded via the file, self-guided mode).
|
||||
|
||||
Does this all look correct before I generate the unit artifacts?
|
||||
|
||||
- Looks correct
|
||||
- Request changes
|
||||
|
||||
[Answer]: Looks correct
|
||||
Reference in New Issue
Block a user