[d1-smoke] building... [d1-smoke] launching in dep order... [d1-smoke] /health probes: ✓ gateway (:3110) → {"status":"ok","service":"gateway"} ✓ storaged (:3211) → {"status":"ok","service":"storaged"} ✓ catalogd (:3212) → {"status":"ok","service":"catalogd"} ✓ ingestd (:3213) → {"status":"ok","service":"ingestd"} ✓ queryd (:3214) → {"status":"ok","service":"queryd"} [d1-smoke] gateway proxy probes (D6+): ✓ POST /v1/ingest (no name) → 400 from ingestd (proxy wired) ✓ POST /v1/sql (no body) → 400 from queryd (proxy wired) [d1-smoke] D1 acceptance gate: PASSED [d1-smoke] cleanup [d2-smoke] building storaged... [d2-smoke] launching storaged... [d2-smoke] PUT round-trip: ✓ PUT d2-smoke/1777712027.bin → 200 [d2-smoke] GET echoes bytes: ✓ GET d2-smoke/1777712027.bin → bytes match [d2-smoke] LIST includes key: ✓ LIST prefix=d2-smoke/ → contains d2-smoke/1777712027.bin [d2-smoke] DELETE then GET → 404: ✓ DELETE then GET → 404 [d2-smoke] 256 MiB cap → 413: ✓ PUT 257 MiB → 413 [d2-smoke] semaphore: 5th concurrent PUT → 503 + Retry-After:5 ✓ 5th concurrent PUT → 503 + Retry-After: 5 [d2-smoke] D2 acceptance gate: PASSED [d2-smoke] cleanup [d3-smoke] building storaged + catalogd... [d3-smoke] launching storaged... [d3-smoke] launching catalogd (first start, empty catalog)... [d3-smoke] POST /catalog/register (fresh): ✓ fresh register → existing=false, dataset_id=200a05a8-4f66-5a86-bdac-e17d87176613 [d3-smoke] GET /catalog/manifest/d3_smoke_dataset: ✓ manifest dataset_id matches [d3-smoke] GET /catalog/list (1 entry): ✓ list count=1 [d3-smoke] restart catalogd → rehydrate from Parquet: ✓ rehydrated dataset_id matches across restart [d3-smoke] re-register (same name + same fingerprint) → existing=true: ✓ existing=true, same dataset_id, objects replaced (count=2) [d3-smoke] re-register (different fingerprint) → 409: ✓ different fingerprint → 409 Conflict [d3-smoke] D3 acceptance gate: PASSED [d3-smoke] cleanup [d4-smoke] building storaged + catalogd + ingestd... [d4-smoke] launching storaged → catalogd → ingestd... [d4-smoke] POST /ingest?name=d4_workers (5 rows, 5 cols): ✓ ingest fresh → row_count=5, existing=false, key=datasets/d4_workers/247165ad7d53e8d5993d3181dc9ce9b1d06383b336c31c999a89bd48d41308a4.parquet [d4-smoke] mc shows the parquet on MinIO: ✓ 247165ad7d53e8d5993d3181dc9ce9b1d06383b336c31c999a89bd48d41308a4.parquet present in lakehouse-go-primary/datasets/d4_workers/ [d4-smoke] catalogd manifest matches: ✓ manifest row_count=5, fp matches, 1 object at datasets/d4_workers/247165ad7d53e8d5993d3181dc9ce9b1d06383b336c31c999a89bd48d41308a4.parquet [d4-smoke] ADR-010 — salary is string (mixed N/A): ✓ deferred to fingerprint stability (next test) [d4-smoke] re-ingest same CSV → existing=true: ✓ idempotent re-ingest: existing=true, same dataset_id, same fingerprint [d4-smoke] schema-drift CSV → 409: ✓ schema drift → 409 Conflict [d4-smoke] D4 acceptance gate: PASSED [d4-smoke] cleanup [d5-smoke] building all 4 backing services... [d5-smoke] launching storaged → catalogd → ingestd... [d5-smoke] ingest 5-row CSV via D4 path: ✓ ingest row_count=5 [d5-smoke] launching queryd (initial Refresh picks up d5_workers)... [d5-smoke] POST /sql SELECT count(*) FROM d5_workers: ✓ count(*)=5 [d5-smoke] POST /sql SELECT * FROM d5_workers LIMIT 3: ✓ rows[0] = (id=1, name=Alice), columns=[id, name, salary] [d5-smoke] schema-drift ingest 409s; existing view still queries: ✓ drift → 409 ✓ post-drift count(*)=5 (view unchanged) [d5-smoke] error path: SELECT FROM nonexistent → 400: ✓ unknown table → 400 [d5-smoke] D5 acceptance gate: PASSED [d5-smoke] cleanup [d6-smoke] building all 5 binaries... [d6-smoke] launching storaged → catalogd → ingestd... [d6-smoke] launching gateway: [d6-smoke] /v1/ingest?name=d6_workers (gateway → ingestd): ✓ ingest row_count=3, content-addressed key [d6-smoke] /v1/catalog/list (gateway → catalogd): ✓ catalog count=1 [d6-smoke] /v1/storage/list?prefix=datasets/d6_workers/ (gateway → storaged): ✓ storage list returned 1 object(s) under datasets/d6_workers/ [d6-smoke] /v1/sql SELECT count(*) (gateway → queryd): ✓ count(*)=3 [d6-smoke] /v1/sql with row data (full round-trip): ✓ rows[0].name=Alice (full ingest → storage → catalog → query through gateway) [d6-smoke] /v1/unknown → 404: ✓ unknown route → 404 [d6-smoke] D6 acceptance gate: PASSED [d6-smoke] cleanup [g1-smoke] building vectord + gateway... [g1-smoke] launching vectord → gateway... [g1-smoke] /v1/vectors/index — create dim=8: ✓ create → 201 [g1-smoke] duplicate create → 409: ✓ duplicate → 409 [g1-smoke] add batch of 200 vectors: ✓ added=200, length=200 [g1-smoke] search for inserted vector w-042 → recall: ✓ top hit = w-042 (dist=5.9604645E-8), 3 results, metadata round-tripped [g1-smoke] dim mismatch on add → 400: ✓ dim mismatch → 400 [g1-smoke] search on missing index → 404: ✓ unknown index → 404 [g1-smoke] DELETE then GET → 404: ✓ post-delete GET → 404 [g1-smoke] G1 acceptance gate: PASSED [g1-smoke] cleanup [g1p-smoke] building storaged + vectord + gateway... [g1p-smoke] launching storaged... [g1p-smoke] launching vectord (round 1) → gateway... [g1p-smoke] create index + add 50 vectors: ✓ added 50 → length=50 [g1p-smoke] verify storaged has the persistence file: ✓ _vectors/persist_demo.lhv1 present in storaged [g1p-smoke] search pre-restart: ✓ pre-restart top hit = w-001 [g1p-smoke] kill + restart vectord (rehydrate path): [g1p-smoke] vectord rehydrated index list shows persist_demo: ✓ list count=1 after restart ✓ length=50 after restart (state survived) [g1p-smoke] search post-restart: ✓ post-restart top hit = w-001 (dist=0) [g1p-smoke] DELETE then restart → index gone: ✓ persistence file removed from storaged ✓ post-delete restart list count=0 [g1p-smoke] G1P acceptance gate: PASSED [g1p-smoke] cleanup [g2-smoke] building embedd + vectord + gateway... [g2-smoke] launching embedd → vectord (no persist) → gateway... [g2-smoke] /v1/embed — two distinct texts: ✓ dim=768, model=nomic-embed-text-v2-moe, 2 distinct vectors [g2-smoke] determinism — same text twice → byte-identical vector: ✓ identical text → identical vector [g2-smoke] empty texts → 400: ✓ empty → 400 [g2-smoke] bad model → 502: ✓ unknown model → 502 [g2-smoke] end-to-end: embed → vectord add → search by embed → recall: ✓ embed → store → search round-trip: w-0 at dist=0 [g2-smoke] G2 acceptance gate: PASSED [g2-smoke] cleanup [chatd-smoke] building chatd + gateway... [chatd-smoke] launching chatd → gateway... [chatd-smoke] /v1/chat/providers — only ollama registered: ✓ exactly 1 provider (ollama, available=true) [chatd-smoke] POST /v1/chat with bare model name: ✓ provider=ollama, latency=11134ms, content=ok… [chatd-smoke] POST /v1/chat with explicit ollama/ prefix: ✓ ollama/qwen3.5:latest → provider=ollama, model=qwen3.5:latest (prefix stripped) [chatd-smoke] POST /v1/chat with :cloud suffix (no cloud provider): ✓ kimi-k2.6:cloud → 404 (ollama_cloud not registered, no silent fall-through to local) [chatd-smoke] POST /v1/chat with unknown/ prefix (falls through, upstream 502s): ✓ unknown/ → ollama default → upstream 502 (no silent prefix-strip) [chatd-smoke] POST /v1/chat with missing model field: ✓ missing model → 400 [chatd-smoke] chatd acceptance gate: PASSED (6/6) [chatd-smoke] cleanup [downgrade-smoke] building matrixd + vectord + gateway... [downgrade-smoke] launching vectord → matrixd → gateway... [downgrade-smoke] strong model + no force → downgrade fires: ✓ codereview_lakehouse → codereview_isolation (downgraded_from=lakehouse) [downgrade-smoke] forced_mode=true bypasses: ✓ caller-forced mode preserved, no downgrade [downgrade-smoke] force_full_override=true bypasses: ✓ env-override bypass, no downgrade [downgrade-smoke] weak model (qwen3.5:latest) bypasses: ✓ weak model keeps lakehouse [downgrade-smoke] non-lakehouse mode → gate not applicable: ✓ codereview_isolation passes through unchanged [downgrade-smoke] empty mode → 400: ✓ empty mode → 400 [downgrade-smoke] Downgrade gate acceptance: PASSED [downgrade-smoke] cleanup [matrix-smoke] building matrixd + vectord + gateway... [matrix-smoke] launching vectord → matrixd → gateway... [matrix-smoke] create two corpora: ✓ corpus_a and corpus_b created [matrix-smoke] add vectors to both corpora: ✓ 3 + 3 vectors loaded [matrix-smoke] /matrix/corpora lists both: ✓ count=2, both corpora listed [matrix-smoke] /matrix/search multi-corpus retrieve+merge: ✓ 4 merged results · 3+3 per-corpus · both corpora represented [matrix-smoke] top hit comes from corpus_b (b-near is globally closest): ✓ top hit: id=b-near corpus=corpus_b (closer than corpus_a's a-near) [matrix-smoke] metadata preserved on merged results: ✓ metadata.label round-trips through matrix [matrix-smoke] results sorted by distance ascending: ✓ distances ascending [matrix-smoke] empty corpora → 400: [matrix-smoke] missing corpus name → 502: [matrix-smoke] no query (empty text and vector) → 400: ✓ empty=400, missing-corpus=502, no-query=400 [matrix-smoke] metadata_filter drops non-matching results: ✓ filter kept 2 ('a near' + 'b near'), dropped 4 mid/far entries [matrix-smoke] Matrix acceptance gate: PASSED [matrix-smoke] cleanup [observer-smoke] building observerd + gateway... [observer-smoke] launching observerd → gateway... [observer-smoke] record 5 ops: ✓ 5 events posted [observer-smoke] /observer/stats aggregates correctly: ✓ total=5 (3 ok + 2 fail) · by_source: mcp=3 scenario=2 · 2 scenario digests [observer-smoke] empty endpoint → 400: ✓ empty endpoint rejected [observer-smoke] kill + restart observerd → ops survive: ✓ total=5 ok=3 err=2 preserved through restart [observer-smoke] Observer acceptance gate: PASSED [observer-smoke] cleanup [pathway-smoke] building pathwayd + gateway... [pathway-smoke] launching pathwayd → gateway... [pathway-smoke] Add → fresh UID + replay_count=1: ✓ uid=27f05e1f-4fee-4e8d-9409-9b7493ef9200 replay_count=1 [pathway-smoke] Get → returns same trace: ✓ content.approach round-trips [pathway-smoke] AddIdempotent same UID → replay_count++: ✓ replay_count bumped to 2 [pathway-smoke] Update → in-place content replace: ✓ Update applied and persisted [pathway-smoke] Revise → new UID with predecessor link: ✓ revision uid=9826a9d0-55f9-4fa7-b342-1bf692966d1a predecessor=27f05e1f-4fee-4e8d-9409-9b7493ef9200 [pathway-smoke] History → walks chain backward: ✓ chain length=2, [0]=9826a9d0-55f9-4fa7-b342-1bf692966d1a [1]=27f05e1f-4fee-4e8d-9409-9b7493ef9200 [pathway-smoke] Search tag=staffing → finds both traces: ✓ tag search count=2 [pathway-smoke] Retire → excluded from Search but Get-able: ✓ retired excluded from default Search, included with flag, still Get-able [pathway-smoke] Stats → total/active/retired counters: ✓ total=2 active=1 retired=1 [pathway-smoke] Negative paths → 4xx semantics: ✓ get/update/revise/retire on unknown → 404; bad content → 400 [pathway-smoke] kill + restart pathwayd → state survives: ✓ replay_count, retired flag, predecessor link all preserved [pathway-smoke] Pathway acceptance gate: PASSED [pathway-smoke] cleanup [playbook-smoke] building stack... [playbook-smoke] launching embedd → vectord → matrixd → gateway... [playbook-smoke] embedding 3 corpus items + query... [playbook-smoke] create corpus widgets + add 3 items... [playbook-smoke] baseline search (no playbook): baseline order: widget-a,widget-b,widget-c widget-c distance=0.6565746 [playbook-smoke] record playbook: (alpha staffing query test full prompt) → widget-c score=1.0 ✓ playbook_id=pb-4f1d0dccdb1df0ae [playbook-smoke] boosted search (use_playbook=true): boosted order: widget-a,widget-c,widget-b widget-c distance=0.3282873 playbook_boosted=1 ✓ playbook_boosted=1 ≥ 1 widget-c distance ratio (boosted/baseline) = 0.5 (expect ≈ 0.5) ✓ ratio in [0.40, 0.60] — boost applied correctly [playbook-smoke] bulk record 3 entries: ✓ 2 recorded, 1 failed (empty query_text caught), per-entry IDs/errors returned [playbook-smoke] Playbook acceptance gate: PASSED [playbook-smoke] cleanup [relevance-smoke] building matrixd + vectord + gateway... [relevance-smoke] launching vectord → matrixd → gateway... [relevance-smoke] adjacency-pollution: Connector outranks Registry, junk dropped: ✓ Connector kept, junk dropped, Connector (0.6799999999999999) > Registry (-0.45555555555555555) [relevance-smoke] empty chunks → 400: ✓ 400 on empty chunks [relevance-smoke] threshold=10 (impossibly high) drops everything: ✓ threshold=10 drops everything (0 kept / 1 dropped) [relevance-smoke] Relevance acceptance gate: PASSED [relevance-smoke] cleanup [cap-smoke] building storaged + gateway... [cap-smoke] launching storaged → gateway... [cap-smoke] generating 300 MiB deterministic payload... size=314572800 sha=17a88af83717... [cap-smoke] Test 1: PUT 300 MiB to _vectors/ (should pass) ✓ PUT _vectors/ → 200 [cap-smoke] Test 2: PUT 300 MiB to datasets/ (should reject) ✓ PUT datasets/ → 413 (default cap protects routine prefixes) [cap-smoke] Test 3: GET _vectors/ — sha matches input ✓ GET round-trip preserves bytes (size=314572800 sha=17a88af83717) [cap-smoke] ✓ Storaged cap smoke: PASSED [cap-smoke] cleanup [workflow-smoke] building observerd + gateway... [workflow-smoke] launching observerd → gateway... [workflow-smoke] /observer/workflow/modes lists fixtures + real modes: ✓ all 7 expected modes registered (fixtures + 4 pure + matrix.search HTTP) [workflow-smoke] 3-node DAG: shape (upper) → weakness → improvement ✓ status=succeeded · shape=HELLO WORLD · refs propagated through 3-node chain [workflow-smoke] /observer/stats reflects workflow ops: ✓ 3 workflow ops recorded (one per node), total=3 [workflow-smoke] unknown mode → 400: ✓ unknown mode aborts with 400 + helpful error [workflow-smoke] real-mode chain: downgrade → distillation.score ✓ downgrade flipped lakehouse→isolation; scorer rated scrum_review attempt_1=accepted [workflow-smoke] Workflow runner acceptance: PASSED [workflow-smoke] cleanup [materializer-smoke] building bin/materializer... [materializer-smoke] dry-run probe [materializer-smoke] first run [evidence_index] 4 read · 3 written · 1 skipped · 0 deduped data/_kb/distilled_facts.jsonl: read=3 wrote=2 skip=1 dedup=0 data/_kb/distilled_procedures.jsonl: (missing — skipped) data/_kb/distilled_config_hints.jsonl: (missing — skipped) data/_kb/contract_analyses.jsonl: (missing — skipped) data/_kb/mode_experiments.jsonl: (missing — skipped) data/_kb/scrum_reviews.jsonl: (missing — skipped) data/_kb/observer_escalations.jsonl: read=1 wrote=1 skip=0 dedup=0 data/_kb/audit_facts.jsonl: (missing — skipped) data/_kb/auto_apply.jsonl: (missing — skipped) data/_kb/observer_reviews.jsonl: (missing — skipped) data/_kb/audits.jsonl: (missing — skipped) data/_kb/outcomes.jsonl: (missing — skipped) [evidence_index] receipt: /tmp/tmp.eOKwqXIezb/reports/distillation/2026-05-02T08-54-40-881776326Z/receipt.json [evidence_index] validation_pass=false [materializer-smoke] idempotent re-run [materializer-smoke] PASS [replay-smoke] building bin/replay... [replay-smoke] dry-run (with retrieval) [replay-smoke] dry-run (no retrieval) [replay-smoke] forced-fail with escalation [replay-smoke] PASS [validatord-smoke] building validatord + gateway... [validatord-smoke] launching validatord → gateway... ✓ validatord roster loaded with 3 records [validatord-smoke] /v1/validate playbook happy path: ✓ playbook OK ({"findings":[],"elapsed_ms":0}) [validatord-smoke] /v1/validate playbook missing fingerprint → 422: ✓ playbook missing fingerprint → 422 schema/fingerprint [validatord-smoke] /v1/validate fill with phantom candidate → 422: ✓ phantom candidate W-PHANTOM → 422 consistency [validatord-smoke] /v1/validate unknown kind → 400: ✓ unknown kind → 400 [validatord-smoke] PASS — 5/5 probes through gateway :3110 [validatord-smoke] cleanup