jj is misconfigured: trunk() points at GitHub's orphan commit #29

Open
opened 2026-08-05 21:14:16 +00:00 by agent.odin · 0 comments
Collaborator

Law 2 says "Local enforcement: jj immutable_heads() extended with tags()" and law 12 assigns that bootstrap to the devshell doctor. Neither exists — and the default that fills the gap is actively wrong.

Measured

trunk()            → a430f4db   main@origin
immutable_heads()  → a430f4db
main @forge        → 4cc81493   (divergent)
main @origin       → a430f4db   (hidden) (empty) bootstrap
                     ahead by ≥10, behind by ≥10

jj's default trunk() only ever matches origin/upstream, so it found GitHub's unrelated bootstrap commit — the very one the Forge Flow page flags for deliberate reset — and never looked at forge.

Consequences

  • immutable_heads() protects nothing real. No actual commit is immutable, so law 2's tag horizon is unenforced locally and --ignore-immutable guards against nothing.
  • jj log's default revset anchors on a disconnected commit.
  • jj new trunk() / jj rebase -d trunk() would target the wrong graph entirely.
  • main reads divergent because two unrelated histories claim one bookmark name.

The fix

Remote-agnostic, because remote names are a local choice — this repo has forge + origin, while a git clone of a lar.ad repo calls the forge origin:

[revset-aliases]
"trunk()" = 'latest(remote_bookmarks(exact:"fastlane") | root())'
"immutable_heads()" = 'trunk() | tags(glob:"v*") | (trunk().. & ~mine())'
"release_horizon()" = 'latest(tags(glob:"v*") | root())'

[git]
write-change-id-header = true

latest() picks the live bookmark over the stale one without being told which is which — verified: on main it selects 4cc81493@forge over the GitHub orphan.

Two blockers, in order

  1. This repo has no fastlane bookmark, so trunk() would resolve to root(). The Forge Flow model requires one.
  2. ~mine() would freeze the entire repo today. jj user.email is [email protected] and mine() matches 0 of 83 commits. Author emails present: [email protected] (51), [email protected] (17), [email protected] (7), [email protected] (4), [email protected] (1), [email protected] (1). Only omo follows AGENTS.md's <persona> <[email protected]> convention — three of those identities are harness defaults that leaked through. The trunk().. prefix normally bounds that scan, but with trunk() degenerating to root() the bound vanishes.

So the ~mine() clause lands after fastlane exists and authorship is consistent, not before.

Config cannot be committed

jj refuses to read config from inside the working copy — "For security reasons, they are not located inside the workspace" — because a tracked config carries [aliases] and ui.editor, so cloning would execute the author's commands. All three scopes live under ~/.config/jj/; .jj/repo/config.toml no longer exists in 0.43. The doctor applies it via jj config set --repo, idempotently, exactly as law 12 describes.

Acceptance

  • Doctor recipe applying the above, idempotent on devshell entry
  • Doctor asserts user.email is a persona address and fails loudly otherwise
  • trunk() resolves to a forge bookmark, never to GitHub
  • Authorship conformance check: commits authored under harness defaults rather than personas are reported
  • Doctor warns on remotes rather than repairing — jj git remote remove also forgets bookmarks, and rewriting origin would clobber personal forks

Related: #22 (build queue — this is the "repo jj config + devshell doctor" box), dendrite#9 (the same doctor, written there first).

Law 2 says *"Local enforcement: jj `immutable_heads()` extended with `tags()`"* and law 12 assigns that bootstrap to the devshell doctor. Neither exists — and the default that fills the gap is actively wrong. ### Measured ``` trunk() → a430f4db main@origin immutable_heads() → a430f4db main @forge → 4cc81493 (divergent) main @origin → a430f4db (hidden) (empty) bootstrap ahead by ≥10, behind by ≥10 ``` jj's default `trunk()` only ever matches `origin`/`upstream`, so it found **GitHub's unrelated bootstrap commit** — the very one the Forge Flow page flags for deliberate reset — and never looked at `forge`. ### Consequences - **`immutable_heads()` protects nothing real.** No actual commit is immutable, so law 2's tag horizon is unenforced locally and `--ignore-immutable` guards against nothing. - `jj log`'s default revset anchors on a disconnected commit. - `jj new trunk()` / `jj rebase -d trunk()` would target the wrong graph entirely. - `main` reads **divergent** because two unrelated histories claim one bookmark name. ### The fix Remote-agnostic, because remote names are a local choice — this repo has `forge` + `origin`, while a `git clone` of a lar.ad repo calls the forge `origin`: ```toml [revset-aliases] "trunk()" = 'latest(remote_bookmarks(exact:"fastlane") | root())' "immutable_heads()" = 'trunk() | tags(glob:"v*") | (trunk().. & ~mine())' "release_horizon()" = 'latest(tags(glob:"v*") | root())' [git] write-change-id-header = true ``` `latest()` picks the live bookmark over the stale one without being told which is which — verified: on `main` it selects `4cc81493@forge` over the GitHub orphan. ### Two blockers, in order 1. **This repo has no `fastlane` bookmark**, so `trunk()` would resolve to `root()`. The Forge Flow model requires one. 2. **`~mine()` would freeze the entire repo today.** `jj user.email` is `a+[email protected]` and `mine()` matches **0 of 83** commits. Author emails present: `[email protected]` (51), `a+[email protected]` (17), `[email protected]` (7), `[email protected]` (4), `[email protected]` (1), `[email protected]` (1). Only `omo` follows AGENTS.md's `<persona> <a+[email protected]>` convention — three of those identities are harness defaults that leaked through. The `trunk()..` prefix normally bounds that scan, but with `trunk()` degenerating to `root()` the bound vanishes. So the `~mine()` clause lands **after** fastlane exists and authorship is consistent, not before. ### Config cannot be committed jj refuses to read config from inside the working copy — *"For security reasons, they are not located inside the workspace"* — because a tracked config carries `[aliases]` and `ui.editor`, so cloning would execute the author's commands. All three scopes live under `~/.config/jj/`; `.jj/repo/config.toml` no longer exists in 0.43. The doctor applies it via `jj config set --repo`, idempotently, exactly as law 12 describes. ### Acceptance - [ ] Doctor recipe applying the above, idempotent on devshell entry - [ ] Doctor asserts `user.email` is a persona address and fails loudly otherwise - [ ] `trunk()` resolves to a forge bookmark, never to GitHub - [ ] Authorship conformance check: commits authored under harness defaults rather than personas are reported - [ ] Doctor **warns** on remotes rather than repairing — `jj git remote remove` also forgets bookmarks, and rewriting `origin` would clobber personal forks Related: #22 (build queue — this is the "repo jj config + devshell doctor" box), dendrite#9 (the same doctor, written there first).
Commenting is not possible because the repository is archived.
No description provided.