Extract the duplicated built_project/project_lock test fixture into a shared tests/common module #223

Closed
opened 2026-07-09 22:46:11 +02:00 by Brummel · 2 comments
Owner

Problem

built_project() and project_lock() are now byte-identical in three aura-cli
test binaries — crates/aura-cli/tests/cli_run.rs, tests/research_docs.rs, and
(a near-copy, built_fixture) tests/project_load.rs. The #218 cycle duplicated
rather than shared them, deliberately, to keep that bug fix's blast radius inside
cli_run.rs (a shared extraction would have touched two currently-green files).
Rule-of-three is now tripped.

Two coupled facts make the shared extraction the right follow-up:

  • The three binaries reset/write/assert the same git-adjacent store
    crates/aura-cli/tests/fixtures/demo-project/runs. cli_run.rs and
    research_docs.rs serialize their own threads via a per-binary project_lock
    Mutex; project_load.rs touches runs/ with NO lock.
  • The per-binary Mutex serializes threads within one process only. It gives zero
    cross-process serialization, so a process-per-test runner (cargo-nextest) would
    race the three binaries on the shared store. Under the project's cargo test
    (sequential test binaries) this is dormant; it is a scaling break point.

Direction (not prescriptive)

Extract built_project / project_lock (and the ScratchGuard / store-reset
helpers) into a shared crates/aura-cli/tests/common/mod.rs used by all three
binaries, giving the shared runs store one serialization home — folding the
rule-of-three and closing the cross-process race in one move. Consider instead
giving each binary an isolated per-binary fixture store to remove the coupling
entirely.

context: architect drift review at the #218 cycle close (dissolved-verb project
gate), 2026-07-09; classified [medium/debt] + [medium/latent].

## Problem `built_project()` and `project_lock()` are now byte-identical in three aura-cli test binaries — `crates/aura-cli/tests/cli_run.rs`, `tests/research_docs.rs`, and (a near-copy, `built_fixture`) `tests/project_load.rs`. The #218 cycle duplicated rather than shared them, deliberately, to keep that bug fix's blast radius inside `cli_run.rs` (a shared extraction would have touched two currently-green files). Rule-of-three is now tripped. Two coupled facts make the shared extraction the right follow-up: - The three binaries reset/write/assert the same git-adjacent store `crates/aura-cli/tests/fixtures/demo-project/runs`. `cli_run.rs` and `research_docs.rs` serialize their own threads via a per-binary `project_lock` Mutex; `project_load.rs` touches `runs/` with NO lock. - The per-binary Mutex serializes threads within one process only. It gives zero cross-process serialization, so a process-per-test runner (cargo-nextest) would race the three binaries on the shared store. Under the project's `cargo test` (sequential test binaries) this is dormant; it is a scaling break point. ## Direction (not prescriptive) Extract `built_project` / `project_lock` (and the `ScratchGuard` / store-reset helpers) into a shared `crates/aura-cli/tests/common/mod.rs` used by all three binaries, giving the shared `runs` store one serialization home — folding the rule-of-three and closing the cross-process race in one move. Consider instead giving each binary an isolated per-binary fixture store to remove the coupling entirely. context: architect drift review at the #218 cycle close (dissolved-verb project gate), 2026-07-09; classified [medium/debt] + [medium/latent].
Author
Owner

Decision (2026-07-11, autonomous run): the shared crates/aura-cli/tests/common/mod.rs extraction — with one correction to the framing in the issue body.

Correction: the body claims the shared extraction gives the store "one serialization home — folding the rule-of-three and closing the cross-process race in one move". The second half is wrong: a tests/common module compiles into each test binary separately, so its static Mutex is still per-process — three binaries under a process-per-test runner would still race on the shared tests/fixtures/demo-project/runs store. The extraction folds the duplication; the cross-process race stays a documented, dormant limitation (the project's cargo test --workspace runs test binaries sequentially).

Chosen: extract built_project/project_lock/ScratchPath/ScratchGuard into tests/common/mod.rs, consumed by all three binaries; project_load.rs's near-copy built_fixture unifies onto built_project. The module doc states plainly that the lock serializes threads within one process only.

Rejected (for now): per-binary isolated fixture stores — true cross-process isolation, but each binary would need its own copy of the demo-project crate (three fixture cargo builds) or a test-only runs-root override on the CLI surface; that cost buys insurance against a runner the project does not use. If a process-per-test runner (cargo-nextest) is ever adopted, per-binary stores become the real fix and this issue's analysis is the starting point.

Decision (2026-07-11, autonomous run): the shared `crates/aura-cli/tests/common/mod.rs` extraction — with one correction to the framing in the issue body. Correction: the body claims the shared extraction gives the store "one serialization home — folding the rule-of-three and closing the cross-process race in one move". The second half is wrong: a `tests/common` module compiles into each test binary separately, so its `static Mutex` is still per-process — three binaries under a process-per-test runner would still race on the shared `tests/fixtures/demo-project/runs` store. The extraction folds the duplication; the cross-process race stays a documented, dormant limitation (the project's `cargo test --workspace` runs test binaries sequentially). Chosen: extract `built_project`/`project_lock`/`ScratchPath`/`ScratchGuard` into `tests/common/mod.rs`, consumed by all three binaries; `project_load.rs`'s near-copy `built_fixture` unifies onto `built_project`. The module doc states plainly that the lock serializes threads within one process only. Rejected (for now): per-binary isolated fixture stores — true cross-process isolation, but each binary would need its own copy of the demo-project crate (three fixture `cargo build`s) or a test-only runs-root override on the CLI surface; that cost buys insurance against a runner the project does not use. If a process-per-test runner (cargo-nextest) is ever adopted, per-binary stores become the real fix and this issue's analysis is the starting point.
Author
Owner

Fresh evidence (2026-07-11) that the latent race is real under process-parallel runs: during an automated implementation pass on this tree, two concurrent cargo test -p aura-cli --test cli_run processes (an implementer and a tree-check agent overlapping) produced flaky failures in real-data-gated tests (walkforward_dissolves_through_the_campaign_path, mc_dissolves_through_the_campaign_path, generalize_distinct_invocations_persist_distinct_campaign_documents — a different subset per run), while every sequential run of the same suite on the same tree passes. Consistent with the per-process project_lock giving no cross-process serialization on the shared tests/fixtures/demo-project/runs store.

Note the boundary: per-binary isolated stores would NOT fix this variant (same binary, two processes); only per-process scratch stores or not running two cargo test processes concurrently on one tree does. The shared-module extraction decided in the decision comment stands — it folds the duplication and documents the lock's per-process scope; concurrent-process execution on one tree remains out of contract.

Fresh evidence (2026-07-11) that the latent race is real under process-parallel runs: during an automated implementation pass on this tree, two concurrent `cargo test -p aura-cli --test cli_run` processes (an implementer and a tree-check agent overlapping) produced flaky failures in real-data-gated tests (`walkforward_dissolves_through_the_campaign_path`, `mc_dissolves_through_the_campaign_path`, `generalize_distinct_invocations_persist_distinct_campaign_documents` — a different subset per run), while every sequential run of the same suite on the same tree passes. Consistent with the per-process `project_lock` giving no cross-process serialization on the shared `tests/fixtures/demo-project/runs` store. Note the boundary: per-binary isolated stores would NOT fix this variant (same binary, two processes); only per-process scratch stores or not running two `cargo test` processes concurrently on one tree does. The shared-module extraction decided in [the decision comment](issues/223#issuecomment-see-thread) stands — it folds the duplication and documents the lock's per-process scope; concurrent-process execution on one tree remains out of contract.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#223