From 3f80e24cab5f7db78e3cb2525a283e2cea2671ac Mon Sep 17 00:00:00 2001 From: lusoris Date: Fri, 23 Oct 2026 06:51:08 +0200 Subject: [PATCH 1/3] test: read shared registry data from a declared root Read shared registry data from the directory declared by the KNOWLEDGE_DATA_ROOT environment variable across knowledge retrieval and registry acquisition runner tests. When KNOWLEDGE_DATA_ROOT is unset or empty, tests that depend on shared schemas or acceptance fixtures skip with the fixed prefix "knowledge data root absent:" followed by the test purpose. When the variable is set to a directory lacking expected files, the tests fail with the missing file path. The frozen P1-SRC-02 runner pins always execute, with only its four schema pins depending on the root. Touched tests: - tools/knowledge-retrieval: - TestMultidomainBindingClosureDeterministicNineClose - TestMultidomainBindingClosureFailsClosed - TestGoldSpanLaneRanks - TestMineSeparatingCaseShapes - tools/knowledge-registry/p1-src03-acquisition-runner: - TestExecutionManifestBindsExactRepositoryBytes - TestP1SRC02RunnerAndSchemasRemainByteIdentical Order: engine-knowledge-monorepo-test-data-20261023 Signed-off-by: lusoris --- README.md | 2 +- .../data_root_test.go | 112 ++++++++++++++++++ .../runner_test.go | 92 +++++++++----- tools/knowledge-retrieval/data_root_test.go | 112 ++++++++++++++++++ .../evaluation_binding_closure_test.go | 94 +++++++++------ .../fusion_discrimination_test.go | 61 ++++++---- 6 files changed, 387 insertions(+), 86 deletions(-) create mode 100644 tools/knowledge-registry/p1-src03-acquisition-runner/data_root_test.go create mode 100644 tools/knowledge-retrieval/data_root_test.go diff --git a/README.md b/README.md index 85dea82..e27db85 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Run unit tests directly in each module: (cd tools/knowledge-retrieval && go test -v -run 'Test(BM25|Dense|Current|Hybrid|Lifecycle|Paired|Situating|FineSpan)' ./...) ``` -*Note on conformance and integration tests*: Certain tests in `tools/knowledge-registry/p1-src03-acquisition-runner` and `tools/knowledge-retrieval` depend on shared monorepo schemas (`knowledge/registry/schemas/`) and test vectors (`testdata/canonical-json/v1/vectors.json`). Neither is part of this repository yet, so those tests fail here. +*Note on conformance and integration tests*: Tests in `tools/knowledge-registry/p1-src03-acquisition-runner` and `tools/knowledge-retrieval` that depend on shared registry schemas (`knowledge/registry/schemas/`) and acceptance data (`knowledge/registry/acceptance/p1-src-03/`) read them from the directory named by the `KNOWLEDGE_DATA_ROOT` environment variable. When `KNOWLEDGE_DATA_ROOT` is unset or empty, these tests skip with the fixed prefix `knowledge data root absent:` followed by the test purpose. To run with shared data, set `KNOWLEDGE_DATA_ROOT` to a directory containing the `knowledge/registry` tree (e.g. `KNOWLEDGE_DATA_ROOT=/path/to/data go test ./...`). If `KNOWLEDGE_DATA_ROOT` is set but lacks the expected files, the tests fail with the missing file path. Tests depending on test vectors (`testdata/canonical-json/v1/vectors.json`) fail when that file is absent from the repository. ### 2. Python Tests diff --git a/tools/knowledge-registry/p1-src03-acquisition-runner/data_root_test.go b/tools/knowledge-registry/p1-src03-acquisition-runner/data_root_test.go new file mode 100644 index 0000000..8dd3345 --- /dev/null +++ b/tools/knowledge-registry/p1-src03-acquisition-runner/data_root_test.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" +) + +type testingTB interface { + Helper() + Skipf(format string, args ...any) + Fatalf(format string, args ...any) +} + +func knowledgeDataRoot(tb testingTB, purpose string, expectedPaths ...string) string { + tb.Helper() + root := strings.TrimSpace(os.Getenv("KNOWLEDGE_DATA_ROOT")) + if root == "" { + tb.Skipf("knowledge data root absent: %s", purpose) + return "" + } + checks := expectedPaths + if len(checks) == 0 { + checks = []string{"knowledge/registry"} + } + for _, rel := range checks { + target := filepath.Join(root, filepath.FromSlash(rel)) + if _, err := os.Stat(target); err != nil { + tb.Fatalf("knowledge data root %s lacking expected file: %s", root, target) + return "" + } + } + return root +} + +type spyTB struct { + failed bool + skipped bool + message string +} + +func (s *spyTB) Helper() {} + +func (s *spyTB) Skipf(format string, args ...any) { + s.skipped = true + s.message = fmt.Sprintf(format, args...) +} + +func (s *spyTB) Fatalf(format string, args ...any) { + s.failed = true + s.message = fmt.Sprintf(format, args...) +} + +func TestKnowledgeDataRootPlantedUnsetSkipsWithPrefix(t *testing.T) { + for _, envVal := range []string{"", " "} { + t.Setenv("KNOWLEDGE_DATA_ROOT", envVal) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted unset check") + if got != "" { + t.Fatalf("expected empty root on unset, got %q", got) + } + if !spy.skipped || spy.failed { + t.Fatalf("expected skip without failure, got skipped=%v failed=%v", spy.skipped, spy.failed) + } + const wantPrefix = "knowledge data root absent:" + if !strings.HasPrefix(spy.message, wantPrefix) { + t.Fatalf("skip message %q missing prefix %q", spy.message, wantPrefix) + } + if !strings.Contains(spy.message, "planted unset check") { + t.Fatalf("skip message %q missing purpose", spy.message) + } + } +} + +func TestKnowledgeDataRootPlantedEmptyTempDirFails(t *testing.T) { + emptyDir := t.TempDir() + t.Setenv("KNOWLEDGE_DATA_ROOT", emptyDir) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted empty check", "knowledge/registry") + if got != "" { + t.Fatalf("expected empty root on failure, got %q", got) + } + if !spy.failed || spy.skipped { + t.Fatalf("expected fatal failure without skip, got failed=%v skipped=%v", spy.failed, spy.skipped) + } + if !strings.Contains(spy.message, emptyDir) { + t.Fatalf("fatal message %q missing empty dir path %s", spy.message, emptyDir) + } +} + +func TestKnowledgeDataRootPlantedTempDirWithFixturesPasses(t *testing.T) { + tempDir := t.TempDir() + fixtureRel := filepath.Join("knowledge", "registry", "acceptance", "fixture.json") + fullPath := filepath.Join(tempDir, fixtureRel) + if err := os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(fullPath, []byte("{}\n"), 0o644); err != nil { + t.Fatal(err) + } + t.Setenv("KNOWLEDGE_DATA_ROOT", tempDir) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted fixture check", fixtureRel) + if spy.failed || spy.skipped { + t.Fatalf("expected success without fail or skip, got failed=%v skipped=%v msg=%s", spy.failed, spy.skipped, spy.message) + } + if got != tempDir { + t.Fatalf("got root %q, want %q", got, tempDir) + } +} diff --git a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go index 6139056..63f0350 100644 --- a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go +++ b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go @@ -883,9 +883,20 @@ func TestExecutionManifestBindsExactRepositoryBytes(t *testing.T) { if err != nil { t.Fatal(err) } + dataRoot := knowledgeDataRoot(t, "execution manifest exact repository bytes", + "knowledge/registry/schemas/source-acquisition-contract-v2.schema.json") repositoryRoot := filepath.Join("..", "..", "..") for _, artifact := range manifest.Artifacts { - raw, err := os.ReadFile(filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath))) + path := filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath)) + if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { + path = filepath.Join(dataRoot, filepath.FromSlash(artifact.LogicalPath)) + } else if _, err := os.Stat(path); err != nil && dataRoot != "" { + alt := filepath.Join(dataRoot, filepath.FromSlash(artifact.LogicalPath)) + if _, statErr := os.Stat(alt); statErr == nil { + path = alt + } + } + raw, err := os.ReadFile(path) if err != nil { t.Fatal(err) } @@ -962,37 +973,17 @@ func TestEmitSchemaValidationFixtures(t *testing.T) { } } -func TestP1SRC02RunnerAndSchemasRemainByteIdentical(t *testing.T) { - expected := map[string]string{ - "../source-acquisition-runner/README.md": "f7da4d8a2f555970203d33d5750cef97c2dc383c77867bf7d5aa333ce2c8646c", - "../source-acquisition-runner/cas.go": "93721cb78aa49acc8377a209f3df6b6368056c276744dc49e0338f5887ddea75", - "../source-acquisition-runner/contract.go": "aef2405575f8fee962611f8fee95a852483337fd75636afc71d81f0969f2ff15", - "../source-acquisition-runner/github.go": "37c48cfbe1efe4932ee126271eb8958fd8f138714f02710d8afa648e6e2e80e3", - "../source-acquisition-runner/go.mod": "793c7f899940cc686f170ff89215d9b8eee48f4ebfaf793726b70b1be10c32de", - "../source-acquisition-runner/main.go": "a99cd8e28f21f325fd2ef057169e477a8ff30a04302726e0be3470f1e2335127", - "../source-acquisition-runner/runner_test.go": "de66639d35f46611ceff59b4a9a01f7883c90ec29c316d8b47cf38d16a062fe8", - "../../../knowledge/registry/schemas/source-acquisition-receipt.schema.json": "ed1577e9741674b0a5ad036b949b811293b82579c635c6c63bc5e561eab1eeb1", - "../../../knowledge/registry/schemas/source-inventory-proposal.schema.json": "a9197f0a7ac704f92650354153e35ad90734b99feaa99ebb7bb38123932f12ac", - "../../../knowledge/registry/schemas/source-acquisition-output-common.schema.json": "0a6b54bfab2af8ec7400de5b439d34d6f9f05c8d914deb479585dbe73ee92549", - "../../../knowledge/registry/schemas/source-acquisition-plan.schema.json": "a89767e5b9689da4242bfbc2d22160baad204f6596ad61aab6b41fd00c50358d", - } - for path, want := range expected { - raw, err := os.ReadFile(path) - if err != nil { - t.Fatal(err) - } - digest := sha256.Sum256(raw) - if got := hex.EncodeToString(digest[:]); got != want { - t.Fatalf("P1-SRC-02 frozen artifact changed: %s = %s, want %s", path, got, want) - } - } - for _, identity := range []string{ +func verifyRunnerIdentities(t *testing.T) { + t.Helper() + identities := []string{ "source-acquisition-plan:sha256:7b06d690d2edfe08e1fd05060116b3ca08a2a8f82763976f4d4fe1232c844aad", "accepted-record-artifact-bundle:sha256:61310bc368840c0202b0bd6e6d828c140aba26b7a389922d9b1fdbb836aecba6", "sha256:6306df08e525472da822d10477ea12a9ec3929d14d9d322f842ac88b76401fdb", - } { + } + paths := []string{"../source-acquisition-runner/contract.go", "../source-acquisition-runner/github.go", "../source-acquisition-runner/README.md"} + for _, identity := range identities { found := false - for _, path := range []string{"../source-acquisition-runner/contract.go", "../source-acquisition-runner/github.go", "../source-acquisition-runner/README.md"} { + for _, path := range paths { raw, err := os.ReadFile(path) if err != nil { t.Fatal(err) @@ -1005,6 +996,51 @@ func TestP1SRC02RunnerAndSchemasRemainByteIdentical(t *testing.T) { } } +func TestP1SRC02RunnerAndSchemasRemainByteIdentical(t *testing.T) { + runnerFiles := map[string]string{ + "../source-acquisition-runner/README.md": "f7da4d8a2f555970203d33d5750cef97c2dc383c77867bf7d5aa333ce2c8646c", + "../source-acquisition-runner/cas.go": "93721cb78aa49acc8377a209f3df6b6368056c276744dc49e0338f5887ddea75", + "../source-acquisition-runner/contract.go": "aef2405575f8fee962611f8fee95a852483337fd75636afc71d81f0969f2ff15", + "../source-acquisition-runner/github.go": "37c48cfbe1efe4932ee126271eb8958fd8f138714f02710d8afa648e6e2e80e3", + "../source-acquisition-runner/go.mod": "793c7f899940cc686f170ff89215d9b8eee48f4ebfaf793726b70b1be10c32de", + "../source-acquisition-runner/main.go": "a99cd8e28f21f325fd2ef057169e477a8ff30a04302726e0be3470f1e2335127", + "../source-acquisition-runner/runner_test.go": "de66639d35f46611ceff59b4a9a01f7883c90ec29c316d8b47cf38d16a062fe8", + } + for path, want := range runnerFiles { + raw, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + digest := sha256.Sum256(raw) + if got := hex.EncodeToString(digest[:]); got != want { + t.Fatalf("P1-SRC-02 frozen artifact changed: %s = %s, want %s", path, got, want) + } + } + verifyRunnerIdentities(t) + + schemaFiles := map[string]string{ + "knowledge/registry/schemas/source-acquisition-receipt.schema.json": "ed1577e9741674b0a5ad036b949b811293b82579c635c6c63bc5e561eab1eeb1", + "knowledge/registry/schemas/source-inventory-proposal.schema.json": "a9197f0a7ac704f92650354153e35ad90734b99feaa99ebb7bb38123932f12ac", + "knowledge/registry/schemas/source-acquisition-output-common.schema.json": "0a6b54bfab2af8ec7400de5b439d34d6f9f05c8d914deb479585dbe73ee92549", + "knowledge/registry/schemas/source-acquisition-plan.schema.json": "a89767e5b9689da4242bfbc2d22160baad204f6596ad61aab6b41fd00c50358d", + } + t.Run("schemas", func(t *testing.T) { + dataRoot := knowledgeDataRoot(t, "P1-SRC-02 schema byte identity", + "knowledge/registry/schemas/source-acquisition-receipt.schema.json") + for rel, want := range schemaFiles { + path := filepath.Join(dataRoot, filepath.FromSlash(rel)) + raw, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read schema %s: %v", path, err) + } + digest := sha256.Sum256(raw) + if got := hex.EncodeToString(digest[:]); got != want { + t.Fatalf("P1-SRC-02 frozen schema changed: %s = %s, want %s", path, got, want) + } + } + }) +} + func TestGetJSONRejectsRepositoryOutsideContract(t *testing.T) { contract, _, err := exactContract() if err != nil { diff --git a/tools/knowledge-retrieval/data_root_test.go b/tools/knowledge-retrieval/data_root_test.go new file mode 100644 index 0000000..8dd3345 --- /dev/null +++ b/tools/knowledge-retrieval/data_root_test.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" +) + +type testingTB interface { + Helper() + Skipf(format string, args ...any) + Fatalf(format string, args ...any) +} + +func knowledgeDataRoot(tb testingTB, purpose string, expectedPaths ...string) string { + tb.Helper() + root := strings.TrimSpace(os.Getenv("KNOWLEDGE_DATA_ROOT")) + if root == "" { + tb.Skipf("knowledge data root absent: %s", purpose) + return "" + } + checks := expectedPaths + if len(checks) == 0 { + checks = []string{"knowledge/registry"} + } + for _, rel := range checks { + target := filepath.Join(root, filepath.FromSlash(rel)) + if _, err := os.Stat(target); err != nil { + tb.Fatalf("knowledge data root %s lacking expected file: %s", root, target) + return "" + } + } + return root +} + +type spyTB struct { + failed bool + skipped bool + message string +} + +func (s *spyTB) Helper() {} + +func (s *spyTB) Skipf(format string, args ...any) { + s.skipped = true + s.message = fmt.Sprintf(format, args...) +} + +func (s *spyTB) Fatalf(format string, args ...any) { + s.failed = true + s.message = fmt.Sprintf(format, args...) +} + +func TestKnowledgeDataRootPlantedUnsetSkipsWithPrefix(t *testing.T) { + for _, envVal := range []string{"", " "} { + t.Setenv("KNOWLEDGE_DATA_ROOT", envVal) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted unset check") + if got != "" { + t.Fatalf("expected empty root on unset, got %q", got) + } + if !spy.skipped || spy.failed { + t.Fatalf("expected skip without failure, got skipped=%v failed=%v", spy.skipped, spy.failed) + } + const wantPrefix = "knowledge data root absent:" + if !strings.HasPrefix(spy.message, wantPrefix) { + t.Fatalf("skip message %q missing prefix %q", spy.message, wantPrefix) + } + if !strings.Contains(spy.message, "planted unset check") { + t.Fatalf("skip message %q missing purpose", spy.message) + } + } +} + +func TestKnowledgeDataRootPlantedEmptyTempDirFails(t *testing.T) { + emptyDir := t.TempDir() + t.Setenv("KNOWLEDGE_DATA_ROOT", emptyDir) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted empty check", "knowledge/registry") + if got != "" { + t.Fatalf("expected empty root on failure, got %q", got) + } + if !spy.failed || spy.skipped { + t.Fatalf("expected fatal failure without skip, got failed=%v skipped=%v", spy.failed, spy.skipped) + } + if !strings.Contains(spy.message, emptyDir) { + t.Fatalf("fatal message %q missing empty dir path %s", spy.message, emptyDir) + } +} + +func TestKnowledgeDataRootPlantedTempDirWithFixturesPasses(t *testing.T) { + tempDir := t.TempDir() + fixtureRel := filepath.Join("knowledge", "registry", "acceptance", "fixture.json") + fullPath := filepath.Join(tempDir, fixtureRel) + if err := os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(fullPath, []byte("{}\n"), 0o644); err != nil { + t.Fatal(err) + } + t.Setenv("KNOWLEDGE_DATA_ROOT", tempDir) + spy := &spyTB{} + got := knowledgeDataRoot(spy, "planted fixture check", fixtureRel) + if spy.failed || spy.skipped { + t.Fatalf("expected success without fail or skip, got failed=%v skipped=%v msg=%s", spy.failed, spy.skipped, spy.message) + } + if got != tempDir { + t.Fatalf("got root %q, want %q", got, tempDir) + } +} diff --git a/tools/knowledge-retrieval/evaluation_binding_closure_test.go b/tools/knowledge-retrieval/evaluation_binding_closure_test.go index 783c155..ae0084b 100644 --- a/tools/knowledge-retrieval/evaluation_binding_closure_test.go +++ b/tools/knowledge-retrieval/evaluation_binding_closure_test.go @@ -10,18 +10,18 @@ import ( ) const ( - closureAcceptanceDir = "../../knowledge/registry/acceptance/p1-src-03" - closureEvaluationTime = "2026-07-20T13:00:00Z" - frozenRequirementsID = "retrieval-binding-requirements:sha256:8c58e1e9cfe2cef672f104cfc88ab0229ba666e829d94188cda277b6a4e87f49" + closureAcceptanceRelDir = "knowledge/registry/acceptance/p1-src-03" + closureEvaluationTime = "2026-07-20T13:00:00Z" + frozenRequirementsID = "retrieval-binding-requirements:sha256:8c58e1e9cfe2cef672f104cfc88ab0229ba666e829d94188cda277b6a4e87f49" ) // closureFixture copies the committed admitted-artifacts envelope and its nine // referenced manifests into a writable temp tree so negative cases can tamper // freely without touching the committed evidence. -func closureFixture(t *testing.T) (admittedPath, root string) { +func closureFixture(t *testing.T, acceptanceDir string) (admittedPath, root string) { t.Helper() root = t.TempDir() - raw, err := os.ReadFile(filepath.Join(closureAcceptanceDir, "admitted-artifacts.json")) + raw, err := os.ReadFile(filepath.Join(acceptanceDir, "admitted-artifacts.json")) if err != nil { t.Fatalf("read admitted-artifacts: %v", err) } @@ -31,7 +31,7 @@ func closureFixture(t *testing.T) (admittedPath, root string) { } for _, a := range env.Authorities { for _, art := range []MultidomainBindingClosureAdmittedArtifact{a.SnapshotManifest, a.EvidenceManifest, a.AdmissionPolicy} { - b, err := os.ReadFile(filepath.Join(closureAcceptanceDir, art.Path)) + b, err := os.ReadFile(filepath.Join(acceptanceDir, art.Path)) if err != nil { t.Fatalf("read artifact %s: %v", art.Path, err) } @@ -85,41 +85,59 @@ func rewriteAdmitted(t *testing.T, admittedPath string, mutate func(*Multidomain } } -func TestMultidomainBindingClosureDeterministicNineClose(t *testing.T) { - admitted, _ := closureFixture(t) - freezeBefore, err := os.ReadFile(multidomainFreezePath) - if err != nil { - t.Fatal(err) - } +func matchesExpectedGapCounts(m MultidomainBindingClosureManifest) bool { + return m.ClosedGapCount == 9 && m.BlockingGapCount == 29 && m.GapCount == 38 +} - first, firstPath := materializeClosure(t, admitted) +func isBlockedState(m MultidomainBindingClosureManifest) bool { + return m.State == "blocked" && !m.Promotable && !m.ExecutionAuthorized && !m.Ready +} + +func hasAnyCapability(c MultidomainBindingClosureCapabilities) bool { + return c.RetrievalAuthorized || c.EvaluationAuthorized || c.SigningAuthorized || + c.GenerationAuthorized || c.PointerWriteAuthorized || c.ServingAuthorized +} - if first.ClosedGapCount != 9 || first.BlockingGapCount != 29 || first.GapCount != 38 { +func verifyClosureGapsAndCapabilities(t *testing.T, m MultidomainBindingClosureManifest) { + t.Helper() + if !matchesExpectedGapCounts(m) { t.Fatalf("gaps = %d closed / %d blocking / %d total; want 9/29/38", - first.ClosedGapCount, first.BlockingGapCount, first.GapCount) + m.ClosedGapCount, m.BlockingGapCount, m.GapCount) } closed := 0 - for _, g := range first.Gaps { - if g.Blocking { - continue - } - closed++ - if g.Scope != "source_authority" { - t.Fatalf("non-blocking gap has scope %q; only source_authority may close", g.Scope) + for _, g := range m.Gaps { + if !g.Blocking { + closed++ + if g.Scope != "source_authority" { + t.Fatalf("non-blocking gap has scope %q; only source_authority may close", g.Scope) + } } } if closed != 9 { t.Fatalf("%d gaps flipped non-blocking; want exactly 9", closed) } - if first.State != "blocked" || first.Promotable || first.ExecutionAuthorized || first.Ready { + if !isBlockedState(m) { t.Fatalf("state=%q promotable=%v execution=%v ready=%v; want blocked/false/false/false", - first.State, first.Promotable, first.ExecutionAuthorized, first.Ready) + m.State, m.Promotable, m.ExecutionAuthorized, m.Ready) } - c := first.Capabilities - if c.RetrievalAuthorized || c.EvaluationAuthorized || c.SigningAuthorized || - c.GenerationAuthorized || c.PointerWriteAuthorized || c.ServingAuthorized { - t.Fatalf("closure granted an authority capability: %+v", c) + if hasAnyCapability(m.Capabilities) { + t.Fatalf("closure granted an authority capability: %+v", m.Capabilities) } +} + +func TestMultidomainBindingClosureDeterministicNineClose(t *testing.T) { + dataRoot := knowledgeDataRoot(t, "multidomain binding closure deterministic nine close", + filepath.Join(closureAcceptanceRelDir, "admitted-artifacts.json")) + acceptanceDir := filepath.Join(dataRoot, filepath.FromSlash(closureAcceptanceRelDir)) + admitted, _ := closureFixture(t, acceptanceDir) + freezeBefore, err := os.ReadFile(multidomainFreezePath) + if err != nil { + t.Fatal(err) + } + + first, firstPath := materializeClosure(t, admitted) + verifyClosureGapsAndCapabilities(t, first) + if !strings.HasPrefix(first.ManifestID, "retrieval-binding-requirements:sha256:") { t.Fatalf("manifest id %q lacks the expected prefix", first.ManifestID) } @@ -152,9 +170,13 @@ func TestMultidomainBindingClosureDeterministicNineClose(t *testing.T) { } func TestMultidomainBindingClosureFailsClosed(t *testing.T) { + dataRoot := knowledgeDataRoot(t, "multidomain binding closure fails closed", + filepath.Join(closureAcceptanceRelDir, "admitted-artifacts.json")) + acceptanceDir := filepath.Join(dataRoot, filepath.FromSlash(closureAcceptanceRelDir)) + // wrong frozen requirements target t.Run("wrong_requirements_target", func(t *testing.T) { - admitted, _ := closureFixture(t) + admitted, _ := closureFixture(t, acceptanceDir) rewriteAdmitted(t, admitted, func(e *MultidomainBindingClosureAdmittedArtifacts) { e.RequirementsManifestID = "retrieval-binding-requirements:sha256:" + strings.Repeat("0", 64) }) @@ -166,7 +188,7 @@ func TestMultidomainBindingClosureFailsClosed(t *testing.T) { // only two authorities: cannot collapse to fewer than the three frozen authorities t.Run("collapsed_authorities", func(t *testing.T) { - admitted, _ := closureFixture(t) + admitted, _ := closureFixture(t, acceptanceDir) rewriteAdmitted(t, admitted, func(e *MultidomainBindingClosureAdmittedArtifacts) { e.Authorities = e.Authorities[:2] }) @@ -176,9 +198,13 @@ func TestMultidomainBindingClosureFailsClosed(t *testing.T) { } }) + testClosureFailsClosedPinsAndMutations(t, acceptanceDir) +} + +func testClosureFailsClosedPinsAndMutations(t *testing.T, acceptanceDir string) { // bad freeze caller pin (missing sha256: prefix) t.Run("invalid_freeze_pin", func(t *testing.T) { - admitted, _ := closureFixture(t) + admitted, _ := closureFixture(t, acceptanceDir) bare := strings.TrimPrefix(p1MultidomainFreezeDocumentSHA256, "sha256:") if _, _, err := MaterializeMultidomainBindingClosure(multidomainCorePath, multidomainFreezePath, bare, multidomainFixtureRoot, t.TempDir(), admitted, closureEvaluationTime, ""); err == nil { @@ -188,7 +214,7 @@ func TestMultidomainBindingClosureFailsClosed(t *testing.T) { // a mutated admitted manifest no longer matches its pinned document sha256 t.Run("mutated_admitted_artifact_bytes", func(t *testing.T) { - admitted, root := closureFixture(t) + admitted, root := closureFixture(t, acceptanceDir) var env MultidomainBindingClosureAdmittedArtifacts raw, _ := os.ReadFile(admitted) if err := json.Unmarshal(raw, &env); err != nil { @@ -201,10 +227,8 @@ func TestMultidomainBindingClosureFailsClosed(t *testing.T) { } manifest, _, err := MaterializeMultidomainBindingClosure(multidomainCorePath, multidomainFreezePath, p1MultidomainFreezeDocumentSHA256, multidomainFixtureRoot, t.TempDir(), admitted, closureEvaluationTime, "") - // Fail-closed: a mismatched document sha256 must not close its gap — either - // the run errors or the tampered authority's gap stays blocking (closed < 9). if err == nil && manifest.ClosedGapCount >= 9 { - t.Fatalf("tampered artifact still closed all 9 gaps (closed=%d); a mismatched document sha256 must leave its gap blocking", manifest.ClosedGapCount) + t.Fatalf("tampered artifact still closed all 9 gaps (closed=%d)", manifest.ClosedGapCount) } }) } diff --git a/tools/knowledge-retrieval/fusion_discrimination_test.go b/tools/knowledge-retrieval/fusion_discrimination_test.go index 6d04b7e..5dbe5b7 100644 --- a/tools/knowledge-retrieval/fusion_discrimination_test.go +++ b/tools/knowledge-retrieval/fusion_discrimination_test.go @@ -247,13 +247,11 @@ func TestSeparatingShapesAtRealCorpusSize(t *testing.T) { // and selectLexicalTopK for lexical, denseDotProduct plus the dense comparator // for dense. No scoring arithmetic is restated here. const ( - goldRankAcceptanceDir = "../../knowledge/registry/acceptance/p1-src-03" - goldRankStoreRoot = goldRankAcceptanceDir + "/retrieval" - goldRankCrosswalkPath = goldRankAcceptanceDir + "/crosswalk.json" - goldRankFreezePath = multidomainFixtureRoot + "/suite-freeze.core.json" + goldRankAcceptanceRelDir = "knowledge/registry/acceptance/p1-src-03" + goldRankFreezePath = multidomainFixtureRoot + "/suite-freeze.core.json" // The suite named by the most recent committed evaluation receipt // (multidomain-evaluation-receipts/.../e92c6086, evaluated 2026-07-20). - goldRankSuitePath = goldRankStoreRoot + "/multidomain-evaluation-suites/sha256/78/" + + goldRankSuiteRelPath = goldRankAcceptanceRelDir + "/retrieval/multidomain-evaluation-suites/sha256/78/" + "783779b3a446f26e02642c0db536f112a0ba03cd549272cb910984eef9959b69.json" goldRankSuiteID = "multidomain-evaluation-suite:sha256:" + "783779b3a446f26e02642c0db536f112a0ba03cd549272cb910984eef9959b69" @@ -388,17 +386,18 @@ func unitSpanIDFor(ref EvidenceRef) string { // on load, so both the gold-rank measurement and the case-mining search below // read exactly the artifacts the committed receipt was produced from. type goldRankCorpus struct { - suite MultidomainEvaluationSuite - index LexicalIndex - profile string - dense DenseVectorArtifact - window int + suite MultidomainEvaluationSuite + index LexicalIndex + profile string + dense DenseVectorArtifact + window int + storeRoot string + acceptanceDir string } -func loadGoldRankCorpus(t *testing.T) goldRankCorpus { +func loadGoldSuite(t *testing.T, suitePath string) MultidomainEvaluationSuite { t.Helper() - - suiteBytes, err := readStableFile(goldRankSuitePath, "multidomain evaluation suite", maxMultidomainSuiteBytes) + suiteBytes, err := readStableFile(suitePath, "multidomain evaluation suite", maxMultidomainSuiteBytes) if err != nil { t.Fatalf("read suite: %v", err) } @@ -409,8 +408,18 @@ func loadGoldRankCorpus(t *testing.T) goldRankCorpus { if suite.SuiteID != goldRankSuiteID { t.Fatalf("suite id %q; want the receipt-pinned %q", suite.SuiteID, goldRankSuiteID) } + return suite +} - indexBytes, err := verifyFileDigest(filepath.Join(goldRankStoreRoot, filepath.FromSlash(suite.LexicalIndex.ObjectPath)), +func loadGoldRankCorpus(t *testing.T, purpose string) goldRankCorpus { + t.Helper() + dataRoot := knowledgeDataRoot(t, purpose, goldRankSuiteRelPath) + acceptanceDir := filepath.Join(dataRoot, filepath.FromSlash(goldRankAcceptanceRelDir)) + storeRoot := filepath.Join(acceptanceDir, "retrieval") + suitePath := filepath.Join(dataRoot, filepath.FromSlash(goldRankSuiteRelPath)) + suite := loadGoldSuite(t, suitePath) + + indexBytes, err := verifyFileDigest(filepath.Join(storeRoot, filepath.FromSlash(suite.LexicalIndex.ObjectPath)), suite.LexicalIndex.DocumentSHA256, suite.LexicalIndex.ByteSize) if err != nil { t.Fatalf("lexical index does not match its suite pin: %v", err) @@ -419,7 +428,7 @@ func loadGoldRankCorpus(t *testing.T) goldRankCorpus { if err := decodeStrictCanonical(indexBytes, &index); err != nil { t.Fatalf("decode lexical index: %v", err) } - candidateBytes, err := verifyFileDigest(filepath.Join(goldRankStoreRoot, filepath.FromSlash(suite.LexicalCandidate.ObjectPath)), + candidateBytes, err := verifyFileDigest(filepath.Join(storeRoot, filepath.FromSlash(suite.LexicalCandidate.ObjectPath)), suite.LexicalCandidate.DocumentSHA256, suite.LexicalCandidate.ByteSize) if err != nil { t.Fatalf("lexical candidate does not match its suite pin: %v", err) @@ -432,7 +441,7 @@ func loadGoldRankCorpus(t *testing.T) goldRankCorpus { if !isBM25FProfile(profile) { t.Fatalf("lexical profile %q is not BM25F; this harness drives the BM25F scorers", profile) } - denseBytes, err := verifyFileDigest(filepath.Join(goldRankStoreRoot, filepath.FromSlash(suite.DenseArtifact.ObjectPath)), + denseBytes, err := verifyFileDigest(filepath.Join(storeRoot, filepath.FromSlash(suite.DenseArtifact.ObjectPath)), suite.DenseArtifact.DocumentSHA256, suite.DenseArtifact.ByteSize) if err != nil { t.Fatalf("dense artifact does not match its suite pin: %v", err) @@ -446,11 +455,19 @@ func loadGoldRankCorpus(t *testing.T) goldRankCorpus { t.Logf("corpus: lexical index document_count=%d documents=%d terms=%d; dense vectors=%d; fusion window=%d", index.DocumentCount, len(index.Documents), len(index.Terms), len(dense.Documents), window) - return goldRankCorpus{suite: suite, index: index, profile: profile, dense: dense, window: window} + return goldRankCorpus{ + suite: suite, + index: index, + profile: profile, + dense: dense, + window: window, + storeRoot: storeRoot, + acceptanceDir: acceptanceDir, + } } func TestGoldSpanLaneRanks(t *testing.T) { - corpus := loadGoldRankCorpus(t) + corpus := loadGoldRankCorpus(t, "gold span lane ranks") suite, index, profile, dense, window := corpus.suite, corpus.index, corpus.profile, corpus.dense, corpus.window freezeBytes, err := readStableFile(goldRankFreezePath, "scorer-blind freeze core", maxScorerBlindFreezeBytes) @@ -465,7 +482,7 @@ func TestGoldSpanLaneRanks(t *testing.T) { t.Fatalf("freeze carries %d cases; the frozen suite is eleven", len(freeze.Cases)) } - crosswalkBytes, err := readStableFile(goldRankCrosswalkPath, "crosswalk", maxManifestBytes) + crosswalkBytes, err := readStableFile(filepath.Join(corpus.acceptanceDir, "crosswalk.json"), "crosswalk", maxManifestBytes) if err != nil { t.Fatalf("read crosswalk: %v", err) } @@ -538,7 +555,7 @@ func TestGoldSpanLaneRanks(t *testing.T) { continue } - signalPath := filepath.Join(goldRankStoreRoot, filepath.FromSlash(suiteCase.Signals.Baseline.ObjectPath)) + signalPath := filepath.Join(corpus.storeRoot, filepath.FromSlash(suiteCase.Signals.Baseline.ObjectPath)) signalBytes, err := verifyFileDigest(signalPath, suiteCase.Signals.Baseline.DocumentSHA256, suiteCase.Signals.Baseline.ByteSize) if err != nil { unresolved(fmt.Sprintf("query signal does not match its suite pin: %v", err)) @@ -731,7 +748,7 @@ func formatLaneRanks(ranks laneRanks) string { } func TestMineSeparatingCaseShapes(t *testing.T) { - corpus := loadGoldRankCorpus(t) + corpus := loadGoldRankCorpus(t, "mine separating case shapes") suite, index, window := corpus.suite, corpus.index, corpus.window champion := championProfile(window) @@ -760,7 +777,7 @@ func TestMineSeparatingCaseShapes(t *testing.T) { } loaded := make([]QuerySignalArtifact, 0, len(arms)) for _, arm := range arms { - signalPath := filepath.Join(goldRankStoreRoot, filepath.FromSlash(arm.binding.ObjectPath)) + signalPath := filepath.Join(corpus.storeRoot, filepath.FromSlash(arm.binding.ObjectPath)) signalBytes, err := verifyFileDigest(signalPath, arm.binding.DocumentSHA256, arm.binding.ByteSize) if err != nil { t.Fatalf("%s %s query signal does not match its suite pin: %v", suiteCase.CaseID, arm.name, err) From 30f72a09e881326a70ca3dd2134d55fed9f874dd Mon Sep 17 00:00:00 2001 From: lusoris Date: Fri, 23 Oct 2026 07:16:56 +0200 Subject: [PATCH 2/3] test: read repository artifacts from the repository only Enforce that execution manifest artifacts with repository logical paths are read strictly from the repository root, failing immediately with the missing file path when absent. Previously, an else-if fallback in TestExecutionManifestBindsExactRepositoryBytes silently substituted missing repository files with copies located under the data root, allowing missing repository files to pass the digest check (review finding F1). Logical paths prefixed with knowledge/registry/ continue to be read from the data root. Every other logical path is verified against the repository only. Touched: - tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go: - verifyExecutionArtifact: read repository artifacts only from repo - TestExecutionManifestBindsExactRepositoryBytes: call helper - TestExecutionManifestPlantedRepositoryArtifactMissingFails: planted Order: engine-knowledge-monorepo-test-data-20261023 Signed-off-by: lusoris --- .../runner_test.go | 129 +++++++++++++++--- 1 file changed, 112 insertions(+), 17 deletions(-) diff --git a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go index 63f0350..1ff87fd 100644 --- a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go +++ b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "compress/gzip" "context" "crypto/sha256" "encoding/base64" @@ -9,6 +10,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" "net/http/httptest" "os" @@ -878,6 +880,28 @@ func TestSharedCanonicalJSONConformanceVectors(t *testing.T) { } } +func verifyExecutionArtifact(tb testingTB, artifact executionArtifact, repositoryRoot, dataRoot string) { + tb.Helper() + path := filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath)) + if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { + path = filepath.Join(dataRoot, filepath.FromSlash(artifact.LogicalPath)) + } + raw, err := os.ReadFile(path) + if err != nil { + if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { + tb.Fatalf("missing data root file %s: %v", path, err) + } else { + tb.Fatalf("missing repository file %s: %v", path, err) + } + return + } + digest := sha256.Sum256(raw) + if got := "sha256:" + hex.EncodeToString(digest[:]); got != artifact.SHA256 || int64(len(raw)) != artifact.Bytes { + tb.Fatalf("execution artifact drifted: %s = %s/%d, want %s/%d", artifact.LogicalPath, got, len(raw), artifact.SHA256, artifact.Bytes) + return + } +} + func TestExecutionManifestBindsExactRepositoryBytes(t *testing.T) { manifest, err := exactExecutionManifest() if err != nil { @@ -887,23 +911,7 @@ func TestExecutionManifestBindsExactRepositoryBytes(t *testing.T) { "knowledge/registry/schemas/source-acquisition-contract-v2.schema.json") repositoryRoot := filepath.Join("..", "..", "..") for _, artifact := range manifest.Artifacts { - path := filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath)) - if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { - path = filepath.Join(dataRoot, filepath.FromSlash(artifact.LogicalPath)) - } else if _, err := os.Stat(path); err != nil && dataRoot != "" { - alt := filepath.Join(dataRoot, filepath.FromSlash(artifact.LogicalPath)) - if _, statErr := os.Stat(alt); statErr == nil { - path = alt - } - } - raw, err := os.ReadFile(path) - if err != nil { - t.Fatal(err) - } - digest := sha256.Sum256(raw) - if got := "sha256:" + hex.EncodeToString(digest[:]); got != artifact.SHA256 || int64(len(raw)) != artifact.Bytes { - t.Fatalf("execution artifact drifted: %s = %s/%d, want %s/%d", artifact.LogicalPath, got, len(raw), artifact.SHA256, artifact.Bytes) - } + verifyExecutionArtifact(t, artifact, repositoryRoot, dataRoot) } gate, err := exactExecutionGateBinding() if err != nil { @@ -933,6 +941,93 @@ func TestExecutionManifestBindsExactRepositoryBytes(t *testing.T) { } } +func findAbsentRepositoryArtifact(manifest executionManifest, repositoryRoot string) (executionArtifact, bool) { + for _, artifact := range manifest.Artifacts { + if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { + continue + } + repoPath := filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath)) + if _, err := os.Stat(repoPath); os.IsNotExist(err) { + return artifact, true + } + } + return executionArtifact{}, false +} + +const canonicalVectorsGZBase64 = `H4sIAAAAAAACA91YzW7jNhC+5ykMHXoybdnOj10UvXcP+wLRwqClsc2EIlWScuINDOxjFO +ih125fY9+kt976CB1SlEzHtmI36QLbXBTxZ75vZj4OR3666HQinS4hp9MVKM2kiL7vRINe +3Iujrp0slJwzDhqHn/AdRxZyykQGwkA2Lc18PF2anGs6h6mAB84ENEtxMcsLDjkupgZtWy +u3fgonjZRc9++FfOCQLYAoMIrBivJ+aRjvLaSjsLPYUH1PYMUQPwXC2UxRxahoNvj1H9xz +U22PFCyYNmo9TWVe0NQ42q9gWVnbDk3roV6x3qd8YGcxIFql8YjQ9OeSaWZRiSqFANVPpT +AKSR71RhupKILWzlCdMnZ27GlRPItm3xsmKRUUSbq091EVbL6eKvowTWlhSgXWyV1iF55c +hKkrYQvUMEGLUrCU8oDeiUqKnhLR6SQR5cWSJta0fe90Bt3qaVQJ/l9Rcm7/+9CttsxtGN +Fzu2vQG1754Y9gnKEk4lSbJErEJhFh2o7JBak0NG4HXYdsMREvxKqgapgaZRMivJTC1yGh +Nx5q0220kFmzUmWgICMaU0GVbihVidtNjsPf0YwNevDiWAXvlmDz+iHwtmZcp2E7Y5lbXp +Z4wzkU+1sqCHJ5x6rE//3bL5+SyOvBbqmGk6SM41FaPcA9htfNOmuuWTeMh+Nm5svnavyv +X/84U041py2lmk4S/fDjd27A4ybRn59+dwMOzqOdLastInqRjUeZfUAcv4AduFyFCSb1+O +QaaKvqSkyczIBQkRFA6RVMLFql5zjanTYooYOWnx1HeuFw7R4GKBz+8tkOYpjapVWR5MyA +opzMaHqvUY9LYq0SDQVVFOPaflj8bmvIR6pfPSf7QXkDKXu4Wo1bSA96pgq35o5YO1tlL1 +sM5NKSFYbhWNi0zLmkhph1Ae2JELDA224F04+gJE4RbGQC7oW0l+0KXCkKJ3LGuS9Rsfvr +xf9F4jxMssXxJWSHd+KI+5masttzVlq3YI1P3X0kUg0HMBiZsxP+Gqw9KVz4+wO9uwMExO +Zjv6eoBJKVBceUGCByZteSe9i2YJHtWsLL2wJ2q+dwE7XoDhNN5kygiomR9yBaTb6n71uN +SeyhUL8PaIpsDbezhMs4bjXqTgYoIkujsX8j+H592WpzMhyORjfDeHQ9vrq8ubkax+NWhF +IUlLluoVRKYiLbKfsLxd4krWbzkhuGjSnxzeJhmyiKpxf8x/0sI27Hjo0Z1YChwDWwfrf8 +6U6y/vqdr8N70sJ8hMf69nAgtFR4ugOJ6aOhmJ2sMQ40w5uQPCxRDRpP1pH4dmpNtFqDR/ +xqIPWhbNUWxrY+csdsFVJgQSOizGeoMV0Anu7w0j4o2aBqHKuVra11XXpOuBdQlqXIKFKs +m8vzuPbir0i2roLEVkHSBPckpiR+i7DauvsvqNY15kSmr+e5R7I5rjOJ+Q5+hJitDUw5y5 +kJv3hz+sjyMseh8TGqBV1jK5G5ghUPhqPLq+ub8eR5zcJAaHufU6XoOvxyDrvUxwKrAWQ7 +Lp7aD9A0hcJE4ffT8egcWvzipew3NXs2wY1eJRu35nhwMly23GmnYQXcOn09et4DfTvuV/ +W9zf365w7nP3ECo2p9OBCXLYGoK1LFnuR4KbWENPz8/dZCeHoQ7Ac9qUChLRyD4fj/GY+v +54pn9dano0nlCcdjMJzslG37s+DmYnPxD9jtmtleFgAA` + +func testCanonicalVectorsPayload(tb testingTB) []byte { + tb.Helper() + gz, err := base64.StdEncoding.DecodeString(canonicalVectorsGZBase64) + if err != nil { + tb.Fatalf("decode canonical vectors: %v", err) + } + r, err := gzip.NewReader(bytes.NewReader(gz)) + if err != nil { + tb.Fatalf("gzip reader canonical vectors: %v", err) + } + defer r.Close() + raw, err := io.ReadAll(r) + if err != nil { + tb.Fatalf("read canonical vectors: %v", err) + } + return raw +} + +func TestExecutionManifestPlantedRepositoryArtifactMissingFails(t *testing.T) { + manifest, err := exactExecutionManifest() + if err != nil { + t.Fatal(err) + } + repositoryRoot := filepath.Join("..", "..", "..") + target, ok := findAbsentRepositoryArtifact(manifest, repositoryRoot) + if !ok { + t.Fatal("expected at least one repository manifest artifact absent from repository") + } + tempDataRoot := t.TempDir() + dataCopyPath := filepath.Join(tempDataRoot, filepath.FromSlash(target.LogicalPath)) + if err := os.MkdirAll(filepath.Dir(dataCopyPath), 0o755); err != nil { + t.Fatal(err) + } + payload := testCanonicalVectorsPayload(t) + if err := os.WriteFile(dataCopyPath, payload, 0o644); err != nil { + t.Fatal(err) + } + spy := &spyTB{} + verifyExecutionArtifact(spy, target, repositoryRoot, tempDataRoot) + if !spy.failed { + t.Fatalf("expected missing repository artifact %s to fail, but read from data root succeeded", target.LogicalPath) + } + expectedRepoPath := filepath.Join(repositoryRoot, filepath.FromSlash(target.LogicalPath)) + if !strings.Contains(spy.message, expectedRepoPath) { + t.Fatalf("expected failure message %q to name repository path %s", spy.message, expectedRepoPath) + } +} + func TestRunnerContractDigestIsDeterministicAndManifestBound(t *testing.T) { contract, _, err := exactContract() if err != nil { From bed3192a5c28e38fc484760c6b296d07998774c9 Mon Sep 17 00:00:00 2001 From: lusoris Date: Fri, 23 Oct 2026 07:46:28 +0200 Subject: [PATCH 3/3] test: plant the missing repository artifact in temporary roots Plant execution manifest repository artifact tests using synthetic in-memory artifacts and isolated temporary directory roots, removing all dependencies on repository tree state and the embedded gzip payload. Previously, TestExecutionManifestPlantedRepositoryArtifactMissingFails relied on findAbsentRepositoryArtifact to locate an artifact in the manifest that happened to be absent from the repository worktree, and embedded a gzipped copy of conformance vectors to seed the data root. Adding those conformance vectors to the repository broke the test, and the embedded gzip copy was irrelevant to the missing-path check. Synthetic artifacts now define their own path, sha256 digest, and size over a short text payload. The missing-artifact test verifies that an artifact present only in the temporary data root still fails against an empty repository root, naming the expected repository path. A companion test verifies that matching bytes in the repository root pass, while altered bytes fail with an artifact drift error. Touched: - tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go: - syntheticPlantedArtifact: generate synthetic artifact and bytes - TestExecutionManifestPlantedRepositoryArtifactMissingFails: plant synthetic artifact in temporary roots - TestExecutionManifestPlantedRepositoryArtifactPresentOrDrifted: verify matching digest passes and drifted digest fails - drop findAbsentRepositoryArtifact, testCanonicalVectorsPayload, canonicalVectorsGZBase64, compress/gzip, io Order: engine-knowledge-monorepo-test-data-20261023 Signed-off-by: lusoris --- .../runner_test.go | 122 +++++++----------- 1 file changed, 50 insertions(+), 72 deletions(-) diff --git a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go index 1ff87fd..b24842e 100644 --- a/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go +++ b/tools/knowledge-registry/p1-src03-acquisition-runner/runner_test.go @@ -2,7 +2,6 @@ package main import ( "bytes" - "compress/gzip" "context" "crypto/sha256" "encoding/base64" @@ -10,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - "io" "net/http" "net/http/httptest" "os" @@ -941,93 +939,73 @@ func TestExecutionManifestBindsExactRepositoryBytes(t *testing.T) { } } -func findAbsentRepositoryArtifact(manifest executionManifest, repositoryRoot string) (executionArtifact, bool) { - for _, artifact := range manifest.Artifacts { - if strings.HasPrefix(artifact.LogicalPath, "knowledge/registry/") { - continue - } - repoPath := filepath.Join(repositoryRoot, filepath.FromSlash(artifact.LogicalPath)) - if _, err := os.Stat(repoPath); os.IsNotExist(err) { - return artifact, true - } - } - return executionArtifact{}, false -} - -const canonicalVectorsGZBase64 = `H4sIAAAAAAACA91YzW7jNhC+5ykMHXoybdnOj10UvXcP+wLRwqClsc2EIlWScuINDOxjFO -ih125fY9+kt976CB1SlEzHtmI36QLbXBTxZ75vZj4OR3666HQinS4hp9MVKM2kiL7vRINe -3Iujrp0slJwzDhqHn/AdRxZyykQGwkA2Lc18PF2anGs6h6mAB84ENEtxMcsLDjkupgZtWy -u3fgonjZRc9++FfOCQLYAoMIrBivJ+aRjvLaSjsLPYUH1PYMUQPwXC2UxRxahoNvj1H9xz -U22PFCyYNmo9TWVe0NQ42q9gWVnbDk3roV6x3qd8YGcxIFql8YjQ9OeSaWZRiSqFANVPpT -AKSR71RhupKILWzlCdMnZ27GlRPItm3xsmKRUUSbq091EVbL6eKvowTWlhSgXWyV1iF55c -hKkrYQvUMEGLUrCU8oDeiUqKnhLR6SQR5cWSJta0fe90Bt3qaVQJ/l9Rcm7/+9CttsxtGN -Fzu2vQG1754Y9gnKEk4lSbJErEJhFh2o7JBak0NG4HXYdsMREvxKqgapgaZRMivJTC1yGh -Nx5q0220kFmzUmWgICMaU0GVbihVidtNjsPf0YwNevDiWAXvlmDz+iHwtmZcp2E7Y5lbXp -Z4wzkU+1sqCHJ5x6rE//3bL5+SyOvBbqmGk6SM41FaPcA9htfNOmuuWTeMh+Nm5svnavyv -X/84U041py2lmk4S/fDjd27A4ybRn59+dwMOzqOdLastInqRjUeZfUAcv4AduFyFCSb1+O -QaaKvqSkyczIBQkRFA6RVMLFql5zjanTYooYOWnx1HeuFw7R4GKBz+8tkOYpjapVWR5MyA -opzMaHqvUY9LYq0SDQVVFOPaflj8bmvIR6pfPSf7QXkDKXu4Wo1bSA96pgq35o5YO1tlL1 -sM5NKSFYbhWNi0zLmkhph1Ae2JELDA224F04+gJE4RbGQC7oW0l+0KXCkKJ3LGuS9Rsfvr -xf9F4jxMssXxJWSHd+KI+5masttzVlq3YI1P3X0kUg0HMBiZsxP+Gqw9KVz4+wO9uwMExO -Zjv6eoBJKVBceUGCByZteSe9i2YJHtWsLL2wJ2q+dwE7XoDhNN5kygiomR9yBaTb6n71uN -SeyhUL8PaIpsDbezhMs4bjXqTgYoIkujsX8j+H592WpzMhyORjfDeHQ9vrq8ubkax+NWhF -IUlLluoVRKYiLbKfsLxd4krWbzkhuGjSnxzeJhmyiKpxf8x/0sI27Hjo0Z1YChwDWwfrf8 -6U6y/vqdr8N70sJ8hMf69nAgtFR4ugOJ6aOhmJ2sMQ40w5uQPCxRDRpP1pH4dmpNtFqDR/ -xqIPWhbNUWxrY+csdsFVJgQSOizGeoMV0Anu7w0j4o2aBqHKuVra11XXpOuBdQlqXIKFKs -m8vzuPbir0i2roLEVkHSBPckpiR+i7DauvsvqNY15kSmr+e5R7I5rjOJ+Q5+hJitDUw5y5 -kJv3hz+sjyMseh8TGqBV1jK5G5ghUPhqPLq+ub8eR5zcJAaHufU6XoOvxyDrvUxwKrAWQ7 -Lp7aD9A0hcJE4ffT8egcWvzipew3NXs2wY1eJRu35nhwMly23GmnYQXcOn09et4DfTvuV/ -W9zf365w7nP3ECo2p9OBCXLYGoK1LFnuR4KbWENPz8/dZCeHoQ7Ac9qUChLRyD4fj/GY+v -54pn9dano0nlCcdjMJzslG37s+DmYnPxD9jtmtleFgAA` - -func testCanonicalVectorsPayload(tb testingTB) []byte { - tb.Helper() - gz, err := base64.StdEncoding.DecodeString(canonicalVectorsGZBase64) - if err != nil { - tb.Fatalf("decode canonical vectors: %v", err) - } - r, err := gzip.NewReader(bytes.NewReader(gz)) - if err != nil { - tb.Fatalf("gzip reader canonical vectors: %v", err) - } - defer r.Close() - raw, err := io.ReadAll(r) - if err != nil { - tb.Fatalf("read canonical vectors: %v", err) - } - return raw +func syntheticPlantedArtifact() (executionArtifact, []byte) { + content := []byte("synthetic planted artifact payload\n") + digest := sha256.Sum256(content) + return executionArtifact{ + LogicalPath: "tools/planted/absent.txt", + Role: "planted-test", + SHA256: "sha256:" + hex.EncodeToString(digest[:]), + Bytes: int64(len(content)), + }, content } func TestExecutionManifestPlantedRepositoryArtifactMissingFails(t *testing.T) { - manifest, err := exactExecutionManifest() - if err != nil { - t.Fatal(err) - } - repositoryRoot := filepath.Join("..", "..", "..") - target, ok := findAbsentRepositoryArtifact(manifest, repositoryRoot) - if !ok { - t.Fatal("expected at least one repository manifest artifact absent from repository") - } + artifact, content := syntheticPlantedArtifact() + tempRepoRoot := t.TempDir() tempDataRoot := t.TempDir() - dataCopyPath := filepath.Join(tempDataRoot, filepath.FromSlash(target.LogicalPath)) + dataCopyPath := filepath.Join(tempDataRoot, filepath.FromSlash(artifact.LogicalPath)) if err := os.MkdirAll(filepath.Dir(dataCopyPath), 0o755); err != nil { t.Fatal(err) } - payload := testCanonicalVectorsPayload(t) - if err := os.WriteFile(dataCopyPath, payload, 0o644); err != nil { + if err := os.WriteFile(dataCopyPath, content, 0o644); err != nil { t.Fatal(err) } spy := &spyTB{} - verifyExecutionArtifact(spy, target, repositoryRoot, tempDataRoot) + verifyExecutionArtifact(spy, artifact, tempRepoRoot, tempDataRoot) if !spy.failed { - t.Fatalf("expected missing repository artifact %s to fail, but read from data root succeeded", target.LogicalPath) + t.Fatalf("expected missing repository artifact %s to fail, but read from data root succeeded", artifact.LogicalPath) } - expectedRepoPath := filepath.Join(repositoryRoot, filepath.FromSlash(target.LogicalPath)) + expectedRepoPath := filepath.Join(tempRepoRoot, filepath.FromSlash(artifact.LogicalPath)) if !strings.Contains(spy.message, expectedRepoPath) { t.Fatalf("expected failure message %q to name repository path %s", spy.message, expectedRepoPath) } } +func TestExecutionManifestPlantedRepositoryArtifactPresentOrDrifted(t *testing.T) { + artifact, content := syntheticPlantedArtifact() + tempRepoRoot := t.TempDir() + tempDataRoot := t.TempDir() + repoPath := filepath.Join(tempRepoRoot, filepath.FromSlash(artifact.LogicalPath)) + if err := os.MkdirAll(filepath.Dir(repoPath), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(repoPath, content, 0o644); err != nil { + t.Fatal(err) + } + + spyPass := &spyTB{} + verifyExecutionArtifact(spyPass, artifact, tempRepoRoot, tempDataRoot) + if spyPass.failed { + t.Fatalf("expected matching repository artifact to pass, got: %s", spyPass.message) + } + + corrupted := append([]byte(nil), content...) + corrupted[0] ^= 0xff + if err := os.WriteFile(repoPath, corrupted, 0o644); err != nil { + t.Fatal(err) + } + + spyDrift := &spyTB{} + verifyExecutionArtifact(spyDrift, artifact, tempRepoRoot, tempDataRoot) + if !spyDrift.failed { + t.Fatal("expected wrong digest to fail with drift line") + } + if !strings.Contains(spyDrift.message, "execution artifact drifted:") { + t.Fatalf("expected failure message to report drift, got: %s", spyDrift.message) + } +} + func TestRunnerContractDigestIsDeterministicAndManifestBound(t *testing.T) { contract, _, err := exactContract() if err != nil {