Define the lexical index manifest schema v0.1 #69
No reviewers
Labels
No labels
area/deployment
area/governance
area/metadata
area/pipeline
area/search
type/data
type/design
type/implementation
type/testing
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Arkive/arkive!69
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/issue-21-index-manifest"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
meta/schemas/index_manifest.schema.json, the v0.1 contract for one built SQLite FTS5 index per distribution domain. Six closed sections:backend(engine + SQLite version),build(table, columns,unicode61options, a total insertion order, BM25 withchunk_idtie-break, per ADR-0004's determinism boundary),compatibility(FTS5 required, minimum SQLite, record schema versions, indexed languages),inputs(explicit included and excluded records, per-document checksum + chunk count + chunk digest),artifact(size + SHA-256 per file), and optionalprovenance.arkive.index_manifestwith the canonical digest form (arkive-json-canonical-v1: the indexed projection of each chunk, sorted keys, compact, UTF-8,(sequence, chunk_id)order) andverify_manifest, a pure function over loaded records.index_manifest.jsoninto the validator. It is verified against the records in the same run and reports missing, duplicate, stale, incompatible, and checksum-invalid conditions with JSON pointers. Auser_localmanifest underdata/is rejected as contamination (storage boundary §7.1).docs/index-manifest.mdand updates the schema README, storage-boundary §6.4, development docs, and CHANGELOG.Design decisions worth a look
provenanceis the only section allowed to hold one, and it is excluded from reproducibility comparison. Every other section isadditionalProperties: false, so a timestamp cannot creep in without a schema change. Tests assert this for each section.embedding_refortoken_counton a chunk does not make a current index stale, while any change to text, identity, offsets, citation anchors, or order does. Reordering/reformattingchunks.jsonis a no-op. Issue #22 should callchunks_digestrather than reimplement it.no_chunk_records,not_bundleable,review_not_acceptedare each verified against the records;operator_exclusionrequires anote. Same spirit as the recipe rules: a reason that cannot be wrong is not a reason.backend.sqlite_versionplusprovenance.environmentlet a reader tell whether comparing two artifacts byte-for-byte is meaningful at all.minimum_sqlite_versionmust be ≥ 3.27.0 whenremove_diacriticsis 2, because that option did not exist earlier.The fixture
tests/fixtures/index/pilot-core/is a real FTS5 database (163,840 bytes, same size as the Issue #20 build) over all 38 committed chunks, built with the ADR-0004 configuration bytests/fixtures/index/make_pilot_core_fixture.py. Two consecutive runs here were byte-identical. It was built under SQLite 3.50.2; the manifest records that. Rebuilding under 3.51.2 will legitimately produce different bytes, which is exactly the boundary the manifest exists to make explicit. The generator is test scaffolding, not the Issue #22 builder, and #22 should supersede it. The fixture is deliberately tied to the committed corpus: adding a source underdata/sources/without regenerating it fails the completeness check.Honest caveat: this commits a 160 KB binary. If you would rather not, the alternative is to generate the artifact in-test, but then the committed checksum cannot be stable across SQLite versions, so the checksum-invalid tests would have to compare against a checksum computed in the same test run rather than a committed value. I chose the committed artifact so the positive example is a real reviewable file. Easy to flip.
Verification
git diff --checkpython pipeline/validate/validate_records.py(unchanged corpus still passes, 0 manifests)python pipeline/validate/validate_records.py data/sources tests/fixtures/index/pilot-core(PASS, 1 manifest)python -m unittest discover -s tests -v— 375 tests, 63 newpython -m ruff check src pipeline testspython -m ruff format --check src pipeline testscompatibility.requiresmust containfts5) is currently unkillable because the enum has only that value; it is kept for when the enum grows.arkive/index_manifest.py: 97% statements; the uncovered branches are the defensivesource is Noneguards on exclusion-reason checks, reachable only when a document references an unknown source, which the validator already reports separately.Scope confirmation
Linked issue
Closes #21
🤖 Generated with Claude Code
https://claude.ai/code/session_015JFC5ueshFKDspps6NRMFU
Thanks for the work on this — the implementation looks very solid overall, and the general manifest/reproducibility design is in good shape.
I found one issue I would like corrected before merging, plus one contract point that should be clarified.
Required change: builder tool/version must not be optional
Issue #21 explicitly requires the manifest to record the build tool, backend, and relevant dependency versions.
Right now the builder identity/version is stored under:
provenance.builder.toolprovenance.builder.versionbut
provenanceis optional, and the test suite explicitly verifies that a manifest without provenance is still valid.That means a schema-valid manifest can currently omit the build tool entirely, which does not satisfy the issue requirement.
Please move the builder identity/version into required reproducible metadata, for example under the existing
buildsection:or use another required top-level structure if you think that is cleaner.
The optional
provenancesection can still contain non-reproducible/runtime information such as build timestamp, environment, repository commit, notes, etc.Please also add a negative validation test confirming that a manifest missing the required builder tool/version is rejected.
Clarify chunk membership semantics
Issue #21 says that included and excluded source, document, and chunk records must be explicit.
The current implementation intentionally does not enumerate individual chunk IDs. Instead, inclusion of a document means all of its chunks are included, with
chunk_countand a canonicalchunks_digestprotecting the exact chunk set.I actually prefer this design because it will scale much better than storing potentially huge lists of chunk IDs, and the digest covers the important indexed/citation fields.
However, please make this contract explicit in the documentation/schema description so there is no ambiguity for later issues:
That should make it clear that the current approach intentionally satisfies the chunk-membership requirement without enumerating every chunk.
Other than those points, the implementation looks very strong. The staleness checks, artifact verification, FTS5 build contract, inclusion/exclusion validation, citation fields, and test coverage all look appropriate for what #21 is trying to establish.
Once the required builder metadata issue is fixed and the chunk-membership contract is made explicit, I should be comfortable merging this.
Thanks for the review. Both points are addressed in
5da32c0.Builder tool/version is now required.
builder(tool,version, both non-empty) moved out ofprovenanceinto the requiredbuildsection, so it is part of the reproducible metadata and cannot be dropped with the optional section.provenancekeeps only runtime detail:built_at,environment,repository_commit,notes. Three negative tests cover it: a manifest with nobuild.builder, one with a missing or emptytoolorversion, and one that records the builder only underprovenance(rejected on both counts). The existing provenance-optional test now also asserts the builder survives dropping that section. Each new test was mutation-checked against the schema rule it guards.Chunk-membership contract is explicit. Your wording is in the schema's
inputsdescription verbatim, restated oninputs.documents, and is now its own subsection (2.1) ofdocs/index-manifest.md, with a note that Issues #22 and #25 must not assume a per-chunk membership list exists. Section 3 explains whybuild.builderlives inbuildrather thanprovenance, and section 7 tells #22 to record itself there.Fixture manifest regenerated; the SQLite artifact is byte-identical. 378 tests pass, ruff clean.