Skip to content

test(infra): cover canonical archive snapshot residuals - #3882

Merged
Sinity merged 4 commits into
masterfrom
feature/test/canonical-snapshot-wave
Aug 8, 2026
Merged

test(infra): cover canonical archive snapshot residuals#3882
Sinity merged 4 commits into
masterfrom
feature/test/canonical-snapshot-wave

Conversation

@Sinity

@Sinity Sinity commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Summary

Expand the canonical archive snapshot comparator and its mutation suite to cover the six residual proof surfaces identified for Ref polylogue-canonical-snapshot, including tokenizer-compatible default FTS probes.

Problem

The comparator omitted path-derived raw identities, default FTS postings, durable user state, web content constructs, excision tombstones, and the index-owned raw revision heads. The initial default probe derivation also missed short, punctuation-separated, and reserved operator terms accepted by the archive tokenizer.

Solution

The comparator now opens user.db, derives stable raw identities from source evidence, selects bounded probes from the SQLite FTS5 vocabulary and validates them against the public FTS relation, excludes reserved operator words, handles an absent public FTS relation, includes the missing relations, and reports the new user_state section in snapshot diffs. The focused tests add relocation equivalence, semantic red mutations, and tokenizer regressions. No production code, schema, or live archive state changed.

Verification

  • direnv exec . devtools test tests/unit/infra/test_archive_canonical_snapshot.py: 17 passed.
  • direnv exec . devtools verify --quick: all 24 steps passed at 4f72518; the final test-only commit passed its focused suite.
  • The downstream Claude-vintage proof passed 3 tests. The related append-prefix property has an existing revision-chain fixture failure outside this two-file change.

Bead disposition matrix

Assigned Bead Whole-Bead disposition Evidence refs Named successor for residual work
polylogue-canonical-snapshot satisfied commit:27533e4a7, commit:2b132c7d3, commit:4f72518c0, commit:9108e75cb, test:17 canonical snapshot tests passed, command:devtools verify --quick: all 24 steps passed n/a

Capture path-independent raw referents, durable user state, web constructs, excision tombstones, and index revision heads in the canonical comparator. Derive default FTS probes from real block text and add red mutations for each newly covered semantic surface.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Canonical archive snapshots now cover user state, web constructs, excision content, raw revision heads, and normalized raw identities. Default search probes support public projection capture. Tests cover relocation equivalence and mutations across these relations.

Changes

Canonical snapshot comparison

Layer / File(s) Summary
Relation coverage and archive connections
tests/infra/archive_canonical_snapshot.py
The snapshot schema includes user-state relations, web constructs, excision content, and index raw revision heads. Capture can access user.db.
Capture normalization and comparison
tests/infra/archive_canonical_snapshot.py
Capture maps raw session IDs to stable identities, derives default search probes, normalizes relation values, stores user state, and compares it.
Snapshot mutation and coverage tests
tests/unit/infra/test_archive_canonical_snapshot.py
Tests cover archive relocation, raw identity changes, FTS posting deletion, user-state mutations, web constructs, excision tombstones, raw revision heads, and relation coverage.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • Sinity/polylogue#3726: Related archive snapshot test infrastructure and FTS/public projection coverage.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies an infrastructure test change that covers residual canonical archive snapshot behavior.
Description check ✅ Passed The description includes the required summary, problem, solution, verification, and bead disposition details; omitted changelog and risks sections are optional here.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/test/canonical-snapshot-wave

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/infra/archive_canonical_snapshot.py`:
- Around line 411-420: Update _default_search_queries to derive candidates using
the archive’s tokenizer-compatible rules, including short and
punctuation-separated searchable terms, and retain only stable candidates that
match the public-search FTS relation. In
tests/unit/infra/test_archive_canonical_snapshot.py lines 155-174, add a
regression fixture containing only those term shapes and verify that deleting an
FTS posting is reported as red.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cf649f57-fafa-4ebf-973a-24b84b8ef2ad

📥 Commits

Reviewing files that changed from the base of the PR and between aa976bb and 27533e4.

📒 Files selected for processing (2)
  • tests/infra/archive_canonical_snapshot.py
  • tests/unit/infra/test_archive_canonical_snapshot.py

Comment thread tests/infra/archive_canonical_snapshot.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 27533e4a78

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for row in connection.execute("SELECT raw_id, origin, source_index, blob_hash, native_id FROM raw_sessions"):
raw_id, origin, source_index, blob_hash, native_id = row
blob_hash_hex = blob_hash.hex() if isinstance(blob_hash, bytes) else str(blob_hash)
stable_identity = f"raw[{origin}|{source_index}|{blob_hash_hex}|{native_id!r}]"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve source paths in normalized raw identities

When two acquisitions have the same origin, source index, bytes, and native ID but come from different source paths, this expression maps their distinct raw IDs to the same comparator identity, even though deterministic_raw_session_id() deliberately hashes source_path. A route can then associate a session, membership, or revision head with the wrong acquisition and still compare equal because every raw-reference column collapses to the same value; include an archive-relative normalized source path so this mapping remains one-to-one.

Useful? React with 👍 / 👎.

Comment on lines +418 to +419
normalized = " ".join(str(search_text).split())
tokens.update(token for token in normalized.split() if len(token) >= 4 and token.isalnum())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive FTS probes with the configured tokenizer

For archives whose searchable words are attached to punctuation, such as hello. or alpha,beta, whitespace splitting leaves tokens that fail isalnum(), even though the configured unicode61 tokenizer indexes those words. If all block text has that shape, this returns no default queries and deleting or corrupting every FTS posting remains invisible to the canonical comparison; extract tokens with semantics compatible with unicode61 instead.

AGENTS.md reference: AGENTS.md:L76-L78

Useful? React with 👍 / 👎.

Comment on lines +439 to +440
if isinstance(value, str) and _is_raw_id_column(column):
value = raw_identity_map.get(value, value)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize raw identities embedded in authority plans

When compared archives contain raw-authority plans, raw IDs are embedded in fields such as raw_authority_plans.input_raw_ids_json and also determine input_digest, plan_id, and the foreign keys referencing that plan, but this code only rewrites a value when the entire scalar column is named like a raw ID. Since production raw IDs change with the source root, semantically identical authority plans created under two roots retain different JSON, digests, and plan keys and therefore compare unequal; normalize the structured plan identity graph as well as scalar raw-reference columns.

Useful? React with 👍 / 👎.

}
ids = tuple(session_ids) if session_ids is not None else _session_ids(connections["index"])
public = _capture_public_projections(root, ids, tuple(search_queries))
effective_search_queries = tuple(search_queries) or _default_search_queries(connections["index"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Canonicalize tied FTS search results

When two blocks match a selected probe with equal BM25 rank, search_archive_blocks() orders only by rank, so SQLite returns tied rows in rowid/insertion order. The order-invariance properties compare archives ingested in different orders; enabling default probes here now places those unstable lists in every snapshot and makes semantically identical archives compare unequal whenever a selected token has tied matches. Sort the returned block IDs for the snapshot or add a stable block-ID tie-breaker to the search.

Useful? React with 👍 / 👎.

Problem: default canonical snapshot probes were derived by splitting block text and excluding short terms, so punctuation-separated tokenizer terms could be absent from the public search projection.

What changed: derive bounded probes from the SQLite FTS5 vocabulary, validate each candidate against the public FTS relation, and add a short punctuation-term regression fixture.

Compatibility/migration: test infrastructure only; archive schemas and production behavior are unchanged.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b132c7d3a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

("source", "raw_hook_events"),
),
"authority": (
("index", "raw_revision_heads"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude the revision-head wall-clock timestamp

When two equivalent routes materialize the same accepted revision head at different times, capturing this entire relation also compares decided_at_ms, which the production writer sets from datetime.now(UTC). Both tests/infra/reindex_differential.py and tests/unit/storage/test_incremental_rebuild_equivalence.py already classify that column as volatile, so canonical route comparisons involving real revision heads will report false differences; add index.raw_revision_heads.decided_at_ms to the run-local normalization allowlist.

Useful? React with 👍 / 👎.

@Sinity
Sinity merged commit 359a369 into master Aug 8, 2026
3 checks passed
@Sinity
Sinity deleted the feature/test/canonical-snapshot-wave branch August 8, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant