{"record":{"id":"11edfe07c17b67e4","repo":"Hmbown/CodeWhale","slug":"budget-fixture-field-must-remain-expected-r","errorCode":null,"errorMessage":"budget fixture.{field} must remain {expected!r}","messagePattern":"budget fixture\\.(.+?) must remain (.+?)","errorType":"exception","errorClass":"PersistenceBacklogError","httpStatus":null,"severity":"error","filePath":"scripts/check-persistence-backlog-budget.py","lineNumber":252,"sourceCode":"        if receipt[\"rss_after_delta_bytes\"] != max(\n            0, receipt[\"rss_after_bytes\"] - before\n        ):\n            raise PersistenceBacklogError(\"rss_after_delta_bytes is inconsistent\")\n    elif any(receipt[field] is not None for field in rss_fields):\n        raise PersistenceBacklogError(\"unsupported RSS fields must be null\")\n\n\ndef validate_budget(budget: dict[str, Any]) -> None:\n    if budget.get(\"document_kind\") != BUDGET_KIND:\n        raise PersistenceBacklogError(f\"budget document_kind must be {BUDGET_KIND}\")\n    if budget.get(\"schema_version\") != SCHEMA_VERSION:\n        raise PersistenceBacklogError(\"budget schema_version changed\")\n    fixture = budget.get(\"fixture\")\n    if not isinstance(fixture, dict) or set(fixture) != set(FIXTURE):\n        raise PersistenceBacklogError(\"budget fixture no longer matches the frozen workload\")\n    for field, expected in FIXTURE.items():\n        if type(fixture[field]) is not type(expected) or fixture[field] != expected:\n            raise PersistenceBacklogError(\n                f\"budget fixture.{field} must remain {expected!r}\"\n            )\n    if budget.get(\"baseline_receipt\") != BASELINE_RECEIPT_REFERENCE:\n        raise PersistenceBacklogError(\"budget baseline_receipt path changed\")\n    ceilings = budget.get(\"ceilings\")\n    baseline = budget.get(\"baseline_observation\")\n    if not isinstance(ceilings, dict) or not isinstance(baseline, dict):\n        raise PersistenceBacklogError(\"budget needs ceilings and baseline_observation objects\")\n    for field in CEILING_FIELDS:\n        ceiling = non_negative_integer(ceilings.get(field), f\"ceilings.{field}\")\n        observed = non_negative_integer(\n            baseline.get(field), f\"baseline_observation.{field}\"\n        )\n        if observed > ceiling:\n            raise PersistenceBacklogError(\n                f\"baseline_observation.{field} exceeds its ceiling\"\n            )\n    baseline_accepted = non_negative_integer(","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/check-persistence-backlog-budget.py#L234-L270","documentation":"Raised by validate_budget() for the first fixture field whose value or Python type differs from the frozen FIXTURE constant - the check is type(fixture[field]) is not type(expected) or value inequality, so true vs 1, 128 vs 128.0, and '128' vs 128 all fail. The frozen values pin the workload exactly (fixture_id 'paused-production-channel-session-snapshot-v1', request_variant 'session_snapshot', payload_estimator 'retained-saved-session-json-bytes-v1', paused_consumer true, requests_attempted 128, content_bytes_per_request 65536, single_session_id true, expected_applied_version 127); changing any of them invalidates every ceiling.","triggerScenarios":"Any per-field drift in budget['fixture']: 65535 instead of 65536, 127.0 as a float, 'true' as a string, a new fixture_id after reworking the workload, or a JSON round-trip that coerced types.","commonSituations":"Hand-tuning fixture values to make a failing measurement pass; tools that re-serialize numbers as floats or booleans as integers; a workload change in measure-persistence-backlog.py not mirrored into the budget fixture.","solutions":["Restore the exact frozen value and JSON type named in the error message (e.g. content_bytes_per_request must be the integer 65536)","If the workload genuinely changed, update FIXTURE in check-persistence-backlog-budget.py and re-baseline the budget in the same change","Never edit fixture values to quiet a ceiling failure - re-measure instead"],"exampleFix":"// before (budget.json)\n\"fixture\": { \"content_bytes_per_request\": 65535.0, \"paused_consumer\": 1 }\n\n// after: exact frozen values and types\n\"fixture\": { \"content_bytes_per_request\": 65536, \"paused_consumer\": true }","handlingStrategy":"validation","validationCode":"def fixture_values_ok(budget: dict, frozen: dict) -> bool:\n    fixture = budget.get(\"fixture\")\n    if not isinstance(fixture, dict):\n        return False\n    return all(\n        type(fixture.get(k)) is type(v) and fixture.get(k) == v\n        for k, v in frozen.items()\n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Load budgets from the repo checkout (scripts/persistence-backlog-budget.json) instead of hand-maintained copies","Validate budget JSON with python -m json.tool and a key-set check before running the checker","Change FIXTURE/SCHEMA_VERSION in the checker only together with regenerating budget and baseline receipt in one commit"],"tags":["json","frozen-workload","python","ci-gate","type-mismatch"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}