Repository navigation
Verification
This contract separates implementation evidence, mechanically enforced checks, and independent acceptance. Passing commands is necessary evidence; it does not replace review of the intended behavior, production path, or risks.
From the repository root, verify a branch and any local changes against its comparison base with:
./scripts/verify.sh changed origin/mainCI uses the equivalent ./scripts/verify.sh ci <pull-request-base-sha> command
contract. The hosted workflow first calls its audit and plan stages, then
runs the selected verification stages as separate parallel jobs. Calling ci
without a stage runs those same checks sequentially for local reproduction.
Both forms classify every changed path, and an unclassified path fails closed.
Documentation-only changes run the documentation profile; every other change
runs the baseline, and browser-affecting changes also run the release Trunk
build. Use ./scripts/verify.sh all to run the baseline and browser build
without changed-path optimization, or ./scripts/verify.sh classify <base> to
inspect the selected profiles.
Hosted native-build jobs refresh Ubuntu's ubuntu.sources package index only.
The required native libraries come from Ubuntu; third-party repositories bundled
with the runner image must not block their installation. APT signature and hash
verification remain enabled.
The required baseline is:
cargo fmt --all -- --check
cargo fmt --manifest-path apps/egui-mcp-inspector/Cargo.toml --all -- --check
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
cargo clippy --locked --manifest-path apps/egui-mcp-inspector/Cargo.toml --all-targets --all-features -- -D warnings
cargo test --locked --workspace --all-features --exclude labello-ui
cargo test --locked -p labello-ui --all-features
cargo check --locked --manifest-path apps/egui-mcp-inspector/Cargo.toml
cargo test --locked --manifest-path apps/egui-mcp-inspector/Cargo.toml --all-features
cargo check --locked -p labello-wasm --target wasm32-unknown-unknown
The workspace and labello-ui tests are disjoint so CI can run them in
parallel. The dedicated UI command uses all features, which keeps
inspector-presets coverage explicit without executing those tests twice.
Browser, shared-rendering, browser-persistence, browser-import,
deployment-asset, and relevant shared dependency changes additionally run,
from apps/labello-wasm:
trunk build --release --locked
CI preserves those test selections with pinned cargo-nextest 0.9.143 and a separate doctest job:
cargo nextest run --locked --workspace --all-features --exclude labello-ui
cargo nextest run --locked -p labello-ui --all-features
cargo test --locked --workspace --all-features --doc
The final Cargo command is intentionally retained because Nextest does not run
doctests on stable Rust. The local changed, baseline, and all commands use
ordinary cargo test, so contributors do not need cargo-nextest. The ci
command requires it and fails if the pinned prebuilt tool was not installed.
Every Cargo command that resolves dependencies and the Trunk build use locked mode. A stale tracked lockfile is therefore a failure and is never implicitly rewritten by verification.
Prerequisites are Python 3.10 or newer for documentation checks, Rust 1.98.0,
Cargo, rustfmt, Clippy, the
wasm32-unknown-unknown target, Trunk 0.21.14, and the native libraries required
by eframe. CI declares the applicable prerequisites per job in
.github/workflows/ci.yml, restores job-scoped dependency build artifacts for
the root or standalone-inspector target directory, downloads pinned prebuilt
Trunk and cargo-nextest binaries only where needed, and invokes this script
rather than duplicating verification commands. Job identity is part of each
cache key, preventing parallel jobs from racing to publish one immutable cache;
keys also include the Rust toolchain, Cargo manifests and lockfiles, and relevant
compiler environment. Caches therefore work across compatible hosted runners
without relying on machine reuse. The final Testing job fails closed unless
the plan and every selected parallel job succeeded, while requiring an
unselected conditional job to be skipped. The script's audit checks those
links, the PR evidence sections, shell syntax, diff whitespace, and complete
classification of tracked paths.
rust-toolchain.toml is the compiler source for local commands and CI bootstrap.
The root workspace and standalone inspector workspace both require Rust 1.98.
Every maintained package inherits that MSRV. Commands from either directory
resolve to the exact 1.98.0 compiler, including rustfmt, Clippy, and the WASM
target. Install the pinned prerequisites with:
rustup showRustup reads the repository toolchain file and installs the declared compiler, components, and target. Cargo manifests declare the MSRV for both workspaces. CI uses that toolchain to build and test the supported matrix below. Release images include the same compiler and build prerequisites. Keep these settings aligned when changing the baseline; there is no custom toolchain-policy audit.
| Workspace or target | Required locked compatibility evidence |
|---|---|
| Root, native host | All maintained members including server and deployment tool; all targets/features in Clippy and all features in tests, with separate UI and doctest coverage |
| Standalone inspector, native host | Its own lockfile; formatting, all-target/all-feature Clippy, compiler check, and all-feature tests |
Browser, wasm32-unknown-unknown
|
Production WASM app compiler check and release Trunk build with the root lockfile |
| Release, Linux x86-64 Debian Bookworm | Same baseline and browser build, then locked release server/deployment-tool builds inside the configured immutable image |
The inspector is a native application. Browser-only code is verified through
labello-wasm; inspector-only features do not imply browser support. Native GUI
and Chromium evidence retain the limits and risk-specific requirements below.
Dependency updates must pass this matrix with both tracked lockfiles on 1.98.0. Do not repair lockfiles during verification. An MSRV increase requires an explicit coordinated change to workspace policies, the toolchain pin, CI/release configuration and images, and current documentation. Optional checks on newer compilers do not replace this baseline. The external release image must be verified before rollout as described in deployment.
The script selects profiles conservatively from changed paths. The machine baseline is shared; the following checks are additional acceptance evidence. If a change crosses profiles, apply all of them.
Read ui-design-guidelines.md and
ui-ownership.md. Add the smallest egui_kittest regression
covering behavior, geometry, and AccessKit semantics. Exercise long content and
loading, empty, stale, failure, disabled, keyboard, focus, and overlay states
that the change can affect. Inspect applicable shared states at the viewport,
DPR, zoom, larger-text, and keyboard matrix in the UI guidelines. Native
inspector evidence proves shared egui behavior only; use Chromium for browser
layout, zoom, input, accessibility-tree, networking, cookie, or IndexedDB
claims. Shared-rendering changes require the locked release Trunk build.
For completion input, build the server and release browser distribution and use
the isolated Python environment from the browser input procedure.
Run python apps/labello-wasm/tests/completion_input.py --kind bounding_box and
repeat with --kind skeleton. Optional --width, --height, and --dpr select
the browser matrix. This creates disposable synthetic work and checks that
trusted repeated Space keydowns cannot complete successive images, while release
and repress can. It reports only browser settings and aggregate counts; shared
UI tests cover custom shortcuts, focused buttons, review, and migration.
For silent image navigation, run
python apps/labello-wasm/tests/silent_loading.py --kind bounding_box and repeat
with --kind skeleton, with and without --review. The procedure uses the same
private Python environment and disposable production server as the completion
check. It delays next/previous assignment requests and samples the retained
image in memory to detect dimmed or blank frames. --width, --height and
--dpr select the browser matrix; --zoom applies actual 200% Chrome tab zoom.
Optional --artifacts captures only the
application bars for review evidence. It does not prove migration-specific
transactions, failure recovery or absence of every possible spinner; shared UI
tests and native inspection cover those presentation states.
For Objects/Overview queues, run python apps/labello-wasm/tests/workflow_items.py --kind bounding_box and repeat with --kind skeleton. It uses disposable
production data to check cross-image Objects work, C → B → A → B → C history,
separate annotation Overview completion, focused review, review Overview submission
through the shortcut and visible action, and one streak unit per completed item.
Optional --artifacts
captures only the workflow selector. Storage tests cover multi-user handoff,
prelabel replacement, migration transactions, and exact score/replay invariants.
To measure navigation, build the release server and browser distribution, then
add --server target/release/labello-server --latency-budget-ms 500 to each
Objects/Overview command. This opt-in Chromium check clicks the visible Submit,
Approve and Previous buttons in annotation and review. Timing starts at pointer
release and ends after successful display validation, the new working-image
draw, an enabled primary action and the next animation frame. It fails if any
measured transition reaches the budget and checks that workflow requests start
before their dispatch frame finishes. The probe uses the fixture's fixed
1440 × 1000 viewport at DPR 1 and 100% zoom; pixels remain in browser memory.
It also checks item order and completion through the API. Terminal empty queues
are checked functionally and have no next-item latency sample. These local
synthetic measurements exclude startup and do not establish a production
network or hardware latency guarantee. Record larger-dataset and migration
measurements separately, including their readiness criteria. Include both fresh
forward work and history return while prefetch runs; warm history alone misses
queue contention. Repeat with --browser firefox when investigating Firefox or
Zen. Install Playwright Firefox in the same private environment and run with a
display, or the inspector guide's Xvfb setup and LIBGL_ALWAYS_SOFTWARE=1.
Record first-use samples separately from warmed operation, and report budget
failures rather than dropping them.
For working-preview decoder changes, run python apps/labello-wasm/tests/preview_decode.py --server target/release/labello-server
in Chromium and repeat with --browser firefox under the same display setup.
It loads the built production decoder module and checks asynchronous completion,
RGBA output, malformed input, mismatched dimensions and bitmap cleanup. Client
unit tests cover encoded-size, profile and header validation before allocation;
the workflow matrix exercises decoding through the production WASM app.
For native inspection, follow the inspector guide. It includes headless startup, MCP readiness checks, independent parallel instances, and evidence tied to the tested checkout. Headless execution does not remove the visual checks or replace the Chromium evidence above.
Read ui-ownership.md,
ui-design-guidelines.md, and the browser portions
of operations.md. Run the WASM compiler check and locked
release Trunk build. In Chromium, exercise startup plus the affected networking,
credentials, persistence, folder import, responsive layout, input, and failure
paths. Record browser version, viewport, DPR/zoom, accessibility inspection, and
unsupported coverage. Do not infer browser behavior from the native inspector.
For startup performance, build the server and release browser distribution,
then run cargo run --locked --release -p labello-deploy -- compress-browser apps/labello-wasm/dist. Use the isolated Python environment from the
browser input procedure to run
python apps/labello-wasm/tests/startup.py --browser chromium, then Firefox
with --browser firefox --headed under the documented Xvfb setup when needed.
The default benchmark uses five fresh contexts, 50 Mbps per static response
and 40 ms latency per request in one reused browser process. It carries only a
disposable session across contexts. The default --screen datasets measures
the first draw of the fixture's recommended-dataset button and verifies that
clicking it opens the dataset. The draw probe uses a fixed point inside that
button at the benchmark viewport, confirmed by an in-memory screenshot.
It fails when median navigation-to-dataset-list-draw time reaches 1000 ms.
Use --screen restored-image to carry a workspace preference and measure the
first draw of the restored synthetic image instead. Reports contain timings,
aggregate sizes and bounded request categories only. Optional --mbps,
--latency-ms, --runs, --dist and --budget-ms select a measurement profile.
This local network model does not prove production TLS, throughput, API latency
or user hardware; verify those after the authorized browser and Caddy rollout.
Pen-input changes also run the focused production-client checks in Stylus input. Record CDP-generated events separately from scripted DOM events. iPadOS Safari/Firefox support requires the named physical-device procedure; desktop WebKit is only adapter evidence.
Read architecture.md, persistence.md,
and any affected import or UI ownership contract. Cover validation and invalid
transitions, replay at every event boundary, current and supported legacy wire
decoding, schema compatibility, digest or provenance behavior, and negative
geometry/identifier bounds. A persisted-shape change also requires interrupted
migration and historical replay evidence across every affected artifact.
Read persistence.md, import.md, and
operations.md. Test the complete lock/reload/validate/
append/replay/cache-invalidate transaction, atomic publication, no-replace and
rollback behavior, cache rebuilding, restart and interruption recovery, limits,
duplicate and invalid input, and concurrent or stale-assignment races relevant
to the change. Import changes must cover parse, plan, build, verification,
publication, durable job recovery, provenance, and bounded-resource failures.
Read api.md, configuration.md, and
operations.md. Cover route and role matrices, exact
assignment ownership, authentication, OAuth state and flow cookies, CSRF,
credentialed CORS, request limits, untrusted-input conversion, safe public
errors, and failure responses. Inspect logs for the redaction contract: no
credentials, raw URLs or bodies, filenames or source paths, image content,
annotation geometry, review comments, or idempotency values. Test denied and
cross-dataset cases, not only the authorized path.
Run ./scripts/verify.sh docs. Review the changed content against current code
and tests, check every changed local link and anchor, run git diff --check, and
inspect the focused diff. Check affected behavior against its complete flow.
Documentation-only changes do not require the Rust baseline unless they exercise
generated contracts or examples. Run python3 scripts/docs.py check for local
links, anchors, metadata, and wiki publication coverage.
Infrastructure changes never receive the documentation-only optimization. They run the baseline, and dependency/workflow/script changes conservatively run the browser build as well. An unknown path has no profile: if the classifier cannot prove a surface irrelevant, verification fails instead of skipping it.
Release workflow, deploy workflow, deployment/, and tools/ changes use the
infrastructure profile. The baseline runs the Rust deployment transaction
tests. The audit also rejects SSH, sudo, package installation, and Python in
the deploy workflow and requires its pinned GitHub CLI checksum, local
verify-release/receive/status boundary, immutable-release check,
attestation signer, and flushed barrier documentation. Real guest systemd,
mount, Caddy, TLS, and GitHub environment tests remain manual rollout evidence.
The requested task determines which lifecycle stages the agent owns. These boundaries do not waive verification or independent acceptance:
| Request | Endpoint and owner |
|---|---|
| Analyze or review | Findings and evidence; no implementation or publication unless requested |
| Clean up or implement a change, then open a PR | Finish the authorized edits, verify, then publish a draft marked Awaiting CI |
| Package existing changes as a PR | Verify and publish the prepared scope as a draft marked Awaiting CI; report implementation blockers to the caller |
| Implement an existing issue end to end | Implement, verify, publish, fix CI failures, and complete the CI-gated Ready for review handoff |
| Ready a draft for review | Manage CI state and handoff metadata; return implementation failures to the implementation owner |
| Independently verify | Audit the requirements, final diff, and evidence; report an acceptance decision separately from implementation |
The repository skills implement these stages: package current changes, open a draft, implement an issue, ready for review, and independent verification. Finish edits authorized by the user before entering the packaging stage. Publication alone does not authorize CI management, assignments, or project transitions. A later request can extend that scope without repeating completed preparation when the verified revision and base remain unchanged.
For a PR without an issue, use the user's requirements as its acceptance contract and apply issue/project updates only to existing linked items. Do not create an issue to satisfy the handoff checklist. Merging, closing issues, and marking work accepted require user authorization as well as the gates below.
Before coordinating multiple issues or testing dependent PRs together, follow parallel development for worktree ownership and verification of the combined group. Each PR still needs its own required CI.
The pull-request template is the required proof bundle. It records:
- changed behavior or contract and the complete production ownership path;
- every acceptance criterion mapped to concrete evidence;
- regression protection and why it would fail before the fix;
- exact commands, outcomes, environment, and material limitations;
- required visual/browser states and artifacts;
- normative documentation reviewed or updated;
- unresolved risks and checks not performed; and
- preservation of unrelated worktree changes.
Every pull request with any visual change must include screenshots or recordings
in its Visual or browser evidence section when the draft is opened. This
includes changes to layout, styling, text, icons, and visible interaction states,
regardless of which files implement them. Apply this requirement when updating
an existing draft too.
Capture the affected states from the verified implementation. Show before and after for existing views where a comparison is available; for a new view, show the resulting view. Explain any unavailable before capture. Use a recording when motion or an interaction sequence cannot be demonstrated by still images. Caption each artifact with the change it demonstrates, state or scenario, viewport, DPR/zoom or native scale, tested revision, and whether it came from the native inspector or Chromium. Record any uncommitted diff at capture time and its resulting published commit. Refresh evidence when later edits change the depicted result.
Embed the captures or link directly to hosted artifacts that PR reviewers can
open. Local filesystem paths, inspection claims, test output, and accessibility
trees alone do not satisfy this requirement. Read back the published PR and
check that its evidence links resolve to the intended captures. If safe capture
or reviewer-accessible hosting is unavailable, report the blocker and leave
publication incomplete. Use Not applicable only when there is no visual change,
with a brief explanation; browser checks may still apply.
Use the inspection procedures and coverage limits in the UI and browser risk profiles above. Prepare captures using disposable, non-sensitive content and apply the artifact redaction requirements below before uploading. Keep evidence outside tracked and runtime dataset paths.
Artifacts and logs must follow operations.md: never upload
secrets, credentials, runtime datasets, raw request data, image bytes,
annotation geometry, review comments, uploaded filenames, or import paths.
After assembling the proof bundle and publishing a draft, the contributor leaves the change Awaiting CI. The required check must succeed for the pull request's exact current head SHA; a local run or success on an earlier head is not a substitute. A failed check returns the change to implementation, while a pending, missing, cancelled, or inaccessible check is recorded as not verified.
Within an authorized review handoff, only after exact-head CI success may the
change become Ready for review.
At that boundary, use the pull-request author as the accountable implementation
owner and assign the pull request and any linked issue to that user. Keep the
existing reviewer requests unchanged. Request review as a lifecycle transition
by moving project items to In review and reporting the change as Ready for
review. The agent does not add or remove requested reviewers.
An independent human or separately instructed verification agent then reconstructs the contract from the original issue, audits the final production diff and proof bundle, and tries to falsify each claim. High-risk review follows the complete applicable transaction, failure, recovery, authorization, compatibility, and redaction boundaries. Only after that review and all required checks pass may an issue be accepted or closed.
The CI pull-request workflow exposes descriptive parallel jobs behind the
required Testing status check. Its aggregate job is the stable branch
protection contract; the worker job names may evolve without changing that
contract. The workflow has read-only repository permissions and uploads no
artifacts. Repository administrators must configure a branch protection rule
or ruleset for main that:
- requires pull requests and at least one approving independent review;
- requires
Testingto pass on the current head; - blocks direct pushes and force pushes, including administrator bypass unless an audited emergency procedure explicitly applies; and
- requires conversations to be resolved before merge.
The workflow file cannot activate repository-hosted branch protection by itself. The rule must be enabled in GitHub before this contract is considered fully enforced; record that repository-setting check in rollout evidence.
Export changes require storage capture, source mutation, cancellation, publication failure, retention/restart, and archive integrity checks. API checks exercise unauthenticated, non-admin, CSRF, revoked-role, safe-error, HEAD, and streamed GET paths. UI checks additionally exercise real browser preflight, start, download, reload/history, cancellation and retry, including the documented viewport and keyboard matrix.
Generate both profiles through the production export service, extract them, and reimport through the production browser-folder protocol:
mkdir -p .worktrees/export-reader-artifacts
LABELLO_EXPORT_ROUND_TRIP_ARTIFACTS="$PWD/.worktrees/export-reader-artifacts" \
cargo test --locked -p labello-storage export::round_tripUse a new artifact directory for each run; the test refuses to overwrite
profile directories. It checks hashes, distinct classes with equal names,
object counts, normalized geometry at 1e-6, Visible/Occluded/Not present
states, keypoint names, empty coverage and train/val/test preservation. It
also asserts the documented loss of native identity/history and materialized
pose boxes. These fixtures are synthetic and contain no user data.
The reader check uses CPython 3.12, a private virtual environment, pinned Ultralytics 8.4.125 and CPU Torch 2.8.0/Torchvision 0.23.0. Dependency setup requires network access; the actual reader script refuses socket connections, uses a local repository font, constructs no model, and checks that production artifacts remain unchanged. Install into the private environment only:
python3.12 -m venv .worktrees/export-reader-venv
.worktrees/export-reader-venv/bin/python -m pip install \
--index-url https://download.pytorch.org/whl/cpu \
torch==2.8.0+cpu torchvision==0.23.0+cpu
.worktrees/export-reader-venv/bin/python -m pip install \
-r crates/labello-storage/tests/export-reader-requirements.txt
.worktrees/export-reader-venv/bin/python \
crates/labello-storage/tests/export_reader.py \
.worktrees/export-reader-artifacts \
--report .worktrees/export-reader-report.jsonThe dataset reader must report both production profiles, preserved image and object counts, zero network attempts, zero constructed models, and unchanged input artifacts. Empty-only validation/test fixtures can produce the reader's expected training warnings. This command validates dataset reading, not training or prediction. Keep the dependency freeze, exact interpreter and reader versions, command logs, archive hashes, and JSON report with acceptance evidence. The reader check supplements canonical verification; it does not replace it.
The opt-in Linux test tests::polling_performance::nine_client_polling_performance
uses the production Axum router with authenticated sessions, authorization, CSRF,
real storage transactions, and disposable synthetic metadata. It does not contact
production or use real user data. It creates 6,928 images with eight annotations
and eight versions per annotation, then warms statistics and presence. Nine
concurrent clients each perform five claim/submit/statistics/presence/availability
cycles. This is an accelerated contention workload, not a simulation of human
labeling speed. Image delivery, browser rendering, TLS and proxy latency are
outside this measurement; route handlers and response bodies are exercised.
This benchmark uses the image-assignment endpoint, not Objects/Overview item
display. Storage workflow regressions separately bound image-state and event-log
reads during warm item claims, display and submission in both annotation and review,
including claims after a prefix of finished images, and
check retained and unseen reservation release on departure.
cargo test --locked --release -p labello-api nine_client_polling_performance -- --ignored --nocaptureLABELLO_BENCH_IMAGES and LABELLO_BENCH_ROUNDS override the default image and
cycle counts. Use at least nine images per round. Output contains only aggregate
fixture size, workload counts, process CPU seconds, logical read bytes, process
peak RSS, wall time, and route mean/p95 microseconds. Peak RSS includes fixture
creation and warming. Logical reads include filesystem-cache hits and do not
measure physical disk throughput. The test requires Linux /proc and getconf.
For a before/after comparison, copy the same test module and its mod declaration
into an isolated checkout of the comparison commit. Build both release test
binaries, then run each on the same otherwise idle machine with identical
parameters. Record the base and changed SHAs, hardware, filesystem, Rust version,
and full aggregate output. Repeat when scheduling variance obscures claim or
submit latency. Keep fixtures out of commits; temporary data is removed when the
test finishes. A smoke run with 100 images and two rounds checks the procedure,
not the production-scale performance claim.
Edit documentation in the Labello repository. The wiki is generated from the current documentation; archived plans stay in the repository.
- Labello documentation
- Labello
- Getting started
- Product glossary
- Annotation and review
- Stylus input
- Dataset administration
- Model prelabels
- Dataset import
- Guided box-to-skeleton migration
- Dataset export
- Assignment
- Contribution scoring
- Current limitations