From 1fe050943303ff5329b6482cfe3586afec5dd739 Mon Sep 17 00:00:00 2001 From: Nubenetes Bot Date: Fri, 19 Jun 2026 15:37:51 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20deterministic=20inventory=20dump=20?= =?UTF-8?q?=E2=80=94=20last=5Fchecked=20as=20INTEGER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit last_checked stored epoch seconds as REAL; SQLite's version-specific REAL->text float printing rewrote ~every row on dump, so a locally regenerated inventory.sql diverged from CI's. Normalize last_checked to int on the entry before both the SQL record and the YAML dump, and make the column INTEGER. All readers do coarse day-level staleness checks, so sub-second precision is unused. Verified: load->save idempotent for inventory.sql AND inventory.yaml, and local (SQLite 3.40.1) output byte-identical to CI-equivalent python:3.11 (SQLite 3.46.1). The deterministic data regenerates on the next pipeline save; committing only the code avoids conflicting with pipeline data churn. Co-Authored-By: Claude Opus 4.8 --- src/inventory_manager.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/inventory_manager.py b/src/inventory_manager.py index 015d55a3..83afe04a 100644 --- a/src/inventory_manager.py +++ b/src/inventory_manager.py @@ -113,7 +113,7 @@ def save_inventory(inv: Dict, shard_file: str = None): addition_method TEXT, content_hash TEXT, health_score REAL, - last_checked REAL, + last_checked INTEGER, needs_ai_refresh BOOLEAN, discovered_at TEXT, last_ai_eval TEXT, @@ -139,7 +139,16 @@ def save_inventory(inv: Dict, shard_file: str = None): for url, entry in inv.items(): if not isinstance(entry, dict): continue - + + # last_checked is a coarse staleness timestamp (epoch seconds). Normalize + # it to int on the entry itself — before building the SQL record AND the + # YAML dump below — so both serializations agree, and SQLite's + # version-specific REAL->text float formatting can't rewrite every row on + # dump. Sub-second precision is not used by any reader. + lc = entry.get("last_checked") + if isinstance(lc, float): + entry["last_checked"] = int(lc) + record = {col: entry.get(col) for col in columns if col not in ["hierarchy", "tags", "v1_locations", "v2_locations", "youtube_mosaic", "extra_metadata"]} record["url"] = url @@ -160,7 +169,7 @@ def save_inventory(inv: Dict, shard_file: str = None): # Conversions record["is_microservice"] = 1 if record.get("is_microservice") else 0 record["needs_ai_refresh"] = 1 if record.get("needs_ai_refresh") else 0 - + placeholders = ", ".join(["?"] * len(columns)) values = [record[col] for col in columns] cursor.execute(f"INSERT OR REPLACE INTO resources ({', '.join(columns)}) VALUES ({placeholders})", values)