{"record":{"id":"0c23c934d9f0bce6","repo":"Hmbown/CodeWhale","slug":"kind-tool-execution-shell-must-be-bash-got-shell-r","errorCode":null,"errorMessage":"{kind} tool execution_shell must be `bash`, got {shell!r}","messagePattern":"(.+?) tool execution_shell must be `bash`, got (.+?)","errorType":"exception","errorClass":"RuntimeContractError","httpStatus":null,"severity":"error","filePath":"scripts/check-runtime-contract-budget.py","lineNumber":215,"sourceCode":"        value = value[part]\n    return value\n\n\ndef tool_identity_digest(names: list[str]) -> str:\n    return hashlib.sha256(\"\\0\".join(names).encode(\"utf-8\")).hexdigest()\n\n\ndef validate_identity_structure(document: dict[str, Any], kind: str) -> None:\n    profile = required_value(document, (\"tool_catalog\", \"surface_profile\"), kind)\n    if profile != TOOL_SURFACE_PROFILE:\n        raise RuntimeContractError(\n            f\"{kind} tool surface_profile must be `{TOOL_SURFACE_PROFILE}`, \"\n            f\"got {profile!r}\"\n        )\n\n    shell = required_value(document, (\"tool_catalog\", \"execution_shell\"), kind)\n    if shell != \"bash\":\n        raise RuntimeContractError(\n            f\"{kind} tool execution_shell must be `bash`, got {shell!r}\"\n        )\n\n    for mode, _label in VISIBLE_MODES:\n        for surface, _surface_label in TOOL_SURFACES:\n            base = (\"tool_catalog\", \"modes\", mode, surface)\n            names = required_value(document, (*base, \"tool_names\"), kind)\n            dotted_names = \".\".join((*base, \"tool_names\"))\n            if (\n                not isinstance(names, list)\n                or any(not isinstance(name, str) or not name for name in names)\n                or names != sorted(set(names))\n            ):\n                raise RuntimeContractError(\n                    f\"{kind} field `{dotted_names}` must be sorted unique non-empty strings\"\n                )\n            count = metric_value(document, (*base, \"tools\"), kind)\n            if count != len(names):","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/check-runtime-contract-budget.py#L197-L233","documentation":"The contract requires the tool catalog to declare bash as its execution shell; any other value makes the measurement non-reproducible against the pinned contract. validate_identity_structure compares tool_catalog.execution_shell to the literal \"bash\" and throws otherwise.","triggerScenarios":"validate_receipt/validate_budget reading a document whose tool_catalog.execution_shell is not exactly \"bash\" (e.g. \"sh\", \"zsh\", null).","commonSituations":"Receipt produced on/for a different shell environment; hand-edited document; generator configured with a non-bash shell.","solutions":["Set tool_catalog.execution_shell to \"bash\" in the document","Regenerate the receipt in a bash environment using the current script","If a non-bash shell is genuinely required, that is a contract change: update the script and all receipts together"],"exampleFix":"// before\n{\"tool_catalog\": {\"execution_shell\": \"sh\"}}\n// after\n{\"tool_catalog\": {\"execution_shell\": \"bash\"}}","handlingStrategy":"validation","validationCode":"assert doc.get(\"tool_catalog\", {}).get(\"execution_shell\") == \"bash\", \\\n    \"receipt must declare bash as execution_shell\"","typeGuard":null,"tryCatchPattern":"try:\n    validate_budget(budget)\nexcept RuntimeContractError as e:\n    if \"execution_shell\" in str(e):\n        raise SystemExit(\"receipt generated for a non-bash shell; regenerate in bash\")\n    raise","preventionTips":["Run measurement scripts with bash (set SHELL or invoke via bash explicitly)","Assert execution_shell == \"bash\" right after loading any receipt","Reject non-bash shells at generator time, not at validation time"],"tags":["python","schema-validation","shell"],"backgroundTag":"invalid-enum-value","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}