How-to: incremental republish (rebuild only what moved)
Goal: understand and operate the F1 incremental rebuild — when a monitored workspace's poll loop sees a git change, it now rebuilds only the changed members and the members that depend on them, not the whole workspace. See the design in incremental-republish.md and the poll loop in running-as-a-server.md.
TL;DR
Nothing to configure. If you run a monitored multi-repo workspace under nornir-server, the poll loop already does this for you. When member util commits, only util and the members that consume util get reindexed; sibling members that don't depend on util are skipped.
How it decides
- The poll sweep fetches each member and records which ones'
HEADmoved (rep.changed). - The republish builds the cross-repo dep graph (
cargo metadata --no-deps, offline). - The affected set =
changed ∪ transitive dependentsis computed from that graph and used to scope the index rebuild.
Watch the server log to see which path ran:
nornir-monitor: myws changed [util] → republish
nornir-monitor: myws → incremental rebuild, affected [util, liba, libb, app]
vs. a full rebuild:
nornir-monitor: myws → full rebuild over all members
When you get a full rebuild instead
A full rebuild (scope = all members) is intentional and safe in these cases:
| situation | why full |
first nornir workspace add (fat mode) |
no prior state to diff |
| empty / wiped warehouse | no change-set; repopulate everything from git |
nornir workspace fetch --force |
a forced fetch means "rebuild all" |
cargo metadata failed (no dep graph) |
can't compute blast radius → rebuild all |
| single-member workspace | no cross-repo edges; the one member rebuilds |
To force a full rebuild on demand:
nornir workspace fetch <name> --force
Verifying it works
Run the inject-assert test that pins the affected-set logic:
cargo test --features server --lib monitor
# → monitor::tests::affected_set_is_changed_union_dependents_and_skips_unaffected ... ok
It feeds a diamond dep graph (app → liba → util, app → libb → util) and asserts that changing liba rebuilds {liba, app} while skipping libb and util, that changing the shared leaf util rebuilds everything, and that a changed member with no checkout is dropped from the scope.
Caveats
- The blast radius is computed from the cross-repo crate dependency graph. A member that depends on another only at runtime (not via
Cargo.toml) won't be picked up as a dependent — but that's also true of every other dep-graph-driven feature (release gating, regression trace). - The per-member knowledge scan was already incremental (HEAD-SHA idempotency); F1 adds incrementality to the code index rebuild specifically.