test: harden offline semantic proof

This commit is contained in:
2026-08-08 20:42:14 +02:00
parent 8240fa4472
commit bff21507df
2 changed files with 133 additions and 6 deletions
+112 -6
View File
@@ -7,6 +7,34 @@ root="$(cd "$(dirname "$0")/.." && pwd -P)"
# shellcheck source=./unified-deployment-smoke.sh
source "$root/scripts/unified-deployment-smoke.sh"
task13_write_offline_semantic_override() {
TASK13_OFFLINE_OVERRIDE="$TASK13_TMP/compose.task13.offline-semantic.yaml"
cat >"$TASK13_OFFLINE_OVERRIDE" <<'EOF'
networks:
thothii:
internal: true
EOF
chmod 0600 "$TASK13_OFFLINE_OVERRIDE"
}
task13_offline_semantic_compose() {
docker compose \
--project-name "$TASK13_PROJECT" \
--project-directory "$TASK13_ROOT" \
--env-file "$TASK13_ENV_FILE" \
-f "$TASK13_ROOT/compose.yaml" \
-f "$TASK13_ROOT/deploy/compose.local.yaml" \
-f "$TASK13_OVERRIDE" \
-f "$TASK13_OFFLINE_OVERRIDE" \
"$@"
}
task13_offline_semantic_compose_logged() {
local label="$1"
shift
task13_run_logged "$label" task13_offline_semantic_compose "$@"
}
task13_wait_internal_embedding_model() {
printf '== Wait for the internal embedding model ==\n'
for _attempt in $(seq 1 30); do
@@ -42,9 +70,49 @@ PY
task13_log_failure "internal embedding model readiness"
}
task13_semantic_python_probe() {
task13_wait_internal_embedding_model_offline() {
printf '== Wait for the internal embedding model ==\n'
for _attempt in $(seq 1 30); do
if docker run --rm -i --pull never \
--label "io.thothii.task13.run=$TASK13_RUN_ID" \
--network "$TASK13_NETWORK" \
--entrypoint /opt/venv/bin/python \
"$TASK13_CORE_IMAGE" - <<'PY' >>"$TASK13_LOG" 2>&1
import json
import urllib.request
import urllib.error
with urllib.request.urlopen("http://embedding:11434/api/tags", timeout=10) as response:
payload = json.load(response)
models = [entry.get("name") for entry in payload.get("models", []) if isinstance(entry, dict)]
if "qwen3-embedding:0.6b" not in models:
raise SystemExit(1)
request = urllib.request.Request(
"http://embedding:11434/api/embed",
data=json.dumps({"model": "qwen3-embedding:0.6b", "input": ["warm semantic smoke"]}).encode("utf-8"),
headers={"content-type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=180) as response:
payload = json.load(response)
except urllib.error.URLError:
raise SystemExit(1)
embeddings = payload.get("embeddings")
raise SystemExit(0 if isinstance(embeddings, list) and len(embeddings) == 1 and len(embeddings[0]) == 1024 else 1)
PY
then
return 0
fi
sleep 1
done
task13_log_failure "offline internal embedding model readiness"
}
task13_semantic_python_probe_with() {
local mode="$1"
task13_compose exec -T core /opt/venv/bin/python - "$mode" <<'PY'
shift
"$@" "$mode" <<'PY'
from __future__ import annotations
import hashlib
@@ -247,6 +315,20 @@ print(json.dumps({
PY
}
task13_semantic_python_probe() {
local mode="$1"
task13_semantic_python_probe_with "$mode" task13_compose exec -T core /opt/venv/bin/python -
}
task13_semantic_python_probe_offline() {
local mode="$1"
task13_semantic_python_probe_with "$mode" docker run --rm -i --pull never \
--label "io.thothii.task13.run=$TASK13_RUN_ID" \
--network "$TASK13_NETWORK" \
--entrypoint /opt/venv/bin/python \
"$TASK13_CORE_IMAGE" -
}
task13_semantic_seed_and_assert() {
local output
printf '== Ensure the semantic collection and seed schema/evidence/memory ==\n'
@@ -257,14 +339,38 @@ task13_semantic_seed_and_assert() {
grep -Fq '"memory"' <<<"$output" || task13_fail "memory semantic verification did not run"
}
task13_assert_offline_semantic_isolation() {
local running
[[ "$(docker network inspect --format '{{.Internal}}' "$TASK13_NETWORK")" == true ]] \
|| task13_fail "offline semantic network still allows egress"
running="$(task13_offline_semantic_compose ps --services --status running | sort)"
[[ "$running" == $'embedding\nqdrant' ]] \
|| task13_fail "offline semantic recreation started non-semantic services"
for service in core frontend embedding-model-init; do
if docker ps -a --filter "label=com.docker.compose.project=$TASK13_PROJECT" \
--filter "label=com.docker.compose.service=$service" --format '{{.ID}}' | grep -q .; then
task13_fail "offline semantic recreation invoked bootstrap service $service"
fi
done
}
task13_semantic_verify_persistence() {
local output
printf '== Restart offline and prove semantic points plus model cache persist ==\n'
task13_write_environment /fixtures/offline.git
task13_compose_logged "offline semantic recreation" up --detach --force-recreate --wait --wait-timeout 120
task13_wait_internal_embedding_model
task13_registry_status >>"$TASK13_LOG" 2>&1 || true
output="$(task13_semantic_python_probe verify)"
task13_write_offline_semantic_override
task13_remove_labeled_container "${TASK13_LLM_CONTAINER:-}" >>"$TASK13_LOG" 2>&1 \
|| task13_fail "offline semantic phase could not remove the temporary LLM fixture"
task13_compose_logged "offline semantic stop" down --remove-orphans --timeout 10
task13_offline_semantic_compose_logged "offline semantic recreation" \
up --detach --wait --wait-timeout 120 --pull never qdrant embedding
TASK13_NETWORK="$(docker network ls \
--filter "label=com.docker.compose.project=$TASK13_PROJECT" \
--filter 'label=com.docker.compose.network=thothii' --format '{{.Name}}')"
[[ -n "$TASK13_NETWORK" && "$TASK13_NETWORK" != *$'\n'* ]] || task13_fail "offline semantic network was not resolved"
task13_assert_offline_semantic_isolation
task13_wait_internal_embedding_model_offline
output="$(task13_semantic_python_probe_offline verify)"
printf '%s\n' "$output" >>"$TASK13_LOG"
grep -Fq '"schema"' <<<"$output" || task13_fail "schema semantic persistence did not verify"
grep -Fq '"evidence"' <<<"$output" || task13_fail "evidence semantic persistence did not verify"