{"record":{"id":"ed015c11819a38b2","repo":"Hmbown/CodeWhale","slug":"project-instruction-candidates-missing-required-en","errorCode":null,"errorMessage":"PROJECT_INSTRUCTION_CANDIDATES missing required entry {candidate!r}","messagePattern":"PROJECT_INSTRUCTION_CANDIDATES missing required entry (.+?)","errorType":"exception","errorClass":"RuntimeContractError","httpStatus":null,"severity":"error","filePath":"scripts/check-runtime-contract-budget.py","lineNumber":566,"sourceCode":"    if \"load_project_instruction_fragment\" not in text:\n        raise RuntimeContractError(\n            \"bounded fragment module must expose load_project_instruction_fragment (project-instruction import as typed fragment)\"\n        )\n    if \"PROJECT_INSTRUCTION_CANDIDATES\" not in text:\n        raise RuntimeContractError(\n            \"bounded fragment module must define PROJECT_INSTRUCTION_CANDIDATES\"\n        )\n    # Required candidate files from #3978\n    required_candidates = [\n        \".cursorrules\",\n        \".clinerules\",\n        \".windsurf/rules\",\n        \".gemini\",\n        \".github/copilot-instructions.md\",\n    ]\n    for candidate in required_candidates:\n        if candidate not in text:\n            raise RuntimeContractError(\n                f\"PROJECT_INSTRUCTION_CANDIDATES missing required entry {candidate!r}\"\n            )\n\n    # matches_text recognizer must exist on the fragment trait\n    if \"fn matches_text\" not in text:\n        raise RuntimeContractError(\n            \"bounded fragment module must define a matches_text recognizer on the fragment trait\"\n        )\n    if \"trait ContextFragment\" not in text:\n        raise RuntimeContractError(\n            \"bounded fragment module must define trait ContextFragment with matches_text\"\n        )\n\n    # No unbounded fragment — enforce that creation clamps to MAX_FRAGMENT_BYTES\n    if \"MAX_FRAGMENT_BYTES\" not in text or \"enforce_byte_cap\" not in text:\n        raise RuntimeContractError(\n            \"bounded fragment module must enforce byte caps via enforce_byte_cap and MAX_FRAGMENT_BYTES\"\n        )","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/check-runtime-contract-budget.py#L548-L584","documentation":"From issue #3978: five well-known agent-instruction files must appear among the scanned candidates - .cursorrules, .clinerules, .windsurf/rules, .gemini, .github/copilot-instructions.md. The check is a whole-file substring search, so an entry may live in either PROJECT_INSTRUCTION_CANDIDATES or ADDITIONAL_PROJECT_INSTRUCTION_CANDIDATES; it fails only when the path string is absent or respelled anywhere in fragments.rs.","triggerScenarios":"Dropping '.windsurf/rules' from the candidate arrays; respelling a path ('.github/Copilot-Instructions.md'); building paths with format!/join at runtime so the literal substring disappears from the file.","commonSituations":"Adding a new editor's rules file and 'tidying' older ones out; porting candidate lists into a runtime-built config struct.","solutions":["Add the missing path (named in the error) back to PROJECT_INSTRUCTION_CANDIDATES or ADDITIONAL_PROJECT_INSTRUCTION_CANDIDATES in crates/core/src/fragments.rs","Keep candidates as literal strings - the gate matches text, not semantics","Cross-check against required_candidates in scripts/check-runtime-contract-budget.py:557-563"],"exampleFix":"// before (crates/core/src/fragments.rs)\npub const PROJECT_INSTRUCTION_CANDIDATES: &[&str] = &[\".cursorrules\", \".clinerules\", \".gemini\"];\n\n// after\npub const PROJECT_INSTRUCTION_CANDIDATES: &[&str] = &[\n    \".cursorrules\",\n    \".clinerules\",\n    \".windsurf/rules\",\n    \".gemini\",\n    \".github/copilot-instructions.md\",\n];","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\ntext = Path(\"crates/core/src/fragments.rs\").read_text(encoding=\"utf-8\")\nfor candidate in (\".cursorrules\", \".clinerules\", \".windsurf/rules\", \".gemini\", \".github/copilot-instructions.md\"):\n    assert candidate in text, f\"candidate {candidate} missing\"","typeGuard":"def is_runtime_contract_error(exc: BaseException) -> bool:\n    return isinstance(exc, ValueError) and type(exc).__name__ == \"RuntimeContractError\"","tryCatchPattern":"try:\n    check_fragment_caps()\nexcept RuntimeContractError as error:\n    print(f\"[gate] {error}\", file=sys.stderr)\n    raise SystemExit(2)","preventionTips":["Keep candidate paths as literal strings, not computed values","When adding a new editor rules file, append - never remove existing candidates without updating the gate list","Cross-check edits against required_candidates in scripts/check-runtime-contract-budget.py:557-563"],"tags":["python","ci","static-analysis","rust","config","editor-integration"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}