#!/usr/bin/env python3 """fake_worker.py — deterministic fake MiMo for pipeline integration testing. NOT the production research worker. This worker produces known, structured artifacts for each stage so the pipeline plumbing (persistence, handoff, gating, retry) can be tested in seconds instead of 20-minute real MiMo runs. Canonical pipeline (RP2, handoff 2026-09-08): ISSUE → INWARD → OUTWARD → APPLICABILITY → optional INNOVATION → ADVERSARIAL → SYNTHESIS → QUALIFY Per the authoritative build prompt §18: "DETERMINISTIC TESTS PROVE THE PIPE. REAL MIMO DOES THE RESEARCH." """ from __future__ import annotations import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent)) from research_task_tree import ResearchTaskTree, STAGES def fake_issue_gate(tree: ResearchTaskTree) -> dict: """ISSUE is deterministic: the Gitea issue content is the DEFINE replacement. The fake worker emits the compiled gate artifact directly.""" issue = tree.issue return { "goal": f"Capability from issue #{issue}", "why": "recorded in issue body", "constraints": ["must not regress existing behavior"], "acceptance": ["issue acceptance criteria"], "quality": "BUILDABLE", } def fake_inward(tree: ResearchTaskTree) -> dict: # Assert ISSUE-gate artifact was actually supplied prior = tree.get_prior_artifacts("INWARD") issue_gate = prior.get("ISSUE", {}) assert issue_gate.get("goal"), "INWARD: ISSUE-gate artifact missing — evidence handoff broken" return { "claims": [ { "id": "I1", "claim": "memory_store uses FTS5", "evidence": ["src/rune/memory_store.py:86"], "status": "CURRENT", }, { "id": "I2", "claim": "shard routing is present", "evidence": ["src/rune/shard_manager.py:114"], "status": "CURRENT", }, ], } def fake_outward(tree: ResearchTaskTree) -> dict: """Unified OUTWARD (RP3): one research task, discovery + reading as SUBSECTIONS of one artifact — not separate stages.""" prior = tree.get_prior_artifacts("OUTWARD") inward = prior.get("INWARD", {}) claims = inward.get("claims", []) assert len(claims) >= 2, f"OUTWARD: expected ≥2 INWARD claims, got {len(claims)}" return { "discovery": { "queries": ["fts5 hybrid search", "sqlite-vec alternatives"], "tool_receipts": [{"tool": "webfetch", "query": "fts5 hybrid search", "status": "completed"}], "sources": [ {"id": "O1", "url": "https://sqlite.org/fts5.html", "title": "FTS5", "source_class": "software"}, { "id": "O2", "url": "https://github.com/asg017/sqlite-vec", "title": "sqlite-vec", "source_class": "software", }, ], }, "reading": { "evidence": [ { "id": "E1", "source_id": "O1", "url": "https://sqlite.org/fts5.html", "claim": "FTS5 supports external content tables", "limitations": ["token porter only"], }, { "id": "E2", "source_id": "O2", "url": "https://github.com/asg017/sqlite-vec", "claim": "vec0 virtual tables for embedding search", "limitations": [], }, ], }, } def fake_applicability(tree: ResearchTaskTree) -> dict: """APPLICABILITY (RP4): classify researched mechanisms against Rune's reality.""" prior = tree.get_prior_artifacts("APPLICABILITY") outward = prior.get("OUTWARD", {}) sources = outward.get("discovery", {}).get("sources", []) assert len(sources) >= 2, f"APPLICABILITY: expected ≥2 OUTWARD sources, got {len(sources)}" return { "route": "INNOVATION_WARRANTED", "candidates": [ { "id": "M1", "source_ids": ["O1", "O2"], "classification": "APPLICABLE_WITH_ADAPTATION", "integration_point": "memory_store.recall", "benefit": "hybrid recall", "cost": "low", "architectural_fit": "fits memory authority", "authority_implications": "none", "risks": ["extension availability"], "required_adaptation": ["fallback when extension missing"], "evidence": ["E1", "E2"], }, ], } def fake_adversarial(tree: ResearchTaskTree) -> dict: prior = tree.get_prior_artifacts("ADVERSARIAL") outward = prior.get("OUTWARD", {}) evidence = outward.get("reading", {}).get("evidence", []) assert len(evidence) >= 2, f"ADVERSARIAL: expected ≥2 evidence items, got {len(evidence)}" return { "disposition": "SURVIVES_WITH_MITIGATIONS", "counter_evidence": [ { "id": "A1", "source_id": "O1", "claim": "FTS5 porter tokenizer may not handle all languages", "derived_from": ["E1"], "limitations": ["minor"], }, ], "surviving_candidates": ["M1"], "rejected_candidates": [], "required_mitigations": ["mode labeling"], "falsification_tests": ["FT1: harness run with embedding backend unreachable"], "attacks": [ { "id": "A1", "target_candidate": "M1", "dimension": "failure modes", "finding": "tokenizer coverage", "evidence": ["E1"], "severity": "minor", }, ], } def fake_innovation(tree: ResearchTaskTree) -> dict: prior = tree.get_prior_artifacts("INNOVATION") inward = prior.get("INWARD", {}) outward = prior.get("OUTWARD", {}) applicability = prior.get("APPLICABILITY", {}) inward_claims = [c["id"] for c in inward.get("claims", [])] evidence_ids = [e["id"] for e in outward.get("reading", {}).get("evidence", [])] applicable = [c["id"] for c in applicability.get("candidates", [])] assert inward_claims, "INNOVATION: no INWARD claims received" assert evidence_ids, "INNOVATION: no OUTWARD evidence received" assert applicable, "INNOVATION: no APPLICABILITY candidates received" return { "conclusion": "ADOPT", "candidates": [ { "id": "C1", "category": "ADAPT", "proposal": "hybrid FTS+vec recall", "derived_from": inward_claims[:1] + evidence_ids[:1] + applicable[:1], "composition_of": [], "novelty": "adapted", "expected_gain": "better recall", "risks": ["latency"], "kill_test": "recall returns >0 rows", }, ], } def fake_synthesis(tree: ResearchTaskTree) -> dict: prior = tree.get_prior_artifacts("SYNTHESIS") innovation = prior.get("INNOVATION", {}) candidates = innovation.get("candidates", []) assert candidates, "SYNTHESIS: no INNOVATION candidates received" return { "selected_design": "hybrid FTS+vec recall", "rejected_alternatives": [{"design": "pure FTS", "reason": "E2 shows vec adds value"}], "evidence_used": ["I1", "E1", "E2", "A1", "M1", "C1"], "architecture_implications": ["memory_store.recall modified"], "files_affected": ["src/rune/memory_store.py"], "contracts": ["recall returns thresholded rows"], "tests_required": ["test_recall_hybrid"], "failure_modes": ["sqlite-vec not installed"], "kill_conditions": ["recall returns 0 rows on seeded store"], "build_instructions": ["modify recall() in memory_store.py", "add tests"], } def fake_qualify(tree: ResearchTaskTree) -> dict: prior = tree.get_prior_artifacts("QUALIFY") synthesis = prior.get("SYNTHESIS", {}) assert synthesis.get("selected_design"), "QUALIFY: no synthesis received" # First QUALIFY pass: build instructions incomplete → REFINE_SYNTHESIS # (narrowed semantics: synthesis-only refinement, no research repeat). # Record the refine round in the tree so the workflow records a 2nd round. if tree.state.get("qualify_outcome") != "REFINE_SYNTHESIS": return { "outcome": "REFINE_SYNTHESIS", "reason": "rollback/recovery not specified", "build_instructions": synthesis.get("build_instructions", []), } # After synthesis refinement: PROCEED return { "outcome": "PROCEED", "selected_design": synthesis.get("selected_design", ""), "evidence_used": synthesis.get("evidence_used", []), } FAKE_WORKERS = { "ISSUE": fake_issue_gate, "INWARD": fake_inward, "OUTWARD": fake_outward, "APPLICABILITY": fake_applicability, "ADVERSARIAL": fake_adversarial, "INNOVATION": fake_innovation, "SYNTHESIS": fake_synthesis, "QUALIFY": fake_qualify, } def run_fake_stage(tree: ResearchTaskTree) -> dict: stage = tree.current_stage worker = FAKE_WORKERS.get(stage) if not worker: raise ValueError(f"no fake worker for stage {stage}") return worker(tree) def main_with(argv: list[str]) -> int: import argparse parser = argparse.ArgumentParser(description="Fake stage worker for pipeline testing") parser.add_argument("--issue", type=int, required=True) parser.add_argument("--round", type=int, default=1) parser.add_argument("--artifact-dir", required=True) parser.add_argument("--out-dir", required=True) args = parser.parse_args(argv[1:]) tree = ResearchTaskTree(issue=args.issue, round_no=args.round, artifact_dir=args.artifact_dir) if tree.is_complete: print("research tree already complete") return 0 artifact = run_fake_stage(tree) out_dir = Path(args.out_dir) out_dir.mkdir(parents=True, exist_ok=True) stage = tree.current_stage (out_dir / f"stage_{stage}.json").write_text(json.dumps(artifact, indent=2)) print(f"fake stage {stage} complete") return 0 if __name__ == "__main__": raise SystemExit(main_with(sys.argv))