feat(nix): package gitea-axi as a flake with a PATH-suffixing wrapper (task 0037) #46

Merged
alexion merged 2 commits from task-0037-flake-package-and-wrapper into main 2026-07-19 23:06:37 -04:00
Owner

Implements .claude/tasks/0037-flake-package-and-wrapper.md.

What was built

A flake at the repository root exposing gitea-axi as a package, with the derivation in its own callable expression (package.nix) that the flake consumes — so it evaluates outside a flake context and is usable in an overlay unchanged. Verified: plain callPackage produces the identical drvPath as the flake build.

  • Dependencies fetched from the lockfile's integrity fields via importNpmLock, so no fixed-output hash to maintain and a dependency bump edits no Nix expression.
  • Version read from the package manifest; no version literal in any Nix expression. license is looked up by SPDX id from the same manifest for the same reason.
  • Source is an explicit allowlist. Verified with a negative control: touching an ADR, spec, bench/ file, PUBLISHING.md, or vitest.e2e.config.ts leaves the output path untouched, while touching src/cli.ts changes it.
  • Binary wrapped with --suffix PATH per ADR 0018. With no ambient PATH at all the closure's tea is found (AUTH_REQUIRED, not TEA_NOT_INSTALLED); with an operator tea earlier on PATH, that one is invoked.
  • The fast tier runs inside the build: 38 files, 410 tests.

Deviations

Three systems, not four. nixpkgs 26.11 dropped x86_64-darwin, and legacyPackages.x86_64-darwin now throws rather than merely failing to build — listing it would break nix flake show and nix flake check for every system at once. Coverage is x86_64-linux, aarch64-linux, aarch64-darwin. This is the one criterion marked [-]. The spec still reads "four common Linux and Darwin targets"; it was left as the historical design record rather than amended.

doCheck = true was silently inert. buildNpmPackage supplies no check hook, so the first green build logged no Makefile or custom checkPhase, doing nothing and shipped a package whose tests had never run. Fixed with an explicit checkPhase plus git/which in nativeCheckInputs and a writable HOME. Recorded as a Gotcha, since the failure mode is a green build.

postUnpack renames the build tree, which the task did not ask for. test/setup.test.ts passes only when the checkout path contains the substring gitea-axi, so the builder's generic source directory fails it. Verified outside Nix by copying the repo to a clean path. The rename makes the build environment representative of a real install; it is commented as a workaround and is scheduled for deletion in task 0042.

ADR 0018 landed earlier in 0cbfe43 during the planning pass, so that criterion is satisfied by an earlier commit rather than this one.

Follow-up: the spec's open verification item is answered, unfavourably

Evidence recorded in 0042. The SDK does not prefer the bare binary name — it records the absolute entrypoint path unless PATH resolution matches. Under Nix that is the content-addressed store path, so the SessionStart hook silently stops running after a rebuild or GC. A second defect from the same line makes setup hooks append duplicates instead of updating in place. Both were deliberately left to 0042 rather than pre-empting its design work here.

Review

Risk

Overall: Medium

  • Blast radius: Low — three new files plus two docs; nothing in src/ or test/ touched, purely additive install channel.
  • Reversibility: Low — deleting the three files fully undoes it; no migrations or published-API change.
  • Test coverage: Medium — the derivation runs the fast tier, but the Nix expressions have no eval check or CI job, so allowlist rot is caught only by a manual nix build.
  • Sensitive domain: Medium — postInstall wraps the credential-resolution path; --suffix correctly keeps the operator's tea and its in-place OAuth refresh authoritative.
  • Size & complexity: Low — ~135 lines of declarative Nix, no branching; the one non-obvious piece is commented.
  • Runtime criticality: Medium — dev/distribution tooling, but ships an install method with a known silent-breakage mode deferred to 0042.

Unaddressed findings

Spec — the spec text still says "four common Linux and Darwin targets". Left divergent deliberately: the spec is a design record, and the reason for three is captured in the task's Implementation Notes, an inline comment at the systems list, and a CLAUDE.md Gotcha.

Standards — the x86_64-darwin and inert-doCheck rationales each appear in three places (inline comment, CLAUDE.md Gotcha, task notes). Two copies are required by repo convention; the third sits where a future editor would re-add the system. Noted only so drift is noticed.

Findings addressed in the diff: hardcoded license now derived from the manifest by SPDX id, and test/e2e excluded from the source allowlist so end-to-end churn no longer invalidates the derivation.

Implements [`.claude/tasks/0037-flake-package-and-wrapper.md`](.claude/tasks/0037-flake-package-and-wrapper.md). ## What was built A flake at the repository root exposing gitea-axi as a package, with the derivation in its own callable expression (`package.nix`) that the flake consumes — so it evaluates outside a flake context and is usable in an overlay unchanged. Verified: plain `callPackage` produces the *identical* `drvPath` as the flake build. - Dependencies fetched from the lockfile's integrity fields via `importNpmLock`, so no fixed-output hash to maintain and a dependency bump edits no Nix expression. - Version read from the package manifest; no version literal in any Nix expression. `license` is looked up by SPDX id from the same manifest for the same reason. - Source is an explicit allowlist. Verified with a negative control: touching an ADR, spec, `bench/` file, `PUBLISHING.md`, or `vitest.e2e.config.ts` leaves the output path untouched, while touching `src/cli.ts` changes it. - Binary wrapped with `--suffix PATH` per ADR 0018. With no ambient `PATH` at all the closure's `tea` is found (`AUTH_REQUIRED`, not `TEA_NOT_INSTALLED`); with an operator `tea` earlier on `PATH`, that one is invoked. - The fast tier runs inside the build: 38 files, 410 tests. ## Deviations **Three systems, not four.** nixpkgs 26.11 dropped `x86_64-darwin`, and `legacyPackages.x86_64-darwin` now *throws* rather than merely failing to build — listing it would break `nix flake show` and `nix flake check` for every system at once. Coverage is `x86_64-linux`, `aarch64-linux`, `aarch64-darwin`. This is the one criterion marked `[-]`. The spec still reads "four common Linux and Darwin targets"; it was left as the historical design record rather than amended. **`doCheck = true` was silently inert.** `buildNpmPackage` supplies no check hook, so the first green build logged `no Makefile or custom checkPhase, doing nothing` and shipped a package whose tests had never run. Fixed with an explicit `checkPhase` plus `git`/`which` in `nativeCheckInputs` and a writable `HOME`. Recorded as a Gotcha, since the failure mode is a *green* build. **`postUnpack` renames the build tree**, which the task did not ask for. `test/setup.test.ts` passes only when the checkout path contains the substring `gitea-axi`, so the builder's generic `source` directory fails it. Verified outside Nix by copying the repo to a clean path. The rename makes the build environment representative of a real install; it is commented as a workaround and is scheduled for deletion in task 0042. **ADR 0018** landed earlier in `0cbfe43` during the planning pass, so that criterion is satisfied by an earlier commit rather than this one. ## Follow-up: the spec's open verification item is answered, unfavourably Evidence recorded in [`0042`](.claude/tasks/0042-verify-hook-path-resolution.md). The SDK does **not** prefer the bare binary name — it records the absolute entrypoint path unless `PATH` resolution matches. Under Nix that is the content-addressed store path, so the `SessionStart` hook silently stops running after a rebuild or GC. A second defect from the same line makes `setup hooks` append duplicates instead of updating in place. Both were deliberately left to 0042 rather than pre-empting its design work here. ## Review ### Risk **Overall: Medium** - Blast radius: Low — three new files plus two docs; nothing in `src/` or `test/` touched, purely additive install channel. - Reversibility: Low — deleting the three files fully undoes it; no migrations or published-API change. - Test coverage: Medium — the derivation runs the fast tier, but the Nix expressions have no eval check or CI job, so allowlist rot is caught only by a manual `nix build`. - Sensitive domain: Medium — `postInstall` wraps the credential-resolution path; `--suffix` correctly keeps the operator's `tea` and its in-place OAuth refresh authoritative. - Size & complexity: Low — ~135 lines of declarative Nix, no branching; the one non-obvious piece is commented. - Runtime criticality: Medium — dev/distribution tooling, but ships an install method with a known silent-breakage mode deferred to 0042. ### Unaddressed findings **Spec — the spec text still says "four common Linux and Darwin targets".** Left divergent deliberately: the spec is a design record, and the reason for three is captured in the task's Implementation Notes, an inline comment at the `systems` list, and a CLAUDE.md Gotcha. **Standards — the `x86_64-darwin` and inert-`doCheck` rationales each appear in three places** (inline comment, CLAUDE.md Gotcha, task notes). Two copies are required by repo convention; the third sits where a future editor would re-add the system. Noted only so drift is noticed. Findings addressed in the diff: hardcoded `license` now derived from the manifest by SPDX id, and `test/e2e` excluded from the source allowlist so end-to-end churn no longer invalidates the derivation.
alexion added 2 commits 2026-07-19 23:01:18 -04:00
The store holds only `alexion` now; `csv-reviewer` is gone for good.

Also records that node/npm/tea are absent from a non-interactive shell on
this host and that git carries no configured identity, both of which cost
a full session of rediscovery.
feat(nix): package gitea-axi as a flake with a PATH-suffixing wrapper (task 0037)
All checks were successful
CI / test (pull_request) Successful in 54s
CI / test (push) Successful in 52s
5a2874d11c
Add a flake at the repository root exposing gitea-axi as a package, with the
derivation in its own callable expression so it stays buildable outside a flake
context and usable in an overlay unchanged.

Dependencies are fetched from the lockfile's integrity fields via importNpmLock
rather than a committed fixed-output hash, and the version is read from the
package manifest, so neither a dependency bump nor a release edits any Nix
expression. The source is an explicit allowlist, keeping ADR, spec, task and
bench churn out of the derivation's inputs.

The installed binary is wrapped with --suffix PATH per ADR 0018: the operator's
own git and tea win, and the closure's are a fresh-machine fallback.

Two things differ from the plan. Systems coverage is three targets, not four:
nixpkgs 26.11 dropped x86_64-darwin and now throws on evaluating it, which
would break nix flake show and nix flake check for every system at once. And
buildNpmPackage supplies no check hook, so doCheck alone was silently inert and
produced a green build whose tests never ran; running the fast tier needs an
explicit checkPhase.
alexion merged commit 5a2874d11c into main 2026-07-19 23:06:37 -04:00
alexion deleted branch task-0037-flake-package-and-wrapper 2026-07-19 23:06:37 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alexion/gitea-axi#46