adr check: resolve cross-repo record links, so an impacts pair cannot go one-way or dangle #530

Closed
opened 2026-09-16 19:08:22 +00:00 by hexajon · 2 comments
Owner

What happens

adr check resolves links inside one tree. A link to a record in ANOTHER repository is prose to it.

That is the normal shape once a decision spans repositories. A record in the top-level repo lists the repositories it constrains in impacts, and each of those repositories carries a record that implements it. The pair is meant to link both ways, so a reader in either tree reaches the other. Today:

  • a link to other-repo/0007 resolves against nothing, so a renumber or a delete leaves a dead citation and the check stays green;
  • a repository named in impacts that carries no implementing record is not reported;
  • a one-way pair, where the top-level record links down but the repo record never links back, is not reported. The same two-way rule already exists for supersession inside a tree.

Ask

Extend the link rule to cross-repo citations, reading the other repository through the forge.

  • Recognise a cross-repo citation: <repo>/NNNN or <owner>/<repo>/NNNN, and a full forge URL into another repository's docs/decisions/.
  • Fail when the cited record does not exist in that repository's tree.
  • Fail when a repository listed in impacts carries no record linking back to this one.
  • Fail when a pair is one-way, naming both files, the same way supersession does.
  • A bare repository name resolves to the same owner as the record's own repository.
  • This needs the forge, so --skip-remote-issues skips it. The flag name no longer says only issues; either widen its meaning in the help or rename it, and say which in the fix.

Not in scope

  • Reading another repository's WORKING TREE. The check reads the other repository's default branch through the forge, so a record still on a branch elsewhere does not count.
  • Any cross-repo rule when impacts is absent. A record with no impacts and no cross-repo citation is unaffected, and a single-repository project sees no change.

Acceptance criteria

  • A record citing other-repo/0007 passes when that record exists and links back, and fails when it does not exist.
  • A record listing other-repo in impacts with no linking record there fails, naming the repository.
  • A one-way pair fails, naming both files.
  • --skip-remote-issues skips every cross-repo rule, and the skip line says so.
  • A repository with no impacts and no cross-repo citations behaves exactly as today.
  • Tests cover each failure, through the existing fake forge client.

Related: #496 (the tooling guides the author), #528 (assent from a second account), and the impacts key from #483.

## What happens `adr check` resolves links inside one tree. A link to a record in ANOTHER repository is prose to it. That is the normal shape once a decision spans repositories. A record in the top-level repo lists the repositories it constrains in `impacts`, and each of those repositories carries a record that implements it. The pair is meant to link both ways, so a reader in either tree reaches the other. Today: - a link to `other-repo/0007` resolves against nothing, so a renumber or a delete leaves a dead citation and the check stays green; - a repository named in `impacts` that carries no implementing record is not reported; - a one-way pair, where the top-level record links down but the repo record never links back, is not reported. The same two-way rule already exists for supersession inside a tree. ## Ask Extend the link rule to cross-repo citations, reading the other repository through the forge. - Recognise a cross-repo citation: `<repo>/NNNN` or `<owner>/<repo>/NNNN`, and a full forge URL into another repository's `docs/decisions/`. - Fail when the cited record does not exist in that repository's tree. - Fail when a repository listed in `impacts` carries no record linking back to this one. - Fail when a pair is one-way, naming both files, the same way supersession does. - A bare repository name resolves to the same owner as the record's own repository. - This needs the forge, so `--skip-remote-issues` skips it. The flag name no longer says only issues; either widen its meaning in the help or rename it, and say which in the fix. ## Not in scope - Reading another repository's WORKING TREE. The check reads the other repository's default branch through the forge, so a record still on a branch elsewhere does not count. - Any cross-repo rule when `impacts` is absent. A record with no `impacts` and no cross-repo citation is unaffected, and a single-repository project sees no change. ## Acceptance criteria - A record citing `other-repo/0007` passes when that record exists and links back, and fails when it does not exist. - A record listing `other-repo` in `impacts` with no linking record there fails, naming the repository. - A one-way pair fails, naming both files. - `--skip-remote-issues` skips every cross-repo rule, and the skip line says so. - A repository with no `impacts` and no cross-repo citations behaves exactly as today. - Tests cover each failure, through the existing fake forge client. Related: #496 (the tooling guides the author), #528 (assent from a second account), and the `impacts` key from #483.
Author
Owner

Decided: the flag is --skip-forge-checks, and the MCP parameter is skip_forge_checks. It replaces --skip-remote-issues, with no alias. I did not pick --offline. On adr new, --offline does the full job from local data. On adr check, the flag removes checks, and the name must say that.

When the flag is set, adr check prints a warning that names each check that did not run. For example:

warning: --skip-forge-checks is set, so these checks did not run:
  - linked issues: the decision issues of 12 records were not read
  - cross-repo links: 3 links to records in other repos were not resolved
Only the local files were checked.

"Decision issues" are the issues in a record's Decision issues: list (#634). The warning names only the checks that exist at the time. It does not change the exit code. The final OK: line must not say that the forge checks ran (#492).

Decided: the flag is `--skip-forge-checks`, and the MCP parameter is `skip_forge_checks`. It replaces `--skip-remote-issues`, with no alias. I did not pick `--offline`. On `adr new`, `--offline` does the full job from local data. On `adr check`, the flag removes checks, and the name must say that. When the flag is set, `adr check` prints a warning that names each check that did not run. For example: ``` warning: --skip-forge-checks is set, so these checks did not run: - linked issues: the decision issues of 12 records were not read - cross-repo links: 3 links to records in other repos were not resolved Only the local files were checked. ``` "Decision issues" are the issues in a record's `Decision issues:` list (#634). The warning names only the checks that exist at the time. It does not change the exit code. The final `OK:` line must not say that the forge checks ran (#492).
Author
Owner

The v0.20.0 breaking set is complete and green on main. The code landed across the v0.20.0 branches, the full local gate passes, and the forge suite is green on both forges at both pinned versions on current main (31693766). Closing as done.

The v0.20.0 breaking set is complete and green on main. The code landed across the v0.20.0 branches, the full local gate passes, and the forge suite is green on both forges at both pinned versions on current main (31693766). Closing as done.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
sixfold-space/madtea#530
No description provided.