-
Notifications
You must be signed in to change notification settings - Fork 2
fix(maintenance): gate reindex on durable schema currency (#3851) #3851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,61 @@ class RebuildDerivedStateProvenanceError(RebuildProvenanceError): | |
| """A derived-state stage was blocked by a failed provenance recheck.""" | ||
|
|
||
|
|
||
| class RebuildSchemaCurrencyError(RuntimeError): | ||
| """The durable tiers do not match the package that would rebuild them.""" | ||
|
|
||
| def __init__(self, diagnostic: dict[str, object]) -> None: | ||
| self.diagnostic = diagnostic | ||
| blocked = diagnostic["blocking_tiers"] | ||
| assert isinstance(blocked, list) | ||
| detail = ", ".join( | ||
| f"{item['tier']}.db:{item['actual_user_version']}!={item['expected_user_version']}" | ||
| for item in blocked | ||
| if isinstance(item, dict) | ||
| ) | ||
| super().__init__(f"rebuild schema currency preflight failed: {detail}") | ||
|
|
||
|
|
||
| def rebuild_schema_currency_preflight(root: Path) -> dict[str, object]: | ||
| """Report whether durable source evidence matches this runtime package. | ||
|
|
||
| ``index.db`` is intentionally absent: rebuilding it is the operation's | ||
| purpose, while a source/user mismatch means this package can interpret or | ||
| write durable evidence using a schema it does not own. | ||
| """ | ||
| from polylogue.storage.archive_readiness import probe_archive_tier | ||
| from polylogue.storage.sqlite.archive_tiers.types import ArchiveTier | ||
|
|
||
| checks: list[dict[str, object]] = [] | ||
| for tier in (ArchiveTier.SOURCE, ArchiveTier.USER): | ||
| probe = probe_archive_tier(tier, root / f"{tier.value}.db") | ||
|
Comment on lines
+95
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The existing AGENTS.md reference: AGENTS.md:L325-L328 Useful? React with 👍 / 👎.
Comment on lines
+95
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The canonical durable migration set already includes Useful? React with 👍 / 👎. |
||
| checks.append( | ||
| { | ||
| "tier": tier.value, | ||
| "path": probe.path, | ||
| "actual_user_version": probe.user_version, | ||
| "expected_user_version": probe.expected_user_version, | ||
| "status": probe.version_status, | ||
| } | ||
| ) | ||
| blocking = [check for check in checks if check["status"] != "ok"] | ||
| return { | ||
| "kind": "rebuild-schema-currency", | ||
| "archive_root": str(root), | ||
| "status": "ready" if not blocking else "blocked", | ||
| "tiers": checks, | ||
| "blocking_tiers": blocking, | ||
| } | ||
|
|
||
|
|
||
| def require_rebuild_schema_currency(root: Path) -> dict[str, object]: | ||
| """Reject a rebuild before it consumes evidence or creates a generation.""" | ||
| diagnostic = rebuild_schema_currency_preflight(root) | ||
| if diagnostic["status"] != "ready": | ||
| raise RebuildSchemaCurrencyError(diagnostic) | ||
| return diagnostic | ||
|
|
||
|
|
||
| @dataclass(frozen=True, slots=True) | ||
| class RebuildProvenanceContext: | ||
| """Validated evidence shared by every mutation in one rebuild pass. | ||
|
|
@@ -1047,6 +1102,7 @@ async def rebuild_index_from_source(request: RebuildIndexRequest) -> RebuildInde | |
| log_mapped_bytes_budget_check(logger, check_mapped_bytes_budget_against_cgroup_limit()) | ||
| validate_rebuild_index_request(request) | ||
| root = request.archive_root | ||
| require_rebuild_schema_currency(root) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a newer package migrates Useful? React with 👍 / 👎. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For local CLI execution when AGENTS.md reference: AGENTS.md:L37-L40 Useful? React with 👍 / 👎. |
||
| consumed_evidence = _validate_rebuild_provenance_receipt(root, request.schema_inference_receipt_path) | ||
| location = ArchiveLocation.resolve(root) | ||
| # The joined raw-frontier projection is rooted at the co-located active | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
--preflightis combined with--daemon, this branch silently ignores bothuse_daemonanddaemon_urland probes the client's localarchive_root()instead. If the CLI is controlling a daemon with a different archive root, it can reportreadyfor the wrong databases—or block because of an unrelated local archive—while the subsequent daemon rebuild targets another root. Either reject this option combination like--daemon --plan, or expose and call a daemon-side preflight endpoint.Useful? React with 👍 / 👎.