audit: packed-versioned-bundle cycle close
Cycle-close tidy for the packed-versioned-index-bundle cycle (issues #3 + #4, both shipped and closed). Architect drift review over d83b10f..HEAD against the spec + glossary (no paths.design_ledger / project CLAUDE.md configured, so spec + glossary are the only references; the regression gate is empty — commands.regression: [] — so architect was the sole cycle-close gate). Architect verdict: drift_found, minor — no spec contract violated. Format, header schema, on-disk layout, and the load_packed_or_store validation order (n_rows → model → corpus hash) match the spec exactly; both #3 and #4 acceptance criteria are test-evidenced; no glossary term drift; the IndexStatus / degraded orthogonality is honored. Resolutions: - [medium] Missing positional-alignment test. The spec § Testing strategy promised a "row i == store.get(entries[i].text)" guard, and it had not shipped — the load-bearing invariant that licenses dropping the per-row SHA256 key (row i = corpus entry i) was unprotected. FIXED: added tests/pack_cli_tests.rs::cli_packed_rows_are_in_corpus_order, which packs a store with order-revealing orthogonal vectors via the CLI, reads the packed file back, and asserts the rows follow corpus-load order (swapped order fails the test). - [low] Stale IndexStatus doc comments still said "structurally valid/invalid" though the variants now also carry semantic model/corpus mismatch. FIXED: refreshed the Ok / Mismatch comments in src/model.rs. - [low] The `index --pack` writer logic lives inline in main rather than in the packed module, leaving its header construction outside library test reach. CARRY-ON: filed as backlog issue #5 (idea/debt) — behaviour is correct and CLI-test-covered; the refactor is a self-contained testability improvement, not forced into this tidy. - [note] No design ledger / project CLAUDE.md configured; drift is measurable only against spec + glossary. Recorded as an infrastructure observation. Regression: no scripts configured (no-op). Full suite green (68 tests, +1 for the alignment guard). cycle packed-versioned-bundle tidy (drift-clean). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -82,10 +82,10 @@ pub enum Mode { Lexical, Hybrid }
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
|
||||||
pub enum IndexStatus {
|
pub enum IndexStatus {
|
||||||
Ok, // packed file present and structurally valid
|
Ok, // packed file present and matches the corpus + model
|
||||||
#[default]
|
#[default]
|
||||||
Absent, // no usable index — intentional lexical-only
|
Absent, // no usable index — intentional lexical-only
|
||||||
Mismatch(String), // packed file present but structurally invalid; reason carried
|
Mismatch(String), // packed file present but structurally or semantically invalid; reason carried
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for IndexStatus {
|
impl std::fmt::Display for IndexStatus {
|
||||||
|
|||||||
@@ -120,3 +120,37 @@ fn cli_packed_file_loads_back_as_ok_index() {
|
|||||||
assert!(vector.is_some(), "packed file written by the CLI must yield an index");
|
assert!(vector.is_some(), "packed file written by the CLI must yield an index");
|
||||||
assert_eq!(status, IndexStatus::Ok);
|
assert_eq!(status, IndexStatus::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Positional alignment (spec § Testing strategy): the packed matrix stores one
|
||||||
|
/// row per corpus entry in corpus-load order, so row `i` is the embedding of
|
||||||
|
/// `entries[i].text`. The two entries carry order-revealing orthogonal vectors;
|
||||||
|
/// if packing did not preserve corpus order the rows would come back swapped.
|
||||||
|
#[test]
|
||||||
|
fn cli_packed_rows_are_in_corpus_order() {
|
||||||
|
use alpha_id::packed::read_packed;
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
let corpus = dir.path().join("corpus.txt");
|
||||||
|
// alpha is line 1 (corpus entry 0), beta is line 2 (corpus entry 1).
|
||||||
|
std::fs::write(&corpus, format!("{}\n{}\n", corpus_line("alpha"), corpus_line("beta"))).unwrap();
|
||||||
|
let index_dir = dir.path().join("index");
|
||||||
|
std::fs::create_dir_all(&index_dir).unwrap();
|
||||||
|
|
||||||
|
let store = alpha_id::embed::EmbeddingStore::open(index_dir.to_str().unwrap(), "test/model").unwrap();
|
||||||
|
store.put("alpha", &[1.0f32, 0.0]).unwrap();
|
||||||
|
store.put("beta", &[0.0f32, 1.0]).unwrap();
|
||||||
|
|
||||||
|
let config = write_config(dir.path(), &corpus, &index_dir);
|
||||||
|
let out = Command::new(env!("CARGO_BIN_EXE_alpha-id"))
|
||||||
|
.args(["--config", config.to_str().unwrap(), "index", "--pack"])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(out.status.success(), "stderr: {}", String::from_utf8_lossy(&out.stderr));
|
||||||
|
|
||||||
|
let (_header, rows) = read_packed(&index_dir.join("packed.test_model.bin")).unwrap();
|
||||||
|
// Row i is the embedding of corpus entry i: alpha→[1,0] at row 0, beta→[0,1] at row 1.
|
||||||
|
assert_eq!(
|
||||||
|
rows,
|
||||||
|
vec![vec![1.0f32, 0.0], vec![0.0f32, 1.0]],
|
||||||
|
"packed rows must follow corpus-load order"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user