Hmbown/CodeWhale · error · RuntimeContractError

TUI fragment module must include ProjectInstructions…

Error message

TUI fragment module must include ProjectInstructions variant (unified with core)

What it means

check_fragment_caps requires the TUI fragment module to mention `ProjectInstructions`, i.e. the enum/variant set in crates/tui/src/model_context/fragment.rs must include the ProjectInstructions fragment so project-instruction imports flow through the same unified fragment type as core. Missing it raises this error. This keeps the TUI and core fragment models aligned (shared crates/core boundary).

Solutions

  1. Add a `ProjectInstructions` variant to the fragment enum in crates/tui/src/model_context/fragment.rs (or re-export the unified enum containing it from codewhale_core::fragments).
  2. Handle the new variant in any exhaustive matches over fragment kinds in the TUI so it compiles.
  3. Prefer importing the enum wholesale from codewhale_core::fragments so TUI and core cannot drift again.

Example fix

// before (tui fragment enum)
pub enum Fragment { SystemPrompt(...), Retrieved(...), ToolResult(...) }

// after
pub enum Fragment {
    SystemPrompt(...),
    ProjectInstructions(...),
    Retrieved(...),
    ToolResult(...),
}
Defensive patterns

Strategy: validation

Validate before calling

text = open('crates/tui/src/model_context/fragment.rs').read()
assert 'ProjectInstructions' in text, 'TUI fragment enum must include ProjectInstructions'

Type guard

def has_project_instructions_variant(tui_text: str) -> bool:
    return 'ProjectInstructions' in tui_text

Try / catch

try:
    check_fragment_caps()
except RuntimeContractError as e:
    if 'ProjectInstructions variant' in str(e):
        add_project_instructions_variant_to_tui_enum()

Prevention

When it happens

Trigger: Running the contract check when crates/tui/src/model_context/fragment.rs exists, re-exports from codewhale_core::fragments, but its local fragment enum lacks a ProjectInstructions variant — e.g. a trimmed enum, a variant renamed to ProjectRules, or project instructions handled outside the fragment system.

Common situations: A developer removes the variant thinking project instructions are only a core concern; a rename to match a new product name; a partial sync where core gained the variant but the TUI enum was hand-written instead of re-exported.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/da268b674d6b017d. Report an issue: GitHub.

Appendix: source

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

    if "MAX_FRAGMENT_BYTES" not in text or "enforce_byte_cap" not in text:
        raise RuntimeContractError(
            "bounded fragment module must enforce byte caps via enforce_byte_cap and MAX_FRAGMENT_BYTES"
        )

    # TUI must be unified with the core boundary (shared crates/core module)
    tui_fragment = REPO_ROOT / "crates" / "tui" / "src" / "model_context" / "fragment.rs"
    try:
        tui_text = tui_fragment.read_text(encoding="utf-8")
    except FileNotFoundError as error:
        raise RuntimeContractError(
            f"missing TUI fragment module: {tui_fragment} ({error})"
        ) from error
    if "codewhale_core::fragments" not in tui_text:
        raise RuntimeContractError(
            "TUI model_context/fragment.rs must re-export caps from codewhale_core::fragments (shared crates/core boundary)"
        )
    if "ProjectInstructions" not in tui_text:
        raise RuntimeContractError(
            "TUI fragment module must include ProjectInstructions variant (unified with core)"
        )
    if "MAX_FRAGMENT_BYTES" not in tui_text:
        raise RuntimeContractError(
            "TUI fragment module must enforce MAX_FRAGMENT_BYTES (10K-token ceiling)"
        )
    if "matches_text" not in tui_text:
        raise RuntimeContractError(
            "TUI fragment module must expose a matches_text recognizer"
        )


def main(argv: Sequence[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--receipt",
        type=Path,
        help="check an existing measurement JSON instead of compiling",

View on GitHub (pinned to 433685b202)