Reviewed helsing-ai/yadr (v0.5.0, already
installed via cargo on this machine). It parses Y-statement ADRs out of #
comments and docstrings in .py, .rs, .nix; TypeScript is not supported.
The paragraph format is regex-strict (In the context of <..>, we faced <..>.
etc.); inner text may contain commas and full stops, but the literal phrases
, and neglected / , accepting must appear exactly once.
Read every module in apps/vxdata-api/src plus tests/conftest.py and
docs/explainers/*, and wrote 17 YADRs next to the code they govern:
auth model + transitional anonymous token (auth.py), fail-closed grants
(access.py), read scope compiled into SQL (crud/_filters.py),
content-hashed payload rows (crud/_payloads.py), transactional lineage table
(crud/_lineage.py), SCD2 tombstones + restore verb (crud/delete.py),
caller-owned transaction (crud/_engine.py), keyset cursors (crud/read.py),
parquet via polars (crud/_parquet.py), flat wire schemas (crud/_flat.py),
derived payload registry (models/registry.py), Literal widening
(models/payloads.py), startup migrations (db.py), wide request event
(app.py), historical ordinal allocation (services/patients.py), presigned
S3 with validated keys (services/storage.py), real-Postgres tests
(tests/conftest.py). Dates come from git log -S on the introducing change.
The prose comments/docstrings each record replaces were condensed to one-line
pointers.
Repo wiring: yadr check . step in .github/workflows/pr_gate.yml (installed
via taiki-e/cache-cargo-install-action, yadr@0.5.0), a yadr-check
lefthook pre-commit command that skips when yadr is not installed locally, a
“Decision records (YADR)” section in the root AGENTS.md, and a pointer bullet
in apps/vxdata-api/AGENTS.md.
Verified yadr check . exits 0 at repo root in about 1.5 s and yadr list apps/vxdata-api shows all 17. Changes are local and uncommitted in worktree
earnest-star per the user’s request.
Lessons Learned: Pitfalls
apps/vxdata-api/pyproject.toml sets [tool.ruff] include = ["src"]. Ruff
treats include as file globs, so with this config ruff check ., ruff format --check . and even explicit ruff check src tests report “No Python
files found”. The project’s lint, format-check and pre-commit ruff hooks
are therefore no-ops; running ruff --isolated shows 12 files (mostly tests)
that would be reformatted and 4 pre-existing lint errors. Worth fixing
(include = ["src/**/*.py", "tests/**/*.py"] or dropping the key).
docs/explainers/database-structure.md says a soft delete “sets valid_to
and does not create a new open-ended row”. The code (crud/delete.py) closes
the open row and appends an is_deleted=True successor. The doc is stale.
tests/conftest.py’s module docstring still described resource_ancestry /
resource_lineage as materialized views with a refresh step; lineage has been
a transactional table since 2026-06-17. Rewritten in this session; the
refresh-materialized-views recipe in apps/vxdata-api/justfile and the
__is_view__ filter in alembic/env.py look like the same leftover.
The rtk cat proxy silently drops blank lines and some comment lines from
its output. For a comment audit this is actively misleading; use the Read
tool or rtk proxy cat.
Sandbox: pixi run in the worktree fails on the rattler global cache lock,
the librarian cache dir under ~/.cache/checkouts and the knowledge repo
under ~/.agents all need an un-sandboxed retry. The worktree’s
.pixi/envs/dev was empty, so ruff had to come from ~/.pixi/bin/ruff.
Lessons Learned: Improvements
Add to wiki/workstreams/infrastructure/sops/vxdata-sdk-and-schema-model.md
(or a new “vxdata-api architecture decisions” SOP) that yadr list apps/vxdata-api is now the index of architectural decisions for the API, and
that a behaviour change must rewrite the matching YADR (new date + changelog
line). That would have saved re-deriving each decision’s rationale from
scattered docstrings and git history this session.
Record the vxdata-api lint-is-a-no-op finding in the same SOP until the
include key is fixed, so agents do not trust a green pixi run lint.
A one-line note in the infrastructure SOP index that “soft delete appends a
tombstone version” would resolve the doc/code contradiction for the next
reader faster than the explainer does.