Skip to content

MODEL AUDIT (#1553): Scenario model registry + provenance gate + bake-off#1554

Merged
100yenadmin merged 1 commit into
mainfrom
model-audit
Jul 11, 2026
Merged

MODEL AUDIT (#1553): Scenario model registry + provenance gate + bake-off#1554
100yenadmin merged 1 commit into
mainfrom
model-audit

Conversation

@100yenadmin

Copy link
Copy Markdown
Member

Closes #1553 (M-ALIGN model audit). Facts pulled from Scenario metadata (model_get/asset_get/assets_list/model_schema_get), not recall.

Provenance — which model made each canonical plate (owner's exact question)

Plate Base Trained LoRA? Style pass
camp truegrey flux.1-dev depth-CN NO — plain flux.1-dev Gemini 3.1 no-ref
tavern flux.1-dev depth-CN NO — plain flux.1-dev Gemini 3.1 (asset_2Bc7…)
crypt incumbent crypt_armb_iter3 (8.0) flux.1-dev depth-CN NO — plain flux.1-dev Gemini iter2f→iter3
crypt-rich (6.5, honest neg) flux.1-dev depth-CN YES G379@0.85 (asset_rYC4…) Gemini 3.1

Answer: the tavern/camp bases applied NO trained LoRA — plain flux.1-dev + depth ControlNet. The RsWE exterior-LoRA camp frames are a separate, unadopted lane. The only canonical-adjacent plate using a trained LoRA (crypt-rich) underperformed the LoRA-free incumbent.

Training-set quality

FLUX.2 ControlNet check (Task 4)

model_schema_get("model_bfl-flux-2-dev") exposes no controlImage/controlModality/controlStrength — only referenceImages. FLUX.2 does not support depth ControlNet today, so the owner's highest-rated model (J97 v2, real refs, txt2img-only) cannot drive the registered geometry-locked path → REFERENCE-ONLY.

Bake-off (one fixed crypt greybox, shared seed 12345, blind 5-scorer panel, 103/120 CU)

Arm Recipe Median (n=5) Δ vs control (9.0) Edge-recall Defects
A plain flux → Gemini 6.0 −3.0 0.862 fake-text 4/5 (signature)
B + G379 interior → Gemini 7.0 −2.0 0.965 none
C + RsWE exterior → Gemini 6.0 −3.0 0.984 fake-text 4/5 + drift
D flux.2 + v2 txt2img (beauty) 7.0 −2.0 n/a none
control real PoE2 plate 9.0 in-band [6.8,9.2] ✓

Control in-band → panel valid. Registered arms cluster 6.0–7.0, far below real art (9.0). v2-Flux2 (D) ties the best styled arm and is defect-clean — top quality, but unregisterable. Arms A/C were dragged under the adoption bar by a hallucinated text/signature artifact on the Gemini pass — a per-seed defect, not proof the interior LoRA beats plain flux (the LoRA-free incumbent scores 8.0). Single-seed caveat documented in bakeoff_panel_verdict.json. Frames embedded below.

Bake-off frames

  • A (plain flux+Gemini): qa/evidence/model-audit/bakeoff/arm_a_styled_plain_flux.png
  • B (G379 interior+Gemini): arm_b_styled_g379_interior.png
  • C (RsWE exterior+Gemini): arm_c_styled_rswe_exterior.png
  • D (flux.2 v2 beauty): arm_d_flux2_v2_beauty.png

Deliverables

  • docs/MODEL-REGISTRY.md — one row/model (base, training-data class, measured results, ROLE, verdict CANONICAL/REFERENCE-ONLY/CANDIDATE/DEPRECATED). Never delete a model (account rule) — deprecate here.
  • qa/model_registry.json — machine-readable allowlist the gate checks.
  • qa/plate_loop.py — stamps the full model chain (base + LoRAs + scales + style-pass model) into each loop JSON row + panel contract, from scenario_meta.json (or a config-declared model_chain).
  • tools/library/promote.py — room provenance gate: REFUSES a candidate whose model_chain uses a model absent from qa/model_registry.json. Additive — a NO-OP when the registry file is absent (default-allow) or a candidate carries no chain (legacy), mirroring the existing _paint_drift_gate.

Tests

New: model-chain extraction (test_plate_loop.py) + registry gate refuse/allow/additive/panel-read (test_visual_promotion_gate.py). 81 passed on the three touched suites; the 1 remaining failure (test_committed_visual_registry_matches_builder) is pre-existing and environmental (LEXAR-mounted bg2ee frames), confirmed by re-running on clean main.

Scenario spend

103 CU of the 120 cap (4 base gens + 3 Gemini passes; per-gen dry-run priced). No training, no deletion. Usage API returned 403 (role lacks GET /usages); CU tracked from each job's cuCost.

Feeds #1546: retrain on REAL refs (v4/v2) only, on a flux.1/z-image base (flux.2 can't register); never on our own generated plates (that made G379 a dead end).

…-off

Governance for the 7 trained Scenario models (M-ALIGN). Facts pulled from
Scenario metadata, not recall.

Findings:
- Provenance: the adopted canonical plates (camp truegrey, tavern, crypt_armb_iter3
  8.0) all use PLAIN flux.1-dev depth-CN base + Gemini 3.1 style pass — NO trained
  WorldOS LoRA. Only crypt-rich (6.5, honest negative) used a trained LoRA (G379).
- Training quality: G379 Architectural FLUX is AI-ON-AI (8/10 training images are
  our own generated plates) -> DEPRECATED. v2/v4 sets are REAL PoE2/ArtStation refs.
- flux.2-dev has NO controlImage/controlModality param (verified live) -> the owner's
  favourite v2 model is txt2img-only, cannot drive the registered path -> REFERENCE-ONLY.
- Bake-off (1 crypt greybox, shared seed, blind 5-scorer panel, control 9.0 in-band,
  103/120 CU): registered arms cluster 6.0-7.0 << real art 9.0; v2-Flux2 beauty ties
  the best styled arm but can't register; plain/exterior arms hit a text-hallucination
  artifact (single-seed caveat documented).

Deliverables:
- docs/MODEL-REGISTRY.md (role + verdict per model) + qa/model_registry.json (gate allowlist)
- plate_loop.py: stamp full model chain (base+loras+scales+style) into loop JSON
- promote.py: additive room provenance gate — refuse a chain using an unregistered
  model; NO-OP when the registry file is absent or a candidate carries no chain
- tests: model-chain extraction + registry-gate (refuse/allow/additive/panel-read)

Evidence: qa/evidence/model-audit/bakeoff/ (frames + bakeoff_panel_verdict.json)
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bfbce60b-13bc-449a-8028-a70a427d4bf4

📥 Commits

Reviewing files that changed from the base of the PR and between 9b95aa5 and d709547.

⛔ Files ignored due to path filters (12)
  • qa/evidence/model-audit/bakeoff/arm_a_base_plain_flux.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_a_styled_plain_flux.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_b_base_g379_interior.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_b_styled_g379_interior.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_c_base_rswe_exterior.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_c_styled_rswe_exterior.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_d_flux2_v2_beauty.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/arm_d_flux2_v2_beauty_view.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/panel/image_1.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/panel/image_3.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/panel/image_4.png is excluded by !**/*.png
  • qa/evidence/model-audit/bakeoff/panel/image_5.png is excluded by !**/*.png
📒 Files selected for processing (9)
  • docs/MODEL-REGISTRY.md
  • qa/evidence/model-audit/bakeoff/bakeoff_panel_verdict.json
  • qa/evidence/model-audit/bakeoff/panel/README.md
  • qa/evidence/model-audit/bakeoff/panel_mapping.json
  • qa/model_registry.json
  • qa/plate_loop.py
  • qa/test_plate_loop.py
  • qa/test_visual_promotion_gate.py
  • tools/library/promote.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch model-audit

Comment @coderabbitai help to get the list of available commands.

@evaos-code-review-bot

evaos-code-review-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

evaOS review status: completed

PR: #1554 - MODEL AUDIT (#1553): Scenario model registry + provenance gate + bake-off
Head: d7095471905a50dfd14ed00c578a6d09d89c0c26
Updated: 2026-07-11T04:15:13.762Z

evaOS review completed for this PR head.

Automation note: agents should wait for this comment to reach completed, stale_head, closed_or_merged_before_review, skipped, or failed before treating evaOS review as settled for this head. provider_deferred means evaOS still intends to retry.

PR URL: #1554

Review URL: #1554 (review)

@evaos-code-review-bot evaos-code-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough

PR: #1554 - MODEL AUDIT (#1553): Scenario model registry + provenance gate + bake-off
Head: d7095471905a50dfd14ed00c578a6d09d89c0c26 into main. Review event: COMMENT.
Provider: GLM/Z.ai through ZCode (zcode-glm, zcode, model GLM-5.2).

Estimated review effort: 5/5 (~70 min)

Changed Files

File Status Churn Purpose Risk
qa/evidence/model-audit/bakeoff/arm_a_base_plain_flux.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_a_styled_plain_flux.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_b_base_g379_interior.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_b_styled_g379_interior.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_c_base_rswe_exterior.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_c_styled_rswe_exterior.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_d_flux2_v2_beauty.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/arm_d_flux2_v2_beauty_view.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/bakeoff_panel_verdict.json added +53/-0 Changed file Low
qa/evidence/model-audit/bakeoff/panel/README.md added +5/-0 Documentation Low
qa/evidence/model-audit/bakeoff/panel/image_1.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/panel/image_3.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/panel/image_4.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/panel/image_5.png added +0/-0 Changed file Low
qa/evidence/model-audit/bakeoff/panel_mapping.json added +1/-0 Changed file Low
qa/model_registry.json added +94/-0 Changed file Moderate: validated P3 finding
qa/plate_loop.py modified +109/-1 Changed file Moderate: validated P3 finding
qa/test_plate_loop.py modified +59/-0 Test coverage Low
qa/test_visual_promotion_gate.py modified +93/-0 Test coverage Low

Review Signal

Validated inline findings: 2 (P0: 0, P1: 0, P2: 0, P3: 2).
Dropped findings before posting: 0. High-severity findings: 0.

Risk Taxonomy

  • Runtime correctness: 1
  • Security boundary: 1

Validation and Proof

1 required validation/proof recommendation(s) selected from changed files.

  • required: Unity editor or Play Mode smoke - WorldOS repo profile implies Unity runtime risk. Proof: Unity editor smoke; Play Mode log; scene/prefab screenshot or recording.
    Proof status: missing - 1 required validation/proof recommendation(s) missing from PR metadata.
    Profile validation hints: Prefer correctness, persistence, CI, release, and regression findings over style-only feedback.
    Profile proof expectations: Look for Unity editor, play-mode, fixture, or focused smoke evidence when runtime behavior changes.

Related Context

Related issues/PRs: #1553, #1546.
Suggested labels: docs, tests.
Suggested reviewers: none from current metadata.

Review Settings Preview

  • Profile: assertive
  • Enabled sections: Review summary (inline_review); Walkthrough (inline_review); Changed-files table (walkthrough); Effort estimate (walkthrough); Related issues/PRs (walkthrough); Suggested labels (suggestion_only); Review status comment (sticky_status)
  • Path instructions: Assets/** - Prioritize scene, prefab, save-state, asset-reference, and gameplay regressions.
  • Path instructions: ProjectSettings/** - Treat build, platform, input, graphics, and release behavior changes as high risk.
  • Label suggestions: unity, gameplay, regression-hardening
  • Reviewer suggestions: none
  • Suggestion behavior: suggestions only; labels and reviewers are not auto-applied.
  • Roadmap-only settings: auto-apply labels; auto-request reviewers; required status checks

Pre-merge checklist

  • Inline comments target current RIGHT-side diff lines.
  • No secret-like content survived into posted inline comments.
  • REQUEST_CHANGES is only used when eligible P0/P1 findings survive validation.
  • Required behavior proof is present or not applicable.
  • Labels and reviewers are suggestions only; the bot did not auto-apply them.

Comment thread qa/plate_loop.py
if "model_ids" not in declared:
declared = dict(declared)
declared["model_ids"] = _collect_chain_model_ids(declared)
return declared

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Declared model_chain returned by reference (minor aliasing)

In read_model_chain, when a config-declared model_chain already contains model_ids, the function returns the declared dict by reference (cfg.raw["model_chain"]) without copying. Downstream the chain is serialized into the gallery row and contract.json (phase1, lines ~824-835). Serialization is read-only today so this is not a live bug, but it aliases the live config object into the written JSON structures. If any future code mutates the returned chain (e.g. stamping a resolved asset id), it would mutate the caller's config in place. The copy-on-derive branch (line 316) already does dict(declared) — applying the same shallow copy on the early-return branch (when model_ids is already present) would make the contract uniform and avoid a subtle future aliasing footgun.

Category: Runtime correctness

Why this matters: Provenance objects that double as live config are a classic source of mutation surprises; this is a cheap preventive consistency fix, not a current defect.

Comment thread qa/model_registry.json
"verdict": "DEPRECATED"
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: New provenance gate is opt-in only until this file is trusted by callers

The model-provenance gate is correctly additive (no-op when qa/model_registry.json is absent), and that contract is well-tested (test_promote_batch_additive_when_registry_file_absent, test_model_registry_gate_noop_when_registry_absent). The trade-off to flag: because the gate only bites when the registry file exists AND a nomination declares a model_chain, any room plate minted before plate_loop stamped provenance (legacy) or any nomination hand-authored without model_chain bypasses the gate entirely. This is the documented additive design, not a defect — but it means the gate does not, by itself, prevent ad-hoc model selection for the legacy/hand-authored path until nominations uniformly carry model_chain (plate_loop now stamps it, but direct nominations.jsonl authoring does not). Consider tracking follow-up enforcement (e.g. require model_chain on room nominations once the registry is considered authoritative) in the #1553 issue rather than in this PR.

Category: Security boundary

Why this matters: A provenance gate that is trivially bypassed by omitting the field it checks gives a false sense of structural control; worth a tracked follow-up so the enforcement ratchet is explicit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d709547190

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread qa/plate_loop.py
Comment on lines +262 to +264
if meta.get("lora"):
loras.append({"id": meta["lora"], "scale": meta.get("lora_scale")})
_add(meta["lora"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not stamp unused recipe LoRAs

For generate_room-controlnet metadata, the top-level lora is only the recipe default; the ControlNet request sends LoRAs from controlnet.loras instead, and current ControlNet metas commonly have that list empty. By unconditionally adding meta["lora"], plain flux depth-ControlNet plates get stamped as using model_MB22..., which corrupts the owner-facing provenance/gate and can falsely reject future valid ControlNet plates whose unused recipe LoRA is not registered.

Useful? React with 👍 / 👎.

Comment thread tools/library/promote.py
passed=False) only when a chain IS present and references a model absent from the registry."""
if registry is None:
return {"ran": False, "passed": True, "reason": "no model registry file (default-allow)"}
chain = nom.get("model_chain") or panel.get("model_chain")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate the chain to the promoted panel

phase1 stamps model_chain into <out_dir>/panel/contract.json/gallery rows, but this fallback reads the JSON loaded from a room nomination's source_path (the completed visual-gate panel), and phase2 never copies the contract's chain into that panel. A normal room nomination following the documented class + source_path flow therefore reaches the legacy no-op path even for newly generated plates, so unregistered/ad-hoc models are not blocked unless the operator manually duplicates model_chain on the nomination.

Useful? React with 👍 / 👎.

Comment thread qa/plate_loop.py
Comment on lines +273 to +275
style_pass = meta.get("style_pass") if isinstance(meta.get("style_pass"), dict) else None
style_out: Optional[dict] = None
if style_pass:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include layered edit models in the chain

When generate_room.py --layered produces the final plate, the Gemini pass2/pass3 edits live under meta["layered"], not meta["style_pass"]. This chain builder only inspects style_pass, so layered plates omit the actual edit models from model_ids; if the layered recipe is switched to an unregistered editor, the provenance gate will still pass because it never sees that model.

Useful? React with 👍 / 👎.

Comment thread tools/library/promote.py
Comment on lines +629 to +631
explicit = chain.get("model_ids")
if isinstance(explicit, list):
return [x for x in explicit if isinstance(x, str) and x]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive IDs instead of trusting model_ids

When a chain carries model_ids, the gate returns that list without checking the structured base_model/loras/style_pass fields. For hand-declared chains or stale panel JSONs, an incomplete model_ids list can omit an unregistered LoRA while still including it under loras, causing the provenance gate to pass a model the chain itself records as used.

Useful? React with 👍 / 👎.

@100yenadmin

Copy link
Copy Markdown
Member Author

Architect review: APPROVED. Gate verified additive/no-op-safe (registry-absent → default-allow; chainless legacy → no-op; refuses only declared-unregistered chains — mirrors the _paint_drift_gate contract). Registry verdicts ratified: G379 DEPRECATED (AI-on-AI confirmed, 8/10 own plates), v2-Flux2 REFERENCE-ONLY (no controlImage on flux.2-dev, schema-verified), canonical chain = flux.1-dev+depth-CN → Gemini-3.1. One follow-up for #1553 (not blocking): consider a deprecated_after date so chains STAMPED after deprecation refuse deprecated models while grandfathered plates stay promotable — today the deprecation is human-advisory only. Training ruling stands for #1546: flux.1/z-image base, REAL refs only (v4+v2 corpus).

@100yenadmin 100yenadmin enabled auto-merge (squash) July 11, 2026 04:22
@100yenadmin 100yenadmin merged commit 2716e6d into main Jul 11, 2026
36 checks passed
@100yenadmin 100yenadmin deleted the model-audit branch July 11, 2026 04:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MODEL AUDIT: Scenario model governance — provenance per canonical plate, training-set quality, registry + gate

1 participant