cache_bundle.json cannot be downloaded from R2; network/integrity failures are no longer treated as cache misses.concurrency so shared R2 keys do not race.EMBEDDINGS_OPENAI_API_KEY for embeddings metadata, related-tools generation, and OpenAI artifact embeddings.row.attributes.tool_slug) and cover it with a regression test.Recent scheduled runs of Build Embeddings Bundle (R2) were cancelled at the 3h timeout or failed after long rebuild attempts. The trigger was a transient R2 connection drop on the ~2.7 GiB cache_bundle.json download (IncompleteRead(...)). The old workflow masked that as a missing cache, rebuilt from partial/no prior state, and uploaded a much smaller bundle that poisoned later runs.
This PR hardens the whole read-transform-write loop: source bundle reads must be real, critical provider/cache/Thermos failures stop the run before canonical upload, and the previous canonical bundle is snapshotted before overwrite.
It also prevents accidental full metadata regeneration. Generated metadata/use cases are currently slug-delta driven: new slugs can generate, existing slugs must reuse cached generated data, and missing existing generated data fails loudly. A separate doc captures the future fingerprint-based invalidation design for intentionally regenerating changed tools.
cache-bundle is produced by build_bundle and consumed by downstream jobs instead of re-downloading from R2.list-objects-v2 rather than load-bearing stderr parsing.--from-scratch is removed from the canonical path. Future hash/fingerprint invalidation should replace slug-delta only in a separate PR.actionlint .github/workflows/embeddings_bundle_r2.yamlgit diff --checkbun test ./embeddings/src/pipeline/turbopuffer.test.tsbun test ./embeddings/src/utils/generate_related_tools.test.tsbun test ./embeddings/src/pipeline/tool_artifact_targets.test.ts ./embeddings/src/pipeline/turbopuffer.test.ts ./embeddings/src/utils/generate_related_tools.test.tsworkflow_dispatch against this branch with namespace=composio-tools-pr-23551-smoke, use_last_checked_sha=false, reconcile_redis_deletes=false.