Local Commands
Use these commands for normal development:cargo for normal repo work. When you need targeted Cargo commands,
use ./scripts/repo-cargo so output roots and multi-agent work stay isolated.
BuildBuddy Opt-In
SetMEERKAT_BUILDBUDDY=1 to route the same Make lanes through the BuildBuddy
backend:
BUILDBUDDY_DRY_RUN=1 with explicit BuildBuddy Make targets to inspect the
selected command without running it.
The explicit targets are make buildbuddy-build, make buildbuddy-check,
make buildbuddy-clippy, make buildbuddy-test,
make buildbuddy-test-unit, make buildbuddy-test-int,
make buildbuddy-e2e-fast, and make buildbuddy-e2e-system. The live-provider
targets are make buildbuddy-e2e-live and make buildbuddy-e2e-smoke when
credentials are configured.
The Make targets delegate through scripts/run-build-backend-lane; when
BuildBuddy is enabled, that switch calls scripts/buildbuddy-dev.
Test Lanes
The canonical e2e lane taxonomy lives in
tests/integration/src/e2e_lanes.rs. Scripts and BuildBuddy targets route to
that taxonomy rather than inventing separate lane names.
Public Live real-audio smoke
Turbo S scenario 98 remains the existinge2e_smoke_s98_gpt_live_public_playback_settlement_and_reopen selector:
gpt-live-1/OpenAI test, not a mock or a readiness
probe. It requires OPENAI_API_KEY (or RKAT_OPENAI_API_KEY) with Live
voice-session access, Node/npm, Chromium, and working provider WebRTC.
Missing credentials, refused transport, and absent speech fail the selected
test; none becomes a successful skip. The canonical lane installs the
browser prerequisites.
The existing browser peer sends checked-in synthetic WAV speech through a
WebAudio media track, never a microphone or user recording. Every checked
exchange requires new inbound RTP and measured non-silent decoded audio
(at least 100 ms) or non-silent WebAudio analyser windows. RTP energy is
diagnostic only; an absent browser statistic remains absent, never a measured
zero or successful audio evidence.
Signaling, transcript deltas, and provider completion events cannot satisfy
that evidence gate. Numeric GPT_LIVE_PUBLIC_AUDIO records report measured
audio. The scenario verifies exact close/reopen on the same durable session,
with a five-second exact-close ceiling and a 90-second open/reconnect ceiling,
spoken code-word recall after reopening, and real tool execution through the
feature-owned ExistingMember background-delegation policy. Generated
operation custody must identify the original member and report a completed
turn; its canonical history must contain a successful pwd result linked to
the exact shell tool call (zero exit, no timeout, and the actual project
directory), followed by a provider assistant answer. Error-only tool results
cannot satisfy this gate. No disposable fork is spawned. Its ordinary text model
and session identity remain unchanged. S98 calls ServiceMemberLiveHost’s
shared, exact-receipt lifecycle directly; S97 retains the RPC/durable-fork
vertical. After the initial delegation completes, S98 commits a later ordinary
background turn that changes the code word, then requires the unchanged live
channel to speak that new word using fresh measured audio. This is separate
from delivery of the initial delegation’s result.
The existing executor model defaults to gpt-5.6-sol; an operator
may select another available ordinary text model with
GPT_LIVE_E2E_EXECUTOR_MODEL without changing the Live channel’s gpt-live-1.
S98’s Bazel shard remains
//:e2e_smoke_turbo_s_s98; both backends use the same Rust catalog and test.
Scenario 99 is a separate opt-in paid acceptance scenario; S97/S98 retain their
existing selectors and behavior:
//:e2e_smoke_turbo_s_s99; it carries the same
public Live test binary and routes through the canonical Rust catalog.
S99 composes LiveContextSummaryPolicy with Concurrent bootstrap and an
externally gated, content-only summarizer held for at least 20 seconds. The
gate carries permission only: after release, a separate factory-built LLM
client summarizes the immutable source snapshot using its exact model/provider
and auth binding. No canned summary is used in paid acceptance. The caller
bounds this real call to 90 seconds and 1024 output tokens, disables caller
and provider-native tools, and requires measured input/output token usage.
S99 requires an exact-receipt Active owner, connected WebRTC, fresh provider
output transcript honestly lacking an unpredictable historical phrase, and
at least 100 ms of fresh decoded non-silent native voice before releasing
the summary. Analyser-only activity, RTP, silence, or transcript alone cannot
qualify S99. Checked-in synthetic WAVs are the only speech input; a zero-gain
oscillator keeps the media track and RTP alive between speech fixtures.
S99 selects ProviderManagedUnmeasured bookkeeping, with no output queue,
polling, publication receipt pump, or manual playback completion. Its required
binder publisher is a fail-closed guard against unexpected actionable playback
publication; the owner must settle internally without calling it. Provider
transcripts and decoded-audio assertions are evidence, never settlement
signals. S98 retains its separate caller-confirmed playback path.
While preparation remains Generating, an ordinary text update and a newer
spoken correction are admitted, and an existing-member delegation must complete
with the same successful pwd evidence as S98. After receipt-validated
ProviderAcknowledged, fresh marked spoken queries must recall the historical
phrase while retaining both newer facts over the old summary. Historical
thinking-context delivery requests no speech, but releasing its barrier can
legitimately release queued speakable work results. S99 neither suppresses
those results nor asserts full-duplex silence. Exact thinking-append/ACK
correlation and absence of fabricated user turns belong to deterministic
provider/owner tests with attribution. Further
close/reopen cycles attempt to release an obsolete job (or observe its
cancellation) while a replacement job remains gated: the replacement must
still report preparation and honestly lack the history until its own job is
released. All waits are bounded (20-minute inner
scenario, 25-minute catalog command). Missing auth is a failure, not a skip.
Compilation and deterministic catalog/audio-evidence tests are not evidence
that this paid scenario has passed; native-provider qualification requires
explicit execution of the selector above.
The dense Mob topology stress has a dedicated GitHub-hosted Linux workflow,
.github/workflows/mob-dense-topology.yml. Nightly calls it (its archive
build alone takes 13-17 minutes on a hosted runner, so it does not fit the
pull-request budget), and the diagnostic Cargo workflow also runs it from the
existing unit-test archive. The test owns a five-minute wire-materialization budget; its nextest
profile reports the named test every minute and terminates a whole-test stall
after eight minutes. The result is bounded to the hosted runner environment:
local macOS
and BuildBuddy runs are supplementary evidence, not latency predictions or
substitutes for this lane.
Architecture Gates
Machine and surface contracts have direct Make targets:make machine-verify is the bounded TLC lane used
for normal validation. Use make machine-verify-full only when you deliberately
need the unbounded verification set.
CI Shape
Pull-request CI is.github/workflows/ci.yml. It runs on pull requests,
pushes to main, and manual dispatches (a branch head runs once, through its
pull request), entirely with Cargo on GitHub-hosted ubuntu-latest runners
(4 vCPU), and it is sized to a 20-minute push-to-terminal budget. Compiled
objects are cached by sccache (content-addressed, shared by every lane and
readable from main by every pull request); rust-cache holds only the
registry, because per-lane target caches exceeded the repository’s 10 GB
cache limit in one pull request:
What runs where (pull_request is budgeted; push: main is not; nightly and
the release tag carry the rest):
Why the meerkat-mob chain is deferred: measured on 4-vCPU hosted runners,
every unit lane that ever exceeded the budget compiled
meerkat-mob’s 442k
lines, either as its own lane (16 min compile plus 4.5 min of tests) or as a
dependent crate rebuilding mob under its own feature unification (rkat, rpc:
17 min). The chain is computed from cargo metadata, and the classifier’s cost
model (1 + (lines + 8000 x dependency closure) / 35000 minutes, 16-minute
ceiling per pull-request unit lane) is asserted by the self-test for every
other crate. Clippy of a changed mob-chain crate still runs in the pull
request (12 min measured for mob itself). A red push: main run shows as a
failed CI gate check on the main commit and blocks the release gate
(require_ci_green needs a successful exact-main run).
The classifier fails closed. Any .rs, Cargo.toml, Cargo.lock,
.cargo/, nextest, toolchain, build-wrapper, or ci.yml change yields at
least one clippy lane and one unit lane; a Rust path that belongs to no
workspace package, a missing diff base, or any global build-configuration
path escalates to the whole workspace (packed into at most eight shards by
estimated build-and-link cost); a
classifier error fails the changes job and therefore the gate. The gate
asserts that clippy, unit, and closure-check all ran and succeeded for a
build-relevant change, and it fails when the classifier produced no lanes.
make ci-lanes-selftest (scripts/ci-cargo-lanes-selftest.mjs) pins these
properties with fixtures for a core touch, docs-only, Cargo.lock-only,
machine-authority-only, an unmapped .rs, and a missing base.
PR CI runs the directly changed packages, not their dependents: measured on
a 4-vCPU runner, compiling the reverse-dependency closure of meerkat-core
(44 of 50 crates) takes 15-18 minutes even when fanned out, which does not
fit the budget together with the local pre-push hook. Dependents are covered
by closure-check (compile only) in PR CI and by the full workspace lanes in
nightly and on the release tag.
The gate emits a schema-4 attestation for successful main pushes, binding
the repository, exact commit SHA, Git tree SHA, workflow run and attempt,
event, and ref. Its backend is github-hosted-cargo; plan records the
selected mode and counts, and component_results records every lane result.
PRs and failed runs emit no such attestation.
.github/workflows/cargo.yml remains a separate reusable/manual workflow with
its own Cargo lane gate; it is a diagnostic fallback, not the per-push job
graph.
CI Retry And Concurrency
Pull request CI uses one concurrency group per PR (pr-<number>) with
cancel-in-progress: true. Starting another PR-associated attempt in that
group automatically cancels the older in-progress attempt, even when nobody
issues an explicit cancel command. Pushes to main use one group per commit
(main-main-<sha>) with no cancellation, so back-to-back merges each
complete their run and emit their attestation. The
CI gate job runs under !cancelled(), so a superseded run surfaces as
cancelled rather than leaving a failed CI gate context on the head. The
reusable BuildBuddy workflow (nightly and release) serializes its shared
executor lifecycle with its own concurrency group; that group’s
cancel-in-progress is false.
Treat check-context precedence as part of retry recovery:
- Preserve the reviewed head commit when approvals or downstream evidence are bound to its exact bytes.
- Compare the active step and elapsed time with a successful exact-head run before classifying a slow job as hung.
- When a new PR-associated attempt is necessary, expect the automatic
cancellation. The recovery attempt must complete every selected lane and
reach the top-level
CI gate. - Inspect every check suite on the reviewed head, including
CI gate. Check the repository’s actual required-check settings rather than inferring them from workflow names (CI gateis the only required context today). A green shard or successful manual Cargo workflow is not proof that the active CI graph or a required context in another suite is green.
GHA Cargo / Cargo lane gate alongside CI gate; that is not the current
workflow inventory. In that observed recovery, auto-merge remained blocked
after the newest of three suites reported a successful CI gate; it fired
only after the last remaining suite reported that context successful. Treat
each suite that publishes a required context as independent recovery evidence, because neither
the newest nor the latest-completed result was observed to supersede the
others. In this recovery, gh pr checks reported pass while guarded merge
remained blocked, so an attempted merge that stays blocked is stronger evidence
than that flattened view.
Inspect the suite records directly when the rollup and merge policy disagree:
Nightly Lanes
Everything pull-request CI deliberately does not run executes daily and on demand (.github/workflows/nightly.yml) on GitHub-hosted runners:
- the full workspace unit lane (
make test-unit) and integration-fast lane (make test-int), covering every crate rather than the changed packages - the deterministic
e2e-fastlane - the 300-member/150-peer dense Mob topology stress
(
mob-dense-topology.yml) - bounded TLC machine verification (
make machine-verify) - the Python + TypeScript SDK suites, unconditionally
- clippy across all targets and all features for the whole workspace
- feature-matrix lint and tests, minimal-feature and surface-modularity tests
e2e-system, the full Web SDK and WASM browser contract suites, release packaging dry-runs, the security audit, and the MobKit docs mirror lag- the whole BuildBuddy/Bazel graph (
buildbuddy.ymlinfull-freshmode): prebuild, fmt/static, the native nextest lanes, governance (seam-inventory, rmat-audit, machine authority), SDK suites, wasm-check, minimal-feature, feature matrix, and audit
Release Validation
The tag release workflow requires successful exact-main CI for the release
commit and downloads that run’s schema-4 attestation (legacy schema 1-3
attestations are still accepted for older commits). It then runs the whole
BuildBuddy/Bazel graph in full-fresh mode (release_validate_buildbuddy_full)
as the release validation gate; the Cargo validation lane remains the
fallback for manual dispatches on the GitHub-hosted backend. It still builds
and publishes the platform-specific release artifacts from the attested
source; Windows binaries are cross-compiled and packaged with cargo-xwin
(clang-cl, lld-link, the Windows SDK) on a hosted Ubuntu runner, then
executed for verification on a windows-latest runner. Registry publication
remains GitHub-hosted.
The repository pre-push dispatcher follows the same identity rule. A complete
successful hook run writes a local Git-tree-keyed evidence stamp. A later push
of the identical tree, including its release tag, validates the pushed object
and checked-out HEAD identity and then reuses the complete gate result.
BuildBuddy remains an opt-in developer backend, the nightly full graph, and
the release-tag validation and Linux/macOS packaging backend.
.github/workflows/buildbuddy.yml is workflow_call-only; nightly.yml and
release.yml call it, ci.yml never does.
Doctor
Run:bb CLI, generated Bazel files, selector
behavior, lane isolation, and docs wiring without printing secrets.
Multi-Agent Work
Separate Git worktrees are already isolated by path hash. If multiple agents share one checkout, set a distinctRUST_LANE_ID per agent when you want stable
warm local output roots.
