Ship the repository doctor as a devenv module, beside .doctor.just #95

Closed
opened 2026-08-28 20:00:21 +00:00 by larandar · 0 comments
Owner

Proposal

Ship Ting's repository doctor as a devenv module (ting-doctor.nix) alongside the existing .doctor.just, so repos can migrate off just + direnv + nix develop onto devenv without a flag day.

.doctor.just stays in this repo for every repo not yet migrated. It is removed only when the last consumer has moved.

Design

ting-doctor.nix is the same doctor, as devenv tasks with package = pkgs.nushell. The nushell bodies are carried over byte-for-byte; what changed is the surrounding mechanism:

  • flake (56 lines, textually patched nushell/gum into the first mkShell in flake.nix) — deleted. packages in the module is the declaration now, and a missing package fails the shell loudly.
  • environment (40 lines, enforced an .envrc header and gated every recipe on a hand-set TING_DEVSHELL="active" marker) — deleted. $env.DEVENV_ROOT is set by devenv itself, so it is both the repo-root lookup and the proof of a loaded environment.
  • doctor-cached ([cache(inputs=..., extra=datetime_utc("%Y%m%d%H"))]) — deleted. A shared status gate script carries the same policy: re-run when a lockfile is newer than the last success, or hourly.
  • sync (raw-HTTP self-fetch from this repo's main branch into an ignored dotfile) — deleted. Consumers take this file as a devenv input; devenv update is the sync and the rev lands in their devenv.lock.
  • ting:pin — new. The only check with no ancestor in .doctor.just: consumers now pin nixpkgs twice (flake.lock and devenv.lock), so this asserts the two agree. Warns rather than rewriting a lockfile behind the operator.

Everything else — openspec-reference, openspec-health, check, remotes, default-branch, governance, gitignore, fastlane, wire, adopt — is Ting forge policy and ports over unchanged. wire and adopt become devenv scripts on PATH guarded by gum confirm, since they edit tracked files and must stay deliberate acts.

Specification Delta

  • ADDED ting-doctor.nix at repo root: a devenv module exporting packages, tasks."ting:*", and scripts.ting-{wire,adopt}.
  • UNCHANGED .doctor.just remains, serving unmigrated repos.

Tasks

  1. Add ting-doctor.nix.
  2. Verify the task graph and a full green run from a consumer repo.
  3. (Follow-up, not this ticket) migrate this repo's own .envrc/.doctor.just usage.

Verification

Proven from lar.ad/flake-ops against this file as a path: input:

  • devenv tasks list renders the chain ting:pin -> openspec-reference -> openspec-health -> config -> remotes -> default-branch -> governance -> gitignore -> fastlane -> ting:doctor -> devenv:enterShell, every task carrying the status gate.
  • devenv tasks run ting:doctor completes green.
  • The gate skips the whole chain on re-run and invalidates when a lockfile moves.
  • All 11 nushell bodies compared byte-exact against the .doctor.just originals after the Nix ''-string round-trip (0 mismatches).
## Proposal Ship Ting's repository doctor as a **devenv module** (`ting-doctor.nix`) alongside the existing `.doctor.just`, so repos can migrate off `just` + `direnv` + `nix develop` onto devenv without a flag day. `.doctor.just` stays in this repo for every repo not yet migrated. It is removed only when the last consumer has moved. ## Design `ting-doctor.nix` is the same doctor, as devenv `tasks` with `package = pkgs.nushell`. The nushell bodies are carried over byte-for-byte; what changed is the surrounding mechanism: - **`flake`** (56 lines, textually patched `nushell`/`gum` into the first `mkShell` in `flake.nix`) — deleted. `packages` in the module *is* the declaration now, and a missing package fails the shell loudly. - **`environment`** (40 lines, enforced an `.envrc` header and gated every recipe on a hand-set `TING_DEVSHELL="active"` marker) — deleted. `$env.DEVENV_ROOT` is set by devenv itself, so it is both the repo-root lookup and the proof of a loaded environment. - **`doctor-cached`** (`[cache(inputs=..., extra=datetime_utc("%Y%m%d%H"))]`) — deleted. A shared `status` gate script carries the same policy: re-run when a lockfile is newer than the last success, or hourly. - **`sync`** (raw-HTTP self-fetch from this repo's main branch into an ignored dotfile) — deleted. Consumers take this file as a devenv input; `devenv update` is the sync and the rev lands in their `devenv.lock`. - **`ting:pin`** — new. The only check with no ancestor in `.doctor.just`: consumers now pin nixpkgs twice (`flake.lock` and `devenv.lock`), so this asserts the two agree. Warns rather than rewriting a lockfile behind the operator. Everything else — `openspec-reference`, `openspec-health`, `check`, `remotes`, `default-branch`, `governance`, `gitignore`, `fastlane`, `wire`, `adopt` — is Ting forge policy and ports over unchanged. `wire` and `adopt` become devenv `scripts` on PATH guarded by `gum confirm`, since they edit tracked files and must stay deliberate acts. ## Specification Delta - **ADDED** `ting-doctor.nix` at repo root: a devenv module exporting `packages`, `tasks."ting:*"`, and `scripts.ting-{wire,adopt}`. - **UNCHANGED** `.doctor.just` remains, serving unmigrated repos. ## Tasks 1. Add `ting-doctor.nix`. 2. Verify the task graph and a full green run from a consumer repo. 3. (Follow-up, not this ticket) migrate this repo's own `.envrc`/`.doctor.just` usage. ## Verification Proven from `lar.ad/flake-ops` against this file as a `path:` input: - `devenv tasks list` renders the chain `ting:pin -> openspec-reference -> openspec-health -> config -> remotes -> default-branch -> governance -> gitignore -> fastlane -> ting:doctor -> devenv:enterShell`, every task carrying the status gate. - `devenv tasks run ting:doctor` completes green. - The gate skips the whole chain on re-run and invalidates when a lockfile moves. - All 11 nushell bodies compared byte-exact against the `.doctor.just` originals after the Nix `''`-string round-trip (0 mismatches).
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.

Dependencies

No dependencies set

Reference
Ting/Jostoph#95
No description provided.