Conformance Testing
What this page covers
Two complementary conformance layers: machine-readable wire vectors for the HTTP API, and a behavioral suite that exercises the full fact/recall/graph/decay/federation/contradiction contract across SQLite, libSQL, and Postgres.
Audience: protocol implementers validating a Stigmem node; contributors adding or changing spec behaviour; operators of forks or alternative backend implementations.
Overviewโ
Wire conformanceโ
The current wire-vector suite is the executable test contract for the v0.9.0a1 wire format.
The files still live under data/conformance/v1.0/ for compatibility
with the pre-reset harness naming โ treat that directory name as
historical, not as a claim that v1.0 has shipped.
Running the suiteโ
# From the repo root
uv run pytest node/tests/conformance/test_conformance_v1.py -v
The runner starts an in-process test node, executes every vector against it, and fails on any regression. Zero skips are enforced โ if your change causes a vector to be skipped, CI will fail.
To run a single vector group:
uv run pytest node/tests/conformance/test_conformance_v1.py -v -k "garden"
CIโ
The Conformance workflow (conformance.yml) runs automatically on every push to main and on pull requests that touch node/, spec/, data/conformance/, or the workflow file.
Vector groupsโ
01_fact_assert.json02_fact_query.json03_wellknown.json/.well-known/stigmem discovery endpoint.05_garden_facts.jsonAdding a new vectorโ
Every new spec section or wire-format change MUST include at least one new conformance vector. PRs that add or modify spec text without a corresponding vector will not be merged.
- Add to an existing group file that covers the relevant spec section. If no group exists, create a new numbered file (e.g.
06_my_feature.json). - Follow the vector structure (see below).
- Run
uv run pytest node/tests/conformance/test_conformance_v1.py -vlocally before opening a PR.
Vector structure:
{
"spec_section": "ยงX.Y",
"title": "Short group title",
"description": "Optional longer description",
"vectors": [
{
"id": "unique-kebab-id",
"description": "What this vector tests",
"method": "POST",
"path": "/v1/facts",
"body": { ... },
"expected_status": 201,
"expected_body_contains": { "entity": "stigmem://testnode/user/alice" },
"expected_body_has_keys": ["id", "timestamp"]
}
]
}
Assertion fields:
expected_statusexpected_body_containsexpected_body_has_keysexpected_nestedDo not add vectors with requires_auth: true.
Zero skips are enforced and auth-dependent scenarios belong under
node/tests/auth/.
Multi-backend behavioral suiteโ
The behavioral suite in node/src/stigmem_conformance/tests/ exercises the full behavioral contract against SQLite, libSQL, and Postgres.
In-process (simplest, no external services)โ
# SQLite (default โ no dependencies)
python -m stigmem_conformance --backend sqlite
# libSQL (requires libsql-experimental)
pip install 'stigmem-node[libsql]'
python -m stigmem_conformance --backend libsql
Postgresโ
# Start a local Postgres instance (Docker)
docker run -d -e POSTGRES_PASSWORD=test -p 5432:5432 postgres:16
# Install dependencies
pip install 'stigmem-node[postgres,conformance]'
# Run
STIGMEM_TEST_PG_DSN="postgresql://postgres:test@localhost/postgres" \
python -m stigmem_conformance --backend postgres
Generate a Markdown reportโ
python -m stigmem_conformance --backend sqlite --report conformance-sqlite.md
The report includes pass/fail counts, test details, and failure traces. Suitable for committing alongside a release or embedding in operator documentation.
Via pytest directlyโ
# All backends (skips unavailable ones automatically)
uv run pytest node/src/stigmem_conformance/tests/ -v
# Pin to one backend
uv run pytest node/src/stigmem_conformance/tests/ --conformance-backend=sqlite -v
Test domainsโ
test_facts.pytest_recall.pytest_graph.pytest_decay_synthesis.pytest_contradiction.pytest_embeddings.pytest_provenance.pytest_federation.pyInterpreting the reportโ
A report with zero failures and only justified skips means the backend is conformant.
Extending the suiteโ
- Create
node/src/stigmem_conformance/tests/test_<domain>.py. - Use only the HTTP API โ no direct DB access.
- Use the
conformance_clientfixture (parametrized over all backends). - Add
pytest.skip(reason="...")for backend-specific features with a clear justification string. - Update the test-domains table above.
# Example: new domain test
from .conftest import ConformanceClient
class TestMyFeature:
def test_something(self, conformance_client: ConformanceClient) -> None:
if conformance_client.backend == "postgres":
pytest.skip("feature X not supported on Postgres (pg_vector needed)")
r = conformance_client.client.post("/v1/my-endpoint", json={...})
assert r.status_code == 200
CI matrixโ
The conformance-multi-backend job runs all three backends in parallel. A conformance-gate job ensures all three are green before a PR can merge. The Postgres backend is feature-flagged (via the postgres extras and STIGMEM_TEST_PG_DSN env var) and runs against a GitHub-hosted Postgres 16 service.
Spec citationsโ
Every vector group file declares the modular spec it covers. Keep these citations up to date with the canonical spec composition in spec/PROTOCOL.md.
When the spec and a vector disagree, the spec is authoritative.
Update the vector and open a bug report for the reference node.