Hmbown/CodeWhale · error · RuntimeContractError

bounded fragment module must expose load_project_instruction

Error message

bounded fragment module must expose load_project_instruction_fragment (project-instruction import as typed fragment)

What it means

The gate enforces that importing project-instruction files goes through the typed fragment API: the substring 'load_project_instruction_fragment' must appear in crates/core/src/fragments.rs. The public wrapper of that name delegates to load_project_instruction_fragment_from_candidates (which also satisfies the substring check), so this error means the typed import path was renamed, moved, or replaced by ad-hoc loading.

Source

Thrown at scripts/check-runtime-contract-budget.py:549

            if not re.search(rf"\b{name}\b", text):
                raise RuntimeContractError(
                    f"FragmentId missing required variant {name}"
                )
    # Marker stability — these strings are pinned by tests / prefix cache
    required_markers = [
        "<!-- cw:ctx:workspace -->",
        "<!-- cw:ctx:project_instructions -->",
        "<!-- cw:ctx:constitution -->",
    ]
    for marker in required_markers:
        if marker not in text:
            raise RuntimeContractError(
                f"bounded fragment module missing required marker {marker!r}"
            )

    # Project-instruction import must be a typed fragment, not ad-hoc
    if "load_project_instruction_fragment" not in text:
        raise RuntimeContractError(
            "bounded fragment module must expose load_project_instruction_fragment (project-instruction import as typed fragment)"
        )
    if "PROJECT_INSTRUCTION_CANDIDATES" not in text:
        raise RuntimeContractError(
            "bounded fragment module must define PROJECT_INSTRUCTION_CANDIDATES"
        )
    # Required candidate files from #3978
    required_candidates = [
        ".cursorrules",
        ".clinerules",
        ".windsurf/rules",
        ".gemini",
        ".github/copilot-instructions.md",
    ]
    for candidate in required_candidates:
        if candidate not in text:
            raise RuntimeContractError(
                f"PROJECT_INSTRUCTION_CANDIDATES missing required entry {candidate!r}"

View on GitHub (pinned to 8880682c63)

Solutions

  1. Keep or re-expose 'pub fn load_project_instruction_fragment(...)' in crates/core/src/fragments.rs - it may simply delegate to *_from_candidates
  2. If the loader moved, add a re-export or rename the new function back - the gate matches the exact substring
  3. Verify: 'grep -n load_project_instruction_fragment crates/core/src/fragments.rs'

Example fix

// before (crates/core/src/fragments.rs)
fn scan_instruction_files(workspace: &Path) -> Option<Fragment> { /* ad-hoc scan */ }

// after
fn scan_instruction_files(workspace: &Path) -> Option<Fragment> {
    load_project_instruction_fragment_from_candidates(workspace, PROJECT_INSTRUCTION_CANDIDATES)
}
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path
text = Path("crates/core/src/fragments.rs").read_text(encoding="utf-8")
assert "load_project_instruction_fragment" in text, "typed project-instruction import missing"

Type guard

def is_runtime_contract_error(exc: BaseException) -> bool:
    return isinstance(exc, ValueError) and type(exc).__name__ == "RuntimeContractError"

Try / catch

try:
    check_fragment_caps()
except RuntimeContractError as error:
    print(f"[gate] {error}", file=sys.stderr)
    raise SystemExit(2)

Prevention

When it happens

Trigger: Renaming or deleting load_project_instruction_fragment(_from_candidates); inlining candidate scanning into the context builder; moving the loader into another crate/module so the name no longer occurs in fragments.rs.

Common situations: Refactors relocating instruction loading into tui or a new crate; deleting the 'legacy' wrapper and keeping only a differently-named internal helper.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/932b128806b723fe. Report an issue: GitHub.