{"record":{"id":"75bf73f354694047","repo":"JuliusBrussee/caveman","slug":"label-unreviewed-sync-proposal-marker-on-line-s","errorCode":null,"errorMessage":"{label}: unreviewed sync proposal marker on line(s) {', '.join(str(number) for number in offending)}: the proposal bumped verified_at, so merging with the marker intact attests a price check nobody performed -- confirm each row against its sources, then delete the {REVIEW_MARKER!r} line","messagePattern":"(.+?): unreviewed sync proposal marker on line\\(s\\) (.+?): the proposal bumped verified_at, so merging with the marker intact attests a price check nobody performed -- confirm each row against its sources, then delete the (.+?) line","errorType":"validation","errorClass":"CatalogError","httpStatus":null,"severity":"error","filePath":"shared/provider-catalog/validate_catalog.py","lineNumber":183,"sourceCode":"    if verified_at < now - timedelta(days=120):\n        raise CatalogError(f\"{label}: verified_at is older than 120 days\")\n    return identity[0], identity[1], identity[2]\n\n\ndef check_review_markers(text: str, label: str) -> None:\n    \"\"\"Refuse a catalog that still carries an unreviewed sync proposal.\n\n    YAML comments are invisible to the parsed rows, so this reads the raw file:\n    a rubber-stamped merge must not be able to advance price provenance while\n    the line saying \"nobody has confirmed this yet\" is still in the file.\n    \"\"\"\n    offending = [\n        index + 1\n        for index, line in enumerate(text.splitlines())\n        if line.lstrip().startswith(REVIEW_MARKER)\n    ]\n    if offending:\n        raise CatalogError(\n            f\"{label}: unreviewed sync proposal marker on line(s) \"\n            f\"{', '.join(str(number) for number in offending)}: the proposal bumped \"\n            \"verified_at, so merging with the marker intact attests a price check \"\n            \"nobody performed -- confirm each row against its sources, then delete \"\n            f\"the {REVIEW_MARKER!r} line\"\n        )\n\n\ndef pricing_identity(row: dict[str, Any]) -> dict[str, Any]:\n    \"\"\"The part of a row the immutable dated snapshot pins.\n\n    Present-with-a-value and absent are different attestations, so only the\n    price-affecting capability keys the row actually carries are recorded:\n    adding one to a row that had none changes that row's price and must break\n    the pin exactly like editing one that was already there.\n    \"\"\"\n    identity = {key: row.get(key) for key in PRICING_IDENTITY_KEYS}\n    capabilities = row.get(\"capabilities\") or {}","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/provider-catalog/validate_catalog.py#L165-L201","documentation":"Raised by check_review_markers(), which scans the RAW text of catalog/current.yaml for lines starting with '# proposed-by:' (REVIEW_MARKER). scripts/catalog_sync_modelsdev.py writes that marker on every row it touched when proposing price changes; because YAML comments are invisible to the parsed rows, only a raw-text scan can enforce that a human confirmed the proposal. Merging with the marker intact would let verified_at (price provenance attested by signed receipts) advance on work nobody performed.","triggerScenarios":"validate_catalog() runs while current.yaml still contains any line whose stripped form starts with '# proposed-by:' — i.e. a sync proposal was merged (or left in the working tree) without a reviewer deleting the marker lines. Line numbers of every offending marker are included in the message.","commonSituations":"An automated modelsdev sync PR is rubber-stamped merged; a developer runs the sync script locally to preview changes and then commits the file; a merge conflict resolution keeps the proposed block including its comment.","solutions":["Open catalog/current.yaml, go to the listed line numbers, and confirm each marked row's pricing against its `sources` URLs on the vendor's own pricing page.","Delete the '# proposed-by: ...' comment line(s) — that deletion IS the review attestation the validator waits for.","If any proposed number is wrong, correct it (and mint the correct dated snapshot) rather than just deleting the marker.","Re-run validate_catalog.py; also ensure any new verified_at date has a matching catalog/<date>.yaml snapshot or you will hit the snapshot-pin error next."],"exampleFix":"# current.yaml (before)\n- provider: anthropic\n  model: claude-*\n  # proposed-by: catalog_sync_modelsdev.py 2026-08-14\n  verified_at: \"2026-08-14T00:00:00Z\"\n\n# after — reviewer confirmed prices, marker deleted\n- provider: anthropic\n  model: claude-*\n  verified_at: \"2026-08-14T00:00:00Z\"","handlingStrategy":"validation","validationCode":"REVIEW_MARKER = \"# proposed-by:\"\n\ndef has_unreviewed_markers(yaml_text: str) -> list[int]:\n    return [i + 1 for i, line in enumerate(yaml_text.splitlines())\n            if line.lstrip().startswith(REVIEW_MARKER)]","typeGuard":null,"tryCatchPattern":"try:\n    validate_catalog()\nexcept CatalogError as e:\n    if \"unreviewed sync proposal\" in str(e):\n        # open the named lines, confirm rows against sources, delete markers\n        request_human_review(e)\n    raise","preventionTips":["Treat '# proposed-by:' lines as merge blockers in review checklists — deleting one is the attestation.","Never merge a branch from catalog_sync_modelsdev.py without a human confirming each marked row.","Configure CI to run the validator so marker-bearing merges fail automatically."],"tags":["validation","catalog","review","provenance","ci-gate"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}