{"record":{"id":"9c553524270f050f","repo":"666ghj/MiroFish","slug":"aggregate-only-history-cannot-contain-reconstructe","errorCode":null,"errorMessage":"aggregate-only history cannot contain reconstructed dates","messagePattern":"aggregate-only history cannot contain reconstructed dates","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":394,"sourceCode":"    _expect_keys(\n        reconstruction,\n        {\"method\", \"generated_at\", \"daily\"},\n        \"reconstruction\",\n    )\n    reconstruction_method = reconstruction[\"method\"]\n    if reconstruction_method not in {\n        \"current_stargazers_starred_at\",\n        \"aggregate_snapshot_only\",\n    }:\n        raise StarHistoryError(\"unsupported reconstruction method\")\n    generated_at = _parse_state_timestamp(\n        reconstruction[\"generated_at\"], \"reconstruction.generated_at\"\n    )\n    daily = reconstruction[\"daily\"]\n    if not isinstance(daily, list):\n        raise StarHistoryError(\"reconstruction.daily must be a list\")\n    if reconstruction_method == \"aggregate_snapshot_only\" and daily:\n        raise StarHistoryError(\"aggregate-only history cannot contain reconstructed dates\")\n\n    previous_day: date | None = None\n    previous_stars = 0\n    for index, raw_point in enumerate(daily):\n        if not isinstance(raw_point, dict):\n            raise StarHistoryError(\"reconstruction point must be an object\")\n        _expect_keys(raw_point, {\"date\", \"stars\"}, \"reconstruction point\")\n        raw_date = raw_point[\"date\"]\n        if not isinstance(raw_date, str):\n            raise StarHistoryError(\"reconstruction date must be a string\")\n        try:\n            point_day = date.fromisoformat(raw_date)\n        except ValueError as exc:\n            raise StarHistoryError(\"reconstruction date is invalid\") from exc\n        if point_day.isoformat() != raw_date:\n            raise StarHistoryError(\"reconstruction date is not canonical\")\n        stars = _strict_non_negative_int(raw_point[\"stars\"], \"reconstruction stars\")\n        if index == 0 and stars <= 0:","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L376-L412","documentation":"Raised by validate_state() when reconstruction.method is 'aggregate_snapshot_only' yet the daily list is non-empty. An aggregate-only history intentionally carries no reconstructed daily points; its star history is derived purely from snapshots. Mixing both is treated as a corrupt or contradictory state.","triggerScenarios":"validate_state(state) with method=\"aggregate_snapshot_only\" and at least one entry in reconstruction.daily.","commonSituations":"Switching a state file from the reconstructed method to aggregate_snapshot_only by editing only the method field while leaving daily data in place; merging states from two runs that used different methods.","solutions":["Either set method to 'current_stargazers_starred_at' (keeping the daily points), or set daily to [] for aggregate_snapshot_only","Do not hand-switch methods on an existing state file; regenerate it with the intended mode"],"exampleFix":"// before\n\"method\": \"aggregate_snapshot_only\",\n\"daily\": [{\"date\": \"2024-01-01\", \"stars\": 10}]\n// after\n\"method\": \"aggregate_snapshot_only\",\n\"daily\": []","handlingStrategy":"validation","validationCode":"method = state[\"reconstruction\"][\"method\"]\ndaily = state[\"reconstruction\"][\"daily\"]\nif method == \"aggregate_snapshot_only\" and daily:\n    state[\"reconstruction\"][\"daily\"] = []  # or switch method if daily is authoritative","typeGuard":"def is_method_daily_consistent(method: str, daily: list) -> bool:\n    return not (method == \"aggregate_snapshot_only\" and daily)","tryCatchPattern":"try:\n    validate_state(state)\nexcept StarHistoryError as exc:\n    if \"aggregate-only history cannot contain reconstructed dates\" in str(exc):\n        # decide which source is authoritative and rebuild the state\n        ...","preventionTips":["Never change reconstruction.method on an existing state file by hand","Regenerate state in the intended mode instead of transforming it","Add an invariant test: aggregate_snapshot_only implies empty daily"],"tags":["validation","state-file","consistency"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}