Repository navigation
Description
Part of #194. A CI review on 9 October (develop at 8941d478) found new evidence about the compiler cache and seven speed paths that #194 does not yet record. #194 keeps ownership of everything it already lists. This issue adds only the new items, so the lane stays in one place.
Owner: not assigned (Anders triages). Task base and PR target: develop.
Current state: #311 owns the private compiler-cache startup repair and its review. Trusted remote write, warm read and cache-budget proof remain open here. Public PR #326 passed all 11 jobs on its first attempt in run 37973992785 (71m01s overall; macOS 65m23s). This remains a long-run baseline; the private cache repair has not been integrated and hosted time savings are still unproved. PR #326 owns local warning/scope consistency and the installed journey preparation window. The remaining speed items are measured follow-ups after the cache baseline; hosted documentation skips also depend on #317 input coverage.
Summary
A CI run takes 50–76 minutes. The macOS job sets the end time: 46–70 minutes, while every other job finishes by about 45 minutes. Two causes dominate:
- The shared Rust compiler cache stores nothing. Every job compiles about 1,800 Rust crates cold, on every event.
- The macOS job runs four long phases one after another: source-home build, model journey, two Runtime builds, and the update journey.
Fix the cache first; the other estimates depend on it.
Evidence
Runs measured: develop push 37902075974 (49m50s) and PR 37906858619 (76m08s), both on 9 October.
| Job | PR run | develop run |
|---|---|---|
| source-gate (all jobs wait for it) | 5.3 min | 3.8 min |
| source-home-macos | 70.2 min | 45.9 min |
| source-home-linux x86-64 / ARM64 | 33.5 / 31.9 min | 40.8 / 32.4 min |
| test-capsules | 26.1 min | 26.4 min |
| custody-harness-smoke | 23.8 min | 23.7 min |
| test-elastos | 20.6 min | 15.9 min |
macOS job steps (PR / develop): source-home 41.1 / 26.4 min, two Runtime versions 15.9 / 9.4 min, model journey 5.1 / 3.6 min, update journey 5.8 / 5.0 min. The same steps vary by 24 minutes between runs, which points to macos-14 runner speed (3 cores).
Compiler cache.
- Rust hit rates, the same in both runs:
- source-home-macos: 2 hits and 1,816 misses (0.11 %);
- source-home-linux x86-64: 4 hits and 1,720 misses (0.23 %).
- All cache error counters are 0, and "Average cache read hit" is 0.000 s. C/C++ hits are about 50 %, which matches repeated compiles in the job's private disk tier.
- The repository cache list (
GET /repos/Elacity/elastos-runtime/actions/caches) holds 34 entries using 8.9 GB of the 10 GB cap. None of them comes from sccache.lint,test-elastosandtest-capsulesuse the same action in single-level GHA mode and print no statistics; they add no sccache entry either. - The develop push is a writer:
CI_SAVE_CACHEis true (ci.yml:35) and the action setsREAD_WRITE(.github/actions/rust-compile-cache/action.yml:11). A writer runs, but no entry persists. - CI and tests: warm caches, fail fast, keep only what catches real bugs #194 (8 October, 18:56) expected the first PR after develop run 37828101157 to read a warm cache. Both runs above came after it and read nothing.
scripts/ci-rust-cache-smoke.pyproves local reuse and read-only GHA lookups in a fixture. It does not prove that a develop push stores remote entries (CI and tests: warm caches, fail fast, keep only what catches real bugs #194, finding 8).- About 4.8 GB of the cache sits in entries last read before 7 October, 03:05 UTC:
ubuntu-22.04-arm-ARM64-elastos-bd-source-home-linux-…2,561 MB;Linux-elastos-test-bd-…-50088228-…1,388 MB;Linux-elastos-bd-lint-…-50088228-…456 MB;- the
50088228capsules entry, themacOS-elastos-bd-…entry, twokubo-macOS-ARM64-…entries (one inrefs/pull/271/merge) andproviders-bd-target-….
Work
Each item is one PR. Item 1 comes first. Items 2–6 are independent of each other, and item 7 comes last.
1. The compiler cache stores and serves entries
Find why no sccache entry persists. Test these candidates in order:
- (a) The GHA backend's write path under cache service v2 (
ACTIONS_RESULTS_URL). - (b) The source-home multi-level chain
disk,ghawithSCCACHE_MULTILEVEL_WRITE_ERROR_POLICY=l0, which can hide level-1 write errors ("set job build directories" step insource-home-linuxandsource-home-macos). - (c) Eviction under the 10 GB cap.
Diagnose with one develop dispatch that sets SCCACHE_LOG=debug and SCCACHE_ERROR_LOG, and uploads the log as an artifact. Then list caches by the sccache- key prefix.
Remove the stale entries listed above. Agree a storage budget per cache family with Anders (#194, finding 8).
- A develop push stores sccache entries. Proof: the cache list after the run shows
sccache-*keys inrefs/heads/develop. - The next PR run shows a Rust hit rate of 70 % or more in
source-home-macosandsource-home-linux. Proof: the sccache statistics in the job summary. - Total cache use stays inside the agreed budget for three consecutive develop pushes, and current entries stay in the cache. Proof: the cache list after each push.
2. The macOS update hop runs as its own job
Today source-home-macos runs the source-home build, the model journey, "build two actual Runtime versions", fixture generation and the update journey in sequence. A separate update-hop-macos job needs a qualified source-home Runtime and support inputs as well as the pinned previous release: source-gate alone does not produce them. Choose a commit/tree-bound producer handoff or an independent build with qualified support. Both jobs use the same accepted source, toolchain and journey profile. Preserve exact N/N+1 stamps, the previous-release pin, refusal checks and Undo (#194, finding 6). Measure both the critical path and additional runner/artifact cost after the compiler-cache baseline is proved.
- The macOS critical path equals the longer of the two jobs. Proof: three PR runs.
- The hop job still proves install N, update to N+1, the refusals and Undo. Proof: its job summary.
- Anders adds the new job to the required checks. Branch protection is his setting.
3. Heavy jobs start without waiting for source-gate
Every heavy job waits for source-gate, which takes about 4–5 minutes. Starting builds earlier can reduce elapsed time and can spend runner minutes on candidates that fail the cheap gate. Keep the current dependency until measurements show that early start improves the agreed cost and latency goals. If adopted for pull requests, retain source-gate as a required check and prove cancellation at its first failure. Push and merge-group runs need their own cancellation evidence.
- On a PR, the heavy jobs start within one minute of the run. Proof: the job timeline.
- A failing
source-gatecancels the PR run. Proof: one deliberate test PR.
4. Capsule workspace throughput is measured and improved
The 25 capsule workspaces already share intermediates through the repository Cargo build directory. First measure Cargo startup, compilation, test execution and shared-directory lock wait. Batch compatible full-package selections within one workspace and identical profile/flags before adding concurrent Cargo processes. Separate capsule manifests require separate workspace calls. Compare a bounded worker count or matrix shards only when the measured bottleneck supports them. Keep warnings as errors, per-package counts, zero-test refusal, failure propagation and readable logs.
-
test-capsulesfinishes in 12 minutes or less. Proof: three runs. - A failing capsule still fails the job, and the log names the capsule. Proof: one deliberate test PR.
5. The custody image build uses prebuilt or cached Rust layers
The image prebuild takes 17 of the 24 minutes (ci.yml:432-457; deploy/custody-host/Dockerfile). Choose one approach:
- Option A: a
cargo-chefdependency layer, so dependency compilation survives source changes. - Option B: build the binaries on the runner with the compiler cache, and
COPYthem into the image.
Either way, pin FROM rust:1.91-bookworm (Dockerfile:21) by digest, as the ARM engine container already is.
- A warm prebuild takes 6 minutes or less. Proof: three runs.
- The base image is pinned by digest. Proof: the Dockerfile and a policy test.
6. test-elastos uses nextest
cargo test takes 12–16 minutes. #194 Part 2 already targets the two 3-minute tests and the 17-minute goal; this item adds process-level parallelism. Compare existing compatible Cargo batching with a pinned, checksummed cargo-nextest experiment. Adopt a new runner only after process isolation, CPU/memory limits and expected fixture failure behavior pass. Keep doctests with cargo test --doc and retain the exact case inventory. Test count equality alone does not prove equivalent behavior.
- The test count is equal before and after. Proof:
cargo nextest listagainstcargo test -- --list. -
test-elastosfinishes in 12 minutes or less. Proof: three runs.
7. Documentation-only PRs skip the heavy matrix safely
Safe documentation-only changes can use an in-job skip that still reports each required check. Markdown and documentation may also be embedded product or build inputs, so file extensions alone cannot qualify a skip. Implement the input-coverage work in #317 first. Then prove negative cases for embedded Markdown, installer/release inputs, product data and mixed changes. Preserve formatting and product-data gates. Public PR #326 narrows the local gate; the hosted matrix still needs this separate proof.
- A docs-only PR completes in 10 minutes or less. Proof: one test PR.
- The policy test refuses a skip filter that matches any non-documentation path. Proof: the test.
Lower priority
cancel-on-failureholds a runner for the whole PR run. A longer polling interval reduces API requests while the runner remains allocated. Runner-minute savings require a different cancellation design; keep write authority outside build jobs.- A larger macOS runner (
macos-14-xlarge) shortens items 1–2 further, at extra cost. This is Anders' budget decision.
Security and consistency rules for every item
- Only trusted producers write shared caches:
developandmainpushes, and the merge group if Anders enables it. PR runs read only (CI and tests: warm caches, fail fast, keep only what catches real bugs #194 Part 0). The cache credential stays with the cache process; a private security advisory linked from the remediation parent issue tracks this. - Shipped release builds stay hermetic:
release-package.ymlkeepsRUSTC_WRAPPER: ''. - Journey builds may use the CI journey profile (LTO off, 16 codegen units). Release acceptance uses the shipping artifacts (CI and tests: warm caches, fail fast, keep only what catches real bugs #194, finding 4).
- New tools (sccache, nextest, cargo-chef) are pinned and checksummed.
- The nine required check names stay the same, unless Anders changes branch protection in the same step.
- Measure three PR runs and three develop runs before and after each item. Record the median wall time and the macOS job time in CI and tests: warm caches, fail fast, keep only what catches real bugs #194.
Decision for Anders: one CI run per tree (merge queue)
Anders decided on 8 October to keep the merge queue off for now. This section records the current evidence for the next review of that decision.
developprotection:required_status_checks.strictisfalse,required_pull_request_reviewsis null, and the nine checks are required.main:strictistrueand reviews are required.- Ruleset "develop merge queue (CI and tests: warm caches, fail fast, keep only what catches real bugs #194)" is
disabled. scripts/release-publish.sh:55-75(checked_ci) now accepts a successfulmerge_grouprun for the exact package SHA, so the release gate is ready for queue evidence.- From 6 to 8 October, 13 of 26 develop push CI runs ended
cancelledand 13 succeeded (gh run list --workflow ci.yml --event push --branch develop --created 2026-10-06..2026-10-08). A cancelled develop run leaves its tree without the develop CI evidence thatpreparerequires. - Anders' 8 October measurement: about 1,545 of 5,622 job-minutes in 24 hours re-proved a tree that CI had already tested.
- Because
strictis false, two PRs that each pass against an older base can merge and breakdeveloptogether. Their combined tree is first tested on the develop push.
Decision requested: enable the queue with lighter PR runs (branch ci/one-run-per-tree, 63bedd01), or keep the current setup and record the accepted risk.
Target
These estimates need measurement:
- Today: 50–76 minutes.
- After item 1: about 30–40 minutes.
- After item 2: about 25–30 minutes.
- After item 3: about 20–25 minutes.
Items 4 and 5 then keep the Linux jobs below that line.
How to work on this (any person or agent)
- Read
AGENTS.mdfirst. Follow its rules for branches, reviews, push approval and the acceptance record. - Branch from current
developasfix/<slug>, one PR per item. Workflow changes conflict easily; check open PRs that editci.yml(for example CI and tests: warm caches, fail fast, keep only what catches real bugs #194's batches) before you start. - Line numbers refer to
develop8941d478. If lines moved, find the code by the quoted step or job name. - Local checks:
just ci-local-prepush. Workflow edits also needpython3 scripts/ci-release-policy-test.pyand the pinned actionlint. - Proof is CI evidence: link the run IDs and quote the job-summary numbers. Keep one acceptance record in this issue, as
AGENTS.mddescribes.
Activity
andersalm commentedon Oct 9, 2026
Merge queue stays off: trains merge one at a time and develop runs are never cancelled (ci.yml concurrency is per run on push). Order: the advisory's cache-credential fix first, then item 1 (prove a develop write and a warm PR read); items 2-7 are measured in #194. The OMP operator owns this.
andersalm commentedon Oct 9, 2026
The current cache failure has a concrete source cause. The cache action starts sccache from a shell after exporting the cache URL and token, but it omits the runner's cache-service-v2 flag. The pinned backend can then choose retired v1 endpoints. Develop run 37943218922 reports 941 cache write errors for 941 compilations in lint; the source-home multilevel checks obscure the remote failure. The existing smoke fixture supplies the v2 flag itself, so it does not reproduce production startup.
The private Group A candidate in #311 is being changed to start the daemon with the runner's complete cache environment and keep routine build-step environments free of the runtime credential. Focused fixtures will cover this startup boundary. Acceptance still needs a real trusted write followed by a separate warm read; local fixtures alone will not close item 1. The next speed measurements will use that corrected baseline.
andersalm commentedon Oct 9, 2026
A fresh source and timing check on develop
7184e044and run 37943218922 attempt 1 refines the next efficiency work.Item 5: custody Docker compilation is separate from the Runtime compiler-cache action. The pre-build took 13m43s and the smoke took 5m07s. The Dockerfile copies source before its Cargo builds and uses cache mounts. Docker's cache-mount documentation confirms that GHA layer export alone does not persist those mounts. Add trusted mount persistence or a reusable dependency layer, then measure a changed-source warm build. Preserve the smoke.
Item 7: #326 repairs local gate scope, but remote PR CI still needs safe documentation-only selection. Complete #317's input coverage first. Embedded documentation and product inputs must select their consumers, and every required check must report a result.
Item 2: the Mac job took 76m40s: source-home 50m01s, model journey 4m52s, two version builds 13m55s, and update hop 5m42s. A job split can remove part of the serial tail only if a qualified source/support producer feeds both consumers.
build-ci-hopconsumes source-home Runtime and support bytes, so a new job that needs only source-gate is insufficient. Preserve SHA/tree bindings, N/N+1 versions, previous-release pin, refusal and Undo proof. Measure added runner and artifact cost after the corrected cache baseline.Current develop already skips Mac packaging on ordinary PR/develop runs, separates Linux x86 from the ARM engine, and disables release LTO in journey builds. Keep those improvements. The cache startup correction remains in #311's private candidate; trusted remote-write and warm-read acceptance is still pending.
andersalm commentedon Oct 9, 2026
Batching follow-up from the current local source gate: separate work selection from Cargo process launch. The gate launches unit commands per package; different dependency-feature graphs can require additional compilation even when the same workspace has a qualified cache. Before adding process parallelism or a new runner, collect compatible full-package test targets and measure one workspace/profile/flags batch against the current launches. Keep module-filtered runs separate where their selectors differ. Acceptance must preserve a passing count for each selected package, zero-test refusal, all required unit targets and failure propagation.
This is a measured experiment to take after the compiler-cache baseline, with measured results as its acceptance gate. Record compilation time, test time and build-directory lock waits. Capsule workspaces have separate manifests; sharing their intermediates does not make simultaneous Cargo commands bypass the shared-directory lock.
andersalm commentedon Oct 9, 2026
A fresh public PR/comment check on 9 October confirms that the current timing evidence still needs careful comparison.
For batching, start with compatible packages in one workspace and profile. Measure compilation, execution and lock waits separately. Run new regressions first with explicit selected-test counts, then retain complete candidate acceptance. Each timed selector needs an exact intended test and a refusal when selection is empty.
Keep the current order: approved advisory integration and measured cache acceptance; #317 input closure; the owner-led #225 timing repair; then qualified Mac handoffs, custody layers and review packages. The unchanged installer suite's128-second idle measurement and repeated transport matrix are recorded in #194.
andersalm commentedon Oct 13, 2026
Postponed to 0.8.1: CI cleanup/hardening; no workflow or deletion changes on release day.
andersalm commentedon Oct 19, 2026
CI state on 19 Oct, measured on source
3a043849e(analysis relayed by Anders). This replaces the older "the compiler cache stores nothing" diagnosis.3a043849egot a manual train dispatch at 08:05:19, develop CI at 08:05:32 and release-PR CI at 08:05:35. The manual run used about 316 job-minutes. Publication only accepts develop push or merge-group evidence.Plan (OMP, within the 0.8.0 batch approved on #93):
ci.yml:636-648,:751-754; 6266619339).andersalm commentedon Oct 19, 2026
OMP changed the push queue to skip unmarked train dispatches and accept a full-HEAD marker for the final candidate. Independent static reads match SHA-256 cbcd6c9057a10236ca0607468be2d56fe407787ca6c18754213f074642636b62; the replacement-worker receipt is OMP’s observation.
The marker records eligibility. Dispatch still resolves a branch name; a failed dispatch still removes the queue entry, while an unchanged re-enqueue exits through the already-pushed check. Bind the final alpha.25 run to its exact source, run and attempt, and retain a recovery path for a failed dispatch before claiming that coverage.
The final dispatch retains the distinct shipped-profile journeys and Browser helper builds. Current develop CI and package preparation remain separate evidence; this static check ran neither the queue nor CI.
andersalm commentedon Oct 19, 2026
The completed Hosted gate at
f37aa1219reports 1,691 passing cases; 49 verdicts from the ends of two unchanged JS files are absent compared withb5847af0e(1,740). The Claude review reconciles 42 product-data and 7 Browser metrics labels, with local file runs of 99 and 26 cases.Node #64833 reports the same
--test-force-exitpattern; fix #64875 remains open. This supports the reporting hypothesis; the reviewer could not reproduce this occurrence locally, so the remote pass count remains a lower bound.Keep the reporting repair in the After 0.8.0 CI lane: choose bounded process cleanup or complete-result accounting, and prove that both missing results and failed cases make the gate fail. Hosted source review PASS and installed Mac acceptance remain separate (#85).
andersalm commentedon Oct 19, 2026
The installed test tools now take and hold the current remote check lock before teardown. The completed
opslease1source review passed; its probes used copies and contacted no real boxes.Independent installed SHA-256 checks match
elastos-remote-check(f1bc351a8bc5eae08b81ed93f95b55eb6e939d4b77deb729be8fa80d36628adf) andelastos-remote-free(e2334c8559841313200dbeb0cb2b7821830fac54752143a4091eebbbec5120b3). Elapsed-time limits now use monotonic time.These source changes close the recorded ownership and clock limits. The active train gate loaded the earlier tools; a real run of the new tools and current candidate acceptance remain unproven.
andersalm commentedon Oct 20, 2026
OMP correction for the remote-check slot ownership findings (Codex root, 19 Oct; local ops tools, not repo code):
elastos-remote-checktakes~/.local/share/elastos-ops/slot-N.lock(flock) before it picks a box and holds it to exit. A second check on the same slot is refused ("slot N is in use by another check on this Mac").@@BUSY: a check that finds the box held by another check keeps the box ("kept: another check holds it").elastos-remote-free SLOT: takes the same local lease, then a holder on the box takes the box's check lock and keeps it until the box is destroyed, so nothing can start between the probe and the deletion.fcdb1f651.