Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions .github/workflows/mindgraph-public-portability-qualification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
name: MindGraph public portability qualification

on:
push:
branches:
- research/mindgraph-public-portability-qualification-20260910
workflow_dispatch:

permissions:
contents: read

jobs:
qualify:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out exact MindGraph source under test
uses: actions/checkout@v4
with:
repository: camerontjs-dot/MindGraph
ref: 4d292179e1478b999bc6b7c36f9de564c07bd1d9
path: mindgraph-source

- name: Verify exact source identity
working-directory: mindgraph-source
run: |
test "$(git rev-parse HEAD)" = "4d292179e1478b999bc6b7c36f9de564c07bd1d9"
echo "commit=$(git rev-parse HEAD)"
echo "tree=$(git rev-parse HEAD^{tree})"
test -z "$(git status --porcelain)"

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install package from clean checkout
working-directory: mindgraph-source
run: |
python -m pip install --upgrade pip
python -m pip install '.[dev]'
python --version
python -m pip show mindgraph

- name: Run maintained test suite
working-directory: mindgraph-source
run: |
set -o pipefail
pytest -q | tee /tmp/mindgraph-pytest.txt

- name: Exercise synthetic external-user retrieval boundary
working-directory: mindgraph-source
run: |
python - <<'PY'
import json
import shutil
import subprocess
import tempfile
from pathlib import Path

source_sha = "4d292179e1478b999bc6b7c36f9de564c07bd1d9"
repo = Path.cwd()
vault = repo / "examples" / "example-vault"
root = Path(tempfile.mkdtemp(prefix="mindgraph-public-qualification-"))
receipt_dir = Path("/tmp/mindgraph-qualification")
receipt_dir.mkdir(parents=True, exist_ok=True)
receipt = []

def run(args, *, expect=0):
proc = subprocess.run(args, capture_output=True, text=True)
receipt.append(f"$ {' '.join(str(x) for x in args)}")
receipt.append(f"exit={proc.returncode}")
if proc.stdout.strip():
receipt.append("stdout:\n" + proc.stdout.strip())
if proc.stderr.strip():
receipt.append("stderr:\n" + proc.stderr.strip())
if expect is not None and proc.returncode != expect:
raise AssertionError(
f"unexpected exit {proc.returncode}, expected {expect}: {' '.join(str(x) for x in args)}"
)
return proc

receipt.append(f"source_commit={source_sha}")
receipt.append("profile=clean GitHub-hosted ubuntu runner; Python 3.11; installed from pinned source checkout")

# Missing-state control: querying an uninitialized DB must not succeed.
missing_db = root / "missing.sqlite"
missing = run(
["mindgraph", "query", "antinet", "--db", str(missing_db), "--top-k", "3", "--json"],
expect=None,
)
if missing.returncode == 0:
raise AssertionError("missing-state query unexpectedly succeeded")
receipt.append("missing_state=PASS_NONZERO")
receipt.append(f"missing_db_created={missing_db.exists()}")

def build_and_query(db_path: Path):
run(["mindgraph", "init", "--db", str(db_path)])
run(["mindgraph", "ingest", str(vault), "--db", str(db_path)])
q = run(
["mindgraph", "query", "antinet", "--db", str(db_path), "--top-k", "7", "--json"]
)
rows = json.loads(q.stdout)
if not isinstance(rows, list) or not rows:
raise AssertionError("query JSON did not return a non-empty list")
return rows

db1 = root / "first.sqlite"
rows1 = build_and_query(db1)
first = rows1[0]
source_path = first.get("source_path") or first.get("path")
if source_path != "mental-models-overview.md":
raise AssertionError(f"unexpected top target: {source_path!r}")

for key in ("source_path", "source_root", "display_path"):
if not first.get(key):
raise AssertionError(f"missing provenance field: {key}")

paths = [(row.get("source_path") or row.get("path")) for row in rows1]
if "unrelated-noise.md" in paths:
if paths.index("unrelated-noise.md") <= paths.index("mental-models-overview.md"):
raise AssertionError("unrelated control outranked intended target")
receipt.append(f"ranked_paths={paths}")
receipt.append("target_retrieval=PASS")
receipt.append("provenance=PASS")
receipt.append("negative_control=PASS")

forbidden_authority_keys = {"verified", "truth", "authoritative", "lifecycle_state"}
inflated = sorted(forbidden_authority_keys.intersection(first))
if inflated:
raise AssertionError(f"authority-inflating result keys present: {inflated}")
receipt.append("authority_inflation=PASS_NONE")

shutil.rmtree(root)
root.mkdir(parents=True)
db2 = root / "rebuilt.sqlite"
rows2 = build_and_query(db2)
first2 = rows2[0]
stable_keys = ("path", "source_path", "display_path", "signal", "lexical_rank", "semantic_rank")
sig1 = tuple(first.get(k) for k in stable_keys)
sig2 = tuple(first2.get(k) for k in stable_keys)
if sig1 != sig2:
raise AssertionError(f"rebuild signature drift: {sig1!r} != {sig2!r}")
receipt.append(f"rebuild_signature={sig1!r}")
receipt.append("rebuild=PASS")

(receipt_dir / "qualification.txt").write_text("\n\n".join(receipt) + "\n", encoding="utf-8")
print("\n".join([
"PUBLIC_MINDGRAPH_QUALIFICATION=PASS",
f"top_target={source_path}",
f"signal={first.get('signal')}",
f"source_path={first.get('source_path')}",
f"display_path={first.get('display_path')}",
"missing_state=nonzero",
"rebuild=stable_identity_and_provenance",
]))
PY

- name: Record dependency/cache footprint
if: always()
working-directory: mindgraph-source
run: |
mkdir -p /tmp/mindgraph-qualification
{
echo "python=$(python --version 2>&1)"
echo "source_commit=$(git rev-parse HEAD)"
echo "source_tree=$(git rev-parse HEAD^{tree})"
python -m pip show mindgraph sentence-transformers sqlite-vec | sed -n '1,160p'
du -sh "$HOME/.cache/huggingface" 2>/dev/null || true
} > /tmp/mindgraph-qualification/environment.txt
cp /tmp/mindgraph-pytest.txt /tmp/mindgraph-qualification/pytest.txt 2>/dev/null || true

- name: Upload qualification receipt
if: always()
uses: actions/upload-artifact@v4
with:
name: mindgraph-public-portability-qualification
path: /tmp/mindgraph-qualification/
if-no-files-found: error
Loading