forge: build the host forge from the Go program #25

Merged
vnprc merged 2 commits from agent/forge-go-cutover into master 2026-08-24 23:36:14 +01:00
Member

This changes the host's forge package from the Bash wrapper to the Go program. Merging this PR alone changes no running machine: allod/archetypes owns the host composition and must advance its nexus pin before a human host rebuild applies it.

The dev-VM cutover is already deployed and verified. With this branch substituted into current allod/archetypes, the host builds the exact same snapshot-enabled Forge derivation now running successfully on allod-dev; without the substitution, the host composition still selects the Bash package.

The Bash source remains available in the pinned allod-tools input. If the host smoke test fails, roll the archetypes nexus pin back to pre-cutover nexus revision da06e247698c4a1ec82fb5220237ae9c46707bce and rebuild.

Risk

R3, per the migration plan. This is the wrapper that swaps the deployed host forge after the consumer pin and rebuild. forge handles every host-side Forge operation, so silent contract drift would affect the host even though merging this repository alone is inert.

The diff against current nexus master touches only the forge package in nix/home.nix; the other six tools are unchanged. Current master is included in the PR head. The Bash forge remains in allod-tools until both deployed cutovers have passed.

This repository deliberately has no allod-tools input of its own. nix/home.nix receives that source from the consumer, so the safe composition is enforced operationally: current allod/archetypes already pins snapshot-enabled tools revision 5649cec426b5d36d740f9286481b5496ab01d4e3, and its nexus pin must move to this PR only after merge. Rolling back means moving the consumer's nexus pin, not editing a nonexistent tools lock here.

The runtime pins change with the implementation. The Bash wrapper pinned jq and curl; the Go API client is in-process and executes neither. The Go binary still invokes git for repository and branch inference, so the new wrapper pins Git instead of relying on the ambient PATH.

Validation

Current nexus master was merged into the cutover branch at 1e201eae7a2e0483bc64e9997e42b72b84478626. Forgejo reports current master as an ancestor and the PR as mergeable; the diff remains the single package replacement in nix/home.nix.

I evaluated the real host composition from current allod/archetypes with this exact Git revision supplied through --override-input nexus. The generated host package changed from forge (the Bash writeShellApplication) to forge-0.1.0 and yielded /nix/store/bd2g9k60i2205c8d9pra17c1513ppjqr-forge-0.1.0.drv. Building it produced /nix/store/bvwm2lm8z9ik91lgcyqwknfjidif1l58-forge-0.1.0.

That derivation and output path are byte-identical to the package currently deployed and smoke-tested on allod-dev. The derivation uses buildGoModule, Go 1.25.10, vendorHash = null, subPackages = cmd/forge, and doCheck = 1, so its command tests include the 19 ported snapshot scenarios. The wrapper prepends pinned Git and executes an ELF Go payload.

The deployed dev witness passed after rebuild: authentication, Git repository inference, help, and live pr snapshot 156 all work from /etc/profiles/per-user/allod/bin/forge, which resolves to the same store output the host preview builds. The snapshot returned schema version 1 with the expected repository and ref projection.

The branch's no-hardcoded-arch check also passes. Its first attempt encountered a transient cache connection failure; an unchanged retry fetched the missing path and completed successfully.

Not covered here: advancing the allod/archetypes nexus lock and rebuilding the host. Both happen after this PR merges, and the host rebuild is a human-only action.

Refs allod/tools#155
Refs allod/tools#98

This changes the host's `forge` package from the Bash wrapper to the Go program. Merging this PR alone changes no running machine: allod/archetypes owns the host composition and must advance its `nexus` pin before a human host rebuild applies it. The dev-VM cutover is already deployed and verified. With this branch substituted into current allod/archetypes, the host builds the exact same snapshot-enabled Forge derivation now running successfully on `allod-dev`; without the substitution, the host composition still selects the Bash package. The Bash source remains available in the pinned allod-tools input. If the host smoke test fails, roll the archetypes `nexus` pin back to pre-cutover nexus revision `da06e247698c4a1ec82fb5220237ae9c46707bce` and rebuild. ## Risk R3, per the migration plan. This is the wrapper that swaps the deployed host `forge` after the consumer pin and rebuild. `forge` handles every host-side Forge operation, so silent contract drift would affect the host even though merging this repository alone is inert. The diff against current nexus master touches only the `forge` package in `nix/home.nix`; the other six tools are unchanged. Current master is included in the PR head. The Bash `forge` remains in allod-tools until both deployed cutovers have passed. This repository deliberately has no `allod-tools` input of its own. `nix/home.nix` receives that source from the consumer, so the safe composition is enforced operationally: current allod/archetypes already pins snapshot-enabled tools revision `5649cec426b5d36d740f9286481b5496ab01d4e3`, and its `nexus` pin must move to this PR only after merge. Rolling back means moving the consumer's `nexus` pin, not editing a nonexistent tools lock here. The runtime pins change with the implementation. The Bash wrapper pinned `jq` and `curl`; the Go API client is in-process and executes neither. The Go binary still invokes `git` for repository and branch inference, so the new wrapper pins Git instead of relying on the ambient PATH. ## Validation Current nexus master was merged into the cutover branch at `1e201eae7a2e0483bc64e9997e42b72b84478626`. Forgejo reports current master as an ancestor and the PR as mergeable; the diff remains the single package replacement in `nix/home.nix`. I evaluated the real host composition from current allod/archetypes with this exact Git revision supplied through `--override-input nexus`. The generated host package changed from `forge` (the Bash `writeShellApplication`) to `forge-0.1.0` and yielded `/nix/store/bd2g9k60i2205c8d9pra17c1513ppjqr-forge-0.1.0.drv`. Building it produced `/nix/store/bvwm2lm8z9ik91lgcyqwknfjidif1l58-forge-0.1.0`. That derivation and output path are byte-identical to the package currently deployed and smoke-tested on `allod-dev`. The derivation uses `buildGoModule`, Go 1.25.10, `vendorHash = null`, `subPackages = cmd/forge`, and `doCheck = 1`, so its command tests include the 19 ported snapshot scenarios. The wrapper prepends pinned Git and executes an ELF Go payload. The deployed dev witness passed after rebuild: authentication, Git repository inference, help, and live `pr snapshot 156` all work from `/etc/profiles/per-user/allod/bin/forge`, which resolves to the same store output the host preview builds. The snapshot returned schema version 1 with the expected repository and ref projection. The branch's `no-hardcoded-arch` check also passes. Its first attempt encountered a transient cache connection failure; an unchanged retry fetched the missing path and completed successfully. Not covered here: advancing the allod/archetypes `nexus` lock and rebuilding the host. Both happen after this PR merges, and the host rebuild is a human-only action. Refs allod/tools#155 Refs allod/tools#98
cmd/forge replaces the bash script: the API client runs in-process, so the
wrapper no longer needs jq or curl, and keeps only git for repository
inference and the current branch. The bash source still ships in the
allod-tools input and stays runnable from a checkout. The input itself is
pinned by the consumer, so this repo has no lock to bump.
Author
Member

Read-only review pass on this PR, findings and what changed as a result. The code diff is unchanged; every fix below was to the PR body, whose opening claim was wrong.

Corrected, and this was the significant one: the body said the next rebuild of the host installs the Go forge. It does not. allod/archetypes owns the host configuration and pins this repo as an input at a fixed rev, so merging this changes nothing anywhere until that nexus pin is bumped and a human rebuilds — a step neither this PR nor allod/archetypes#40 performs. The summary and the risk section now say so, and the rollback line says the same in reverse: reverting this commit also does nothing until the pin moves.

Corrected: the coupling to allod/archetypes#40 was stated as "must merge together". Merge order is not the constraint. That PR moves allod-tools to the rev containing cmd/forge, and the requirement is that the pin is in place before the consumer bumps its nexus input past this commit; either PR merging alone is harmless.

Corrected: two claims narrowed. doCheck runs the cmd/forge tests only, because subPackages scopes the check phase, so the internal/ tests do not run in this build. And the validation output forge: GET ... failed: curl exit 7 is a label the Go program prints from curlExitCode in cmd/forge/api.go, mapping Go transport errors onto curl's exit-code numbering; it is not a curl invocation, which matters because dropping pkgs.curl rests on that.

Checked and clean: the only child process anywhere in the Go program is git, from internal/gitremote — no LookPath, no shell-out, no editor or pager, and the API client uses net/http and encoding/json in-process, so dropping jq and curl is safe. Nothing in this repo depends on forge being a shell script. no-hardcoded-arch, the check that guards nix/, still passes, and the added lines contain no literal system string. The bash source is present in the newly pinned input, verified in the store path this build read.

Two non-blocking observations for the owner, neither addressed here. src = allod-tools is the whole repository, so any commit to allod/tools — a README edit included — changes the source hash and rebuilds the Go binary and reruns its test suite on the host; lib.fileset on the source or doCheck = false would decouple that if rebuild time becomes annoying. And the packaging expression now exists in three places, of which allod/tools' own dev flake is the odd one out: it has no git wrap, so nix build there yields an unwrapped binary that differs from what is deployed.

Read-only review pass on this PR, findings and what changed as a result. The code diff is unchanged; every fix below was to the PR body, whose opening claim was wrong. Corrected, and this was the significant one: the body said the next rebuild of the host installs the Go `forge`. It does not. allod/archetypes owns the host configuration and pins this repo as an input at a fixed rev, so merging this changes nothing anywhere until that `nexus` pin is bumped and a human rebuilds — a step neither this PR nor allod/archetypes#40 performs. The summary and the risk section now say so, and the rollback line says the same in reverse: reverting this commit also does nothing until the pin moves. Corrected: the coupling to allod/archetypes#40 was stated as "must merge together". Merge order is not the constraint. That PR moves `allod-tools` to the rev containing `cmd/forge`, and the requirement is that the pin is in place before the consumer bumps its `nexus` input past this commit; either PR merging alone is harmless. Corrected: two claims narrowed. `doCheck` runs the `cmd/forge` tests only, because `subPackages` scopes the check phase, so the `internal/` tests do not run in this build. And the validation output `forge: GET ... failed: curl exit 7` is a label the Go program prints from `curlExitCode` in `cmd/forge/api.go`, mapping Go transport errors onto curl's exit-code numbering; it is not a curl invocation, which matters because dropping `pkgs.curl` rests on that. Checked and clean: the only child process anywhere in the Go program is `git`, from `internal/gitremote` — no `LookPath`, no shell-out, no editor or pager, and the API client uses `net/http` and `encoding/json` in-process, so dropping `jq` and `curl` is safe. Nothing in this repo depends on `forge` being a shell script. `no-hardcoded-arch`, the check that guards `nix/`, still passes, and the added lines contain no literal system string. The bash source is present in the newly pinned input, verified in the store path this build read. Two non-blocking observations for the owner, neither addressed here. `src = allod-tools` is the whole repository, so any commit to allod/tools — a README edit included — changes the source hash and rebuilds the Go binary and reruns its test suite on the host; `lib.fileset` on the source or `doCheck = false` would decouple that if rebuild time becomes annoying. And the packaging expression now exists in three places, of which allod/tools' own dev flake is the odd one out: it has no git wrap, so `nix build` there yields an unwrapped binary that differs from what is deployed.
Author
Member

Cutover dependency update: the host-side Go forge must include pr snapshot, whose port is in allod/tools#156. The consuming allod/archetypes pins must not advance this wrapper against the older tools rev.

After #156 merges, refresh the consumer's allod-tools pin and rerun the host package/snapshot checks before the human host rebuild.

Refs allod/tools#155

Cutover dependency update: the host-side Go `forge` must include `pr snapshot`, whose port is in allod/tools#156. The consuming allod/archetypes pins must not advance this wrapper against the older tools rev. After #156 merges, refresh the consumer's `allod-tools` pin and rerun the host package/snapshot checks before the human host rebuild. Refs allod/tools#155
Author
Member

The dev-VM cutover has now been rebuilt and verified successfully, and the owner asked to roll forward to this host cutover. I am refreshing this branch against current master and rebuilding the generated host package through the current allod/archetypes composition with the snapshot-enabled allod-tools pin.

Refs allod/tools#155

The dev-VM cutover has now been rebuilt and verified successfully, and the owner asked to roll forward to this host cutover. I am refreshing this branch against current `master` and rebuilding the generated host package through the current allod/archetypes composition with the snapshot-enabled `allod-tools` pin. Refs allod/tools#155
Author
Member

Host cutover refresh complete at 1e201ea.

  • current nexus master is an ancestor of the PR head and Forgejo reports it mergeable
  • the PR diff remains only the Bash-to-Go forge package replacement
  • evaluating current allod/archetypes with this exact Git revision changes the host package from forge to forge-0.1.0
  • the host preview builds /nix/store/bvwm2lm8z9ik91lgcyqwknfjidif1l58-forge-0.1.0, exactly the store output now deployed and verified on allod-dev
  • the branch's no-hardcoded-arch check passes

The PR body now records the current composition, deployed dev witness, rollback pin, and human-only host steps. Next gate: merge this PR; after merge, advance the allod/archetypes nexus pin and rebuild/smoke-test the host.

Refs allod/tools#155

Host cutover refresh complete at `1e201ea`. - current nexus `master` is an ancestor of the PR head and Forgejo reports it mergeable - the PR diff remains only the Bash-to-Go `forge` package replacement - evaluating current allod/archetypes with this exact Git revision changes the host package from `forge` to `forge-0.1.0` - the host preview builds `/nix/store/bvwm2lm8z9ik91lgcyqwknfjidif1l58-forge-0.1.0`, exactly the store output now deployed and verified on `allod-dev` - the branch's `no-hardcoded-arch` check passes The PR body now records the current composition, deployed dev witness, rollback pin, and human-only host steps. Next gate: merge this PR; after merge, advance the allod/archetypes `nexus` pin and rebuild/smoke-test the host. Refs allod/tools#155
vnprc approved these changes 2026-08-24 23:36:08 +01:00
vnprc merged commit 1e201eae7a into master 2026-08-24 23:36:14 +01:00
vnprc deleted branch agent/forge-go-cutover 2026-08-24 23:36:14 +01:00
Sign in to join this conversation.
No description provided.