# W19 — floor plan / background prompt migration design brief

Status: **design only**, no code patch, no prompt rewrite yet.
Source wave: W18 A → J (closure 2026-05-26, see
[`session_20260526_w18_wave_closure_summary.md`](../../../../.claude/projects/-Users-manta-Documents-Projects-TheRoad-I1/memory/session_20260526_w18_wave_closure_summary.md)
and the W18J planner contract memo
[`w18j_planner_contract.md`](../../../../.claude/projects/-Users-manta-Documents-Projects-TheRoad-I1/memory/w18j_planner_contract.md)).
Reviewer: Codex (this brief must be Codex-approved before any
production prompt or pipeline code is touched).

**Accepted output set carried into this brief**: W18B base FP image,
W18I L05B02 anchor, and W18J L05B05 / L05B04 / L05B03 / L05B01. The
**W18G / W18H 5-BG outputs are deprecated archives only** (luxury /
showroom drift, cross-BG identity collision) and must not be treated
as production targets. The W19 migration's image-level acceptance bar
is parity with the accepted set, not parity with the deprecated set.

This document captures the contract change that W18 experimentally
validated, the production migration candidates that follow, the
guard/test plan that must accompany them, and the rollout risk
profile. It does **not** prescribe specific file edits; concrete
patches are deferred to a separate W19A/W19B implementation wave.

## 1. Current production root problem

Two production prompts coexist today and disagree about which markers
belong in which layer.

### 1.1 `floor_plan_prompt` v5 — "plot-critical visual device" leak

- v5 instructs the FP renderer to embed every marker the runtime
  declares as visually meaningful, including event/state cues such
  as transient wall marks, transient floor trails, and transient
  displaced objects.
- During the W17 wave the W15e candidate carried 23 markers (17
  structural + 6 transient) and every marker was sent to gpt-image-2
  as `must_show`. The model compressed multiple plot transients into
  the same private room and the room geometry visibly bent to
  accommodate them.
- Net effect: the FP image stopped being a stable layout reference and
  started behaving as a "scene poster". Downstream consumers (BG
  prompt, shot prompt) inherited the noise rather than the layout.

### 1.2 `background_prompt` v6 — undifferentiated `numbered_elements`

- v6 already consumes a floor plan reference, but it forwards the
  W15e `use_numbered_elements` / `ignore_numbered_elements` arrays as
  a flat list with no layer separation. Transient markers travel side
  by side with structural ones.
- For a "clean" BG (a BG whose runtime payload carries zero
  transient markers), there is no explicit sentinel that says "this
  BG carries zero transient cues". The model is left to infer it.
- Symptom: clean BGs can still inherit residual stain / floor-trail /
  displaced-object cues from neighboring dirty BGs in the same FP, or
  from the FP image itself.

### 1.3 Why W17 retries failed

Every W17 patch (mapping banner column reordering, must_show ranking,
re-numbering) still treated transient + structural markers as peers
on a single FP image. The mechanism, not the wording, was wrong.

## 2. Target contract (validated by W18)

### 2.1 Two layers, two surfaces

| layer            | what goes in                                                            | output surface                                   |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| **base FP**      | structural units, openings, fixed fixtures, persistent anchor furniture | **one FP image** rendered once per fp_id         |
| **per-bg overlay** | event / state / transient markers, BG-specific                          | **background prose only** + reference base FP PNG |

The base FP image must not be re-rendered or mutated per BG. Transient
markers must never appear as drawn icons on the FP image.

### 2.2 `base_layer_decision` enum (W18A2)

Every numbered marker carries one of:

- `base_structural_unit`
- `base_opening`
- `base_persistent_fixture`
- `base_persistent_furniture`
- `state_overlay_plot_cue`
- `state_overlay_transient_object`

The first four belong to the base FP layer. The last two belong to
the per-bg overlay layer. The enum is the migration's primary data
hook; v5/v6 do not have it today.

### 2.3 Per-bg overlay payload shape

For each `bg_id`, the per-bg payload must carry:

- `target_unit_ids`: which spatial units the BG actually views.
- `base_markers_to_reference`: which base-layer markers the BG must
  point at (subset of `use_numbered_elements` ∩ base layer).
- `transient_markers_to_describe`: subset of
  `use_numbered_elements` ∩ overlay layer. Empty list signals a
  clean BG.
- `prompt_appendix_hint`: short anchoring sentence (e.g. "anchor on
  living, then add only the specified temporary floor cues").

`ignore_numbered_elements` is treated as a hard veto on the consumer
side — neither base nor overlay references may leak from there.

### 2.4 Background prompt assembly contract (W18F)

Per BG the rendered consumer prompt is the deterministic concatenation:

```
<source render prompt prose>            # existing W15e per_bg final_prompt_assembly_preview
\n\n----- background_prompt_region_appendix (W18E preview) -----\n\n
<region_ref_appendix>                   # deterministic enumeration of:
  - "Base FP image reference (layout / rooms / fixed anchors only): <path>"
  - "Do not redraw, relocate, or add transient overlay markers onto the base FP image; transient markers belong only in the background prose."
  - "Target spatial units for this background:" + enumerated lines
  - "Base markers visible on the base FP image:" + enumerated lines
  - "Transient overlay markers to describe in the prose:" + enumerated lines
                                          OR fixed sentinel
                                          "No transient overlay markers for this background."
```

No new prose is generated at assembly time. Only labels and hints
already present in the upstream payload are enumerated.

### 2.5 Image rendering shape (W18I / W18J accepted; supersedes W18G/H)

`images.edit(model='gpt-image-2', image=<reference_paths>, prompt=<preamble> + <mode_guidance> + <assembled_prompt>, size='1024x1024', n=1)`.

`reference_paths` is selected by the W18J overlap-driven planner (see
§2.6) — the base FP PNG for an anchor BG, or one to two prior BG PNGs
for a reference-derived BG. Retry = 0. One image call per BG. A short
generic preamble ("Create an interior background image matching the
referenced base floor plan region / referenced dwelling identity; use
the references as layout / identity guidance, not as a visible
overlay. … Do not render any person, body, or corpse.") plus a
**mode-keyed** guidance text (one of `fp_seeded_anchor`,
`reference_derived`, `style_reference_new_space`; see §2.6) is
allowed. No scenario-specific prose may be appended; no BG-id-keyed
prose dict is permitted.

The deprecated W18G/H shape — each BG independently calls
`images.edit` with the base FP PNG alone, with no cross-BG identity
graph — is retained as an archive baseline for visual diff only, not
as a production target.

### 2.6 Cross-BG reference graph (W18J overlap-driven planner)

The base FP image alone does not carry the dwelling's visual
identity. When multiple BGs share the same FP they must also share
floor / wall / window-covering / lighting / fixed-fixture palette so
they read as one home. W18G/H violated this and produced luxury /
showroom drift plus cross-BG identity collision. W18I/J restored it
via a small planner that selects per-BG visual references from a
growing catalog of already-generated BGs.

The planner exposes three modes:

| mode                          | use case                                                                                                                                  | `image=` payload                                | FP included? |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------ |
| `fp_seeded_anchor`            | first anchor for a brand-new dwelling identity, or a new region whose catalog overlap is weak                                             | `[base_fp_png]` only                            | yes          |
| `reference_derived`           | strong overlap with already-generated catalog entries: identity inherited directly from prior BG PNG(s)                                   | `[ref1]` or `[ref1, ref2]`, max 2; FP excluded  | no           |
| `style_reference_new_space`*  | the BG depicts a new local space (e.g. a service-room-only or open-service-zone-only space) absent from the catalog, yet must read as the same dwelling | `[style_ref]` (1, optionally 2); FP excluded    | no           |

`* style_reference_new_space` was identified during W18J review as the
cleaner mode for the L05B01 artifact (a new local service space
rendered with a mirror reflection of an adjacent shared-space
identity). The W18J wave folded that case into `reference_derived`;
W19 must surface it as a first-class mode so non-L05 fps with
service-room-only or open-service-zone-only BGs can be handled
without forcing a misleading overlap classification.

Overlap is scored **exact-ID only** — no regex, no substring, no
lexical extraction. The two sets that participate in scoring are:

- `shared_units = target_unit_refs.unit_id ∩ catalog_entry.unit_set`
- `shared_base_markers = base_marker_refs.marker_number ∩ catalog_entry.base_marker_set`
- `score = |shared_units| + 0.5 * |shared_base_markers|`
- a candidate qualifies as a strong overlap iff
  `|shared_units| ≥ 1 AND (|shared_units| ≥ 2 OR |shared_base_markers| ≥ 1)`

Decision dispatch (deterministic on exact-ID criteria; LLM-emitted
hints are supporting / diagnostic only and never trigger a mode
change on their own):

1. Compute score and overlap classification against every catalog
   entry from the **same `fp_id`** as the target BG.
2. If any strong-overlap candidate exists → `mode = reference_derived`;
   pick top-2 by `(score desc, ref_bg_id asc)`; `max_refs_per_bg = 2`;
   FP is **not** included.
3. **Else if** the BG's local / dominant target unit (the
   `target_unit_refs.unit_id` selected as the BG's primary focus
   unit; see §7 #6 on the shape question) is **not** present in any
   catalog entry's `unit_set`, **and** at least one same-fp catalog
   entry exists as a style reference (any overlap level accepted),
   then → `mode = style_reference_new_space`;
   pick top-`max_refs_per_bg` by `(score desc, ref_bg_id asc)`;
   `max_refs_per_bg = 2` (open question §7 #7 on whether one ref is
   sufficient); FP is **not** included.
4. **Else** → `mode = fp_seeded_anchor`; `image = [base_fp_png]`.
   Fallback-of-last-resort when no usable style reference is
   available in the catalog.

An LLM-emitted payload hint (e.g. `living_adjacent_inheritance:
true`) is permitted as a *supporting / diagnostic* field recorded on
the planner record (§3.3 `overlap_reference_decision`), but it
**must not** by itself change the dispatch outcome — the dispatch
above is exact-ID deterministic.

Constraints (frozen contract):

- Dispatch is **deterministic on exact-ID criteria**
  (`target_unit_refs.unit_id`, `base_marker_refs.marker_number`,
  catalog `unit_set` / `base_marker_set` / `fp_id`,
  `source_kind == catalog_seed` flag). LLM-emitted hints are
  diagnostic / supporting only and never the sole trigger for a mode
  change.
- `max_refs_per_bg = 2`. Retry = `0`. Exactly one image call per BG.
- The catalog is incremental: each accepted BG is appended to the
  catalog and becomes a candidate for later BGs in the same fp.
- Anchor BGs (W18I-style catalog seeds) are produced in a separate
  seed wave and **never re-generated** by the W18J / successor
  planner; they are carried as catalog seeds only.
- All guidance text is **mode-keyed**. BG-id-keyed prose / per-BG
  hand-written sentences / lookup dicts (the W18I
  `_REFERENCE_GUIDANCE_BY_BG` shape) are forbidden — that pattern is
  what dragged scenario knowledge back into the static code, and is
  the explicit reason W18J replaced W18I.
- Clean BGs (empty `transient_markers_to_describe`) keep the W18E
  sentinel `No transient overlay markers for this background.` and
  their assembled prompt must not name any `#N` from the overlay
  layer.
- Scenario-specific tokens stay at zero in static text. All
  scenario-shaped content (unit ids, marker numbers, modesty hints,
  per-unit furniture lists) is carried as runtime payload only.

### 2.7 No manual per-BG prompt authoring

The W18I run included a small `_REFERENCE_GUIDANCE_BY_BG` dict whose
entries were hand-written per BG. W18J removed this dict and proved it
is unnecessary: the per-BG body text comes from the W15e source prose
plus the W18E / W18F assembly, and the BG-level orientation comes from
the mode-keyed guidance described in §2.6. The W19 migration must
preserve that property — no production code or prompt template may
carry a mapping of the shape "if `bg_id == X` then prepend prose Y".
Per-BG variation is expressed only through runtime payload (target
units, base markers, transient markers, planner-emitted mode and
refs).

## 3. Production migration candidates

Each candidate is a separate version bump that must land behind a
feature flag and be reviewable in isolation. None of these are
allowed to silently fall back to the old behavior.

### 3.1 `floor_plan_prompt` v6 — layer-aware FP rendering

- Add `base_layer_decision` (see §2.2) to every marker emitted by
  the FP prompt LLM.
- Restrict the rendered FP image to markers whose decision starts
  with `base_*`. `state_overlay_*` markers are excluded from the
  FP image prompt entirely.
- Spec the FP prompt to assert: "Do not render, renumber, omit, or
  invent any numbered marker; every listed marker number must remain
  legible exactly as written, and no other numbered markers may be
  added." (Same numbered-marker contract W18A2 already enforces in
  the candidate prompt.)

Migration note: v6 strictly **shrinks** the FP marker set. Existing
candidates that contain transients must be re-partitioned via the
W18A2 LLM step before they are safe to render under v6.

### 3.2 `background_prompt` v7 — overlay-aware BG rendering

- Inputs:
  - base FP PNG reference (path or url to v6 FP output);
  - per-bg overlay payload (§2.3);
  - the W18J-shaped reference-graph decision (§2.6) — selected
    `mode`, ordered `reference_paths`, scoring metadata for audit.
- Output prompt assembled per §2.4 contract, extended with the
  mode-keyed guidance text (§2.6).
- Image call shape per §2.5 — `images.edit(image=reference_paths, …)`
  with `max_refs_per_bg = 2`, retry `= 0`, exactly one call per BG.
- The catalog (`bg_reference_catalog`, §3.3) is updated incrementally
  as each BG completes; a failed BG must not enter the catalog.
- v7 must error closed if **any** of the following hold:
  - the per-bg overlay payload references a marker number not present
    in the upstream FP candidate;
  - the planner emits a `reference_derived` /
    `style_reference_new_space` decision whose `reference_paths`
    cannot all be resolved to a previously generated PNG;
  - the planner attempts to include the base FP PNG together with a
    catalog reference. **FP and prior-BG refs are mutually exclusive
    by locked contract** — this applies to every mode including
    `style_reference_new_space`. If FP-level layout assistance is
    needed, the planner must escalate to `fp_seeded_anchor` instead
    of mixing FP and catalog refs in a single call;
  - the planner emits more than `max_refs_per_bg = 2` refs for a
    single BG;
  - any BG-id-keyed prose appears in the assembled prompt (static
    code grep over guidance / template literals must not contain a
    BG-identifier-keyed branch).

### 3.3 Pipeline data shapes

- `bg_to_fp_region_ref` (W18D shape) becomes a first-class artifact
  the BG prompt stage consumes. It is the deterministic join of
  `per_bg_render_reference_instructions` + base FP candidate layer
  partition + (optional) VLM readback layout for relative `10x10`
  region rects.
- `background_prompt_region_appendix` (W18E shape) becomes the
  canonical "what to tell the BG image about the FP" appendix.
- `assembled_background_prompt_preview` (W18F shape) is the
  consumer's final BG prompt before image API.
- `overlap_reference_decision` (W18J planner record) is the per-BG
  decision shape carrying `mode`, `fp_included`, `reference_paths`,
  `selected_refs`, `candidate_scores`, `reference_decision_reason`,
  `transient_overlay_marker_numbers`, `clean_background_expected`,
  `prompt_text_len_chars`, `style_preamble`, `mode_guidance`. The
  generation step appends `png_relative_path`, `png_size_bytes`,
  `cost_meta.provider_usage`, and `actual_api_response_meta` once the
  PNG is written.
- `bg_reference_catalog` is the cumulative seed-and-grow structure
  containing one entry per accepted BG. Each entry carries:
  `bg_id`, `png_relative_path`, `unit_set`, `base_marker_set`,
  `fp_id`, `ingestion_order`, **`source_kind`** ∈ {`catalog_seed`,
  `derived`} (anchor-wave outputs vs per-bg planner outputs),
  **`seed_run_id`** (run identifier of the originating seed wave for
  `catalog_seed` entries; `null` for `derived`),
  **`immutable = true`**, and **`regen_allowed = false`**. The
  planner must consult `source_kind` / `regen_allowed` on every
  candidate before dispatch; an entry with
  `source_kind == catalog_seed` is never a regeneration target inside
  the per-bg run. Catalog entries are immutable once added; a failed
  BG does not enter the catalog.

These shapes must be added to the pipeline schema (or its
equivalent) and validated by invariants identical in spirit to the
W18D / W18E / W18F / W18J invariants.

### 3.4 Component naming

- `floor_plan_layer_partition` (replaces ad-hoc "include / exclude"
  arrays).
- `per_bg_overlay_payload` (replaces flat
  `use_numbered_elements` / `ignore_numbered_elements` consumption).
- `background_prompt_region_appendix`.
- `assembled_background_prompt`.
- `overlap_reference_decision` (per-BG W18J planner record; carries
  `mode`, `reference_paths`, scoring metadata).
- `bg_reference_catalog` (cumulative seed-and-grow structure of
  accepted BG PNGs available as future references).
- `reference_mode_guidance` (mode-keyed guidance text registry; one
  entry each for `fp_seeded_anchor`, `reference_derived`,
  `style_reference_new_space`).

Names are illustrative; the migration wave is free to pick
production-conformant names so long as the contract above holds. The
prohibition on BG-id-keyed prose / dict shapes (§2.6, §2.7) is
**not** illustrative — that one is locked.

## 4. Guard / test plan

The migration must carry these invariants forward from the W18 wave.
None of them is optional.

### 4.1 Layer integrity

- For every `base_*` marker: it appears in the FP image prompt and
  never appears in the per-bg overlay list.
- For every `state_overlay_*` marker: it never appears in the FP
  image prompt and only appears in per-bg overlay lists for BGs that
  have it in `use_numbered_elements`.
- `ignore_numbered_elements` markers never appear in any per-bg
  payload they ignore.

### 4.2 Clean BG sentinel

- Any BG whose `transient_markers_to_describe` is empty must emit the
  fixed sentinel string in its `background_prompt_region_appendix`.
- The assembled BG prompt for such a BG must not reference any
  transient marker number (exact integer match on `#N`, not
  substring).

### 4.3 Source preview residue

- The existing W15e source prose may still reference transient
  marker numbers. v7 must surface those as IMPORTANT diagnostics
  rather than silently passing them through. The migration wave is
  responsible for either rewriting the W15e source step or stripping
  residue at consumer side, with explicit visibility.

### 4.4 Image generation guards

- Exactly one `images.edit` (or per-bg-equivalent) call per BG per
  generation run. No retry. No second batch in the same run.
- The base FP PNG is referenced, never re-rendered, by the BG step.
- For any BG that fails generation, the failure must surface in the
  run report and `image_generation_count` must equal the number of
  successful PNG writes (not attempted calls).

### 4.5 Test plan

Each new component lands with at minimum:

- one happy-path invariant test mirroring the W18 minimal pattern;
- one diagnostic / failure test (e.g. clean BG with transient
  injection should fail invariant 4.2);
- one methodology grep that asserts no scenario-specific tokens are
  baked into the production prompt/code.

Full `backend/tests/scripts` regression must remain at parity
(currently 605/605 PASS at W18J closure).

### 4.6 Cross-BG reference graph integrity

- The W18J-shaped planner decision is the **only** authority on which
  images are passed to `images.edit` for each BG. Hand-edited per-BG
  reference lists must not appear in any pipeline path.
- `max_refs_per_bg ≤ 2`. Exactly one image call per BG. Retry `= 0`.
- `fp_seeded_anchor` decisions include exactly the base FP PNG and
  nothing else; `reference_derived` / `style_reference_new_space`
  decisions include only catalog PNG(s) and **never** the base FP.
- All overlap scoring is exact-ID. Static code may not contain
  regex / substring matchers / Korean particle whitelists / term
  lexicons over unit ids, marker numbers, or guidance text — the
  user has marked literal-pattern semantic extraction as a hard
  prohibition (memo `feedback-no-literal-substring-meaning`).
- Anchor BGs (W18I-style catalog seeds) are produced in a separate
  seed wave and **not** regenerated by the per-BG planner.
  Identification is by the explicit `source_kind == catalog_seed`
  flag (§3.3), never by inference from absence of a planner record.
  A test must assert: for every catalog entry whose
  `source_kind == catalog_seed`, (a) the planner attempts no
  generation against it (the catalog seed path is unchanged and no
  `images.edit` call is made for that `bg_id`), (b) the on-disk
  `png_relative_path` is unchanged byte-for-byte between runs, and
  (c) the catalog entry is never overwritten or mutated in
  `bg_reference_catalog`.
- `bg_reference_catalog` entries are append-only within a single run;
  a generation failure does not promote a BG into the catalog.

### 4.7 BG-id-keyed prose detection

- Static-code grep must reject any dictionary or branch literal whose
  key is a BG-identifier string (e.g. `"L05B01"`, `"L05B02"`, …)
  controlling prompt text or guidance text. Guidance text is
  **mode-keyed** only.
- W18I's `_REFERENCE_GUIDANCE_BY_BG` is the explicit counter-example —
  it must not be ported into production code in any form.

## 5. Rollout risk

### 5.1 Behavior parity gate

- v5 / v6 must remain the default until v6 / v7 reach Codex
  `APPROVED` on the migration wave.
- The new path lands behind a feature flag or version bump (e.g.
  `floor_plan_prompt_version = 6`, `background_prompt_version = 7`).
- No silent fallback. If v6 / v7 is selected and a required input
  (layer partition, overlay payload) is missing, the pipeline must
  error closed, not revert to the old prompt.

### 5.2 Scenario hygiene

- The migration must preserve the W18 invariant that scenario-specific
  tokens (e.g. specific room or fixture names from a real scenario)
  do not appear in any production prompt or code path. Runtime
  scenario data is carried via runtime payload only; static prompt
  text stays generic.

### 5.3 Cross-fp / cross-scenario debt

- W18 validated only `fp_l05_01`. fp_l07_01, fp_l11_01 and any
  non-L05 scenario must be re-validated after v6 / v7 lands. That
  re-validation belongs to a separate W19C+ wave; do not block W19A/B
  on it, but do not declare migration done before it runs.

### 5.4 DB / asset write blast radius

- The W18 wave wrote zero DB rows and zero ImageAsset rows. The
  migration wave is allowed to touch those, but only after the
  prompt-only path (no DB, no ImageAsset) is approved end to end.

### 5.5 Visual regression

- Before the new path is enabled in production, at minimum the L05
  accepted 5-BG visual set (W18I L05B02 anchor + W18J L05B05 /
  L05B04 / L05B03 / L05B01) must be matched **or exceeded** by the
  v6/v7 pipeline on the same fp_l05_01 inputs — including cross-BG
  dwelling identity, modest style, and clean / dirty BG layer
  separation. The W18G/H 5-BG outputs are archive baselines for diff
  only; image-level parity to *them* is explicitly not the goal,
  because they exhibit the luxury / showroom drift this migration is
  meant to remove. Image-level parity against the **accepted set** is
  the user-facing acceptance bar; deterministic invariants alone are
  insufficient.

## 6. Suggested migration wave breakdown

- **W19A** — `floor_plan_prompt` v6 prompt + LLM partition wiring.
  Wires the `base_layer_decision` enum (§2.2) into FP candidate
  emission so transient markers are dropped from the FP image at the
  source. No DB write. Behind flag.
- **W19B** — `background_prompt` v7 prompt + per-bg overlay payload
  + `images.edit` call shape with the **W18J reference-graph planner
  (§2.6) injected at the BG prompt stage**. Adds the
  `overlap_reference_decision` artifact, the `bg_reference_catalog`
  seed-and-grow structure, and the mode-keyed
  `reference_mode_guidance` registry. No DB write. Behind flag. Must
  consume W19A output. The `style_reference_new_space` mode must be
  wired up at this stage even if no L05 BG triggers it (so cross-fp
  expansion does not require a second migration wave to enable it).
- **W19C** — cross-fp re-validation (fp_l07_01, fp_l11_01) on the
  new path before flag flip. The validation run must observe a
  **non-trivial reference graph / non-trivial overlap topology**: at
  minimum one `fp_seeded_anchor` decision, one `reference_derived`
  decision, and (where the candidate set permits) one
  `style_reference_new_space` decision. Specific room-kind coverage
  (e.g. a service-room-only or open-service-zone-only BG) is a
  useful example signal, not a hard gate — the planner branches
  themselves are the contract.
- **W19D** — flag flip + production migration in the actual pipeline
  + DB / ImageAsset writes.

Each sub-wave goes through Codex review before the next starts. No
sub-wave skips ahead.

## 7. Open questions for Codex review

1. Is `base_layer_decision` (6-value enum) the right discriminator,
   or should the migration introduce two independent boolean fields
   (`is_base_structural`, `is_state_overlay`)?
2. Should the FP image be re-rendered for every BG even if only the
   overlay differs (per-bg FP copy + overlay), or strictly shared
   once per fp_id as W18 validated (single FP PNG referenced by all
   BGs)? W18 evidence favors the single-FP-shared model.
3. Should W15e source prose be rewritten upstream to strip transient
   marker references, or should v7 keep "carry + diagnostic"
   behavior as W18F validated?
4. Where does the per-bg overlay payload live in the production
   pipeline — alongside the FP candidate, or as a new pipeline
   stage that runs between `floor_plan_prompt` and
   `background_prompt`?
5. What is the canonical name for the new artifact shapes
   (`bg_to_fp_region_ref`, `background_prompt_region_appendix`,
   `assembled_background_prompt`,
   `overlap_reference_decision`, `bg_reference_catalog`) in the
   production schema?
6. The `style_reference_new_space` dispatch (§2.6 step 3) is now
   anchored on "the BG's local / dominant target unit is not yet
   present in any catalog entry's `unit_set`". How should that
   *dominant target unit* be represented in the per-bg payload
   shape? Candidates: (a) the planner picks the first / lowest-id
   member of `target_unit_refs`; (b) the upstream W18A2 stage marks
   exactly one `target_unit_refs` entry as `is_primary_focus`; (c)
   the per-bg payload carries an explicit `dominant_target_unit_id`
   field. All three options remain exact-ID deterministic and avoid
   lexical inference; the choice is a shape question. The earlier
   wording of this question (numeric overlap threshold vs LLM hint
   trigger) is **resolved**: the dispatch is deterministic on
   exact-ID criteria, FP / catalog-ref mutual exclusion is a locked
   rule (§3.2), and any LLM-emitted hint such as
   `living_adjacent_inheritance: true` is recorded as a supporting
   / diagnostic field only on the planner record.
7. For `style_reference_new_space`, should `image` carry exactly one
   reference, or up to two? W18J's L05B01 used two references but the
   second contributed little measurable identity carry; a single
   strong style ref may be sufficient.
8. Is `bg_reference_catalog` a per-run ephemeral artifact, or does it
   persist alongside ImageAsset so a future "regenerate one BG"
   workflow can resume against a frozen catalog without rebuilding
   prior PNGs?
9. How should the migration generalize when a single fp contains
   multiple service-room-only spaces (e.g. two service-room-only
   spaces of the same kind, or two distinct single-purpose service
   spaces)? The current planner has no per-room-kind constraint and
   would allow two distinct service-room-only anchors to converge
   via `reference_derived` ties; that may produce style drift inside
   what should be visually distinct rooms.
