Skip to content

Commit fe09ca4

Browse files
committed
Prove runtime-created world eval path
1 parent d538756 commit fe09ca4

9 files changed

Lines changed: 265 additions & 2 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ For a guided walkthrough of the canonical demo flow, see [docs/demo/fog-harbor-w
426426
- Phase 67 closeout shorthand: `#507` `Phase 67 exit gate` closed by PR `#514`; `#508` closed by PR `#510`; `#509` closed by PR `#512`; `#511` closed by PR `#513`.
427427
- Post-Phase-67 successor intake audit keeps the queue paused; `docs/plans/post-phase-67-successor-intake-audit-2026-06-08.md` records the successor-intake decision. No Phase 68 successor queue is opened by this audit. Do not open Phase 68 as an execution queue until this intake audit identifies a new source-backed minimum-loop gap or protected-core contract blocker. The intake remains tied to `corpus -> chunks -> graph -> personas -> scenarios -> deterministic runs -> report/claims -> eval`.
428428
- Post-Phase-67 outcome/report/eval generalization audit keeps the queue paused; `docs/plans/post-phase-67-outcome-report-eval-generalization-audit-2026-06-08.md` records that selected-world proof is current for `fog-harbor-east-gate`, `museum-night`, and `library-rain`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this audit.
429+
- Post-Phase-67 runtime-created world eval proof keeps the queue paused; `docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md` records that a runtime-created bounded world can pass `eval-world`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this proof.
429430
- Phase 48 is closed after PR `#382`, issue `#375`, and milestone `Phase 48 - Successor Intake and Boundary Contract Triage`.
430431
- Phase 49 is closed after PR `#395`, issue `#383`, and milestone `Phase 49 - Kernel, Perturbation, and Runtime Contract Hardening`; completed work items were `#384`, `#386`, `#388`, `#390`, `#392`, and `#394`.
431432
- Phase 50 is closed after PR `#402`, issue `#396`, and milestone `Phase 50 - Runtime Orchestration Measurement and Product Boundary`; completed work items were `#397`, `#398`, and `#401`. Phase 50 measured before any `task_id` or worker contract is introduced and kept the private-beta launch hub planning-only for now.

backend/app/evals/service.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
DEFAULT_TRANSFER_WORLD_IDS = [CANONICAL_DEMO_WORLD_ID, "museum-night", "library-rain"]
2929

3030

31+
def _default_redlines_path(repo_root: Path) -> Path:
32+
runtime_path = repo_root / "evals" / "assertions" / "redlines.yaml"
33+
if runtime_path.exists():
34+
return runtime_path
35+
return Path(__file__).resolve().parents[3] / "evals" / "assertions" / "redlines.yaml"
36+
37+
3138
def _compare(op: str, left: Any, right: Any) -> bool:
3239
if op == "gt":
3340
return left > right
@@ -559,7 +566,7 @@ def record(name: str, passed: bool, details: str) -> None:
559566
)
560567

561568
redline_failures = _evaluate_redlines_texts(
562-
world_paths.repo_root / "evals" / "assertions" / "redlines.yaml",
569+
_default_redlines_path(world_paths.repo_root),
563570
_transfer_redline_texts(artifacts_root),
564571
)
565572
record("redlines_pass", not redline_failures, "; ".join(redline_failures) if redline_failures else "ok")

backend/app/world_templates/service.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,24 @@ def _baseline_title(spec: CreateWorldTemplateInput) -> str:
173173
return f"Baseline {spec.world_name}"
174174

175175

176+
def _default_report_scenario_title(spec: CreateWorldTemplateInput) -> str:
177+
if _is_chinese(spec):
178+
return f"{spec.evidence_document_name}延迟"
179+
return f"{spec.evidence_document_name} Delay"
180+
181+
182+
def _default_report_scenario_description(spec: CreateWorldTemplateInput) -> str:
183+
if _is_chinese(spec):
184+
return (
185+
f"{spec.evidence_document_name}比基线晚两个回合进入决策链,"
186+
f"以验证{spec.public_event_name}{spec.response_location_name}响应是否随证据延迟而变化。"
187+
)
188+
return (
189+
f"{spec.evidence_document_name} reaches the decision loop two turns later than baseline, "
190+
f"testing whether {spec.public_event_name} and the response around {spec.response_location_name} change."
191+
)
192+
193+
176194
def _evaluation_questions(spec: CreateWorldTemplateInput) -> list[str]:
177195
if _is_chinese(spec):
178196
return [
@@ -598,10 +616,11 @@ def create_bounded_incident_world(
598616
}
599617
)
600618

619+
default_report_scenario = "evidence_delayed"
601620
simulation_rules = {
602621
"world_id": world_id,
603622
"compare_id": f"scenario_{world_id}_template_matrix",
604-
"default_report_scenario": "baseline",
623+
"default_report_scenario": default_report_scenario,
605624
"communications_down_field": "communications_down_until",
606625
"blocked_contacts_field": "blocked_contacts",
607626
"turn_sequence": [
@@ -895,6 +914,34 @@ def create_bounded_incident_world(
895914
}
896915
_write_yaml(world_root / "scenarios" / "baseline.yaml", baseline_scenario)
897916

917+
injected_scenario_id = f"scenario_{world_id}_{default_report_scenario}"
918+
injected_scenario = {
919+
"scenario_id": injected_scenario_id,
920+
"world_id": world_id,
921+
"title": _default_report_scenario_title(spec),
922+
"description": _default_report_scenario_description(spec),
923+
"seed": 11,
924+
"turn_budget": 8,
925+
"branch_count": 1,
926+
"evaluation_questions": _evaluation_questions(spec),
927+
"injections": [
928+
{
929+
"injection_id": "inj_evidence_delayed",
930+
"kind": "delay_document",
931+
"target_id": "doc_user_01",
932+
"actor_id": _role_persona_id("records_lead"),
933+
"params": {
934+
"delay_turns": 2,
935+
"cause": "routing_delay",
936+
},
937+
"rationale": (
938+
f"{spec.evidence_document_name} is delayed two turns before it reaches the decision loop."
939+
),
940+
}
941+
],
942+
}
943+
_write_yaml(world_root / "scenarios" / f"{default_report_scenario}.yaml", injected_scenario)
944+
898945
product_payload = {
899946
"world_id": world_id,
900947
"world_name": spec.world_name,

backend/tests/test_cli.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def test_cli_create_world_writes_runtime_world_pack(tmp_path: Path, capsys, monk
179179
assert (runtime_root / "state" / "worlds" / world_id / "config" / "world_model.yaml").exists()
180180
assert (runtime_root / "state" / "worlds" / world_id / "config" / "simulation_rules.yaml").exists()
181181
assert (runtime_root / "state" / "worlds" / world_id / "config" / "decision_schema.yaml").exists()
182+
assert (runtime_root / "state" / "worlds" / world_id / "scenarios" / "evidence_delayed.yaml").exists()
182183
assert (runtime_root / "state" / "artifacts" / "worlds" / world_id / "graph" / "graph.json").exists()
183184
assert (runtime_root / "state" / "artifacts" / "worlds" / world_id / "personas" / "personas.json").exists()
184185

@@ -198,6 +199,37 @@ def test_cli_create_world_writes_runtime_world_pack(tmp_path: Path, capsys, monk
198199
assert session_payload["world_id"] == world_id
199200

200201

202+
def test_cli_runtime_created_world_passes_eval_world(tmp_path: Path, capsys, monkeypatch) -> None:
203+
runtime_root = tmp_path / "repo"
204+
runtime_root.mkdir(parents=True, exist_ok=True)
205+
monkeypatch.setattr(cli_module, "get_settings", lambda: _runtime_settings(runtime_root))
206+
207+
assert main(["create-world", "--spec", json.dumps(_safe_world_template_spec())]) == 0
208+
create_payload = json.loads(capsys.readouterr().out)
209+
world_id = create_payload["world_id"]
210+
211+
assert main(["eval-world", "--world", world_id]) == 0
212+
eval_payload = json.loads(capsys.readouterr().out)
213+
214+
assert eval_payload["world_id"] == world_id
215+
assert eval_payload["status"] == "pass"
216+
assert eval_payload["metrics"]["tracked_outcome_count"] == 5
217+
assert eval_payload["metrics"]["tracked_outcome_fields_covered"] == 5
218+
assert eval_payload["metrics"]["compare_outcome_fields_covered"] == 5
219+
assert eval_payload["metrics"]["changed_tracked_outcome_count"] >= 1
220+
assert eval_payload["metrics"]["default_report_changed_outcome_count"] >= 1
221+
assert eval_payload["metrics"]["report_compare_sourced"] is True
222+
assert eval_payload["metrics"]["transfer_proof_world_local"] is True
223+
224+
artifacts_root = runtime_root / "state" / "artifacts" / "worlds" / world_id
225+
claims = json.loads((artifacts_root / "report" / "claims.json").read_text(encoding="utf-8"))
226+
assert claims
227+
assert all(claim.get("label") for claim in claims)
228+
assert all(claim.get("evidence_ids") for claim in claims)
229+
assert (artifacts_root / "eval" / "summary.json").exists()
230+
assert (artifacts_root / "compare" / "scenario_harbor_night_drill_template_matrix" / "compare.json").exists()
231+
232+
201233
def test_cli_create_world_uses_locale_for_generated_product_copy(
202234
tmp_path: Path, capsys, monkeypatch
203235
) -> None:
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
5+
6+
PROOF_PATH = Path("docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md")
7+
MINIMUM_LOOP = (
8+
"corpus -> chunks -> graph -> personas -> scenarios -> deterministic runs -> "
9+
"report/claims -> eval"
10+
)
11+
12+
13+
def _read(path: Path) -> str:
14+
assert path.exists(), path
15+
return path.read_text(encoding="utf-8")
16+
17+
18+
def test_runtime_created_world_eval_proof_exists_with_guardrails() -> None:
19+
proof = _read(PROOF_PATH)
20+
required_sections = [
21+
"# Post-Phase-67 Runtime-Created World Eval Proof",
22+
"## Scope",
23+
"## Source Evidence",
24+
"## Validation Evidence",
25+
"## Queue Decision",
26+
"## Boundaries",
27+
"## Validation Commands",
28+
]
29+
for section in required_sections:
30+
assert section in proof
31+
32+
required_phrases = [
33+
f"`{MINIMUM_LOOP}`",
34+
"runtime-created bounded world can pass `eval-world`",
35+
"This closes only the narrow runtime-created template proof question",
36+
"The queue remains paused.",
37+
"Do not open Phase 68 from this proof.",
38+
"does not claim future-world readiness",
39+
"Do not present Mirror as a real-world prediction machine.",
40+
"Do not build real-person personas or digital doubles.",
41+
"Do not build political persuasion, hidden surveillance, law-enforcement scoring, hiring, credit, medical, or judicial decision systems.",
42+
]
43+
for phrase in required_phrases:
44+
assert phrase in proof, phrase
45+
46+
47+
def test_runtime_created_world_eval_proof_is_source_backed() -> None:
48+
proof = _read(PROOF_PATH)
49+
template_service = _read(Path("backend/app/world_templates/service.py"))
50+
eval_service = _read(Path("backend/app/evals/service.py"))
51+
cli_tests = _read(Path("backend/tests/test_cli.py"))
52+
53+
for phrase in [
54+
'default_report_scenario = "evidence_delayed"',
55+
'"default_report_scenario": default_report_scenario',
56+
'world_root / "scenarios" / f"{default_report_scenario}.yaml"',
57+
'"kind": "delay_document"',
58+
]:
59+
assert phrase in template_service
60+
assert phrase in proof
61+
62+
for phrase in [
63+
"def _default_redlines_path(repo_root: Path) -> Path:",
64+
"runtime_path = repo_root / \"evals\" / \"assertions\" / \"redlines.yaml\"",
65+
"Path(__file__).resolve().parents[3] / \"evals\" / \"assertions\" / \"redlines.yaml\"",
66+
]:
67+
assert phrase in eval_service
68+
69+
for phrase in [
70+
"test_cli_runtime_created_world_passes_eval_world",
71+
'main(["eval-world", "--world", world_id])',
72+
'eval_payload["metrics"]["tracked_outcome_fields_covered"] == 5',
73+
'eval_payload["metrics"]["compare_outcome_fields_covered"] == 5',
74+
'eval_payload["metrics"]["report_compare_sourced"] is True',
75+
'eval_payload["metrics"]["transfer_proof_world_local"] is True',
76+
'claim.get("label")',
77+
'claim.get("evidence_ids")',
78+
'"scenario_harbor_night_drill_template_matrix"',
79+
]:
80+
assert phrase in cli_tests
81+
assert phrase in proof
82+
83+
84+
def test_current_docs_point_to_runtime_created_world_eval_proof_without_phase68() -> None:
85+
docs = [
86+
Path("README.md"),
87+
Path("docs/plans/current-state-baseline.md"),
88+
Path("docs/plans/phase-execution-queue.md"),
89+
Path("docs/plans/automation-roadmap.md"),
90+
]
91+
required_phrases = [
92+
"`docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md`",
93+
"Post-Phase-67 runtime-created world eval proof keeps the queue paused",
94+
"runtime-created bounded world can pass `eval-world`",
95+
"does not claim future-world readiness",
96+
"Do not open Phase 68 from this proof.",
97+
]
98+
forbidden_phrases = [
99+
"Phase 68 is active",
100+
"Phase 68 execution queue is open",
101+
"`audit-github-queue` reports `ready` for Phase 68",
102+
"milestone `Phase 68",
103+
]
104+
for path in docs:
105+
text = _read(path)
106+
for phrase in required_phrases:
107+
assert phrase in text, f"{path} is missing runtime-created eval proof pointer: {phrase}"
108+
for phrase in forbidden_phrases:
109+
assert phrase not in text, f"{path} opens Phase 68 prematurely: {phrase}"

docs/plans/automation-roadmap.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Day 0 bootstrap is complete, Phase 5 closeout is complete, Phase 6 closeout is c
2929
- Phase 67 closeout shorthand: `#507` `Phase 67 exit gate` closed by PR `#514`; `#508` closed by PR `#510`; `#509` closed by PR `#512`; `#511` closed by PR `#513`.
3030
- Post-Phase-67 successor intake audit keeps the queue paused; `docs/plans/post-phase-67-successor-intake-audit-2026-06-08.md` records the successor-intake decision. No Phase 68 successor queue is opened by this audit. Do not open Phase 68 as an execution queue until this intake audit identifies a new source-backed minimum-loop gap or protected-core contract blocker. The intake remains tied to `corpus -> chunks -> graph -> personas -> scenarios -> deterministic runs -> report/claims -> eval`.
3131
- Post-Phase-67 outcome/report/eval generalization audit keeps the queue paused; `docs/plans/post-phase-67-outcome-report-eval-generalization-audit-2026-06-08.md` records that selected-world proof is current for `fog-harbor-east-gate`, `museum-night`, and `library-rain`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this audit.
32+
- Post-Phase-67 runtime-created world eval proof keeps the queue paused; `docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md` records that a runtime-created bounded world can pass `eval-world`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this proof.
3233
- Phase 1 and Phase 2 gates are closed.
3334
- Phase 3 is closed locally and in GitHub.
3435
- Phase 3 exit issue `#4` is closed and milestone `Phase 3 - Eval/UI/Demo` is closed.

docs/plans/current-state-baseline.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Post-Phase-67 successor intake audit keeps the queue paused; `docs/plans/post-ph
2828

2929
Post-Phase-67 outcome/report/eval generalization audit keeps the queue paused; `docs/plans/post-phase-67-outcome-report-eval-generalization-audit-2026-06-08.md` records that selected-world proof is current for `fog-harbor-east-gate`, `museum-night`, and `library-rain`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this audit.
3030

31+
Post-Phase-67 runtime-created world eval proof keeps the queue paused; `docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md` records that a runtime-created bounded world can pass `eval-world`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this proof.
32+
3133
## Snapshot
3234

3335
- Local quality baseline:

docs/plans/phase-execution-queue.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ Phase 67 - Blueprint Calibration and Minimum-Loop Value Gate
118118
- Do not open another adjacent surface/readiness/fidelity/continuity gate as the primary successor scope without a source-backed tie to scenario/intervention/branch-comparison/eval value.
119119
- Post-Phase-67 successor intake audit keeps the queue paused; `docs/plans/post-phase-67-successor-intake-audit-2026-06-08.md` records the successor-intake decision. No Phase 68 successor queue is opened by this audit. Do not open Phase 68 as an execution queue until this intake audit identifies a new source-backed minimum-loop gap or protected-core contract blocker. The intake remains tied to `corpus -> chunks -> graph -> personas -> scenarios -> deterministic runs -> report/claims -> eval`.
120120
- Post-Phase-67 outcome/report/eval generalization audit keeps the queue paused; `docs/plans/post-phase-67-outcome-report-eval-generalization-audit-2026-06-08.md` records that selected-world proof is current for `fog-harbor-east-gate`, `museum-night`, and `library-rain`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this audit.
121+
- Post-Phase-67 runtime-created world eval proof keeps the queue paused; `docs/plans/post-phase-67-runtime-created-world-eval-proof-2026-06-08.md` records that a runtime-created bounded world can pass `eval-world`, does not claim future-world readiness, and does not prove a Phase 68 blocker. Do not open Phase 68 from this proof.
121122
- If a future minimum-loop audit finds a contract gap, split a separate protected-core contract issue before changing schema, scenario DSL, claim labels, run trace shape, or artifact layout.
122123

123124
## Phase 66 Closed Queue

0 commit comments

Comments
 (0)