myxce/.kiro/specs/eliminate-frontend-makefile/brief.md
Rongsong Shen 5e68fcc0d8
docs(spec): promote eliminate-frontend-makefile backlog item to a brief
/kiro-discovery investigation of removing src/frontend/Makefile in favor
of Meson as the sole build system. Records the quick investigation's
findings (5 boundary seams, current-state evidence that build-cli/
build-server are already dead from /xce-build's perspective and
build-server is already broken today) and the user's confirmed decision
to fully remove the Makefile rather than keep a compat wrapper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
2026-08-27 08:27:55 +00:00

9.2 KiB

Brief: eliminate-frontend-makefile

Problem

src/frontend/Makefile and Meson's tools/go_build wrapper are two independent build systems for the same two Go binaries (apiserver, xcecli), each computing its own copy of the same version-fingerprint logic (commit_id/build_time/dirty_fingerprint). This is an already-realized, not theoretical, drift risk: the Makefile's independent fingerprint computation needed three adversarial review rounds to fix a shell exit-status bug during dirty-content-fingerprint task 4.3 (roadmap.md:82), and build-server — the Makefile's OWN apiserver build target — is independently confirmed currently broken (bug-1597, .wolf/cerebrum.md:48): a bare go build with no CGO_CFLAGS/CGO_LDFLAGS, failing outright with fatal error: client.h: No such file or directory. src/docs/deployment.md:243-247 already documents this exact failure as a "build gotcha" and tells developers to use /xce-build apiserver instead — i.e., the project's own docs already steer people away from the target that's supposed to be the Makefile's main value proposition.

Current State

  • src/frontend/Makefile (195 lines) has 5 targets: build-cli, build-server, test, test-backend, test-integration (+ test-all).
  • build-cli/build-server are each 2 lines of actual build logic; the surrounding ~130 lines exist entirely to independently re-derive version-fingerprint -ldflags, duplicating logic src/tools/xce-build.sh already owns.
  • Meson already builds both binaries today via tools/go_build (apiserver/meson.build's custom_target, xcecli/meson.build's equivalent) — confirmed working, lands in the per-profile build dir (e.g. build.dbg/frontend/apiserver/xce_apiserver).
  • /xce-build apiserver//xce-build all (xce-build.sh) already build via meson exclusively (meson compile ... apiserver xcecli, line 237) — the Makefile's build-cli/build-server are not in that path at all today.
  • xce-build.sh DOES still shell out to cd frontend && make test for running Go unit tests (lines 240, 287) — this is the one live automation dependency on the Makefile from the project's own canonical build tool.
  • No meson test() exists anywhere for the CGO-backed backend test suite (apiserver/meson.build has a build-only custom_target, zero test registrations) — make test-backend is the ONLY way to run these tests today.
  • One other live script (run-resource-verify.sh:350) checks for a binary at the Makefile's hardcoded /tmp/apiserver output path and prints a make build-server-referencing error if absent.
  • deploy-ha.sh used to hard-depend on the same /tmp/apiserver path; this was just fixed (this session, uncommitted) to prefer the meson build-dir path first, matching the pattern already used for xceadmin/worker/scheduler, falling back to /tmp/apiserver only if the meson one is absent.

Desired Outcome

src/frontend/Makefile is deleted. All Go builds for apiserver/xcecli happen exclusively via Meson (/xce-build apiserver//xce-build xcecli//xce-build all). Go test execution (unit + CGO backend + integration) is either wired into meson as real test() targets, or reduced to plain, documented go test/shell invocations with no Makefile indirection — matching the pattern xce-build.sh's own xcecli case (line 249) already uses today for xcecli's tests, bypassing Make entirely. No developer or script depends on a Makefile-specific fixed output path (/tmp/apiserver, /tmp/xce_static) after this lands.

Approach

Decision confirmed with user (2026-08-27): keep a single build system — Meson survives, src/frontend/Makefile is removed entirely, not kept as a thin/compat wrapper. No alternative approach was considered or offered; this was a direct instruction, not a selection among options.

Phased replacement, test-coverage-preserving order (see Boundary Candidates below for the split). Not a single mechanical deletion — the CGO backend test suite has no meson equivalent today, so that gap must be closed BEFORE the Makefile can be safely removed, or backend CGO regression coverage silently disappears.

Two sub-approaches were considered for the CGO backend test gap specifically:

  1. Add a meson test() wired with the same CGO env apiserver/meson.build's custom_target already derives (cgo_cflags/cgo_ldflags via the same apiserver_cgo_deps pkg-config loop, lines 20-38) — single source of truth, no duplicate derivation. Recommended.
  2. Keep a minimal, build-free shell script (not a Makefile) that just runs go test ./backend/... with hand-derived CGO flags — avoids touching apiserver/meson.build, but reintroduces exactly the duplicate-derivation risk this whole effort exists to eliminate.

Scope

  • In: deleting src/frontend/Makefile; migrating xce-build.sh's 2 make test call sites to direct go test invocations (mirroring the existing xcecli case); adding a meson test() (or equivalent) for the CGO backend suite so that coverage isn't lost; migrating test-integration's XCE_BIN/SRV_URL convention to point at the meson-built binary; updating the ~9 files with live-relevant doc references (tech.md, build-deployment.md, testing.md, structure.md, frontend/CLAUDE.md, src/docs/deployment.md, xce-deploy-ha/SKILL.md); updating run-resource-verify.sh's apiserver-binary discovery to the same dual-path pattern deploy-ha.sh now uses.
  • Out: rewriting historical spec docs (tasks.md/research.md/design.md under already-completed specs like ha-config-bootstrap, component-failover-adoption, etc.) that mention make test/make build-server as acceptance criteria for work already shipped — those are frozen records, not live automation, and editing them provides no value. Any change to the underlying version-fingerprint computation itself (xce-build.sh's own logic) — this effort only removes the SECOND, duplicate computation site, not the first.

Boundary Candidates

  • Seam 1 — Build targets (build-cli/build-server): already effectively dead from /xce-build's perspective; lowest risk, smallest diff. Can land independently of the other seams.
  • Seam 2 — Unit test target (test): 2 call sites in xce-build.sh, already has a proven direct-go test replacement pattern in the same file. Low risk.
  • Seam 3 — CGO backend test target (test-backend): needs a genuinely new meson test() registration (no existing equivalent) before the Makefile target can be removed without losing coverage. This is the one seam that's real net-new work, not just deletion — highest-effort seam.
  • Seam 4 — Integration test target (test-integration): depends on Seam 1 (needs a build-cli replacement first) plus its own XCE_BIN path update.
  • Seam 5 — Doc/script updates: mechanical once seams 1-4 land; the actual reference list is already enumerated (see this investigation's own findings).

Given all 5 seams touch the same small src/frontend/ + src/tools/xce-build.sh area, share one dependency graph (Seam 4 depends on Seam 1; nothing else cross-depends), and total scope is well under 20 tasks, this is a single spec, not a multi-spec decomposition — Path C.

Out of Boundary

  • Any change to apiserver/meson.build's existing CGO flag derivation logic itself (only reusing it for the new test() target, not modifying it).
  • Any change to xce-build.sh's version-fingerprint computation (the "source of truth" side of the duplication, not the Makefile side being removed).
  • Rewriting frozen historical spec documents.
  • The set -euo pipefail-causes-CGO-tests-to-be-structurally-skipped-in-all gap noted in component-failover-adoption/tasks.md:201 — real, adjacent, but a separate xce-build.sh control-flow bug, not something this removal effort should silently fix as a side effect.

Upstream / Downstream

  • Upstream: apiserver/meson.build's existing CGO dependency list (apiserver_cgo_deps) is the thing Seam 3's new test() target must reuse, not re-derive.
  • Downstream: deploy-ha.sh (already migrated this session), run-resource-verify.sh (needs the same dual-path treatment), any future skill/script that currently assumes /tmp/apiserver//tmp/xce_static as a fixed discovery path.

Existing Spec Touchpoints

  • Extends: none directly — this is genuinely new spec-shaped work, not an extension.
  • Adjacent: dirty-content-fingerprint (the spec whose task 4.3 review first surfaced the duplication risk this effort resolves — provenance only, not reopened); build-time-versioning (owns the version-fingerprint computation xce-build.sh is the single source of truth for, post this change).

Constraints

  • Must not reduce CGO backend test coverage at any point during the migration (Seam 3 must land before Seam 3's Makefile target is removed, not after).
  • Nix devShell already bundles the full C/Go/Python toolchain uniformly — there is no "avoid installing the C toolchain" argument for keeping a Make-only path, unlike projects where Go-only contributors might want to skip C dependencies.
  • go test -race is confirmed unusable in this ASAN-linked CGO environment (independently hit 3 times per component-failover-adoption/tasks.md:197) — any new test() wiring must not attempt to add -race.