# Provenance: Derived vs. Questionnaire-Answered Fields A requirement surfaced from the "Upgrading `/impeccable init`" landscape doc: the new visual document seed (chat asset/reference upload + local-browser slides for Color, Typography, Motion, Layout, Elevation, Iconography) must be **resettable**. A user can go back and redo one slide (e.g. Iconography) or the whole seed, without disturbing fields that came from somewhere else. Everything that isn't scanned off code is a **questionnaire answer** in the broad sense — nothing in `PRODUCT.md` or `DESIGN.md` is invented by the agent unprompted. But "questionnaire" isn't one thing: it happens through different commands and different UIs (chat vs. a local-browser slide). "Planned" vs. "already shipped" is a maturity detail on the specific field (called out in that field's `Value`/`Derived from` columns in [`CONTENTS-TABLE.md`](./CONTENTS-TABLE.md)), not a different provenance category — the new seed flow's chat portion is more of the same `init.md`/`document.md`-style chat interview, just under `document.md`; its browser portion is more of the same card-UI pattern the Layout-strictness slide already uses today. So provenance is four tags, not seven: - **Derived** — read directly off existing code (scanned CSS tokens, component classes). Changing it means re-scanning, not re-asking. - **Questionnaire — In-chat (init)** — `PRODUCT.md` fields, asked in chat during `/impeccable init`'s Step 3. Today's mechanism for every non-Derived `PRODUCT.md` field (Users, Purpose, Positioning, Brand Personality, Anti-references, Conversion & proof, Design Principles, Accessibility). Free-form, not persisted for reset. - **Questionnaire — In-chat (document)** — `DESIGN.md` fields asked in chat during `document.md`. Covers both today's qualitative round (North Star name, color role names/strategy, elevation/component feel, signature-component ideas) and the new seed flow's chat portion (asset/logo/moodboard upload, three named references, one named anti-reference, the image-gen capability check). Free-form, not persisted for reset — except where the new seed work adds persistence (see below). - **Questionnaire — Browser (document)** — `DESIGN.md` fields asked through a visual card UI during `document.md`. Covers both today's shipped Layout-strictness slide (Simple grid / Balanced / Editorial / Freeform) and the new seed flow's browser slides (Color amount, Visual cues, Palette tokens, Typography, Motion, Layout, Elevation, Iconography). - **Computed** — generated by the agent from other values (tonal ramps, breakpoints, HTML/CSS snippets). Never directly asked at all. The persisted/resettable mechanism below is in scope only for the **new, not-yet-shipped fields** within `Browser (document)` and `In-chat (document)` — i.e. the fields `CONTENTS-TABLE.md` marks `(planned)`. The fields already shipped under those same two tags (today's qualitative round, today's Layout-strictness slide) aren't persisted and stay that way unless retrofitted — see [`MISSING.md`](./MISSING.md) and open question #1 below. ## Where it's stored In `design.json`, not inline in `DESIGN.md`. `DESIGN.md` stays a clean, human-readable artifact; `design.json` is already the structured sidecar other tooling reads (`colorMeta`, `typographyMeta`, `shadows`, `motion`, `breakpoints`, `components`, `narrative`), so provenance belongs next to it, not as HTML comments scattered through the markdown. ## Proposed schema addition Two changes to `design.json`: **1. A `source` tag on existing per-field metadata**, so a value's provenance travels with it: ```json "extensions": { "colorMeta": { "dusty-plum": { "role": "primary", "source": "crawl" } }, "typographyMeta": { "display": { "source": "questionnaire" } } } ``` Values: `"crawl"`, `"chat-init"`, `"chat-document"`, `"browser-document"`, `"computed"`. A field's `(planned)` status (i.e. whether it's part of the new, not-yet-shipped seed work) is tracked by whether it has a `questionnaire.sections` entry at all, not by a separate source value — see the block below. **2. A top-level `questionnaire` block** — the actual answer log, keyed by slide/section, needed for reset at either granularity: ```json "questionnaire": { "version": 1, "lastRunAt": "2026-07-09T22:40:00.000Z", "sections": { "assets": { "status": "answered", "answeredAt": "...", "answers": { "logos": [], "referenceImages": [], "moodboards": [] }, "producedPaths": [] }, "references": { "status": "answered", "answeredAt": "...", "answers": { "named": ["Kinfolk", "Cereal"] }, "producedPaths": ["narrative.overview"] }, "antiReference": { "status": "answered", "answeredAt": "...", "answers": { "named": "Squarespace wedding-florist template" }, "producedPaths": ["narrative.donts"] }, "color": { "status": "answered", "answeredAt": "...", "answers": { "amount": "restrained", "visualCue": "...", "paletteTokens": {"...": "..."} }, "producedPaths": ["extensions.colorMeta"] }, "typography": { "status": "answered", "answeredAt": "...", "answers": { "fontPair": "Shippori Mincho / Source Sans 3", "typeDirection": "editorial" }, "producedPaths": ["extensions.typographyMeta"] }, "motion": { "status": "answered", "answeredAt": "...", "answers": { "easing": "ease-standard", "duration": "150ms", "animationType": "crossfade" }, "producedPaths": ["extensions.motion"] }, "layout": { "status": "answered", "answeredAt": "...", "answers": { "radii": "square", "spacingStrategy": "fluid", "boundaryStyle": "position/distance" }, "producedPaths": ["rounded", "spacing"] }, "elevation": { "status": "answered", "answeredAt": "...", "answers": { "shadowSystem": "flat-by-doctrine" }, "producedPaths": ["extensions.shadows"] }, "iconography": { "status": "answered", "answeredAt": "...", "answers": { "pack": "Lucide" }, "producedPaths": ["extensions.iconography"] } } } ``` `producedPaths` is what makes reset safe: it tells the reset routine exactly which `design.json`/`DESIGN.md` fields that section's answer wrote to, so redoing one slide only touches those paths and leaves everything else (crawl-derived or answered in a different slide) untouched. ## Reset, both granularities - **Whole-flow reset**: clear all `questionnaire.sections`, re-run the seed from the assets/references chat step through every browser slide, same as a first-time seed. - **Per-section reset**: user says "redo iconography" (or picks it from a menu). Agent reads `questionnaire.sections.iconography.answers` to show what was previously picked, lets the user redo just that slide, and overwrites only `producedPaths` for that section — no re-scan, no touching Color/Typography/etc. - **Fields with `source: "crawl"`**: not resettable through this mechanism at all. Changing them means re-running `/impeccable document`'s scan (Step 1-2), or a manual code edit. The questionnaire reset flow should refuse to "reset" a crawl-derived field and say so. ## Open questions 1. **Scope**: this spec covers the new, not-yet-shipped fields within `In-chat (document)` and `Browser (document)` only. Should the fields already shipped under those same two tags (today's qualitative round, today's Layout-strictness slide), plus all of `In-chat (init)`, get the same persisted/resettable treatment eventually, so *all* of `PRODUCT.md`/`DESIGN.md` becomes resettable, not just the new seed's slice? That's a bigger lift — it touches `init.md`'s chat rounds too, and it would mean retrofitting a `questionnaire.sections` entry for flows that already shipped without one. 2. **Drift after manual edits**: if a user hand-edits a questionnaire-sourced value directly in `DESIGN.md` after the seed ran, does `source` flip to a fourth state (`"manual"`), or does the stale `questionnaire.sections` entry silently go out of sync with the doc? Needs a decision before reset ships, or resets could clobber a deliberate manual change. 3. **Existing repos with `design.json` but no `questionnaire` block** (every file generated before this ships): reset should degrade gracefully — treat missing `questionnaire` as "nothing resettable yet, only a fresh full seed is available" rather than erroring. 4. **`producedPaths` granularity**: paths above are section-level (e.g. `extensions.colorMeta`). If two slides ever write into the same object (unlikely given the current slide breakdown, but worth checking against the final slide list), path-level conflicts need a tie-break rule.