market-research-reports: fix ledger validator crash on publication_date=not-stated
The sentinel "not-stated" is exactly 10 characters, so it satisfied the
len(publication) == 10 ISO-date guard and reached
date.fromisoformat("not-stated"), raising an uncaught ValueError instead of
the documented warning. SKILL.md instructs recording "not-stated" when the
publication date is unavailable, so this crashed on valid ledgers.
Check the sentinel before the retrieval/publication comparison, and add
regression tests for both the not-stated warning and the still-enforced
retrieval-precedes-publication error.
Fixes #219
This commit is contained in:
@@ -4,7 +4,7 @@ description: Build evidence-traceable market research reports and assumption-dri
|
||||
license: MIT
|
||||
compatibility: Python 3.11+ standard library for optional offline CLIs. The optional LaTeX template uses XeLaTeX or LuaLaTeX. Online research requires user-approved network access and source-specific terms; bundled scripts make no network, LLM, or image calls.
|
||||
metadata:
|
||||
version: "1.1"
|
||||
version: "1.2"
|
||||
skill-author: "K-Dense Inc."
|
||||
---
|
||||
|
||||
|
||||
@@ -177,14 +177,14 @@ def validate_records(records: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
retrieval = parse_iso_date(
|
||||
record["retrieval_date"], f"{context}.retrieval_date"
|
||||
)
|
||||
if len(publication) == 10 and date.fromisoformat(retrieval) < date.fromisoformat(
|
||||
publication
|
||||
):
|
||||
if publication == "not-stated":
|
||||
warnings.append(f"{source_id}: publication date is not stated")
|
||||
elif len(publication) == 10 and date.fromisoformat(
|
||||
retrieval
|
||||
) < date.fromisoformat(publication):
|
||||
raise ValidationError(
|
||||
f"{context}.retrieval_date precedes publication_date"
|
||||
)
|
||||
if publication == "not-stated":
|
||||
warnings.append(f"{source_id}: publication date is not stated")
|
||||
|
||||
require_text(record["geography"], f"{context}.geography")
|
||||
currency = parse_currency(
|
||||
|
||||
@@ -59,6 +59,27 @@ class EvidenceLedgerTests(unittest.TestCase):
|
||||
self.assertFalse(report["valid"])
|
||||
self.assertTrue(any("duplicate" in error for error in report["errors"]))
|
||||
|
||||
def test_not_stated_publication_date_warns_without_crashing(self) -> None:
|
||||
records = _load_records(ASSETS / "source_ledger_template.csv")
|
||||
records[0]["publication_date"] = "not-stated"
|
||||
report = validate_records(records)
|
||||
self.assertTrue(report["valid"], report["errors"])
|
||||
self.assertTrue(
|
||||
any("publication date is not stated" in warning
|
||||
for warning in report["warnings"])
|
||||
)
|
||||
|
||||
def test_retrieval_before_publication_fails(self) -> None:
|
||||
records = _load_records(ASSETS / "source_ledger_template.csv")
|
||||
records[0]["publication_date"] = "2026-07-30"
|
||||
records[0]["retrieval_date"] = "2026-07-01"
|
||||
report = validate_records(records)
|
||||
self.assertFalse(report["valid"])
|
||||
self.assertTrue(
|
||||
any("retrieval_date precedes publication_date" in error
|
||||
for error in report["errors"])
|
||||
)
|
||||
|
||||
|
||||
class MarketSizingTests(unittest.TestCase):
|
||||
def test_synthetic_sizing_reconciles_and_returns_scenarios(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user