mirror of
https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
synced 2026-03-22 22:30:45 -07:00
M07: Opts snapshot introduction
- Add modules/opts_snapshot.py with create_opts_snapshot(opts) - Capture snapshot in process_images_inner after prepare_prompt_seed_state - Full shallow copy of opts.data via SimpleNamespace - No runtime behavior change; snapshot write-only for M07 Made-with: Cursor
This commit is contained in:
parent
044e827dee
commit
87c8fe8651
4 changed files with 387 additions and 10 deletions
|
|
@ -1,12 +1,363 @@
|
|||
# M07 Plan — Opts Snapshot Introduction
|
||||
|
||||
Project: Serena
|
||||
Phase: Phase II — Runtime Seam Preparation
|
||||
Milestone: M07
|
||||
Title: Opts snapshot introduction
|
||||
Posture: Behavior-preserving refactor
|
||||
Target: TBD
|
||||
Project: Serena
|
||||
Phase: Phase II — Runtime Seam Preparation
|
||||
Milestone: M07
|
||||
Title: **Opts snapshot introduction**
|
||||
Posture: Behavior-preserving refactor
|
||||
Target: Introduce a stable **options snapshot mechanism** for generation runs.
|
||||
|
||||
Context: M06 isolated prompt/seed preparation into `prepare_prompt_seed_state(p)`, establishing a second runtime seam.
|
||||
|
||||
M07 introduces the **third seam**: a deterministic snapshot of `shared.opts` used for the duration of a generation run.
|
||||
|
||||
This prepares the runtime pipeline for dependency injection and removal of global option mutation in later milestones.
|
||||
|
||||
The milestone map defines this sequence explicitly:
|
||||
|
||||
* M05 — override isolation
|
||||
* M06 — prompt/seed prep extraction
|
||||
* **M07 — opts snapshot introduction**
|
||||
* M08 — snapshot threading into `process_images_inner`
|
||||
* M09 — execution context/state seam
|
||||
|
||||
---
|
||||
|
||||
*Plan to be populated.*
|
||||
# 1. Intent / Target
|
||||
|
||||
The current pipeline mutates `shared.opts` during generation via:
|
||||
|
||||
```
|
||||
override_settings
|
||||
```
|
||||
|
||||
This occurs in `process_images()` where overrides are temporarily applied and later restored.
|
||||
|
||||
This creates problems:
|
||||
|
||||
* hidden global mutation
|
||||
* non-deterministic runtime state
|
||||
* difficult testing
|
||||
|
||||
The goal of **M07** is to introduce an **immutable snapshot of opts** for generation runs without changing runtime behavior.
|
||||
|
||||
The snapshot is **not yet threaded through the runtime** (that happens in M08).
|
||||
|
||||
Instead, this milestone:
|
||||
|
||||
1. Creates a function that builds an **opts snapshot object**
|
||||
2. Captures it once at the start of `process_images()`
|
||||
3. Stores it on the processing object (`p.opts_snapshot`)
|
||||
|
||||
The runtime will continue to read from `shared.opts` for now.
|
||||
|
||||
This is purely **infrastructure preparation**.
|
||||
|
||||
---
|
||||
|
||||
# 2. Scope Boundaries
|
||||
|
||||
## In Scope
|
||||
|
||||
Introduce a new helper module:
|
||||
|
||||
```
|
||||
modules/opts_snapshot.py
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```
|
||||
create_opts_snapshot(opts)
|
||||
```
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* Copy relevant values from `shared.opts`
|
||||
* Return an immutable snapshot structure
|
||||
* Attach snapshot to `StableDiffusionProcessing`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
p.opts_snapshot = create_opts_snapshot(shared.opts)
|
||||
```
|
||||
|
||||
Snapshot should include frequently accessed generation settings such as:
|
||||
|
||||
* outdir configuration
|
||||
* sampler defaults
|
||||
* VAE settings
|
||||
* precision settings
|
||||
* clip skip
|
||||
* model settings
|
||||
|
||||
Exact contents may initially mirror `opts.data`.
|
||||
|
||||
---
|
||||
|
||||
## Out of Scope
|
||||
|
||||
This milestone **does NOT**:
|
||||
|
||||
* replace reads of `shared.opts`
|
||||
* remove override logic
|
||||
* change how options are applied
|
||||
* modify extension access patterns
|
||||
* alter UI/API option behavior
|
||||
|
||||
Those changes happen later (M08–M09).
|
||||
|
||||
---
|
||||
|
||||
# 3. Invariants
|
||||
|
||||
The following must remain identical.
|
||||
|
||||
### Generation behavior
|
||||
|
||||
Identical inputs must produce identical outputs.
|
||||
|
||||
### Options behavior
|
||||
|
||||
* override_settings logic unchanged
|
||||
* UI settings unchanged
|
||||
* CLI flags unchanged
|
||||
|
||||
### Extension compatibility
|
||||
|
||||
Extensions accessing:
|
||||
|
||||
```
|
||||
shared.opts
|
||||
```
|
||||
|
||||
must continue working.
|
||||
|
||||
### API compatibility
|
||||
|
||||
txt2img and img2img responses remain unchanged.
|
||||
|
||||
### Runtime state
|
||||
|
||||
No behavioral change to model loading or VAE logic.
|
||||
|
||||
---
|
||||
|
||||
# 4. Verification Plan
|
||||
|
||||
## CI Gates
|
||||
|
||||
All existing CI checks must pass:
|
||||
|
||||
* Smoke Tests
|
||||
* Linter
|
||||
* Quality Tests
|
||||
* Coverage ≥ 40%
|
||||
|
||||
The CI suite already executes the generation path via API smoke tests.
|
||||
|
||||
If option behavior breaks, smoke tests will fail.
|
||||
|
||||
---
|
||||
|
||||
## Local verification
|
||||
|
||||
Recommended commands:
|
||||
|
||||
```
|
||||
pytest test/smoke
|
||||
pytest test/quality
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Implementation Steps
|
||||
|
||||
## Step 1 — Create snapshot module
|
||||
|
||||
Create file:
|
||||
|
||||
```
|
||||
modules/opts_snapshot.py
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```
|
||||
create_opts_snapshot(opts)
|
||||
```
|
||||
|
||||
Example structure:
|
||||
|
||||
```python
|
||||
from types import SimpleNamespace
|
||||
|
||||
def create_opts_snapshot(opts):
|
||||
return SimpleNamespace(**opts.data.copy())
|
||||
```
|
||||
|
||||
Important properties:
|
||||
|
||||
* shallow copy of `opts.data`
|
||||
* no mutation allowed
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Capture snapshot
|
||||
|
||||
Inside:
|
||||
|
||||
```
|
||||
process_images_inner(p)
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```
|
||||
p.opts_snapshot = create_opts_snapshot(shared.opts)
|
||||
```
|
||||
|
||||
Placement:
|
||||
|
||||
Immediately after prompt/seed preparation.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Preserve override behavior
|
||||
|
||||
The snapshot must capture **post-override settings**.
|
||||
|
||||
Therefore ensure the snapshot is created **after override_settings are applied**.
|
||||
|
||||
Current order:
|
||||
|
||||
```
|
||||
apply override_settings
|
||||
prepare prompts/seeds
|
||||
```
|
||||
|
||||
New order:
|
||||
|
||||
```
|
||||
apply override_settings
|
||||
prepare prompts/seeds
|
||||
capture opts snapshot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Avoid runtime behavior change
|
||||
|
||||
The snapshot should **not yet replace any option reads**.
|
||||
|
||||
Example:
|
||||
|
||||
Keep existing code:
|
||||
|
||||
```
|
||||
opts.outdir_samples
|
||||
```
|
||||
|
||||
Do NOT change to:
|
||||
|
||||
```
|
||||
p.opts_snapshot.outdir_samples
|
||||
```
|
||||
|
||||
That change occurs in **M08**.
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Minimal structural validation
|
||||
|
||||
Optionally add a small test:
|
||||
|
||||
```
|
||||
test_opts_snapshot.py
|
||||
```
|
||||
|
||||
Validate:
|
||||
|
||||
* snapshot contains expected attributes
|
||||
* snapshot does not mutate when opts change afterward
|
||||
|
||||
This is optional.
|
||||
|
||||
---
|
||||
|
||||
# 6. Risk & Rollback Plan
|
||||
|
||||
Risk: **Very low**
|
||||
|
||||
Changes:
|
||||
|
||||
```
|
||||
modules/opts_snapshot.py
|
||||
modules/processing.py
|
||||
```
|
||||
|
||||
Failure scenarios:
|
||||
|
||||
* snapshot created before overrides
|
||||
* extension code accidentally reading snapshot
|
||||
|
||||
Mitigation:
|
||||
|
||||
* ensure snapshot is write-only in M07
|
||||
* snapshot stored only on `p`
|
||||
|
||||
Rollback:
|
||||
|
||||
Revert the commit.
|
||||
|
||||
---
|
||||
|
||||
# 7. Deliverables
|
||||
|
||||
Expected files:
|
||||
|
||||
```
|
||||
modules/opts_snapshot.py (new)
|
||||
modules/processing.py (modified)
|
||||
docs/milestones/M07/* (plan, toolcalls, CI reports)
|
||||
```
|
||||
|
||||
No other modules should change.
|
||||
|
||||
---
|
||||
|
||||
# 8. Expected Outcome
|
||||
|
||||
After M07:
|
||||
|
||||
* generation runs capture a **deterministic opts snapshot**
|
||||
* runtime seams now include:
|
||||
|
||||
```
|
||||
temporary_opts() (M05)
|
||||
prepare_prompt_seed_state (M06)
|
||||
opts snapshot (M07)
|
||||
```
|
||||
|
||||
These seams prepare the system for:
|
||||
|
||||
```
|
||||
M08 — snapshot threading into process_images_inner
|
||||
M09 — execution context/state seam
|
||||
```
|
||||
|
||||
Together they begin removing the **global state dependency** identified in the pre-refactor audit.
|
||||
|
||||
---
|
||||
|
||||
# 9. Success Criteria
|
||||
|
||||
M07 is complete when:
|
||||
|
||||
* opts snapshot helper exists
|
||||
* snapshot attached to `StableDiffusionProcessing`
|
||||
* no runtime behavior change
|
||||
* CI fully green
|
||||
* milestone artifacts generated
|
||||
* ledger updated
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
# M07 Toolcalls — Opts Snapshot Introduction
|
||||
|
||||
| Timestamp | Tool | Purpose | Files/Target | Status |
|
||||
|-----------|------|---------|-------------|--------|
|
||||
| | | | | |
|
||||
Implementation toolcalls for Cursor execution.
|
||||
|
||||
(To be filled during milestone execution.)
|
||||
|
||||
| Timestamp | Tool | Purpose | Files | Status |
|
||||
|-----------|------|---------|-------|--------|
|
||||
| 2026-03-10 | write | Create M07_plan.md | docs/milestones/M07/M07_plan.md | ✓ |
|
||||
| 2026-03-10 | write | Create M07_toolcalls.md | docs/milestones/M07/M07_toolcalls.md | ✓ |
|
||||
| 2026-03-10 | write | Create opts_snapshot module | modules/opts_snapshot.py | ✓ |
|
||||
| 2026-03-10 | search_replace | Add create_opts_snapshot import | modules/processing.py | ✓ |
|
||||
| 2026-03-10 | search_replace | Add opts snapshot capture after prepare_prompt_seed_state | modules/processing.py | ✓ |
|
||||
| 2026-03-10 | run | Local pytest (smoke/quality) | — | Skipped: full env (gradio, torch) not installed locally; CI will verify |
|
||||
|
|
|
|||
15
modules/opts_snapshot.py
Normal file
15
modules/opts_snapshot.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
"""Opts snapshot for generation runs.
|
||||
|
||||
M07: Deterministic snapshot of shared.opts for the duration of a run.
|
||||
Behavior-preserving: shallow copy of opts.data.
|
||||
Not yet threaded through runtime.
|
||||
"""
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
def create_opts_snapshot(opts):
|
||||
"""
|
||||
Create an immutable snapshot of shared.opts for a generation run.
|
||||
Behavior-preserving: shallow copy of opts.data.
|
||||
"""
|
||||
return SimpleNamespace(**opts.data.copy())
|
||||
|
|
@ -26,6 +26,7 @@ import modules.paths as paths
|
|||
import modules.face_restoration
|
||||
import modules.images as images
|
||||
import modules.styles
|
||||
from modules.opts_snapshot import create_opts_snapshot
|
||||
import modules.prompt_seed_prep as prompt_seed_prep
|
||||
import modules.runtime_utils as runtime_utils
|
||||
import modules.sd_models as sd_models
|
||||
|
|
@ -891,6 +892,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
|||
p.setup_prompts()
|
||||
|
||||
prompt_seed_prep.prepare_prompt_seed_state(p)
|
||||
p.opts_snapshot = create_opts_snapshot(shared.opts)
|
||||
|
||||
if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
|
||||
model_hijack.embedding_db.load_textual_inversion_embeddings()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue