From 5d17aa4290eb8dfa424cc8e3b81afbe97a92b40f Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 11 Jul 2026 20:38:56 -0700 Subject: [PATCH] Use a cold profile for hosted Bevy codegen. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retain the same linked build and test surface while removing interactive optimization, debug-symbol, and incremental-cache work that made fresh Spindle runners exceed their deadline. 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta Code --- .tangled/workflows/check-bevy-build.yml | 8 ++-- .tangled/workflows/check-bevy-test.yml | 8 ++-- Cargo.toml | 14 ++++++ tools/test_ci_workflows.py | 18 ++++++- .../log/2026-07-12-ci-cold-codegen-profile.md | 47 +++++++++++++++++++ wiki/log/DEVLOG.md | 5 ++ wiki/process/agent-scale.md | 27 +++++++---- wiki/process/workflows.md | 9 ++++ 8 files changed, 116 insertions(+), 20 deletions(-) create mode 100644 wiki/log/2026-07-12-ci-cold-codegen-profile.md diff --git a/.tangled/workflows/check-bevy-build.yml b/.tangled/workflows/check-bevy-build.yml index 3595b201..3ac5a26c 100644 --- a/.tangled/workflows/check-bevy-build.yml +++ b/.tangled/workflows/check-bevy-build.yml @@ -1,6 +1,6 @@ -# Bevy normal-build shard of the Rust definition-of-done wall. This remains -# separate from Bevy tests and Clippy so each cold Bevy compile fits inside -# Spindle's workflow deadline. +# Bevy linked-binary shard of the Rust definition-of-done wall. The ci profile +# keeps the same target and features while removing the local interactive +# profile's expensive cold optimization/debug codegen. when: - event: ["push"] @@ -62,7 +62,7 @@ steps: set -euo pipefail . /tangled/workspace/setup-pc.sh log=/tangled/workspace/bevy-build.log - if cargo build -p misaligned-bevy --quiet > "$log" 2>&1; then + if cargo build --profile ci -p misaligned-bevy --quiet > "$log" 2>&1; then echo "bevy build: OK" else echo "=== bevy build FAILED ===" diff --git a/.tangled/workflows/check-bevy-test.yml b/.tangled/workflows/check-bevy-test.yml index e2b9b42f..329e85f9 100644 --- a/.tangled/workflows/check-bevy-test.yml +++ b/.tangled/workflows/check-bevy-test.yml @@ -1,6 +1,6 @@ -# Bevy test shard of the Rust definition-of-done wall. This remains separate -# from Bevy Clippy and the normal binary build so each cold Bevy compile fits -# inside Spindle's workflow deadline. +# Bevy test shard of the Rust definition-of-done wall. The ci profile keeps +# the same targets, features, assertions, and overflow checks while removing +# the local interactive profile's expensive cold optimization/debug codegen. when: - event: ["push"] @@ -62,7 +62,7 @@ steps: set -euo pipefail . /tangled/workspace/setup-pc.sh log=/tangled/workspace/cargo-test-bevy.log - if cargo test -p misaligned-bevy -p misaligned-assets --quiet > "$log" 2>&1; then + if cargo test --profile ci -p misaligned-bevy -p misaligned-assets --quiet > "$log" 2>&1; then echo "cargo test (bevy + assets): OK" else echo "=== cargo test (bevy + assets) FAILED ===" diff --git a/Cargo.toml b/Cargo.toml index 9a1dc959..f57b4d86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,3 +31,17 @@ opt-level = 1 [profile.dev.package."*"] opt-level = 3 + +# Hosted CI starts from a cold target directory. The optimized dependency +# profile above is useful for interactive Bevy runs, but makes fresh codegen +# and linking exceed Spindle's workflow deadline. CI still builds and tests +# the same targets/features with debug assertions and overflow checks enabled; +# it only omits optimization, debug symbols, and incremental-cache overhead. +[profile.ci] +inherits = "dev" +opt-level = 0 +debug = 0 +incremental = false + +[profile.ci.package."*"] +opt-level = 0 diff --git a/tools/test_ci_workflows.py b/tools/test_ci_workflows.py index 098e7774..cdd0cf42 100755 --- a/tools/test_ci_workflows.py +++ b/tools/test_ci_workflows.py @@ -23,6 +23,7 @@ CHECK = RUST_SHARDS["core"] CORPUS = (WORKFLOWS / "corpus.yml").read_text(encoding="utf-8") SPEC = (WORKFLOWS / "spec-check.yml").read_text(encoding="utf-8") PKG_CONFIG = (ROOT / "tools/ci-pkg-config.sh").read_text(encoding="utf-8") +CARGO = (ROOT / "Cargo.toml").read_text(encoding="utf-8") def require(haystack: str, needle: str, contract: str) -> None: @@ -101,10 +102,23 @@ def main() -> int: if "cargo test --workspace" in CHECK: raise AssertionError("check.yml restored the deadline-consuming workspace test") + ci_profile = CARGO.split("[profile.ci]", 1)[1].split( + '[profile.ci.package."*"]', 1 + )[0] + for setting in ( + 'inherits = "dev"', + "opt-level = 0", + "debug = 0", + "incremental = false", + ): + require(ci_profile, setting, "cold hosted CI profile") + ci_dependencies = CARGO.split('[profile.ci.package."*"]', 1)[1] + require(ci_dependencies, "opt-level = 0", "cold hosted dependency profile") + bevy_commands = { - "bevy tests": "cargo test -p misaligned-bevy -p misaligned-assets --quiet", + "bevy tests": "cargo test --profile ci -p misaligned-bevy -p misaligned-assets --quiet", "bevy clippy": "cargo clippy -p misaligned-bevy -p misaligned-assets --all-targets", - "bevy build": "cargo build -p misaligned-bevy", + "bevy build": "cargo build --profile ci -p misaligned-bevy", } for shard, cargo_command in bevy_commands.items(): workflow = RUST_SHARDS[shard] diff --git a/wiki/log/2026-07-12-ci-cold-codegen-profile.md b/wiki/log/2026-07-12-ci-cold-codegen-profile.md new file mode 100644 index 00000000..83a71cf1 --- /dev/null +++ b/wiki/log/2026-07-12-ci-cold-codegen-profile.md @@ -0,0 +1,47 @@ +# CI cold-codegen profile + +``` +Type: log +``` + +## Intent + +Observe the first timeout-sharded Rust wall through hosted completion and +repair the remaining deadline failure rather than assuming that one Cargo +command per workflow was sufficient. + +## Finding + +Source `99dd3e33` proved the topology split but falsified its timing premise. +Hosted `check.yml` passed in 3 minutes 49 seconds and +`check-bevy-clippy.yml` passed in 5 minutes 39 seconds. The linked-codegen +workflows did not: `check-bevy-build.yml` was cancelled after 27 minutes +41 seconds and `check-bevy-test.yml` after 28 minutes 14 seconds. Corpus, +site, and design-amendment workflows remained green. + +The difference isolates code generation rather than dependency resolution, +parsing, type checking, or linting. The ordinary development profile optimizes +all Bevy dependencies at level 3 for playable local runs and emits debug +information. That is appropriate once a local target is warm, but it makes +fresh hosted builds spend the deadline optimizing and linking artifacts that +CI never runs interactively. + +## Repair + +Add an explicit Cargo `ci` profile that inherits development semantics while +setting workspace and dependency optimization to zero, omitting debug symbols, +and disabling incremental compilation. The Bevy test and linked-binary shards +select that profile. They still compile the same packages, targets, features, +test harnesses, debug assertions, and overflow checks; the repair changes only +cold artifact-generation cost. Bevy Clippy keeps its already-green all-target +command and ordinary profile. + +`tools/test_ci_workflows.py` pins the profile settings and requires both +linked-codegen shards to select it, preventing the local interactive profile +from silently returning to hosted cold builds. + +**Defense:** [agent-scale.md](../process/agent-scale.md) requires every hosted +proof to finish inside an independent workflow deadline. A dedicated +cold-start profile preserves the proof surface while removing optimization, +debug-symbol, and incremental-cache work that has no evidentiary value in a +fresh disposable runner. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index b5ca7a04..15e30ada 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -56,6 +56,11 @@ add or amend a session log, then re-run the generator. - Intent: Audit every Tangled workflow as an executable system: trigger semantics, changed-file coverage, package availability, step ordering, and whether the advertised gates actually execute the behavior they claim to protect. - Log: [wiki/log/2026-07-12-ci-correctness-audit.md](2026-07-12-ci-correctness-audit.md) +## 2026-07-12 - CI cold-codegen profile + +- Intent: Observe the first timeout-sharded Rust wall through hosted completion and repair the remaining deadline failure rather than assuming that one Cargo command per workflow was sufficient. +- Log: [wiki/log/2026-07-12-ci-cold-codegen-profile.md](2026-07-12-ci-cold-codegen-profile.md) + ## 2026-07-12 - CI Clippy version compatibility - Intent: Follow the repaired Tangled Rust wall through its first real execution and repair any failure proven by the hosted environment rather than inferred from local green checks. diff --git a/wiki/process/agent-scale.md b/wiki/process/agent-scale.md index b3e032dc..91be3179 100644 --- a/wiki/process/agent-scale.md +++ b/wiki/process/agent-scale.md @@ -167,11 +167,18 @@ all four shards. Tangled has no scheduled trigger, so the manual trigger is the supported full safety run instead of pretending a scheduler exists. Each Bevy shard establishes identical Linux `pkg-config` shims through -`tools/ci-pkg-config.sh` before its one expensive Cargo command. The local hook -and server-side design gate call one `tools/design_amendment_gate.sh`; the local -path reads binding page types from the staged snapshot, and both paths treat -source deletions as source changes. Workflow fixtures pin the shard inventory, -ordering, dependencies, path filters, commands, and shared-policy contracts. +`tools/ci-pkg-config.sh` before its one expensive Cargo command. Linked Bevy +tests and the binary build use the explicit `ci` Cargo profile: the same +targets, features, debug assertions, and overflow checks as development, but +without the interactive profile's dependency optimization, debug symbols, or +incremental-cache overhead. This keeps cold code generation inside the hosted +deadline; Bevy Clippy continues to use the development profile because it does +not perform that linked codegen and is independently deadline-green. The local +hook and server-side design gate call one `tools/design_amendment_gate.sh`; the +local path reads binding page types from the staged snapshot, and both paths +treat source deletions as source changes. Workflow fixtures pin the shard +inventory, CI profile, ordering, dependencies, path filters, commands, and +shared-policy contracts. ### Acceptance criteria (slice B) @@ -186,16 +193,16 @@ ordering, dependencies, path filters, commands, and shared-policy contracts. work; non-Rust pushes skip the Rust wall, while pull-request/manual runs are full — HELD. 5. No hosted Rust workflow contains more than one cold Bevy Cargo command; - core/terminal and each Bevy proof complete in independently bounded shards - — HELD. + core/terminal and each Bevy proof complete in independently bounded shards, + with linked test/build codegen using the cold-start `ci` profile — HELD. **Defense:** the native ref-update path filter implements the proportional-gate contract without trusting a two-commit clone to describe an arbitrary push. The shared amendment gate implements the living-spec same-commit rule from the actual candidate tree (the index locally, checked-out commit in CI), while the -timeout-bounded Bevy shards, shared pkg-config setup, and executable scenarios -make the advertised Rust wall an honest product gate rather than a guaranteed -deadline/setup failure or syntax-only smoke. +timeout-bounded Bevy shards, cold-start profile, shared pkg-config setup, and +executable scenarios make the advertised Rust wall an honest product gate +rather than a guaranteed deadline/setup failure or syntax-only smoke. ## 3. Append-only ledgers and generated indexes diff --git a/wiki/process/workflows.md b/wiki/process/workflows.md index adb77a68..9b875050 100644 --- a/wiki/process/workflows.md +++ b/wiki/process/workflows.md @@ -208,6 +208,15 @@ tests, warning-clean all-target compilation, and a normal binary build. This preserves the complete wall without asking one cold Bevy compilation to leave enough of Spindle's workflow deadline for every later command. +The linked Bevy test and binary-build shards select Cargo's checked-in `ci` +profile. It inherits development semantics—including debug assertions and +overflow checks—but sets workspace and dependency optimization to zero, +omits debug symbols, and disables incremental compilation. The ordinary +development profile remains optimized for playable local Bevy runs; applying +that interactive profile to an empty hosted target made code generation alone +outlive the workflow deadline. Clippy remains on the development profile and +proves every target without linked codegen. + All four use Tangled's native push `paths` constraint over the knot's complete ref-update changed-file set, so only Rust-impacting pushes enter the wall; every pull request and manual invocation remains a conservative full safety -- 2.51.2