Seed-ah!
An empty database makes every screenshot, demo and dev session lie — and a
database full of Test User 3 / lorem ipsum / grey SVG placeholders lies
louder. This skill seeds a world that reads as real: locale-correct
names, timestamps that spread like history, a few heavy users and a long
tail of quiet ones, real photographs in the image fields. All of it
invented, none of it labelled, all of it wipeable through a channel the UI
never renders.
The Prime Directive (family rule)
The schema is read, never assumed. Production is never touched. And the
data never announces itself.
Every column seeded exists in evidence (migration/model/introspection,
cited). The target database is verified and confirmed by the user before
the first row is written. Every seeded row can be identified and wiped —
by provenance metadata, never by a visible "demo" tell inside the data.
Hard safety rules
- Production gate ⛔ — before seeding, resolve the actual connection
(env/config,
file:line), print host + database name + environment to
the user, and require explicit confirmation. Names that smell like
production (prod, a public host, a managed-DB hostname) require the
user to type the database name back. When in doubt, refuse and suggest
a local copy. The gate is checked TWICE: once here, and again at run
time — immediately before executing, query the live connection for its
own identity (SELECT DATABASE() / current_database() /
PRAGMA database_list) and compare host + database name against what
the user confirmed. Any mismatch = abort, zero rows written. If no
user can respond (headless run), the gate cannot pass — write the
scripts and stop; never execute a seed unattended.
- No tells in the data 🚫 — no seeded value a human or screenshot can
see may contain
demo, test, sample, fake, placeholder,
lorem ipsum, foo/bar/baz, John Doe, asdf, TBD, xxx, or
a sequential User 1 / User 2 pattern. Titles are real sentences,
descriptions are real paragraphs about the product's actual domain,
prices are prices. The only sanctioned exceptions are non-routable
contact values kept for safety (reserved e-mail domains, reserved
phone ranges) — see rule 3 — and they are declared in the Seed Brief,
not slipped in. Step 6 runs a tell-scan over the seeded text
columns; a hit blocks the run.
- Contactability beats cosmetics — seeded e-mail/phone values must be
incapable of reaching a real human: IETF-reserved domains
(
example.com, .example, .invalid, .test) or a domain the
project owns and null-routes. If the user wants screenshot-perfect
addresses instead, they choose it explicitly in the Seed Brief, mail
transport must be verified OFF in the target env (file:line), and the
choice is recorded in the manifest.
- Wipeable by construction — and proven, not promised — provenance
lives in an invisible channel (seed-ledger table, tag column, reserved
key range, or a pre-seed snapshot), chosen per
references/provenance-and-wipe.md.
An unseed script ships alongside the seed script, and the wipe
round-trip in Step 6 must pass on a one-row skeleton before any mass
insert.
- No real humans, no real data — no real names, e-mails, photos or
copied production rows. Text is generated, never lifted from a
production dump. Photos come from licensed libraries with the licence
recorded (Step 5), and identifiable people are never presented as
staff, testimonials or endorsers.
- No credentials unless asked — user rows are seeded like any other
entity, with a valid hash in the password column so auth code behaves,
and nothing is reported: no password roster, no login testing, no
credentials in the manifest. If the user wants to log in as a seeded
user, they ask — then follow "Add-on: login accounts" at the bottom
of this file.
Progress checklist
Copy this into your response and check items off:
Seed-ah Progress:
- [ ] Step 1: Frame — target env confirmed ⛔, volume, locale, purpose
- [ ] Step 2: Schema census — Census Questions answered with evidence, FK graph, seed order
- [ ] Step 3: Realism plan — per-table shape, distributions, edge cases, provenance channel; Seed Brief confirmed
- [ ] Step 4: Seed scripts — framework-native, committed, idempotent, side effects muted or accepted
- [ ] Step 5: Images — real licensed photos for every image field, locked + credited
- [ ] Step 6: Run + verify — target re-checked ⛔, skeleton + wipe round-trip proven, tell-scan clean, then mass seed
- [ ] Step 7: Manifest — what was seeded, image credits, re-seed/wipe commands
Step 1 — Frame
Volume (S: enough for screenshots / M: realistic dev / L: pagination and
performance testing), locale for the identities (Thai names for a Thai
product — locale mismatch screams "fake"), and purpose (feeding
love-me-love-my-docs screenshots? a customer walkthrough? dev fixtures?).
Purpose drives realism: data destined for screenshots must survive being
zoomed into. Then run the production gate from the hard rules —
nothing proceeds past this step without the confirmation.
If no database is reachable (connection fails, credentials missing),
stop here: write the seed scripts and manifest template as deliverables,
but execution cannot proceed — report the blocker and what's needed to
resolve it (connection string, credentials, network access).
Step 2 — Schema census
Read the structure from evidence, per
references/schema-census.md: migrations and
ORM models first (they carry intent: enums, defaults, validation), live
introspection to confirm (information_schema / SHOW CREATE TABLE / PRAGMA),
FK relationships → a dependency graph that dictates seed order (parents
before children), and every constraint that can reject a row (NOT NULL,
UNIQUE, CHECK, enum values). Note which tables the app writes vs
reference/lookup tables that may already be populated.
The census exists to answer the numbered Census Questions in that
reference — constraints, FK order, what fires on insert, what already
lives in the target, where provenance can be stored — before a single row
is invented. Every answer carries evidence (file:line or pasted
introspection output). A question you cannot answer from evidence never
becomes a guess: it becomes a named probe (insert one throwaway row
inside a transaction, observe, roll back) or the table waits. The census
is complete when every question is answered or probed — not when every
file has been read.
Step 3 — Realism plan
Per table, decide what "reads as real" means — rules in
references/realism-guide.md: locale-correct
identities, domain-true text (an article about the product's actual
subject, not filler), timestamps spread over months with plausible
rhythms, power-law distributions (a few heavy users, a long tail, some
ghosts), statuses covering the whole enum including the ugly ones
(cancelled, banned, pending), and deliberate edge cases (longest
plausible name, unicode, empty optionals) that still look like real
records rather than QA fixtures.
Then pick the provenance channel per
references/provenance-and-wipe.md —
ledger table, tag column, key range or snapshot — and verify it is
invisible to the UI (grep the templates/serializers for SELECT *-style
exposure of a tag column, cite the check).
Seed Brief Gate — before writing a single script, present a compact
brief in chat: the target database (exactly as confirmed at the production
gate), per-table row counts, the provenance channel and how the wipe uses
it, the contact-value policy (rule 3), the image sources Step 5 will draw
from, and any side effects that will fire or be muted. Add one line:
"no seeded user is loggable-in — say the word if you want access
accounts." 10–20 lines total; ask for confirmation once. Changing a
row count here costs one message; changing it after the scripts and images
exist costs a rewrite. If the user cannot respond, write the scripts
anyway (files are reversible) — but execution stays behind the production
gate, which never passes unattended.
Step 4 — Write the seed scripts
Use the framework's blessed mechanism — Laravel seeders/factories, Symfony
Foundry, Prisma seed, Django fixtures/factory_boy, plain SQL as last
resort — cited from the project's own conventions (file:line of an
existing example if one exists). Scripts are committed (database/seeds/
or the stack's home), deterministic (fixed random seed so re-runs produce
the same world), and paired with the unseed script. Provenance is written
as rows are created, not reconstructed afterwards. Every insert-time side
effect the census found (Census Question 4 — observers, signals,
callbacks, queued jobs) is handled IN the script: muted with the
framework's own switch (cite it) or left firing with a one-line
justification. Silence is not handling.
Step 5 — Images and media
Image fields get real photographs, not generated placeholder graphics
— rules and the source ladder in
references/images-and-media.md: the
project's own asset library first, then licensed photo libraries by API
(Unsplash, Pexels, Openverse, Wikimedia Commons) queried with terms drawn
from the product's actual domain, then AI generation for imagery no
library carries. Hand-rendered SVG/placeholder graphics are a
last-resort offline fallback only, taken with the user's knowledge and
labelled as a downgrade in the manifest.
Files are downloaded once, committed to the seed assets folder, and
recorded in an image lockfile (photo id + source + licence + author) so a
re-seed rebuilds the identical world and the manifest can credit every
file. Never hotlink a live URL from seeded rows — a demo that needs the
network to render an avatar is a demo that breaks on stage. Store files
where the app actually serves media from (file:line of the storage
config), at the dimensions the app expects.
Step 6 — Run and verify
Re-check the target first (the run-time half of the production gate ⛔),
then prove the pipeline before trusting it with volume — in this order:
- Baseline — record pre-seed row counts per table, and confirm the
provenance channel is clean (ledger empty / tag column all NULL / key
range unused). If it isn't, and the rows aren't a prior seed run per
the manifest, resolve that before going on — a provenance collision
turns the wipe into a data-loss tool.
- Walking skeleton — seed exactly ONE row per table through the real
seeder (including one image landing in real storage), then check FK
integrity and that one page renders it. The thinnest slice that
exercises the whole pipeline.
- Wipe round-trip — run the unseed script for real against the
skeleton. Re-query the counts: every table must equal the baseline,
and the copied media files must be gone. A diff of zero is the proof
that "wipeable" is true. Until this passes, mass seeding is forbidden
— a wipe that fails on 1 row per table would have failed on thousands.
- Mass seed — now run the full seed, and verify like it matters:
- Row counts per table match the plan.
- FK integrity: zero orphans (query it, don't assume it).
- Tell-scan: query every seeded text column for the banned tokens
of rule 2 (
demo, test, sample, lorem, placeholder,
foo, asdf, …). Expected result: zero rows, except the declared
reserved contact values. A hit is a seed defect — fix and re-seed.
- Eyeball pass: render one page per major entity and read it as a
stranger would. Does it look like a product in use, or like a
fixture file? Report what you saw.
Step 7 — The manifest
Write the summary per
references/manifest-template.md to
SEED_MANIFEST.md (repo root or docs/): per-table seeded counts and shape
notes, the provenance channel and exact wipe/re-seed commands, the image
inventory with source + licence + author per batch, the tagged edge-case
rows, and any drift the census surfaced.
End by reporting the manifest inline: what was seeded (counts), where the
images came from, and the one-command re-seed and wipe.
Add-on: login accounts (only when the user asks)
Not part of a normal run. When the user explicitly asks for accounts they
can log in with:
- Read the app's roles/permissions from code or DB (cite
file:line) —
the roster comes from the app, not from a template.
- Pick existing seeded users to promote where possible, so the accounts
have lived-in history instead of being obvious plants.
- Passwords: unique to this seed, policy-compliant, typeable on stage,
never a credential reused from anywhere. Hash through the app's OWN
hasher (
file:line of the hashing call/config) — bcrypt/argon2 config
differences WILL lock you out.
- Log in as every account through the app's real auth (HTTP or the
app's test client). An account that can't log in is a failure, not a
footnote.
- Report the roster in chat and append an Access accounts section to
SEED_MANIFEST.md with a header warning that the file now contains
credentials — keep it out of public repos unless the database is
disposable.
When things go wrong
| Situation |
Response |
| Production gate fails (smells like prod) |
Refuse; suggest local copy or explicit database name confirmation typed back by user |
| No database reachable |
Write scripts and manifest template as deliverables; report blocker (connection, credentials, network) — execution cannot proceed |
| User cannot respond (headless run) |
Write scripts (reversible) but never execute — production gate cannot pass unattended |
| Provenance channel already has rows |
Resolve before seeding (prior run? reused id range?) — a collision turns the wipe into a data-loss tool |
| No provenance channel possible (no new table, no column, no id range) |
Fall back to snapshot-and-restore on a disposable DB; if even that is refused, write the scripts and refuse the mass seed |
| Wipe round-trip fails on skeleton |
Fix wipe script before mass seed — a wipe that fails on 1 row/table would fail on thousands |
| Tell-scan finds banned tokens |
Seed defect: fix the generator, re-seed the affected tables — never ship data that labels itself |
| No image API key / no network |
Try keyless sources (Openverse, Wikimedia) first; if still blocked, ask before falling back to rendered placeholders and label the downgrade in the manifest |
| Insert-time side effects discovered |
Mute with framework's own switch (cite) or accept with one-line justification — silence is not handling |
| User asks "how do I log in?" |
That's the add-on above — do it properly (real hasher, real login test), not by inventing a password |
1---2name: seed-ah3description: Seeds a database with data that looks like a real, lived-in production database: reads the real DB structure (migrations, ORM models, live introspection), builds a dependency-ordered seeding plan using the framework's own seeder mechanism, generates locale-correct identities, timestamps spread like history, power-law distributions and deliberate edge cases, and fills image fields with real licensed photos pulled from photo libraries (Unsplash, Pexels, Openverse, Wikimedia) instead of hand-drawn placeholders. Nothing in the seeded rows says "demo", "test", "sample" or "lorem" — provenance is kept in an invisible ledger so every row stays wipeable. Hard production gate: verifies the target database before writing a single row. Login accounts and credentials are produced ONLY when the user explicitly asks for them. Use when the user asks to seed demo/test/sample data, create fixtures, populate a dev database, or mentions seed-ah or /seed-ah.4license: MIT5---67# Seed-ah!89An empty database makes every screenshot, demo and dev session lie — and a10database full of `Test User 3` / `lorem ipsum` / grey SVG placeholders lies11louder. This skill seeds a world that reads as **real**: locale-correct12names, timestamps that spread like history, a few heavy users and a long13tail of quiet ones, real photographs in the image fields. All of it14invented, none of it labelled, all of it wipeable through a channel the UI15never renders.1617## The Prime Directive (family rule)1819> **The schema is read, never assumed. Production is never touched. And the20> data never announces itself.**21> Every column seeded exists in evidence (migration/model/introspection,22> cited). The target database is verified and confirmed by the user before23> the first row is written. Every seeded row can be identified and wiped —24> by provenance metadata, never by a visible "demo" tell inside the data.2526## Hard safety rules27281. **Production gate ⛔** — before seeding, resolve the actual connection29 (env/config, `file:line`), print host + database name + environment to30 the user, and require explicit confirmation. Names that smell like31 production (`prod`, a public host, a managed-DB hostname) require the32 user to type the database name back. When in doubt, refuse and suggest33 a local copy. The gate is checked TWICE: once here, and again at run34 time — immediately before executing, query the live connection for its35 own identity (`SELECT DATABASE()` / `current_database()` /36 `PRAGMA database_list`) and compare host + database name against what37 the user confirmed. Any mismatch = abort, zero rows written. If no38 user can respond (headless run), the gate cannot pass — write the39 scripts and stop; never execute a seed unattended.402. **No tells in the data 🚫** — no seeded value a human or screenshot can41 see may contain `demo`, `test`, `sample`, `fake`, `placeholder`,42 `lorem ipsum`, `foo`/`bar`/`baz`, `John Doe`, `asdf`, `TBD`, `xxx`, or43 a sequential `User 1 / User 2` pattern. Titles are real sentences,44 descriptions are real paragraphs about the product's actual domain,45 prices are prices. The only sanctioned exceptions are non-routable46 contact values kept for safety (reserved e-mail domains, reserved47 phone ranges) — see rule 3 — and they are declared in the Seed Brief,48 not slipped in. Step 6 runs a **tell-scan** over the seeded text49 columns; a hit blocks the run.503. **Contactability beats cosmetics** — seeded e-mail/phone values must be51 incapable of reaching a real human: IETF-reserved domains52 (`example.com`, `.example`, `.invalid`, `.test`) or a domain the53 project owns and null-routes. If the user wants screenshot-perfect54 addresses instead, they choose it explicitly in the Seed Brief, mail55 transport must be verified OFF in the target env (`file:line`), and the56 choice is recorded in the manifest.574. **Wipeable by construction — and proven, not promised** — provenance58 lives in an invisible channel (seed-ledger table, tag column, reserved59 key range, or a pre-seed snapshot), chosen per60 [references/provenance-and-wipe.md](references/provenance-and-wipe.md).61 An **unseed script** ships alongside the seed script, and the wipe62 round-trip in Step 6 must pass on a one-row skeleton before any mass63 insert.645. **No real humans, no real data** — no real names, e-mails, photos or65 copied production rows. Text is generated, never lifted from a66 production dump. Photos come from licensed libraries with the licence67 recorded (Step 5), and identifiable people are never presented as68 staff, testimonials or endorsers.696. **No credentials unless asked** — user rows are seeded like any other70 entity, with a valid hash in the password column so auth code behaves,71 and **nothing is reported**: no password roster, no login testing, no72 credentials in the manifest. If the user wants to log in as a seeded73 user, they ask — then follow *"Add-on: login accounts"* at the bottom74 of this file.7576## Progress checklist7778Copy this into your response and check items off:7980```81Seed-ah Progress:82- [ ] Step 1: Frame — target env confirmed ⛔, volume, locale, purpose83- [ ] Step 2: Schema census — Census Questions answered with evidence, FK graph, seed order84- [ ] Step 3: Realism plan — per-table shape, distributions, edge cases, provenance channel; Seed Brief confirmed85- [ ] Step 4: Seed scripts — framework-native, committed, idempotent, side effects muted or accepted86- [ ] Step 5: Images — real licensed photos for every image field, locked + credited87- [ ] Step 6: Run + verify — target re-checked ⛔, skeleton + wipe round-trip proven, tell-scan clean, then mass seed88- [ ] Step 7: Manifest — what was seeded, image credits, re-seed/wipe commands89```9091## Step 1 — Frame9293Volume (S: enough for screenshots / M: realistic dev / L: pagination and94performance testing), locale for the identities (Thai names for a Thai95product — locale mismatch screams "fake"), and purpose (feeding96love-me-love-my-docs screenshots? a customer walkthrough? dev fixtures?).97Purpose drives realism: data destined for screenshots must survive being98zoomed into. Then run the **production gate** from the hard rules —99nothing proceeds past this step without the confirmation.100101**If no database is reachable** (connection fails, credentials missing),102stop here: write the seed scripts and manifest template as deliverables,103but execution cannot proceed — report the blocker and what's needed to104resolve it (connection string, credentials, network access).105106## Step 2 — Schema census107108Read the structure from evidence, per109[references/schema-census.md](references/schema-census.md): migrations and110ORM models first (they carry intent: enums, defaults, validation), live111introspection to confirm (information_schema / SHOW CREATE TABLE / PRAGMA),112FK relationships → a dependency graph that dictates seed order (parents113before children), and every constraint that can reject a row (NOT NULL,114UNIQUE, CHECK, enum values). Note which tables the app writes vs115reference/lookup tables that may already be populated.116117The census exists to answer the numbered **Census Questions** in that118reference — constraints, FK order, what fires on insert, what already119lives in the target, where provenance can be stored — before a single row120is invented. Every answer carries evidence (`file:line` or pasted121introspection output). A question you cannot answer from evidence never122becomes a guess: it becomes a named **probe** (insert one throwaway row123inside a transaction, observe, roll back) or the table waits. The census124is complete when every question is answered or probed — not when every125file has been read.126127## Step 3 — Realism plan128129Per table, decide what "reads as real" means — rules in130[references/realism-guide.md](references/realism-guide.md): locale-correct131identities, domain-true text (an article about the product's actual132subject, not filler), timestamps spread over months with plausible133rhythms, power-law distributions (a few heavy users, a long tail, some134ghosts), statuses covering the whole enum including the ugly ones135(cancelled, banned, pending), and **deliberate edge cases** (longest136plausible name, unicode, empty optionals) that still look like real137records rather than QA fixtures.138139Then pick the **provenance channel** per140[references/provenance-and-wipe.md](references/provenance-and-wipe.md) —141ledger table, tag column, key range or snapshot — and verify it is142invisible to the UI (grep the templates/serializers for `SELECT *`-style143exposure of a tag column, cite the check).144145**Seed Brief Gate** — before writing a single script, present a compact146brief in chat: the target database (exactly as confirmed at the production147gate), per-table row counts, the provenance channel and how the wipe uses148it, the contact-value policy (rule 3), the image sources Step 5 will draw149from, and any side effects that will fire or be muted. Add one line:150*"no seeded user is loggable-in — say the word if you want access151accounts."* 10–20 lines total; ask for confirmation **once**. Changing a152row count here costs one message; changing it after the scripts and images153exist costs a rewrite. If the user cannot respond, write the scripts154anyway (files are reversible) — but execution stays behind the production155gate, which never passes unattended.156157## Step 4 — Write the seed scripts158159Use the framework's blessed mechanism — Laravel seeders/factories, Symfony160Foundry, Prisma seed, Django fixtures/factory_boy, plain SQL as last161resort — cited from the project's own conventions (`file:line` of an162existing example if one exists). Scripts are committed (`database/seeds/`163or the stack's home), deterministic (fixed random seed so re-runs produce164the same world), and paired with the unseed script. Provenance is written165as rows are created, not reconstructed afterwards. Every insert-time side166effect the census found (Census Question 4 — observers, signals,167callbacks, queued jobs) is handled IN the script: muted with the168framework's own switch (cite it) or left firing with a one-line169justification. Silence is not handling.170171## Step 5 — Images and media172173Image fields get **real photographs**, not generated placeholder graphics174— rules and the source ladder in175[references/images-and-media.md](references/images-and-media.md): the176project's own asset library first, then licensed photo libraries by API177(Unsplash, Pexels, Openverse, Wikimedia Commons) queried with terms drawn178from the product's actual domain, then AI generation for imagery no179library carries. Hand-rendered SVG/placeholder graphics are a180last-resort offline fallback only, taken with the user's knowledge and181labelled as a downgrade in the manifest.182183Files are downloaded once, committed to the seed assets folder, and184recorded in an image lockfile (photo id + source + licence + author) so a185re-seed rebuilds the identical world and the manifest can credit every186file. Never hotlink a live URL from seeded rows — a demo that needs the187network to render an avatar is a demo that breaks on stage. Store files188where the app actually serves media from (`file:line` of the storage189config), at the dimensions the app expects.190191## Step 6 — Run and verify192193Re-check the target first (the run-time half of the production gate ⛔),194then prove the pipeline before trusting it with volume — in this order:1951961. **Baseline** — record pre-seed row counts per table, and confirm the197 provenance channel is clean (ledger empty / tag column all NULL / key198 range unused). If it isn't, and the rows aren't a prior seed run per199 the manifest, resolve that before going on — a provenance collision200 turns the wipe into a data-loss tool.2012. **Walking skeleton** — seed exactly ONE row per table through the real202 seeder (including one image landing in real storage), then check FK203 integrity and that one page renders it. The thinnest slice that204 exercises the whole pipeline.2053. **Wipe round-trip** — run the unseed script for real against the206 skeleton. Re-query the counts: every table must equal the baseline,207 and the copied media files must be gone. A diff of zero is the proof208 that "wipeable" is true. Until this passes, mass seeding is forbidden209 — a wipe that fails on 1 row per table would have failed on thousands.2104. **Mass seed** — now run the full seed, and verify like it matters:211 - Row counts per table match the plan.212 - FK integrity: zero orphans (query it, don't assume it).213 - **Tell-scan**: query every seeded text column for the banned tokens214 of rule 2 (`demo`, `test`, `sample`, `lorem`, `placeholder`,215 `foo`, `asdf`, …). Expected result: zero rows, except the declared216 reserved contact values. A hit is a seed defect — fix and re-seed.217 - **Eyeball pass**: render one page per major entity and read it as a218 stranger would. Does it look like a product in use, or like a219 fixture file? Report what you saw.220221## Step 7 — The manifest222223Write the summary per224[references/manifest-template.md](references/manifest-template.md) to225`SEED_MANIFEST.md` (repo root or docs/): per-table seeded counts and shape226notes, the provenance channel and exact wipe/re-seed commands, the image227inventory with source + licence + author per batch, the tagged edge-case228rows, and any drift the census surfaced.229230End by reporting the manifest inline: what was seeded (counts), where the231images came from, and the one-command re-seed and wipe.232233## Add-on: login accounts (only when the user asks)234235Not part of a normal run. When the user explicitly asks for accounts they236can log in with:2372381. Read the app's roles/permissions from code or DB (cite `file:line`) —239 the roster comes from the app, not from a template.2402. Pick existing seeded users to promote where possible, so the accounts241 have lived-in history instead of being obvious plants.2423. Passwords: unique to this seed, policy-compliant, typeable on stage,243 never a credential reused from anywhere. Hash through the app's OWN244 hasher (`file:line` of the hashing call/config) — bcrypt/argon2 config245 differences WILL lock you out.2464. Log in as **every** account through the app's real auth (HTTP or the247 app's test client). An account that can't log in is a failure, not a248 footnote.2495. Report the roster in chat and append an **Access accounts** section to250 `SEED_MANIFEST.md` with a header warning that the file now contains251 credentials — keep it out of public repos unless the database is252 disposable.253254## When things go wrong255256| Situation | Response |257|-----------|----------|258| **Production gate fails (smells like prod)** | Refuse; suggest local copy or explicit database name confirmation typed back by user |259| **No database reachable** | Write scripts and manifest template as deliverables; report blocker (connection, credentials, network) — execution cannot proceed |260| **User cannot respond (headless run)** | Write scripts (reversible) but never execute — production gate cannot pass unattended |261| **Provenance channel already has rows** | Resolve before seeding (prior run? reused id range?) — a collision turns the wipe into a data-loss tool |262| **No provenance channel possible** (no new table, no column, no id range) | Fall back to snapshot-and-restore on a disposable DB; if even that is refused, write the scripts and refuse the mass seed |263| **Wipe round-trip fails on skeleton** | Fix wipe script before mass seed — a wipe that fails on 1 row/table would fail on thousands |264| **Tell-scan finds banned tokens** | Seed defect: fix the generator, re-seed the affected tables — never ship data that labels itself |265| **No image API key / no network** | Try keyless sources (Openverse, Wikimedia) first; if still blocked, ask before falling back to rendered placeholders and label the downgrade in the manifest |266| **Insert-time side effects discovered** | Mute with framework's own switch (cite) or accept with one-line justification — silence is not handling |267| **User asks "how do I log in?"** | That's the add-on above — do it properly (real hasher, real login test), not by inventing a password |