From 3b7fd719251bfc79b2cbb026d318c2f00c83c626 Mon Sep 17 00:00:00 2001 From: Research Assistant Date: Mon, 1 Jun 2026 13:27:45 +0800 Subject: [PATCH] fix: wire --rebuild-index flag to bypass hash check, enabling ocr_redo regeneration --- paperforge/commands/sync.py | 7 +++++-- paperforge/services/sync_service.py | 7 ++++--- paperforge/worker/asset_index.py | 13 ++----------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/paperforge/commands/sync.py b/paperforge/commands/sync.py index 17383712..5c43d43f 100644 --- a/paperforge/commands/sync.py +++ b/paperforge/commands/sync.py @@ -62,6 +62,7 @@ def run(args: argparse.Namespace) -> int: "index_only": index_only, "prune": prune_flag, "prune_force": prune_force, + "rebuild_index": getattr(args, "rebuild_index", False), } try: sig = inspect.signature(svc.run) @@ -82,7 +83,8 @@ def run(args: argparse.Namespace) -> int: except Exception: pass try: - import subprocess, sys + import subprocess + import sys subprocess.Popen( [sys.executable, "-m", "paperforge", "embed", "build", "--resume"], cwd=str(vault), @@ -105,7 +107,8 @@ def run(args: argparse.Namespace) -> int: print(f"memory: deferred ({e})") try: - import subprocess, sys + import subprocess + import sys subprocess.Popen( [sys.executable, "-m", "paperforge", "embed", "build", "--resume"], cwd=str(vault), diff --git a/paperforge/services/sync_service.py b/paperforge/services/sync_service.py index 1d407287..8b037fe0 100644 --- a/paperforge/services/sync_service.py +++ b/paperforge/services/sync_service.py @@ -200,7 +200,7 @@ class SyncService: def run( self, verbose: bool = False, json_output: bool = False, selection_only: bool = False, index_only: bool = False, - prune: bool = False, prune_force: bool = False, + prune: bool = False, prune_force: bool = False, rebuild_index: bool = False, ) -> PFResult: """Full sync orchestration. Returns PFResult contract. @@ -229,9 +229,10 @@ class SyncService: # ── Phase 1: Select ── if not index_only: - from paperforge.worker.sync import run_selection_sync import time as _time + from paperforge.worker.sync import run_selection_sync + _t0 = _time.time() try: selection_result = run_selection_sync(self.vault, verbose=verbose, json_output=json_output) @@ -288,7 +289,7 @@ class SyncService: flat_cleaned = self.clean_flat_notes(paths, json_output=json_output) if orphaned > 0 or flat_cleaned > 0: - index_count = asset_index.build_index(self.vault, verbose) + index_count = asset_index.build_index(self.vault, verbose, force_rebuild=rebuild_index) # ── Phase 4: Prune orphans ── prune_data = None diff --git a/paperforge/worker/asset_index.py b/paperforge/worker/asset_index.py index 921efd1c..46684236 100644 --- a/paperforge/worker/asset_index.py +++ b/paperforge/worker/asset_index.py @@ -524,17 +524,8 @@ def _compute_export_hash(paths: dict) -> str: return h.hexdigest() -def build_index(vault: Path, verbose: bool = False) -> int: +def build_index(vault: Path, verbose: bool = False, force_rebuild: bool = False) -> int: """Full rebuild of the canonical asset index for *vault*. - - 3-tier fast-path: - 1. Computes a hash of BBT export JSON files. - 2. Compares with ``export_hash`` stored in the existing index envelope. - 3. If unchanged AND schema version matches, skips the entire rebuild loop. - - Returns: - Number of items written to (or already present in) the index. - """ from paperforge.config import load_vault_config from paperforge.worker._utils import pipeline_paths # noqa: F811 from paperforge.worker.base_views import ensure_base_views @@ -559,7 +550,7 @@ def build_index(vault: Path, verbose: bool = False) -> int: zotero_dir = vault / cfg.get("system_dir", "System") / "Zotero" export_hash = _compute_export_hash(paths) - if isinstance(existing_data, dict) and existing_data.get("export_hash") == export_hash: + if not force_rebuild and isinstance(existing_data, dict) and existing_data.get("export_hash") == export_hash: if existing_data.get("schema_version") == CURRENT_SCHEMA_VERSION: count = len(existing_data.get("items", [])) if verbose: