Skip to content

chore(qa): RRI scorer + GUI runbook/workbook + RRI gates (operating goal & scorecard) - #413

Merged
100yenadmin merged 1 commit into
mainfrom
chore/rri-artifacts
May 30, 2026
Merged

chore(qa): RRI scorer + GUI runbook/workbook + RRI gates (operating goal & scorecard)#413
100yenadmin merged 1 commit into
mainfrom
chore/rri-artifacts

Conversation

@100yenadmin

@100yenadmin 100yenadmin commented May 30, 2026

Copy link
Copy Markdown
Member

Release Readiness Index tooling + the GUI look-and-wire runbook, from the 2026-05-31 GUI reorientation. qa/release_readiness.py (11 hard gates → 0-10, disk-artifact reader). WorldOS-GUI-RUNBOOK.md (two-surface loop). qa/GUI_WORKBOOK.md (punch-list). OPERATING-GOAL §4 + SCORECARD extended with RRI (adds image-render-rate + palette-live gates — the two owner-visible defects). Docs/tooling only; engine + wire contracts untouched.

Summary by CodeRabbit

  • Documentation

    • Added comprehensive guides for release testing, verification procedures, and operational standards.
    • Created QA workbook documenting verified issues, testing methodology, and fix verification.
  • Tests

    • Implemented automated release readiness assessment system with quality gates to ensure consistent product stability and feature completion before release.

Review Change Stack

…oal & scorecard)

Release Readiness Index (qa/release_readiness.py): 11 hard gates -> 0-10, reads disk
artifacts (robust to tool-channel fabrication). Adds image-render-rate + palette-live
gates (the two owner-visible defects the old gate could pass while broken).
WorldOS-GUI-RUNBOOK.md: two-surface look-and-wire loop (iterate 8799-from-canonical,
gate on built .app). qa/GUI_WORKBOOK.md: living punch-list. OPERATING-GOAL section 4 +
SCORECARD extended with RRI. Docs/tooling only; engine + wire contracts untouched.
@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR establishes a Release Readiness Index (RRI) framework for the WorldOS GUI: defining hard-gated success criteria in policy documents, implementing a Python script that aggregates on-disk QA artifacts into a single readiness signal, and integrating RRI scoring into the daily release and fix loop.

Changes

Release Readiness Index (RRI) Framework, Script, and Operational Integration

Layer / File(s) Summary
Operating Goal and Release Readiness Index Policy
WorldOS-OPERATING-GOAL.md
Defines the operating goal (fresh player completes 8-beat native session without "feels broken"), establishes P0 testing constraints (use built dist/WorldOS.app only), introduces Release Readiness Index with 11 hard gates (native routing, arc/combat/travel/rest completion, satisfaction/give-up/critical bug thresholds, story/mech/behavioral rubrics, UI/a11y health, image-render rate, palette-live/clickable tools), and specifies fail/iterate/maintain loops, release-verifier role, and load-bearing discipline around the built-and-played app as ground truth.
Release Readiness Index Script Implementation
qa/release_readiness.py
Pure on-disk artifact reader that parses persona run directories (score.json, network.ndjson, run.json) to compute image-render-rate signal, aggregates cross-persona metrics (average satisfaction, total critical bugs, weighted image rate), evaluates all 11 gates using hard-floor rule (release-ready only if all gates pass), and outputs JSON report with RRI score, gate details, per-persona signals, and aligned exit code. Accepts external-gated inputs (--behavioral, --ui-audit, --palette-live) and optional story/mech rubric JSON files for numeric thresholds.
GUI Runbook, QA Workbook, and Scorecard Integration
WorldOS-GUI-RUNBOOK.md, qa/GUI_WORKBOOK.md, qa/SCORECARD.md
Operational documentation integrating RRI into daily loop: runbook specifies two-surface test model (iteration on 8799 vs built-app gate), LOOK verification with curl/HTTP/JSON, fix→PR→merge→rebuild→LOOK loop with worktree hygiene, gate sweep using qa/release_readiness.py, release instructions, and hard operational rules; workbook is living QA punch-list of verified GUI defects (G3–G7) with root causes and fix status; scorecard records release readiness sweeps referencing RRI computation and merged fixes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • electricsheephq/WorldOS#325: The new qa/release_readiness.py script parses the same persona run artifacts (score.json, network.ndjson) generated by the playtester harness added in this PR, making them directly connected at the QA artifact integration level.
  • electricsheephq/WorldOS#374: This PR's qa/release_readiness.py computes RRI from on-disk persona/app playtest artifacts (e.g., run.json, score.json, network.ndjson) produced by the BUILT .app harness in qa/ui_playtest_app.sh.

Poem

🐰 A runbook for the rabbit to read,
Eleven gates to measure our seed,
From artifact to RRI we score,
Release readiness—the ground truth floor!
hop → build → test → gate → ship! 🚀

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description outlines key changes but is missing required CLA and validation checkboxes from the repository template. Add the required 'Licensing / CLA' and 'Validation' sections with appropriate checkboxes as specified in the template.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: new Release Readiness Index scoring tool, GUI runbook/workbook, and RRI gate additions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qa/release_readiness.py`:
- Line 140: The tuple entry for "arc_completed" uses an unnecessary f-string
literal f"completed_intro_flow on >=1 persona" which triggers Ruff F541; change
that literal to a plain string "completed_intro_flow on >=1 persona" in the
mapping where "arc_completed" is defined (the tuple containing any_completed and
the message) so the code uses a regular string rather than an f-string with no
placeholders.
- Around line 67-70: The status parsing in image_render_rate (variables net,
img, ok calculation) can raise when n.get("status") is non-numeric; change the
ok computation to safely coerce status to int (or treat as non-OK) by wrapping
int conversion in a try/except (ValueError, TypeError) or using a small helper
like safe_int(status, default=0) and only count entries where the parsed int is
>0 and <400; ensure you reference the same variables (img, ok, total) and retain
the existing logic that malformed statuses are treated as failures (not
incrementing ok).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c9f511c6-9ee9-4969-ad79-45b9f26dc7b6

📥 Commits

Reviewing files that changed from the base of the PR and between b23884c and 41ff488.

📒 Files selected for processing (5)
  • WorldOS-GUI-RUNBOOK.md
  • WorldOS-OPERATING-GOAL.md
  • qa/GUI_WORKBOOK.md
  • qa/SCORECARD.md
  • qa/release_readiness.py

Comment thread qa/release_readiness.py
Comment on lines +67 to +70
img = [n for n in net if "/image" in str(n.get("url", ""))]
if img:
ok = sum(1 for n in img if int(n.get("status", 0) or 0) and int(n.get("status")) < 400)
total = len(img)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant portion around the reported lines
sed -n '1,120p' qa/release_readiness.py | nl -ba | sed -n '55,95p'

# Locate the function definition and show its full body (if not too large)
rg -n "def image_render_rate" -S qa/release_readiness.py
python3 - <<'PY'
import re, itertools
path="qa/release_readiness.py"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
# find def image_render_rate
start=None
for i,l in enumerate(lines):
    if re.search(r'^\s*def\s+image_render_rate\s*\(', l):
        start=i
        break
if start is None:
    raise SystemExit("image_render_rate not found")
# print until next def/class at same indent (best-effort)
indent=re.match(r'^(\s*)def', lines[start]).group(1)
end=len(lines)
for j in range(start+1,len(lines)):
    if re.match(r'^'+re.escape(indent)+r'(def|class)\s', lines[j]):
        end=j
        break
for k in range(start,end):
    print(f"{k+1:4d}:{lines[k].rstrip()}")
PY

# Check for any existing safe parsing helpers or similar logic in this file
rg -n "int\\(.*status" qa/release_readiness.py
rg -n "status.*int\\(" qa/release_readiness.py
rg -n "ValueError|TypeError" qa/release_readiness.py

Repository: electricsheephq/WorldOS

Length of output: 110


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Snippet around lines ~55-95 =="
awk 'NR>=55 && NR<=95 {printf "%4d:%s\n", NR, $0}' qa/release_readiness.py

echo "== Find image_render_rate definition =="
rg -n "def image_render_rate" qa/release_readiness.py

echo "== Show image_render_rate function body (best-effort) =="
python3 - <<'PY'
import re
path="qa/release_readiness.py"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()

start=None
for i,l in enumerate(lines):
    if re.search(r'^\s*def\s+image_render_rate\s*\(', l):
        start=i
        break
if start is None:
    raise SystemExit("image_render_rate not found")

indent = re.match(r'^(\s*)def', lines[start]).group(1)
end=len(lines)
for j in range(start+1, len(lines)):
    if re.match(r'^'+re.escape(indent)+r'(def|class)\s', lines[j]):
        end=j
        break

for k in range(start, end):
    print(f"{k+1:4d}:{lines[k].rstrip()}")
PY

echo "== Search for status int parsing in this file =="
rg -n "int\(.{0,40}status|status.{0,40}int\(" qa/release_readiness.py

echo "== Search for ValueError/TypeError handling =="
rg -n "ValueError|TypeError" qa/release_readiness.py

Repository: electricsheephq/WorldOS

Length of output: 3502


Harden status parsing in image_render_rate to avoid scorer crashes on non-numeric status
Line 69 calls int(n.get("status")) without guarding, so malformed/non-numeric status values in network.ndjson can raise and terminate scoring.

💡 Proposed fix
 def image_render_rate(run: Path, score: dict) -> tuple[float, int, int]:
@@
-    if img:
-        ok = sum(1 for n in img if int(n.get("status", 0) or 0) and int(n.get("status")) < 400)
+    if img:
+        def _status_code(v: object) -> int:
+            try:
+                return int(v or 0)
+            except (TypeError, ValueError):
+                return 0
+
+        ok = sum(
+            1
+            for n in img
+            if (code := _status_code(n.get("status"))) and code < 400
+        )
         total = len(img)
         return (ok / total if total else 1.0), ok, total
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qa/release_readiness.py` around lines 67 - 70, The status parsing in
image_render_rate (variables net, img, ok calculation) can raise when
n.get("status") is non-numeric; change the ok computation to safely coerce
status to int (or treat as non-OK) by wrapping int conversion in a try/except
(ValueError, TypeError) or using a small helper like safe_int(status, default=0)
and only count entries where the parsed int is >0 and <400; ensure you reference
the same variables (img, ok, total) and retain the existing logic that malformed
statuses are treated as failures (not incrementing ok).

Comment thread qa/release_readiness.py
# ---- the 11 gates (each contributes to RRI; all must hold for 10/10) ----
gates = {
"native_gate": (native == "PASS", f"part_a={native or 'n/a'}"),
"arc_completed": (any_completed, f"completed_intro_flow on >=1 persona"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the exact referenced line with context
nl -ba qa/release_readiness.py | sed -n '120,160p'

# Search for the specific string usage in the repo for consistency
rg -n 'completed_intro_flow on >=1 persona' -S .
rg -n 'F541|f"[^"]*{[^}]*}' qa/release_readiness.py -S || true

Repository: electricsheephq/WorldOS

Length of output: 110


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("qa/release_readiness.py")
lines = p.read_text(encoding="utf-8").splitlines()
start, end = 120, 160
for i in range(start, end+1):
    if 1 <= i <= len(lines):
        print(f"{i:4d}: {lines[i-1]}")
PY

python3 - <<'PY'
from pathlib import Path
p = Path("qa/release_readiness.py")
text = p.read_text(encoding="utf-8")
needle = 'completed_intro_flow on >=1 persona'
print("needle occurrences:", text.count(needle))
print("line with needle(s):")
for i, line in enumerate(text.splitlines(), 1):
    if needle in line:
        print(f"{i}: {line}")
PY

Repository: electricsheephq/WorldOS

Length of output: 2725


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find Ruff config (common names)
rg -n --hidden --no-ignore-vcs "ruff" pyproject.toml setup.cfg .ruff.toml ruff.toml 2>/dev/null || true
ls -la | head

# Locate Ruff config files
fd -tf ".ruff.toml" -d 4 . || true
fd -tf "pyproject.toml" -d 6 . || true
fd -tf "setup.cfg" -d 6 . || true
fd -tf "ruff.toml" -d 6 . || true

# Print relevant Ruff sections if pyproject.toml exists
if [ -f "pyproject.toml" ]; then
  echo "----- pyproject.toml ruff sections -----"
  python3 - <<'PY'
import re
from pathlib import Path
p=Path("pyproject.toml")
t=p.read_text(encoding="utf-8")
# crude extraction around ruff blocks
m=re.search(r"\[tool\.ruff[^\]]*\]", t)
print("Found tool.ruff:", bool(m))
PY
  rg -n "tool\.ruff|select|ignore|F541" pyproject.toml || true
fi

# Also directly search for F541 in repo config
rg -n "F541" -S . || true

Repository: electricsheephq/WorldOS

Length of output: 711


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show ruff config
echo "---- ruff.toml ----"
sed -n '1,200p' ruff.toml
echo "---- end preview ----"

# Search for F541 / ignore rules
rg -n "F541|f-string|F5(41|[0-9]{2})|select|ignore|extend-select|extend-ignore" ruff.toml || true

# Also locate any tool.ruff config in pyproject.toml files
for f in servers/*/pyproject.toml; do
  echo "---- $f ----"
  rg -n "tool\.ruff|F541|select|ignore|extend-select|extend-ignore" "$f" || true
done

Repository: electricsheephq/WorldOS

Length of output: 1595


Remove unused f-string prefix (F541)

qa/release_readiness.py:140 uses f"completed_intro_flow on >=1 persona" without placeholders; Ruff F541 will flag it.

💡 Proposed fix
-        "arc_completed":      (any_completed,               f"completed_intro_flow on >=1 persona"),
+        "arc_completed":      (any_completed,               "completed_intro_flow on >=1 persona"),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"arc_completed": (any_completed, f"completed_intro_flow on >=1 persona"),
"arc_completed": (any_completed, "completed_intro_flow on >=1 persona"),
🧰 Tools
🪛 Ruff (0.15.14)

[error] 140-140: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qa/release_readiness.py` at line 140, The tuple entry for "arc_completed"
uses an unnecessary f-string literal f"completed_intro_flow on >=1 persona"
which triggers Ruff F541; change that literal to a plain string
"completed_intro_flow on >=1 persona" in the mapping where "arc_completed" is
defined (the tuple containing any_completed and the message) so the code uses a
regular string rather than an f-string with no placeholders.

@100yenadmin
100yenadmin merged commit c6480a3 into main May 30, 2026
9 checks passed
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.

1 participant