{"record":{"id":"989c523a3a460ea0","repo":"ultraworkers/claw-code","slug":"could-not-locate-source-omx-with-plans-claw-code","errorCode":null,"errorMessage":"could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/","messagePattern":"could not locate source \\.omx with plans/claw-code-2-0-adaptive-plan\\.md and research/","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"scripts/generate_cc2_board.py","lineNumber":111,"sourceCode":"    return slug[:limit].strip(\"-\") or \"item\"\n\n\ndef find_source_omx(repo_root: Path) -> Path:\n    candidates = []\n    env = None\n    try:\n        import os\n        env = os.environ.get(\"CC2_SOURCE_OMX\")\n    except Exception:\n        env = None\n    if env:\n        candidates.append(Path(env).expanduser())\n    candidates.append(repo_root / \".omx\")\n    candidates.extend(parent / \".omx\" for parent in repo_root.parents)\n    for candidate in candidates:\n        if (candidate / \"plans\" / \"claw-code-2-0-adaptive-plan.md\").exists() and (candidate / \"research\").exists():\n            return candidate\n    raise FileNotFoundError(\"could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/\")\n\n\ndef parse_roadmap(path: Path) -> tuple[list[RoadmapRecord], list[RoadmapRecord]]:\n    headings: list[RoadmapRecord] = []\n    actions: list[RoadmapRecord] = []\n    stack: list[tuple[str, int, int]] = []\n    for line_no, line in enumerate(path.read_text(encoding=\"utf-8\").splitlines(), 1):\n        heading = re.match(r\"^(#{1,6})\\s+(.*?)(?:\\s+#+)?\\s*$\", line)\n        if heading:\n            level = len(heading.group(1))\n            title = heading.group(2).strip()\n            stack = [entry for entry in stack if entry[1] < level] + [(title, level, line_no)]\n            headings.append(RoadmapRecord(line_no, level, title, \" > \".join(entry[0] for entry in stack), \"roadmap_heading\"))\n            continue\n        ordered = re.match(r\"^(\\s*)(\\d+)\\.\\s+(.+?)\\s*$\", line)\n        if ordered and len(ordered.group(1)) <= 4:\n            title = ordered.group(3).strip()\n            if len(title) > 10:","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/ultraworkers/claw-code/blob/b71afddae100ced324457337925a694686b8fef2/scripts/generate_cc2_board.py#L93-L129","documentation":"Raised by find_source_omx() in scripts/generate_cc2_board.py when none of the candidate .omx directories contains BOTH plans/claw-code-2-0-adaptive-plan.md AND a research/ directory. The generator needs this frozen 'source evidence' tree (approved plan + research JSON manifests like claw-open-latest.json, claw-issues.json, opencode-repo.json, codex-repo.json) to build the board, so it refuses to run without it. Candidates are checked in order: $CC2_SOURCE_OMX, <repo_root>/.omx, then .omx in every parent directory of repo_root.","triggerScenarios":"Running `python3 scripts/generate_cc2_board.py` (or `--repo-root <path>`) from a checkout where .omx/ exists but only holds cc2/ and ultragoal/ output dirs (exactly this repo's state), or where .omx/, plans/, or research/ were deleted, renamed, or never committed because .omx is gitignored evidence. Also fires when CC2_SOURCE_OMX points at a directory missing either the plan file or the research/ subdir, or when running with --repo-root on a different filesystem branch (e.g. /tmp worktree) whose parents have no .omx either.","commonSituations":"Cloning the repo fresh: the frozen evidence tree is machine-local or distributed out-of-band, so CI and new clones lack it. Running from a temp/scratch worktree whose parent directories contain no .omx. Typos or stale paths in CC2_SOURCE_OMX after the evidence was moved. Renaming the plan file (e.g. version bump from claw-code-2-0-adaptive-plan.md) without updating the hardcoded filename at scripts/generate_cc2_board.py:109.","solutions":["Point the script at the evidence tree explicitly: `export CC2_SOURCE_OMX=/path/to/omx-evidence` where that dir has plans/claw-code-2-0-adaptive-plan.md and research/, then rerun.","If the evidence should live in-repo, restore it: `mkdir -p .omx/plans .omx/research` and place claw-code-2-0-adaptive-plan.md plus claw-open-latest.json, claw-issues.json, opencode-repo.json, codex-repo.json under them (from the machine/archive that froze the roadmap).","If you only need roadmap-derived items and the research manifests genuinely don't exist, copy a sibling checkout's .omx to a parent of your --repo-root so the parent-walk at scripts/generate_cc2_board.py:107 finds it.","If the plan file was renamed upstream, update the hardcoded name in find_source_omx() and the 'approved_plan' path in build_board() to match, or symlink the new name to the old one."],"exampleFix":"# before\npython3 scripts/generate_cc2_board.py\n# error: could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/\n\n# after (option A: env override)\nexport CC2_SOURCE_OMX=\"$HOME/evidence/claw2-omx\"   # contains plans/ and research/\npython3 scripts/generate_cc2_board.py\n\n# after (option B: restore in-repo evidence)\nmkdir -p .omx/plans .omx/research\ncp /archive/claw-code-2-0-adaptive-plan.md .omx/plans/\ncp /archive/{claw-open-latest,claw-issues,opencode-repo,codex-repo}.json .omx/research/","handlingStrategy":"validation","validationCode":"import os\nfrom pathlib import Path\n\ndef source_omx_ready(repo_root: Path) -> bool:\n    candidates: list[Path] = []\n    env = os.environ.get(\"CC2_SOURCE_OMX\")\n    if env:\n        candidates.append(Path(env).expanduser())\n    candidates.append(repo_root / \".omx\")\n    candidates.extend(parent / \".omx\" for parent in repo_root.parents)\n    return any(\n        (c / \"plans\" / \"claw-code-2-0-adaptive-plan.md\").is_file()\n        and (c / \"research\").is_dir()\n        and (c / \"research\" / \"claw-open-latest.json\").is_file()  # build_board reads this next\n        for c in candidates\n    )\n\nif not source_omx_ready(Path.cwd().resolve()):\n    raise SystemExit(\"source .omx evidence missing; set CC2_SOURCE_OMX or restore .omx/plans + .omx/research\")","typeGuard":"null","tryCatchPattern":"from pathlib import Path\nimport scripts.generate_cc2_board as gen\n\ntry:\n    board = gen.build_board(Path.cwd().resolve())\nexcept FileNotFoundError as exc:\n    # message names both required paths; fail with actionable output, no partial board\n    raise SystemExit(f\"cannot build board: {exc}; set CC2_SOURCE_OMX to the evidence tree\") from exc","preventionTips":["Keep the frozen evidence tree at a stable path and always invoke the generator with `CC2_SOURCE_OMX=/path/to/omx-evidence` in CI instead of relying on parent-directory luck.","Check `.omx/plans/claw-code-2-0-adaptive-plan.md` and `.omx/research/*.json` existence in a preflight CI step before running the generator, so failures point at the missing evidence rather than a mid-build crash.","If .omx is gitignored, record in CONTRIBUTING where the evidence archive lives and how to restore it, so fresh clones don't discover this error at generation time.","When renaming the plan file or restructuring .omx, update the hardcoded names in find_source_omx() and the sources block of build_board() in the same commit."],"tags":["python","filesystem","missing-evidence","environment","build-tooling","configuration"],"backgroundTag":null,"analyzedSha":"b71afddae100ced324457337925a694686b8fef2","analyzedAt":"2026-08-16T02:39:29.677Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}