ultraworkers/claw-code · error · FileNotFoundError

could not locate source .omx with plans/claw-code-2-0-adapti

Error message

could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/

What it means

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.

Source

Thrown at scripts/generate_cc2_board.py:111

    return slug[:limit].strip("-") or "item"


def find_source_omx(repo_root: Path) -> Path:
    candidates = []
    env = None
    try:
        import os
        env = os.environ.get("CC2_SOURCE_OMX")
    except Exception:
        env = None
    if env:
        candidates.append(Path(env).expanduser())
    candidates.append(repo_root / ".omx")
    candidates.extend(parent / ".omx" for parent in repo_root.parents)
    for candidate in candidates:
        if (candidate / "plans" / "claw-code-2-0-adaptive-plan.md").exists() and (candidate / "research").exists():
            return candidate
    raise FileNotFoundError("could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/")


def parse_roadmap(path: Path) -> tuple[list[RoadmapRecord], list[RoadmapRecord]]:
    headings: list[RoadmapRecord] = []
    actions: list[RoadmapRecord] = []
    stack: list[tuple[str, int, int]] = []
    for line_no, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
        heading = re.match(r"^(#{1,6})\s+(.*?)(?:\s+#+)?\s*$", line)
        if heading:
            level = len(heading.group(1))
            title = heading.group(2).strip()
            stack = [entry for entry in stack if entry[1] < level] + [(title, level, line_no)]
            headings.append(RoadmapRecord(line_no, level, title, " > ".join(entry[0] for entry in stack), "roadmap_heading"))
            continue
        ordered = re.match(r"^(\s*)(\d+)\.\s+(.+?)\s*$", line)
        if ordered and len(ordered.group(1)) <= 4:
            title = ordered.group(3).strip()
            if len(title) > 10:

View on GitHub (pinned to b71afddae1)

Solutions

  1. 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.
  2. 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).
  3. 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.
  4. 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.

Example fix

# before
python3 scripts/generate_cc2_board.py
# error: could not locate source .omx with plans/claw-code-2-0-adaptive-plan.md and research/

# after (option A: env override)
export CC2_SOURCE_OMX="$HOME/evidence/claw2-omx"   # contains plans/ and research/
python3 scripts/generate_cc2_board.py

# after (option B: restore in-repo evidence)
mkdir -p .omx/plans .omx/research
cp /archive/claw-code-2-0-adaptive-plan.md .omx/plans/
cp /archive/{claw-open-latest,claw-issues,opencode-repo,codex-repo}.json .omx/research/
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def source_omx_ready(repo_root: Path) -> bool:
    candidates: list[Path] = []
    env = os.environ.get("CC2_SOURCE_OMX")
    if env:
        candidates.append(Path(env).expanduser())
    candidates.append(repo_root / ".omx")
    candidates.extend(parent / ".omx" for parent in repo_root.parents)
    return any(
        (c / "plans" / "claw-code-2-0-adaptive-plan.md").is_file()
        and (c / "research").is_dir()
        and (c / "research" / "claw-open-latest.json").is_file()  # build_board reads this next
        for c in candidates
    )

if not source_omx_ready(Path.cwd().resolve()):
    raise SystemExit("source .omx evidence missing; set CC2_SOURCE_OMX or restore .omx/plans + .omx/research")

Type guard

null

Try / catch

from pathlib import Path
import scripts.generate_cc2_board as gen

try:
    board = gen.build_board(Path.cwd().resolve())
except FileNotFoundError as exc:
    # message names both required paths; fail with actionable output, no partial board
    raise SystemExit(f"cannot build board: {exc}; set CC2_SOURCE_OMX to the evidence tree") from exc

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ultraworkers/claw-code@b71afddae1 (2026-08-16). Data as JSON: /api/errors/989c523a3a460ea0. Report an issue: GitHub.