Requirements: 6 requirement areas covering single build path, unit/ backend/integration test migration, binary discovery, and doc consistency. Design: 6 rounds of independent adversarial review to convergence (2 real technical bugs caught -- unresolved Meson placeholder tokens in CGO flags, invalid unquoted dict-literal keys -- plus a long tail of stale Makefile references across docs/scripts/ source comments, closed by a scope-rule restructure rather than continued line-by-line patching). Tasks: 4 major / 12 sub-tasks, task-graph sanity review passed after one repair round. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XYdtrEWWZfKRRGED7raEYg
15 KiB
15 KiB
Summary
- Feature:
eliminate-frontend-makefile - Discovery Scope: Extension (existing build system, light discovery — brief.md's own Path C investigation already covered most of the ground; this pass verified currency and filled architecture-level gaps)
- Key Findings:
- Only one live automated caller of
src/frontend/Makefileexists today:xce-build.sh's twocd frontend && make testcall sites (apiserverandallcases).build-cli/build-server/test-backend/test-integrationhave no live automated caller — they are developer-manual-only. apiserver/meson.buildalready computes the exact CGO flags (apiserver_cgo_deps: librtti, c-capnproto, openssl, tinylog, math, rt) the Makefile'stest-backendindependently re-derives via pkg-config. A shared derivation is directly reusable for a newtest()target — no new mechanism needed.xcecli's case inxce-build.shalready bypasses Make entirely (directgo testinvocation) — this is a live, working precedent for the apiserver unit-test migration, not a hypothetical pattern.run-resource-verify.shalready has an established$BUILD_DIR/<component>/<binary>discovery convention for its other three binaries (BINARY,SCHED_BIN,XT); onlyAPISERVER_BINis the odd one out still hardcoded to/tmp/apiserver.tests/regression/run.shis already a standalone, fully-parameterized script (XCE/URLenv vars). The Makefile'stest-integrationtarget added zero logic beyond an env-var rename (XCE_BIN→XCE,SRV_URL→URL) plus abuild-cliprerequisite. No new script is needed for Requirement 4 — only documentation of the direct invocation.
- Only one live automated caller of
Research Log
Live automation dependency surface
- Context: requirements.md's Boundary Context needed to state precisely what currently depends on the Makefile, to scope the coverage-preservation requirements accurately.
- Sources Consulted:
grep -rn --include="*.sh" -E '\bmake\b' src/tools/ .claude/skills/, direct read ofxce-build.shlines 255-328. - Findings: Exactly 2 live
makeinvocations exist in the whole repo's live automation (xce-build.sh:275,:322, bothcd frontend && make test).deploy-ha.shandrun-resource-verify.shreference the Makefile only in human-facing strings (error/log messages) or by checking for its output path, never by executingmake. - Implications: The coverage-preservation requirements (2, 3, 4) protect manual developer workflows and documentation accuracy, not any existing automated pipeline — this made scope smaller and safer than it might first appear, and confirmed as a direct answer to a user clarifying question during the requirements phase.
CGO backend test flag derivation reuse
- Context: requirements.md 3.2 requires the new backend test path to derive CGO flags from "the same single source" as Meson's existing apiserver build, not a second independent derivation (the exact failure mode this whole spec exists to eliminate).
- Sources Consulted:
apiserver/meson.build(full read),src/meson.build(go_compiler = find_program('go'),pkgconfig = find_program('pkg-config')),src/frontend/Makefile's owntest-backendrecipe (FRONTEND_CGO_PKGS := librtti c-capnproto openssl tinylog,-lm -lrt). - Findings:
apiserver/meson.build'sapiserver_cgo_depsloop already producescgo_cflags/cgo_ldflagscovering the identical dependency set the Makefile independently re-derives via pkg-config.go_compiler(the rawgoprogram object) is already available at top-level scope — no newfind_program()call needed. - Implications: A new
test()in the same file can read the samecgo_cflags/cgo_ldflagsvariables the existingcustom_targetalready computes — genuinely one derivation, not two, satisfying 3.2 directly rather than by convention/discipline.
run-resource-verify.sh's own established discovery pattern
- Context: requirements.md 5.1-5.3 needed a concrete replacement for
run-resource-verify.sh's/tmp/apiserverdefault. - Sources Consulted: full grep of
_BIN=/BUILD_DIRinrun-resource-verify.sh. - Findings:
BINARY,SCHED_BIN,XTalready resolve as"${ENV_VAR_OVERRIDE:-$BUILD_DIR/<component>/<binary>}", each independently overridable, with$BUILD_DIRdefaulting to$REPO/src/xce.build. OnlyAPISERVER_BINdeviates, hardcoded to/tmp/apiserverwith no$BUILD_DIR-relative default at all. - Implications: the correct fix is not "mirror
deploy-ha.sh's dual-path pattern" as brief.md's Downstream section literally suggested, but "match this script's own sibling convention exactly" — see Design Decision below.
Architecture Pattern Evaluation
| Option | Description | Strengths | Risks / Limitations | Notes |
|---|---|---|---|---|
Meson test() reusing apiserver_cgo_deps |
New backend test target shares the existing custom_target's CGO derivation |
Single source of truth (satisfies 3.2 directly); no wrapper script | Requires the derivation to be readable by both a custom_target and a test() in the same meson.build — confirmed straightforward, both are just Meson variables in scope |
Selected |
| Standalone shell script re-deriving CGO flags via pkg-config | Keep a Makefile-free script mirroring the Makefile's own test-backend pkg-config derivation |
Avoids touching apiserver/meson.build |
Reintroduces exactly the duplicate-derivation risk this spec exists to eliminate | Rejected (brief.md's own "not recommended" option 2) |
Design Decisions
Decision: run-resource-verify.sh's APISERVER_BIN follows its own sibling convention, not deploy-ha.sh's dual-path fallback
- Context: brief.md's Downstream section suggested mirroring
deploy-ha.sh's meson-first //tmp/apiserver-fallback pattern. - Alternatives Considered:
- Mirror
deploy-ha.sh's dual-path pattern (meson path first,/tmp/apiserverfallback). - Match
run-resource-verify.sh's own existingBINARY/SCHED_BIN/XTconvention (single$BUILD_DIR-relative default, no fallback).
- Mirror
- Selected Approach: Option 2.
- Rationale: once
src/frontend/Makefileis deleted, nothing in the project's own tooling will ever populate/tmp/apiserveragain — a fallback to it is a fallback to a path only a developer's own hand-rungo buildcould produce, which is not a real safety net worth the inconsistency of being the only binary in this script with different default-resolution logic than its three siblings. - Trade-offs: slightly diverges from the brief's literal suggestion, but produces a more internally consistent script and satisfies requirements.md 5.3 ("shall not require... as its only means") without needing a fallback at all, since the primary path is now proven reliable (Meson always builds apiserver via
/xce-build apiserver/all). - Follow-up:
deploy-ha.sh's own/tmp/apiserverfallback becomes similarly vestigial once the Makefile is gone — out of boundary for this spec (already migrated in a prior session per brief.md), but worth flagging as a small future cleanup, not a blocker here.
Decision: No wrapper script for the new backend test target
- Context: Meson
test()needs an executable;go testwith CGO env and a specific working directory could be wrapped in a small shell script for clarity. - Alternatives Considered:
- A thin wrapper shell script invoking
go testwith the right env, registered as thetest()'s executable. test()invokes thego_compilerprogram object directly, withargs,env, andworkdirkwargs.
- A thin wrapper shell script invoking
- Selected Approach: Option 2.
- Rationale: Meson's
test()natively supportsworkdirandenv; no wrapper is needed, and one fewer file avoids exactly the kind of incidental indirection this spec exists to remove elsewhere. - Trade-offs: revised after an independent adversarial review round (2026-09-03) caught a real one:
cgo_cflags/cgo_ldflagscontain literal@CURRENT_SOURCE_DIR@/@BUILD_ROOT@placeholder text that is normally resolved bytools/go_build's ownfix_envsed machinery — bypassinggo_buildmeans bypassing that resolution too. Fixed by resolving both tokens directly with Meson's own.replace()string method at configure time (cgo_cflags.replace('@CURRENT_SOURCE_DIR@', meson.current_source_dir()).replace('@BUILD_ROOT@', meson.project_build_root())) rather than reintroducing a wrapper script — still net simpler than Option 1, but not the zero-cost choice the first design pass assumed.
Decision: deploy-ha.sh's dead-target message strings are in boundary even though its discovery logic is not
- Context: the first design draft excluded
deploy-ha.shentirely as "already migrated in a prior session," reasoning from the binary-discovery logic (genuinely already meson-first). An independent adversarial review round caught that its threemake build-server//tmp/apiserver-referencingechostrings (lines ~157-164) were not part of that prior migration and would still tell a developer to run a target that no longer exists, oncesrc/frontend/Makefileis deleted. - Selected Approach: split the file's two concerns — discovery logic (out of boundary, unchanged) vs. message text (in boundary, added to File Structure Plan) — rather than treating "already touched once" as "fully out of scope."
- Follow-up: none needed beyond the File Structure Plan entry; this is a 2-string text edit, not a logic change.
Decision: status.md and apiserver-backend-tasks.md are live documentation, not historical spec records
- Context: requirements.md 6.3 exempts historical, already-completed spec documents from doc updates. An independent adversarial review round found two files outside
.kiro/specs/(src/frontend/docs/status.md:67,src/docs/apiserver-backend-tasks.md:70,120) statingmake test/make test-integrationas current fact — missed by the original brief's doc inventory, which only enumerated files already known to be live-authoritative. - Selected Approach: treat both as live documentation in scope for update, since 6.3's exemption is worded specifically around ".kiro/specs" historical records, not arbitrary status/changelog files elsewhere in the repo.
- Follow-up: added both to File Structure Plan.
Decision: doc-file File Structure Plan entries state a scope rule, not a closed line-number list
- Context: three successive independent adversarial review rounds each found at least one live
make-target/fixed-path reference in a file the design already had in scope, in a section/line the enumeration hadn't named (round 1: two new doc files entirely; round 2:xce-test-resources/SKILL.md,run.sh's error message; round 3:tech.md:81-82,testing.md:95,deploy-ha.sh:138-155's comment block,xce-deploy-ha/SKILL.md:294 — all in files already listed). A closed line-number enumeration kept being treated as if it were the completeness boundary, when it was really just a snapshot of what one investigation pass happened to find. - Selected Approach: reworded every doc/script File Structure Plan entry around a stated scope rule ("every live reference in this file," not just the enumerated lines) and moved the Testing Strategy's live-reference sweep to run per-file BEFORE Phase 4, not only repo-wide after — so a task implementing one file is verifiably complete against that file's own grep, independent of whether this design's own enumeration was exhaustive.
- Rationale: the recurring pattern strongly suggested the enumeration approach itself, not any individual miss, was the actual defect — fixing instances one at a time without changing the underlying acceptance criterion risked a fourth, fifth round finding the same class of gap indefinitely.
- Follow-up: a fourth review round found the sweep's own "zero hits" bar was itself unachievable as worded (several legitimate, deliberately-excluded classes — vendored files, dated historical records, an inert placeholder default, OpenWolf's own logs — all match the same grep). Named each exclusion class explicitly in the Testing Strategy rather than leaving "zero hits" ambiguous; also found two C testsuite files (
test_ha_bootstrap.c,test_ha_ctrlhello.c) with comments namingmake test-integrationby name, outside any doc/script file category considered so far — added to File Structure Plan (a 3-line rename, not a logic change). A fifth review round, specifically scanning.gosource-file comments (a category rounds 1-4 never checked), found two more: the ROOTCLAUDE.md's "Key Files" entry (line 42, the single most-visible live reference in the repo — loaded into every session, distinct from the already-coveredsrc/frontend/CLAUDE.md) and both Go modules'cmd/main.goldflags-injection comments naming the Makefile'sbuild-server/build-clitargets. Both added to File Structure Plan. The recurring lesson across rounds 1, 4, and 5: each round's "fresh eyes, no assumptions" instruction and switch to an unchecked file category (docs → scripts → C test comments → Go source comments) is what surfaces genuinely new gaps — re-reading the same already-covered files more carefully stopped finding anything past round 2.
Risks & Mitigations
- Risk: the new backend
test()silently links againstbackend/stub.go(the//go:build !cgofallback) instead of the real CGO path, producing a vacuous pass. Mitigation: Testing Strategy's "New capability verification" step deliberately breaksapiserver_cgo_depsand confirms the test fails for the expected linker reason before trusting a green run. - Risk: deleting the Makefile before all manual-developer-only targets (
test-backend,test-integration) have a proven equivalent silently drops coverage nobody notices until someone needs it. Mitigation: Migration Strategy's explicit Phase ordering (1-3 must land and be verified before Phase 4). - Risk:
run-resource-verify.sh's new discovery default assumes$BUILD_DIR($REPO/src/xce.build, theasanprofile dir) always contains a built apiserver — true only after/xce-build apiserver/allhas actually been run. Mitigation: this matches the existing behavior/risk profile of the script's other three binaries (BINARY/SCHED_BIN/XT), which already assume the same; no new risk class introduced.
References
.kiro/specs/eliminate-frontend-makefile/brief.md— original Path C discovery investigation (2026-08-27), the primary source for scope/seam decomposition.src/tools/xce-build.sh(lines 255-328) — live call-site evidence.src/frontend/apiserver/meson.build,src/meson.build— CGO derivation and program-object reuse evidence..claude/skills/xce-test-resources/run-resource-verify.sh(lines 200-207, 348-351) — existing sibling discovery convention.