{"record":{"id":"ef5731a48fa9c115","repo":"mvanhorn/last30days-skill","slug":"judgments-file-path-must-carry-a-top-level-jud","errorCode":null,"errorMessage":"Judgments file {path} must carry a top-level \\\"judgments\\\" list.","messagePattern":"Judgments file (.+?) must carry a top-level \\\\\"judgments\\\\\" list\\.","errorType":"exception","errorClass":"HandoffContractError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/discovery_handoff.py","lineNumber":764,"sourceCode":"    save_dir: str | Path | None = None,\n    config_dir: Path | None = None,\n) -> dict[str, HostJudgment]:\n    \"\"\"Read the host judgments file for leg 2, keyed by nomination id.\n\n    Strict at the top level (readable, valid JSON object, ``judgments`` list,\n    bundle_id bound to ``bundle``), lenient per row: an unknown id is warned\n    and ignored, a missing/unusable name or junk field is per-row-absent, and\n    worthiness is clamped to 0-100 integers. Nominations with no row at all\n    are simply missing from the mapping - use ``judgment_for`` to get the\n    ROW_ABSENT marker for them.\n    \"\"\"\n    payload = _load_host_file(path, \"judgments\")\n    _require_bundle_binding(\n        payload, bundle, label=\"judgments\", save_dir=save_dir, config_dir=config_dir,\n    )\n    rows = payload.get(\"judgments\")\n    if not isinstance(rows, list):\n        raise HandoffContractError(\n            f\"Judgments file {path} must carry a top-level \\\"judgments\\\" list.\"\n        )\n    known = {entry.nomination_id for entry in bundle.nominations}\n    judgments: dict[str, HostJudgment] = {}\n    for row_id, row in _known_rows(\n        rows, known, row_label=\"judgments\", unknown_label=\"judgment\"\n    ):\n        # Only a real JSON boolean is a junk verdict: null, \"false\", 0, or\n        # any other non-bool value is per-row-absent (bundle heuristic),\n        # never coerced - bool(\"false\") is True.\n        raw_junk = row.get(\"junk\")\n        judgments[row_id] = HostJudgment(\n            name=_sanitized_name(row.get(\"name\")),\n            junk=raw_junk if isinstance(raw_junk, bool) else None,\n            worthiness=_clamped_worthiness(row.get(\"worthiness\")),\n        )\n    return judgments\n","sourceCodeStart":746,"sourceCodeEnd":782,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/discovery_handoff.py#L746-L782","documentation":"Raised by the judgments loader in discovery_handoff.py when the file is valid JSON, is a top-level object, and is correctly bundle-bound, but the 'judgments' key is missing or is not a JSON list. This is the third strictness tier: strict on top-level structure, lenient per row (unknown ids are warned, junk fields degrade per-row). It is a HandoffContractError, so the fix is always on the host-file side.","triggerScenarios":"Passing a judgments file whose top-level object omits the 'judgments' key entirely; naming the key differently ('rows', 'entries', 'items'); setting \"judgments\": {...} (an object) instead of an array; setting it to null.","commonSituations":"The host model paraphrases the schema and renames the key; a partially written file from an interrupted edit; copy-pasting an angles-file shape for a judgments file.","solutions":["Ensure the top-level object contains \"judgments\": [...] — a JSON array of row objects, each with nomination_id.","Check spelling and case exactly: the key must be lowercase 'judgments'.","After fixing, re-run the same leg; per-row problems will not raise this error, only the missing/mistyped key does."],"exampleFix":"// before\n{\n  \"bundle_id\": \"...\",\n  \"rows\": [{\"nomination_id\": \"n1\", \"junk\": false}]\n}\n\n// after\n{\n  \"bundle_id\": \"...\",\n  \"judgments\": [{\"nomination_id\": \"n1\", \"junk\": false}]\n}","handlingStrategy":"validation","validationCode":"import json\n\ndef valid_judgments_file(path: str) -> bool:\n    payload = json.loads(open(path, encoding=\"utf-8\").read())\n    return isinstance(payload, dict) and isinstance(payload.get(\"judgments\"), list)","typeGuard":null,"tryCatchPattern":"try:\n    load_judgments(path, bundle, ...)\nexcept HandoffContractError as e:\n    if 'top-level' in str(e) and 'judgments' in str(e):\n        # structural fix on host side: add/rename the \"judgments\" array key\n        ...","preventionTips":["Generate the file from a dict literal: {\"bundle_id\": ..., \"judgments\": rows} — the key name cannot drift.","Do not paraphrase schema keys; copy them verbatim from the docs.","Per-row leniency means only top-level shape raises — focus review on the wrapper, not each row."],"tags":["json","contract","discovery-handoff","schema"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}