Skip to content

ci: build the binary's tests, which nothing did - #67

Merged
myobie merged 1 commit into
mainfrom
fix/bin-tests-compile
Aug 24, 2026
Merged

ci: build the binary's tests, which nothing did#67
myobie merged 1 commit into
mainfrom
fix/bin-tests-compile

Conversation

@myobie

@myobie myobie commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

What this changes

cargo test does not compile on main today. The sync ls --json schema
test in src/main.rs builds a SyncEntryStatus literally, and #61 added a
sweep field to that struct without updating it. The bin test target fails with
E0063: missing field sweep.

Every check stayed green through all of it. The workflow runs --lib plus
three named integration targets, and never builds the binary's own tests.

So the defect is not the missing field. The defect is that a test could stop
compiling and CI could not tell you.

Fixing the compile error then exposed a real failure, which is the whole
point. sync_ls_json_schema_exposes_counts_and_drift pins the exact JSON of
fabric sync ls --json. #61 added sweep to that output. The test that exists
to catch a wire-schema change did not catch it, because it had not run since
before the change landed.

Two changes, together, because either one alone leaves the hole open:

  1. the schema expectation now carries sweep
  2. the workflow now runs cargo test --locked --bins

What was verified, and what was not

Platform: macOS 15 on arm64 (Silber). Linux is CI's to confirm, and this PR is
the first run that will actually build these tests there.

I watched the new check fail, in this order:

  1. cargo test --bins failed to compile — E0063: missing field sweep.
  2. With the field added, it failed again on the assertion: sweep: "disabled"
    present on the left, absent on the right.
  3. With the expectation updated, 12 bin tests pass.

I also confirmed the compile error pre-existed my work rather than assuming it:
I stashed my changes, ran cargo test on clean main, and reproduced the same
E0063 before restoring them.

Not verified: whether any other target is unbuilt by this workflow. I fixed
the one I tripped over and did not audit the rest.

`cargo test` did not compile on main. The `sync ls --json` schema test in
`src/main.rs` builds a `SyncEntryStatus` literally, and #61 added a
`sweep` field to that struct without updating it, so the bin test target
failed with E0063.

CI stayed green through all of it, because the workflow runs `--lib` and
three named integration targets and never builds the binary's own tests.

So the gap is not the missing field. The gap is that a test could stop
COMPILING and every check still passed.

FIXING THE COMPILE ERROR THEN EXPOSED A REAL FAILURE, which is the point.
`sync_ls_json_schema_exposes_counts_and_drift` pins the exact JSON of
`fabric sync ls --json`. #61 added `sweep` to that output. The test that
exists to catch a wire-schema change did not catch it, because it had not
run since before the change.

I WATCHED THE NEW CHECK FAIL. `cargo test --bins` failed on the compile
error, then failed again on the schema assertion with `sweep` present on
the left and absent on the right, then passed once the expectation
carried the field. That is the positive control, in this order, on this
machine.

Two changes, and they belong together because either alone leaves the
hole open: the expectation now carries `sweep`, and the workflow now runs
`cargo test --locked --bins`.

Verified on macOS 15 arm64. 12 bin tests pass. Linux is CI's to confirm.

Agent: Silber.fabric
@myobie
myobie merged commit 5ae4abd into main Aug 24, 2026
2 checks passed
@myobie
myobie deleted the fix/bin-tests-compile branch August 24, 2026 16:45
myobie added a commit that referenced this pull request Aug 24, 2026
Nathan says fabric uses too much CPU. Nobody can currently say which part
of a sync pass spends it, and three attributions were reported and
withdrawn in one evening because of that. Each guess cost more than
measuring would have. This adds the measurement.

TWO COUNTERS, AND THE FIRST ONE IS A BUG FIX AS MUCH AS AN INSTRUMENT.

`sync_passes` counts calls to `sync_once`. `full_scans` does NOT: it
counts TWO per call, because `sync_once` scans before the peer step and
again after. Reading `full_scans` as a pass rate doubles it, and dividing
a per-pass cost by it halves the answer. That is exactly how a guard
effectiveness figure of 58 percent was reported against the live fleet
and then withdrawn; the honest number was at most about 15 percent.

`scan_micros`, `materialize_micros`, `persist_micros` and
`reconcile_micros` are cumulative microseconds per phase. Cumulative, not
per-pass, so a reader takes two samples and divides. A total on its own
describes the past.

All of it is exposed through `fabric sync ls` and its `--json` form, next
to the counters already there.

WHY CUMULATIVE COUNTERS RATHER THAN LOG LINES. The existing observability
counters are read by sampling `fabric sync ls` twice, and a log line
would need a parser and a retention policy to answer the same question.

TESTS, AND I WATCHED BOTH FAIL.

`full_scans_counts_two_per_pass_and_sync_passes_counts_one` pins the 2:1
ratio as a property of the function. Mutated `sync_passes` to increment
by two: "left: 10, right: 5".

`phase_timers_follow_the_work_and_not_the_pass` pins that a phase timer
is wired to the work it names, not to the pass. Every pass scans; only a
changed pass writes. So `scan_micros` must keep rising while
`persist_micros` stays flat across no-op passes. Moved the persist timer
outside the guard that skips the write, and it failed.

Neither test mirrors the change. Both would fail if the timers were
attached to the wrong call sites.

THE NEW FIELDS BROKE THE `sync ls --json` SCHEMA TEST, AS THEY SHOULD.
That test only runs at all because #67 added `cargo test --bins` an hour
ago. Before that it did not compile and CI could not see it. This is the
first change it has caught.

WHAT THIS DOES NOT DO. It fixes no CPU. It makes the next fix aimable.
The walk is already known not to be the answer: the watched tree is
16.6 MB across 17,175 files, a full stat pass over it costs about 36 ms,
and one `sync_once` costs roughly 1.8 s.

Agent: Silber.fabric
myobie added a commit that referenced this pull request Aug 25, 2026
The adversarial delete matrix was added to `tests/folder_sync.rs` on
2026-08-25 and no step was added here, so the two tests that reproduce a
file-loss incident ran only on the author's laptop. CI stayed green
throughout and told nobody.

That is the SECOND time. #67 fixed the same shape for the binary's own
tests: `cargo test --locked --lib` plus a few named integration targets
means a whole file can be invisible, and the suite reports success while
the new tests never execute.

TWO CHANGES.

`--test folder_sync` now runs, so the guards against last night's loss
are checked by something other than me remembering.

And a step that FAILS when a `tests/*.rs` target is neither run above nor
named in the list of known gaps. Adding a test file and nothing else now
breaks the build, which is the point. Forgetting should be loud.

I RAN THE GUARD BOTH WAYS BEFORE SHIPPING IT. Against the current tree it
passes and prints what it accounted for. With a throwaway extra target in
`tests/` it fails and names it. A guard that cannot fail is decoration.

THE KNOWN GAPS ARE NAMED RATHER THAN HIDDEN: `lifecycle`,
`pathwatch_slice` and `shell` still do not run here. All three pass on
macOS locally and none has been verified on Linux CI, so I am not
switching them on in the same change that fixes the reporting. The list is
meant to get shorter.

Agent: Silber.fabric
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant