This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
<!-- 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-13T13:10:00Z — Interpretation — funnies NFR mirrors ai-draft (human: same questions/answers): moderate latency, strict isolation (cartoon fetch only), graceful fallback, light logging, plain Python+uv. Library unit -> security + tech-stack only.
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
# NFR Requirements — Questions (unit: funnies)
|
||||
|
||||
> Fill in each `[Answer]:` tag. Options A-E plus X (Other). The file is the
|
||||
> authoritative record of the funnies unit's NFR targets.
|
||||
|
||||
## Q1: Puzzle generation performance
|
||||
|
||||
The funnies unit builds a 10×10 crossword + find-a-word (AI-drafted clues) and embeds a cartoon. How long may the funnies build take?
|
||||
|
||||
A) Relaxed — some seconds for puzzle layout + cartoon fetch; no strict latency SLA (local one-shot generation) (recommended)
|
||||
B) Moderate — aim for under several seconds, log if slower
|
||||
C) Strict — hard timeout with fallback
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Q2: Content privacy / security posture
|
||||
|
||||
funnies may fetch a cartoon/comic from the internet at build time (sanctioned content-enrichment). What security posture applies to the fetch?
|
||||
|
||||
A) Allow the real xkcd/selected source fetch ONLY — no data other than the context search query leaves; fetched assets are embedded locally and the emitted page stays local (recommended)
|
||||
B) Strict — no internet fetch, only local/generated cartoons
|
||||
C) Allow broader enrichment but log every external fetch for review
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Q3: Reliability / graceful degradation
|
||||
|
||||
When the cartoon fetch or puzzle build fails (already: graceful fallback), how should reliability be handled?
|
||||
|
||||
A) Best-effort with graceful fallback — a tasteful placeholder/empty funnies result, the paper builds without that piece, clear message (recommended)
|
||||
B) Retry the fetch a bounded number of times before falling back
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Q4: Observability
|
||||
|
||||
How much logging does the local funnies unit need?
|
||||
|
||||
A) Light — a concise log per section build (crossword/find-a-word/cartoon status + fallback triggers) enough to debug locally (recommended)
|
||||
B) More — per-puzzle duration + fetch logs
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Q5: Tech stack
|
||||
|
||||
Any constraints on the funnies tech stack (Python + uv)?
|
||||
|
||||
A) Plain Python + uv, minimal deps — stdlib for layout/grid, a thin HTTP client only for the allowed cartoon/comic fetch (recommended)
|
||||
B) Add a puzzle-generation library to simplify layout
|
||||
X) Other (please specify)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Consolidated Summary Confirmation
|
||||
|
||||
> Summary of the five funnies NFR answers (mirror ai-draft, human-approved):
|
||||
>
|
||||
> - Puzzle perf: moderate (Q1=B)
|
||||
> - Fetch/security: strict isolation, only cartoon fetch query leaves, assets embedded locally (Q2=A)
|
||||
> - Reliability: best-effort graceful fallback (Q3=A)
|
||||
> - Observability: light logging (Q4=A)
|
||||
> - Tech stack: plain Python + uv, thin HTTP client only (Q5=A)
|
||||
>
|
||||
> Human auto-approved (same answers as ai-draft recorded in the file).
|
||||
|
||||
Does this all look correct before I generate the unit artifacts?
|
||||
|
||||
- Looks correct
|
||||
- Request changes
|
||||
|
||||
[Answer]: Looks correct
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# NFR Requirements — Security (unit: funnies)
|
||||
|
||||
## NFR9.1 — Allowed internet fetch only for the cartoon/comic (MUST)
|
||||
- **Target** — The real-xkcd / selected-source fetch is the ONE allowed external call for this unit. Only the context-search query leaves; no secrets/credentials/wedding content beyond the cartoon-search context is transmitted. Fetched assets are embedded locally and the emitted page stays fully local + zero-network (NFR4).
|
||||
- **Rationale** — Confirmed Q2=A; content-enrichment is allowed but scoped to the cartoon fetch only.
|
||||
|
||||
## NFR9.2 — No secrets / credentials embedded (MUST)
|
||||
- No API keys, tokens, or private data are hard-coded or logged.
|
||||
|
||||
## NFR9.3 — Local-only elsewhere (MUST)
|
||||
- Puzzle layout (crossword/find-a-word) is purely local; the emitted page makes zero network requests (NFR4).
|
||||
|
||||
## Threat considerations (advisory)
|
||||
- The cartoon fetch is the exposure surface; scope the query to the search context only, embed the result locally, and never resolve remote URLs at print (NFR4).
|
||||
|
||||
<!-- nfr funnies after-confirm -->
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# NFR Requirements — Tech Stack Decisions (unit: funnies)
|
||||
|
||||
## Decisions
|
||||
| Choice | Decision | Rationale |
|
||||
|---|---|---|
|
||||
| Language | **Python** | Matches the Python + uv generator tool. |
|
||||
| Runtime | **uv** | The affirmed primary runtime. |
|
||||
| Fetch client | **Thin HTTP client** | For the allowed cartoon/comic fetch only (Q2/Q5=A). |
|
||||
| Puzzle layout | **stdlib** | Crossword/find-a-word grid layout in stdlib; no heavy puzzle lib (Q5=A). |
|
||||
| Dependencies | **Minimal** | Only the thin HTTP client for the sanctioned fetch (Q5=A). |
|
||||
|
||||
## Non-decisions (per produces_kinds)
|
||||
- No DB; no framework (library unit).
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"stage": "nfr-requirements",
|
||||
"unit": "funnies",
|
||||
"upstream_ids": ["NFR1", "NFR2", "NFR3", "NFR4", "NFR5", "NFR6", "NFR7", "NFR8", "NFR9"],
|
||||
"coverage": [
|
||||
{ "id": "NFR1", "status": "N/A", "target": "printability is the generator/emitted-page responsibility, not the funnies library" },
|
||||
{ "id": "NFR2", "status": "N/A", "target": "layout integrity is the generator layout concern; funnies emits bounded self-contained blocks" },
|
||||
{ "id": "NFR3", "status": "OK", "target": "NFR9.3" },
|
||||
{ "id": "NFR4", "status": "OK", "target": "NFR9.1, NFR9.3 (the cartoon fetch is the sanctioned network exception; emitted page zero-network)" },
|
||||
{ "id": "NFR5", "status": "N/A", "target": "content-read policy applies to the generator/review-page file-picker" },
|
||||
{ "id": "NFR6", "status": "N/A", "target": "pure dependency-free RENDER is a generator/emitted-page property; funnies uses a thin client only" },
|
||||
{ "id": "NFR7", "status": "N/A", "target": "markdown fidelity is the generator transform's concern" },
|
||||
{ "id": "NFR8", "status": "N/A", "target": "broadsheet aesthetic is a generator/design-system concern" },
|
||||
{ "id": "NFR9", "status": "OK", "target": "NFR9.1, NFR9.2, NFR9.3" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user