fix(harness): workspace + write-URL + L2 tests per accesso REST reale

Bug trovato provando la connessione reale col .env: il write endpoint vive su un
PATH DEDICATO /vector/write/v1/ (non /vector/v1/), e il modello Config ha write_rest/
vector_write_rest a TOP-LEVEL (non nidificati in vector_db).

- .env.example: aggiunge THOTH_VEC_WRITE_REST_URL (path dedicato del writer, con
  avviso che le due chiavi valgono su path separati).
- workspaces/chirone-test.yaml: riscritto allineato a chirone.example.yaml + config.py
  (vector_rest/vector_write_rest top-level; write_rest punta a THOTH_VEC_WRITE_REST_URL).
- tests/l2/*: corretti gli accessi strutturali (ws.vector_write_rest invece di
  ws.vector_db.write_rest; ws.vector_rest invece di ws.vector_db.rest).
  test_value_grounding_real skip-when-import-fails su nsp.lshindex (modulo deferred da B3).

Verificato end-to-end: save_one_memory (embeddings -> writer REST /vector/write/v1/
-> upsert pgvector -> read-back reader) PASSED. Suite L0+L1: 109 passed. Suite L2:
4 passed, 1 skipped (lshindex deferred).

Nota operativa: THOTH_SSL_CA va lasciato VUOTO sulla workstation (cert GoDaddy
pubblico in certifi). I campi direct-transport (THOTH_DB_*, THOTH_VEC_PASSWORD)
sono obbligatori per il modello ma inutilizzati in transport=rest: riempiti con
dummy nel .env locale (come faceva ChironeWp3).
This commit is contained in:
2026-06-27 08:20:36 +02:00
parent 276717005d
commit e58f6c092e
5 changed files with 59 additions and 32 deletions
@@ -27,10 +27,10 @@ def test_save_one_upserts_to_real_pgvector(l2_env):
from nsp.vectorstore.rest_client import VectorRestClient
ws = load_workspace(WORKSPACE)
if not ws.vector_db.write_rest or not ws.vector_db.write_rest.api_key.strip():
pytest.skip("vector_db.write_rest not configured (no writer key)")
if not ws.vector_write_rest or not ws.vector_write_rest.api_key.strip():
pytest.skip("vector_write_rest not configured (no writer key)")
writer = VectorRestClient(ws.vector_db.write_rest)
writer = VectorRestClient(ws.vector_write_rest)
embedder = OllamaEmbeddings(ws.embeddings)
record = MemoryRecord(
@@ -42,8 +42,8 @@ def test_save_one_upserts_to_real_pgvector(l2_env):
upserted = save_one_memory([record], decision_seq=999, writer=writer, embedder=embedder)
assert upserted >= 0 # idempotent: 0 on unchanged, >=1 on new/updated
# read it back via the READER key
reader = VectorRestClient(ws.vector_db.rest)
# read it back via the READER key (vector_rest, path /vector/v1/)
reader = VectorRestClient(ws.vector_rest)
qvec = embedder.embed_query("ablazione")
hits = reader.search_similar("memory", qvec, 10)
ids = {h.get("metadata", {}).get("record_key", "") for h in hits}
+3 -2
View File
@@ -40,8 +40,9 @@ def test_workspace_chirone_test_loads(l2_env):
ws = load_workspace(WORKSPACE)
# secrets must be expanded (not the literal ${...} token)
assert not ws.vector_db.rest.api_key.startswith("${")
assert not ws.vector_db.write_rest.api_key.startswith("${")
assert not ws.rest.api_key.startswith("${")
assert not ws.vector_rest.api_key.startswith("${")
assert not ws.vector_write_rest.api_key.startswith("${")
def test_pi_binary_available(l2_env):
@@ -21,7 +21,10 @@ def test_ablazione_returns_multiple_columns(l2_env):
a flag and a free-text patologia field) -- the whole point of D14a's
non-collapsing aggregation. Requires a built LSH index (nsp lsh build)."""
from nsp.config import LshConfig
from nsp.lshindex import load_index, query_index # ported with the lsh build path
try:
from nsp.lshindex import load_index, query_index # ported with the lsh build path
except ModuleNotFoundError:
pytest.skip("nsp.lshindex not yet ported (deferred from B3; lands with nsp lsh build)")
from nsp.search import aggregate_lsh_multi
# NOTE: this test assumes the LSH index was built (nsp lsh build --workspace