Files
tool-crosscheck/README.md
T
mikkeli 447c578b6c
/ crosscheck (push) Successful in 1s
topic check: imu signals
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
2026-10-13 23:23:32 +09:00

56 lines
3.1 KiB
Markdown

---
type: reference
---
# Crosscheck
Part of **Project Yukart**, making an old 2008 Mitsubishi Z27AG a bit smarter with modern technologies.
Mechanical consistency checks across every yukart repository. A fact stated in
more than one repo (a decision's status, a topic, a service list, a path in
another repo's docs) is checked against the one place that owns it. No model,
no network: plain Python over the tracked files.
| Check | Source of truth | Catches |
|---|---|---|
| `decision` | project-yukart `docs/ARCHITECTURE.md`, decisions table | a decision number that does not exist; a line calling an Accepted decision proposed |
| `topic` | contracts `schema/topics.json`, `schema/signals.json` | a `yukart/...` topic matching no pattern; a vehicle, host, gnss or imu signal that is not registered, or has the wrong source |
| `docref` | the repos' own trees | ``<repo> `FILE.md` `` naming a file that does not exist; relative markdown links that do not resolve |
| `binaries` | each repo's `Cargo.toml` and `deploy/*.service` | project-yukart `REPOS.md` missing a deployed binary; `ORIN-RUNTIME.md` missing a deployed service |
| `frontmatter` | the docs convention | a `docs/**/*.md` without front matter, or with an unknown `type` |
| `copy` | contracts | a file under `assets/contracts/<path>` that is not byte-identical to contracts' `<path>` (or has no source there) |
## Run it
```bash
python3 crosscheck.py ~/dev/yukart # the directory holding the repos side by side
```
Findings print as `repo/path:line: [check] message`; exit status 1 if any.
## In CI: every repo, on every push
`.gitea/workflows/crosscheck.yml` is a reusable workflow. Each yukart repo carries
[`caller/crosscheck.yml`](caller/crosscheck.yml) as its own
`.gitea/workflows/crosscheck.yml`. On a push it clones every repo of the org at
`master`, puts the pushed repo at the pushed commit, and runs the script. A finding
fails that push's run: the commit that made two repos disagree is the one marked.
A new repo is checked as soon as it exists in the org; it needs the caller only to
trigger checks on its own pushes.
- ⚠ **The caller must say `runs-on: halogen`** (the yukart org's runner, `halogen-yukart`). Gitea hands a reusable-workflow
call to a runner chosen by the *caller's* `runs-on`; the called workflow's own is not
consulted for that. Without it, the instance-wide `pi5-runner` on the Gitea host takes
the job, and its jobs see the server as `http://gitea:3000`, which does not resolve.
- All yukart repos are public, so cloning needs no token. A private one would need a
read-only org secret `YUKART_READ_TOKEN`, which the workflow already uses if set.
## Adding to it
- **A false positive** is fixed in the rule, not silenced per line. Shapes that look
like topics but are not (Flutter channel names, systemd directories) are listed in
`NOT_TOPIC`; test-only topic roots in `IGNORED_TOPIC_ROOTS`.
- **A new check** reads a source of truth that already exists in some repo. If the
fact has no single owner yet, give it one first; a check between two copies only
says that they differ, not which is right.