From 51131e377e22f3b89dcb21f6dcd424a1809546f9 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Fri, 14 Aug 2026 20:54:41 +0200 Subject: [PATCH] docs(agents): document the knowledge graph as an optional routing aid Records how to fetch the map for a checkout's version and how to tell whether it is current, so the graph is used for orientation only while it demonstrably matches the code being read. --- AGENTS.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 6 +++++ 2 files changed, 86 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 509fb1c3..18c4a186 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,6 +34,86 @@ Console scripts declared in `pyproject.toml`: - `bec-designer` — Qt Designer with the BEC widget plugins loaded. - `bw-generate-cli` — regenerates the RPC client and Designer plugin stubs. +## Knowledge Graph (optional) + +CI builds a [graphify](https://pypi.org/project/graphifyy/) knowledge graph of this repository on every +release and attaches it to that release as `knowledge-graph.tar.gz`. It maps modules, classes, and the +import/call relationships between them, and it answers "what talks to what" faster than a repo-wide +grep does. + +**It is optional and never committed** — `graphify-out/` is gitignored. If graphify is not installed or +no graph is present, skip this section entirely and work from the layout above; nothing here is a +prerequisite for contributing. + +When a graph *is* present, use it for routing before falling back to grep: + +```bash +graphify query "How does a waveform get its scan data?" # BFS context around a question +graphify path "ScanControl" "BECDispatcher" # shortest path between two nodes +graphify explain "BECConnector" # one node and its neighbours +graphify affected "BECWidget" --depth 2 # reverse impact of a change +``` + +### Fetching and refreshing the map + +The graph describes the code in a checkout, so match it to the checkout you are reading — not to +whatever happens to be installed in the environment, which for an editable install can be several +releases behind: + +```bash +VERSION=$(python -c "import tomllib, pathlib; \ + print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])") +TMP=$(mktemp -d) +gh release download "v$VERSION" --repo bec-project/bec_widgets \ + --pattern 'knowledge-graph-*.tar.gz' --dir "$TMP" +mkdir -p graphify-out && tar -xzf "$TMP"/knowledge-graph-v*.tar.gz -C graphify-out && rm -rf "$TMP" +``` + +Unpacking through a temp directory keeps the tarball out of the working tree — only `graphify-out/` +is gitignored, so a downloaded archive left in the repo root is one `git add -A` away from being +committed. + +`pyproject.toml`'s version is always a released one — semantic-release bumps it in the release commit — +so `v$VERSION` reliably resolves. + +The map is self-describing. `graphify-out/build_meta.json` records what it covers — `version`/`tag` for +the release, `packages` for every distribution built from that tree, `commit` for the exact revision, +and `requires` for cross-repo BEC-family constraints — and the same block is embedded in `graph.json` +under `build_meta`, so a map that gets copied around on its own still says which release it belongs to: + +```bash +python -c "import json; print(json.load(open('graphify-out/graph.json'))['build_meta'])" +``` + +**Check `commit` before trusting the graph**, because a checkout normally sits *ahead* of its last +release and matching version strings do not mean matching code: + +```bash +GRAPH_COMMIT=$(python -c \ + "import json; print(json.load(open('graphify-out/build_meta.json'))['commit'] or '')" 2>/dev/null) +git rev-list --count "${GRAPH_COMMIT:?no stamped build_meta.json - refetch the map}..HEAD" +``` + +Read the result as: + +- **`0`** — the map matches HEAD exactly. +- **a small number** — it lags by that many commits. Usable for orientation, but confirm anything it + says about recently touched code by reading the file. +- **`fatal: Invalid revision range`** — the map was built from a commit that is not in your history, so + it describes a different line of development. Do not rely on it. +- **`no stamped build_meta.json`** — there is no CI-built map here. Either nothing was downloaded, or + the graph was built locally (a locally rebuilt graph tracks your tree continuously and needs no + version check). + +The `:?` guard matters: without it an unreadable `build_meta.json` yields an empty revision range and +`git rev-list` cheerfully answers `0`, which is indistinguishable from a perfectly current map. In every +non-zero case, say the map is stale rather than presenting its answer as current. + +`requires` is what to check when a *cross-repo* answer looks wrong. Note these are floors +(`bec_lib~=3.134`), not the version resolved at build time — `bec` may be many releases past the floor — +so treat them as a coarse signal, and read `bec`'s own graph or source when the question is really about +`bec_lib`. + ## Local Environment Overlay If a file named **`AGENTS_PERSONAL.md`** exists next to this one, read it and treat it as an extension diff --git a/CLAUDE.md b/CLAUDE.md index 5027c7e2..291363c7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,6 +8,12 @@ truth). The points that matter most in day-to-day work: - **Check for `AGENTS_PERSONAL.md` first.** If it exists, it extends `AGENTS.md` with machine-specific environment setup and takes precedence over the generic venv/pip instructions there. It is untracked and personal — never commit it, and never assume it exists. +- **If `graphify-out/` exists, route through it before grepping** — `graphify query/path/explain/affected` + answer "what talks to what" faster than a repo-wide search. It is optional and gitignored; if it is + missing, just work from the code. Before trusting a downloaded map, check it against the checkout — + not the installed package, which can lag — with the `git rev-list --count` snippet in `AGENTS.md`. + Anything but `0` means the map is behind your working tree: say so and verify against the code + instead of answering from the graph. - **Import from `qtpy`, never `PySide6.*`.** CI greps for `from PySide6.` and fails the build (only `PySide6.QtDesigner` and `PySide6.scripts` are exempt). - **`bec_widgets/cli/client.py` and the Designer plugin files are generated — never hand-edit them.**