{"record":{"id":"eaac299acef78fdf","repo":"mvanhorn/last30days-skill","slug":"no-pending-discovery-report-found-searched-n-se","errorCode":null,"errorMessage":"No pending discovery report found. Searched:\\n{_searched_lines(searched)}\\n{_RESUME_REMEDY}","messagePattern":"No pending discovery report found\\. Searched:\\\\n(.+?)\\\\n(.+?)","errorType":"exception","errorClass":"HandoffContractError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/discovery_handoff.py","lineNumber":567,"sourceCode":"def read_pending_report(\n    *,\n    save_dir: str | Path | None = None,\n    config_dir: Path | None = None,\n) -> PendingReport:\n    \"\"\"Locate and parse the leg-2 pending report for the finalize leg.\n\n    Same strictness family as the bundle reader: missing file (the searched\n    location named - save dir when supplied, else config dir, never a\n    cross-store fallback), unreadable, invalid JSON, wrong kind or schema version,\n    missing bundle_id, or stale TTL all raise HandoffContractError (mapped to\n    exit 2 by the CLI layer). Staleness is measured from the PENDING report's\n    own generated_at - the leg-2 write started a fresh authoring window - and\n    the remedy is the resume leg, not a full re-sweep.\n    \"\"\"\n    searched = _search_paths(save_dir, config_dir, pending_report_path)\n    path = next((candidate for candidate in searched if candidate.exists()), None)\n    if path is None:\n        raise HandoffContractError(\n            \"No pending discovery report found. Searched:\\n\"\n            f\"{_searched_lines(searched)}\\n{_RESUME_REMEDY}\"\n        )\n    return _parse_pending_file(path)\n\n\ndef _parse_pending_file(path: Path) -> PendingReport:\n    payload, bundle_id, generated_at = _parse_handoff_envelope(\n        path,\n        label=\"Pending discovery report\",\n        kind=schema.DISCOVERY_PENDING_KIND,\n        schema_version=schema.DISCOVERY_PENDING_SCHEMA_VERSION,\n        remedy=_RESUME_REMEDY,\n        missing_id_context=\"angles cannot bind to it\",\n        stale_context=\"the judged window it captured has moved on\",\n    )\n    version = payload.get(\"schema_version\")\n    report = payload.get(\"report\")","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/discovery_handoff.py#L549-L585","documentation":"`load_pending_report` raises HandoffContractError (exit 2) when no `discover-pending.json` exists in any searched location — save dir when `--save-dir` was supplied, else the config dir, never a cross-store fallback. The pending report is leg-2 output that leg 3 (`--discover --finalize`) finalizes, so its absence means leg 2 never ran (or ran into a different store). The message names the searched paths and prescribes the resume remedy: re-run `--discover --judgments <file>`, or restart the whole protocol if the bundle is stale too.","triggerScenarios":"Running `--discover --finalize [--angles <file>]` before completing leg 2; running leg 2 with `--save-dir A` and leg 3 with a different or absent save dir; the pending file deleted or never written because leg 2 failed.","commonSituations":"Sessions split across days/directories where leg 2 happened elsewhere; agents attempting to finalize straight from a bundle; save-dir typos between invocations.","solutions":["Run leg 2 first (`--discover --judgments <file>`) with the SAME `--save-dir` (or config dir) you will use for `--finalize`.","Confirm `discover-pending.json` exists in the path listed under 'Searched:'.","If leg 2 failed earlier, fix that failure first (its bundle errors surface as errors 25-34), then re-run it.","If more than an hour passed, expect staleness next (error 32): budget to re-run the resume leg rather than the full sweep."],"exampleFix":"# before\npython3 last30days.py \"topic\" --discover --finalize --save-dir /tmp/run   # leg 2 never ran here\n# after\npython3 last30days.py \"topic\" --discover --judgments judgments.json --save-dir /tmp/run && python3 last30days.py \"topic\" --discover --finalize --angles angles.json --save-dir /tmp/run","handlingStrategy":"validation","validationCode":"from pathlib import Path\nfrom lib.discovery_handoff import pending_report_path, handoff_state_dir\n\nstate = handoff_state_dir(save_dir, config_dir)\nif state is None or not pending_report_path(state).exists():\n    raise SystemExit(\"no pending report: run `--discover --judgments <file>` first in this store\")","typeGuard":null,"tryCatchPattern":"from lib import discovery_handoff\ntry:\n    pending = discovery_handoff.load_pending_report(save_dir=save_dir, config_dir=config_dir)\nexcept discovery_handoff.HandoffContractError as exc:\n    sys.stderr.write(exc.message + \"\\n\")\n    sys.exit(2)","preventionTips":["Confirm discover-pending.json exists after leg 2 and before launching --finalize.","Use one --save-dir for legs 2 and 3 without exception.","Chain the legs in one script or session to avoid store drift between invocations."],"tags":["discovery","handoff","protocol-state","exit-code-2"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}