The doctor: one .doctor.just, distributed from the steward #8

Merged
larandar merged 1 commit from agent.teyla/Jostoph:tango/7-doctor-just into main 2026-08-10 05:48:37 +00:00
Contributor

Lands the canonical .doctor.just here, beside .fastlane.toml (#6). Three hand-copied variants exist today — vordr/.doctor.just, dendrite/.justfile, and modron's — and they had drifted apart silently; dendrite's immutable_heads() carries (trunk().. & ~mine()) that the others do not. One copy, fetched rather than copied, is the fix.

In scope

  • .doctor.just at the repository root, fetched raw over anonymous HTTPS by every consuming repo.
  • sync — fetches the canonical copy over the local one on default, so a repo self-updates.
  • check — one table of settings with a scope column (git repo-local, jj repo-local).
  • governance — report-only: does a repo on a Ting forge remote declare Ting governance in AGENTS.md.

Out of scope

  • Writing any tracked file. governance reports and does not edit AGENTS.md — a governance declaration belongs in a reviewed commit, not a side effect of a setup tool.
  • User-global state. Both write scopes are repo-local. git --global would make every repo on a machine inherit whatever the last one wanted.
  • Gating pushes. Measured: jj git push bypasses git hooks entirely (a pre-push hook blocked git push, then jj pushed the same branch past it), and jj has no per-remote push allowlist. Nothing here pretends otherwise; that is server-side work.
  • doctor-fastlane, which follows once this lands and #6 defines the manifest.

Boundary

Public repo, executed by every consumer: no credential values, only the $FORGEJO_ACCESS_TOKEN reference inside the helper string.

sync makes local edits deliberately temporary — improvements land here or they are lost. The write is staged beside the target and renamed, since the file is read by the process rewriting it.

nix := require("nix") is the only host dependency. nu and gum deliberately are not: they come from the consuming repo's devShell, and requiring them on PATH would test the wrong environment — passing on a machine that has them ambiently while flake.nix omits them, failing on a clean machine where the devShell is correct.

Two things this deliberately does not catch, measured rather than assumed, and recorded in the file so nobody re-derives them:

  • A devShell that omits gum still runs green, because nix develop does not isolate the environment and the host's ~/.nix-profile/bin/gum leaks in. --ignore-env does catch it but is unusable — it also strips $FORGEJO_ACCESS_TOKEN and drops nix off PATH.
  • git config --local needs a real git work tree, so a jj/tango workspace (no .git) exits 128. That raises rather than pretending; run the doctor from the colocated checkout.

Acceptance

Verified against this machine's repos:

  • doctor reports every row and is idempotent — second run rewrites nothing, fixed: false throughout.
  • Unset key is repaired (unset release_horizon()❌ → 🔧 → correct value); a key already correct is left alone.
  • A default counts as satisfied. git.write-change-id-header is true by jj built-in default since 0.43 (upstream change for Gerrit compatibility), so it reads without a repo-local write. The row stays to catch a user-level config turning it off.
  • Tool failure is distinguishable from unset. Both git config --get and jj config get exit 1 on a missing key, which is a value; anything above raises. A malformed key surfaced as a real error during development instead of becoming "???".
  • sync replaces on difference (+94/-119 against a real remote), is silent when identical, and soft-fails keeping the local copy on 404 and on DNS failure.
  • No credential value in the file.

Note for review: this repo has no fastlane branch, so the doctor's trunk() resolves to root() when run here. That is #6's territory, not this PR's.

Closes #7

Lands the canonical `.doctor.just` here, beside `.fastlane.toml` (#6). Three hand-copied variants exist today — `vordr/.doctor.just`, `dendrite/.justfile`, and modron's — and they had drifted apart silently; `dendrite`'s `immutable_heads()` carries `(trunk().. & ~mine())` that the others do not. One copy, fetched rather than copied, is the fix. ## In scope - `.doctor.just` at the repository root, fetched raw over anonymous HTTPS by every consuming repo. - `sync` — fetches the canonical copy over the local one on `default`, so a repo self-updates. - `check` — one table of settings with a `scope` column (`git` repo-local, `jj` repo-local). - `governance` — report-only: does a repo on a Ting forge remote declare Ting governance in `AGENTS.md`. ## Out of scope - **Writing any tracked file.** `governance` reports and does not edit `AGENTS.md` — a governance declaration belongs in a reviewed commit, not a side effect of a setup tool. - **User-global state.** Both write scopes are repo-local. `git --global` would make every repo on a machine inherit whatever the last one wanted. - **Gating pushes.** Measured: `jj git push` bypasses git hooks entirely (a `pre-push` hook blocked `git push`, then jj pushed the same branch past it), and jj has no per-remote push allowlist. Nothing here pretends otherwise; that is server-side work. - `doctor-fastlane`, which follows once this lands and #6 defines the manifest. ## Boundary Public repo, executed by every consumer: no credential values, only the `$FORGEJO_ACCESS_TOKEN` reference inside the helper string. `sync` makes local edits deliberately temporary — improvements land here or they are lost. The write is staged beside the target and renamed, since the file is read by the process rewriting it. `nix := require("nix")` is the only host dependency. `nu` and `gum` deliberately are not: they come from the consuming repo's devShell, and requiring them on PATH would test the wrong environment — passing on a machine that has them ambiently while `flake.nix` omits them, failing on a clean machine where the devShell is correct. Two things this deliberately does **not** catch, measured rather than assumed, and recorded in the file so nobody re-derives them: - A devShell that omits `gum` still runs green, because `nix develop` does not isolate the environment and the host's `~/.nix-profile/bin/gum` leaks in. `--ignore-env` does catch it but is unusable — it also strips `$FORGEJO_ACCESS_TOKEN` and drops `nix` off PATH. - `git config --local` needs a real git work tree, so a jj/tango workspace (no `.git`) exits 128. That raises rather than pretending; run the doctor from the colocated checkout. ## Acceptance Verified against this machine's repos: - `doctor` reports every row and is idempotent — second run rewrites nothing, `fixed: false` throughout. - Unset key is repaired (unset `release_horizon()` → `❌ → 🔧` → correct value); a key already correct is left alone. - **A default counts as satisfied.** `git.write-change-id-header` is `true` by jj built-in default since 0.43 (upstream change for Gerrit compatibility), so it reads ✅ without a repo-local write. The row stays to catch a user-level config turning it off. - **Tool failure is distinguishable from unset.** Both `git config --get` and `jj config get` exit 1 on a missing key, which is a value; anything above raises. A malformed key surfaced as a real error during development instead of becoming `"???"`. - `sync` replaces on difference (`+94/-119` against a real remote), is silent when identical, and soft-fails keeping the local copy on 404 and on DNS failure. - No credential value in the file. Note for review: this repo has no `fastlane` branch, so the doctor's `trunk()` resolves to `root()` when run here. That is #6's territory, not this PR's. Closes #7
One copy every repo fetches instead of three that drifted silently.

Closes #7
larandar deleted branch tango/7-doctor-just 2026-08-10 05:48:37 +00:00
Sign in to join this conversation.
No reviewers
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.

Dependencies

No dependencies set

Reference
Ting/Jostoph!8
No description provided.