From 1fdd7cf7cc19df498eb7553ea72792093d4e93ce Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 15 Oct 2026 20:13:41 +0100 Subject: [PATCH 01/65] Rename the `delivery-server` submodule to `delivery` The repository was renamed on GitHub to `SpineEventEngine/delivery`, so the submodule's name, path, and URL now follow it. The `cascade` script, the dependency graph, the README, and the rollout docs use the new name. The Maven artifact is still `spine-delivery-server`, so the registry probe marker is unchanged. Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade.md | 4 ++-- .agents/tasks/toolbase-split-migration.md | 2 +- .gitmodules | 6 +++--- README.md | 12 ++++++------ cascade | 6 +++--- delivery-server => delivery | 0 docs/dependency-graph.md | 24 +++++++++++------------ docs/rollout/rebuild.md | 2 +- 8 files changed, 28 insertions(+), 28 deletions(-) rename delivery-server => delivery (100%) diff --git a/.agents/tasks/cascade.md b/.agents/tasks/cascade.md index 64c1a5b..60240d6 100644 --- a/.agents/tasks/cascade.md +++ b/.agents/tasks/cascade.md @@ -250,7 +250,7 @@ on-hold throttling task's cache/proxy phases before unattended cloud waves. 1. **Graph**: `cascade graph` output renders on GitHub, matches the known order (base-libraries → logging/testlib/base-types/change/time → tool-base/ProtoTap/ compiler → validation → core-jvm-compiler → core-jvm → jdbc-storage/gcloud-jvm/ - delivery-server; BuildSpeed verify-only); `graph --check` flags drift after a + delivery; BuildSpeed verify-only); `graph --check` flags drift after a hand-edited edge. 2. **Unit-level**: `plan --kind refresh` reads the graph and freezes edges; `plan --kind ripple --seed base-libraries@` scopes to the downstream closure only. @@ -365,7 +365,7 @@ and refuses to run on drift. 132-edge set stays canonical in a machine-readable ```edges block (each edge is a direct pin the wave advances, so none can be dropped from the data — only from the rendering). - * `delivery-server` publishes **only to GitHub Packages** (proprietary) — + * `delivery` publishes **only to GitHub Packages** (proprietary) — probes gained a per-repo registry field; reading GH Packages needs the `read:packages` token scope (playbook prerequisite; `plan` warns, ship hard-requires). diff --git a/.agents/tasks/toolbase-split-migration.md b/.agents/tasks/toolbase-split-migration.md index 4b32bc9..154d416 100644 --- a/.agents/tasks/toolbase-split-migration.md +++ b/.agents/tasks/toolbase-split-migration.md @@ -84,7 +84,7 @@ migrating: `core-java-1x` (2023-06-29), `model-tools` (2022-10-04). nothing from the artifact. The fix is to drop the entry, or replace it with the specific modules if the forced version still matters: -- [ ] `base-types` · `bootstrap` · `change` · `core-jvm` · `delivery-server` +- [ ] `base-types` · `bootstrap` · `change` · `core-jvm` · `delivery` - [ ] `dokka-tools` · `gcloud-jvm` · `jdbc-storage` · `logging` · `model-compiler` - [ ] `reflect` · `time` · `validation` · `web` diff --git a/.gitmodules b/.gitmodules index 6f34f85..f95103f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,9 +58,9 @@ [submodule "agents"] path = agents url = https://github.com/SpineEventEngine/agents.git -[submodule "delivery-server"] - path = delivery-server - url = https://github.com/SpineEventEngine/delivery-server.git +[submodule "delivery"] + path = delivery + url = https://github.com/SpineEventEngine/delivery.git [submodule "BuildSpeed"] path = BuildSpeed url = https://github.com/SpineEventEngine/BuildSpeed.git diff --git a/README.md b/README.md index 4d09e1c..8266d04 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,11 @@ does against the SDK repositories above. ### Storage & runtime -| Submodule | Role | -|--------------------------------------|--------------------------------------------------------------| -| [`jdbc-storage`][jdbc-storage] | Support for storage in JDBC-compliant databases | -| [`gcloud-jvm`][gcloud-jvm] | Support for Spine-based Kotlin and Java apps on Google Cloud | -| [`delivery-server`][delivery-server] | gRPC services providing sharded message delivery | +| Submodule | Role | +|--------------------------------|--------------------------------------------------------------| +| [`jdbc-storage`][jdbc-storage] | Support for storage in JDBC-compliant databases | +| [`gcloud-jvm`][gcloud-jvm] | Support for Spine-based Kotlin and Java apps on Google Cloud | +| [`delivery`][delivery] | gRPC services providing sharded message delivery | ### Benchmarks & documentation @@ -128,6 +128,6 @@ available skills are described in [`AGENTS.md`](AGENTS.md). [core-jvm]: https://github.com/SpineEventEngine/core-jvm [jdbc-storage]: https://github.com/SpineEventEngine/jdbc-storage [gcloud-jvm]: https://github.com/SpineEventEngine/gcloud-jvm -[delivery-server]: https://github.com/SpineEventEngine/delivery-server +[delivery]: https://github.com/SpineEventEngine/delivery [BuildSpeed]: https://github.com/SpineEventEngine/BuildSpeed [documentation]: https://github.com/SpineEventEngine/documentation diff --git a/cascade b/cascade index 2e7493f..aebd0a8 100755 --- a/cascade +++ b/cascade @@ -102,7 +102,7 @@ write_pin_constant() { # repos_all() { echo "base-libraries reflect logging testlib dokka-tools tool-base \ ProtoTap compiler validation core-jvm-compiler base-types change time money \ -core-jvm jdbc-storage gcloud-jvm delivery-server BuildSpeed" +core-jvm jdbc-storage gcloud-jvm delivery BuildSpeed" } # Position of a repo in the canonical order (1-based; 0 = unknown). @@ -186,7 +186,7 @@ repo_track_constants() { # marker-artifact: one definitely-published artifact used for registry probes. # class: library (full pipeline) | verify-only (no version/publishing steps). # registry: gcar (public europe-maven.pkg.dev) | github (GitHub Packages — -# delivery-server is proprietary and publishes only there; probes authenticate +# delivery is proprietary and publishes only there; probes authenticate # with `gh auth token`). repo_meta() { case "$1" in @@ -207,7 +207,7 @@ repo_meta() { core-jvm) echo "io/spine|spine-core|versionToPublish|library|gcar" ;; jdbc-storage) echo "io/spine|spine-rdbms|versionToPublish|library|gcar" ;; gcloud-jvm) echo "io/spine/gcloud|spine-datastore|versionToPublish|library|gcar" ;; - delivery-server) echo "io/spine/delivery|spine-delivery-server|versionToPublish|library|github" ;; + delivery) echo "io/spine/delivery|spine-delivery-server|versionToPublish|library|github" ;; BuildSpeed) echo "|||verify-only|" ;; *) echo "" ;; esac diff --git a/delivery-server b/delivery similarity index 100% rename from delivery-server rename to delivery diff --git a/docs/dependency-graph.md b/docs/dependency-graph.md index aba456b..20d0af4 100644 --- a/docs/dependency-graph.md +++ b/docs/dependency-graph.md @@ -58,7 +58,7 @@ consumed at runtime. 15. `core-jvm` 16. `jdbc-storage` 17. `gcloud-jvm` -18. `delivery-server` +18. `delivery` 19. `BuildSpeed` ## Documentation tooling @@ -93,7 +93,7 @@ flowchart BT core-jvm --> base-types core-jvm --> change validation --> compiler - delivery-server --> core-jvm + delivery --> core-jvm gcloud-jvm --> core-jvm jdbc-storage --> core-jvm BuildSpeed --> core-jvm-compiler @@ -125,12 +125,12 @@ flowchart BT time --> logging ProtoTap --> testlib base-types --> testlib - delivery-server --> testlib + delivery --> testlib gcloud-jvm --> testlib money --> testlib time --> testlib validation --> testlib - delivery-server --> time + delivery --> time ``` @@ -191,7 +191,7 @@ of the literal in the repository's `version.gradle.kts`. | `core-jvm` | library | gcar : `io.spine:spine-core` | `versionToPublish` | | `jdbc-storage` | library | gcar : `io.spine:spine-rdbms` | `versionToPublish` | | `gcloud-jvm` | library | gcar : `io.spine.gcloud:spine-datastore` | `versionToPublish` | -| `delivery-server` | library | github : `io.spine.delivery:spine-delivery-server` | `versionToPublish` | +| `delivery` | library | github : `io.spine.delivery:spine-delivery-server` | `versionToPublish` | | `BuildSpeed` | verify-only | — | — | `documentation` is not on the graph: it is the documentation area of the @@ -271,13 +271,13 @@ core-jvm-compiler testlib core-jvm-compiler time core-jvm-compiler tool-base core-jvm-compiler validation -delivery-server compiler -delivery-server core-jvm -delivery-server core-jvm-compiler -delivery-server logging -delivery-server testlib -delivery-server time -delivery-server validation +delivery compiler +delivery core-jvm +delivery core-jvm-compiler +delivery logging +delivery testlib +delivery time +delivery validation dokka-tools base-libraries gcloud-jvm base-libraries gcloud-jvm base-types diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 186653d..171d2eb 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -34,7 +34,7 @@ Wave kinds: set it to the JDK 17 path directly, or use your distribution's alternatives mechanism. - `gh auth status` shows a token with `repo` + `workflow` scope, plus - `read:packages` — `delivery-server` publishes to GitHub Packages, and + `read:packages` — `delivery` publishes to GitHub Packages, and `ship` and `close` cannot verify its artifacts without that scope. - Builds run **strictly sequentially** — never start a second Gradle build while a wave build runs. Maven Central consumption blocks (HTTP 429) are machine-wide From df7fbef5fc1ddcfd5f5f0957dc414ebacbfcf1cc Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 15 Oct 2026 20:13:42 +0100 Subject: [PATCH 02/65] Check out `config` at the recorded commit before `./config/pull` `prep` pulls the consumer's base branch, which moves the recorded `config` pointer but not its checkout, so the tree looked dirty and `prep` stopped. A repository whose `config` submodule was never initialized passed for one that does not consume `config` and silently skipped the pull. `prep` now runs `git submodule update --init -- config` right after branching. Co-Authored-By: Claude Opus 5.5 --- cascade | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cascade b/cascade index aebd0a8..aac68e8 100755 --- a/cascade +++ b/cascade @@ -1220,6 +1220,13 @@ cmd_prep() { git switch -q -c "$branch" 2>/dev/null || git switch -q "$branch" fi + # Check `config` out at the commit the branch records: `git pull` moves the + # recorded pointer but not the checkout (a false "not clean" below), and an + # uninitialized one would pass for a repo that does not consume `config`. + if git config -f .gitmodules --get submodule.config.path >/dev/null 2>&1; then + git submodule update --init --quiet -- config + fi + # ./config/pull — commit only what it actually changed. A repo that does not # consume `config` (its own hand-written buildSrc, no `config` submodule) has # nothing to pull; skipping keeps it a wave participant instead of a hard error. From 0e45e7da3e69d609221b30dd875c66e0d738c5fb Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 15 Oct 2026 20:15:58 +0100 Subject: [PATCH 03/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 558 +++++++++++++++++++++ .agents/tasks/cascade-refresh-a0cbbbf.md | 38 ++ 2 files changed, 596 insertions(+) create mode 100644 .agents/tasks/cascade-refresh-a0cbbbf.json create mode 100644 .agents/tasks/cascade-refresh-a0cbbbf.md diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json new file mode 100644 index 0000000..53ddd7b --- /dev/null +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -0,0 +1,558 @@ +{ + "schema": 1, + "wave": "cascade-refresh-a0cbbbf", + "kind": "refresh", + "created": "2026-10-15T19:00:56Z", + "base": "master", + "config_sha": "a0cbbbfe66c12475224563439fb6deb3da71ba58", + "seed": null, + "target": null, + "branch": "cascade-refresh-a0cbbbf", + "halted": null, + "order": [ + "base-libraries", + "reflect", + "logging", + "testlib", + "dokka-tools", + "tool-base", + "ProtoTap", + "compiler", + "validation", + "core-jvm-compiler", + "base-types", + "change", + "time", + "money", + "core-jvm", + "jdbc-storage", + "gcloud-jvm", + "delivery", + "BuildSpeed" + ], + "repos": { + "base-libraries": { + "upstreams": [], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-base" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.461", + "pin_vector": {}, + "adapt_rounds": 1, + "built": { + "head": "1634e4c5eb47649831b0666717ec81610f77c9f6", + "at": "2026-10-15T19:09:34Z" + }, + "pr": { + "url": "https://github.com/SpineEventEngine/base-libraries/pull/967", + "head": "1634e4c5eb47649831b0666717ec81610f77c9f6" + }, + "parked": null + }, + "reflect": { + "upstreams": [], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-reflect" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.202", + "pin_vector": {}, + "adapt_rounds": 0, + "built": { + "head": "23d55db7a207c0df47ae5abf584d7cd2a89e75e8", + "at": "2026-10-15T19:10:08Z" + }, + "pr": null, + "parked": null + }, + "logging": { + "upstreams": [ + "base-libraries", + "reflect" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-logging" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.426", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "reflect": "2.0.0-SNAPSHOT.202" + }, + "adapt_rounds": 0, + "built": { + "head": "79766b3c73d9c11ed13b1081a084d87bc21b12a7", + "at": "2026-10-15T19:11:03Z" + }, + "pr": null, + "parked": null + }, + "testlib": { + "upstreams": [ + "logging" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "base-testlib" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.215", + "pin_vector": { + "logging": "2.0.0-SNAPSHOT.426" + }, + "adapt_rounds": 0, + "built": { + "head": "835b21d4587c265b49abb0f63ae4552f75175215", + "at": "2026-10-15T19:11:35Z" + }, + "pr": null, + "parked": null + }, + "dokka-tools": { + "upstreams": [ + "base-libraries" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "dokka-extensions" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.11", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461" + }, + "adapt_rounds": 0, + "built": { + "head": "880762b8ff3472c17e02d3441c5d239d30da8825", + "at": "2026-10-15T19:12:18Z" + }, + "pr": null, + "parked": null + }, + "tool-base": { + "upstreams": [ + "base-libraries", + "logging", + "testlib" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "jvm-tools" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.426", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "logging": "2.0.0-SNAPSHOT.426", + "testlib": "2.0.0-SNAPSHOT.215" + }, + "adapt_rounds": 0, + "built": { + "head": "b1071b8b25e87619031f011350887bd949c0875a", + "at": "2026-10-15T19:14:48Z" + }, + "pr": null, + "parked": null + }, + "ProtoTap": { + "upstreams": [ + "base-libraries", + "logging", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "prototap-gradle-plugin" + }, + "state": "bumped", + "target_version": "0.17.3", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "logging": "2.0.0-SNAPSHOT.426", + "testlib": "2.0.0-SNAPSHOT.215", + "tool-base": "2.0.0-SNAPSHOT.426" + }, + "adapt_rounds": 1, + "built": null, + "pr": null, + "parked": null + }, + "compiler": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "logging", + "reflect", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "compilerVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "compiler-jvm" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.070", + "pin_vector": { + "ProtoTap": "0.17.3", + "base-libraries": "2.0.0-SNAPSHOT.461", + "logging": "2.0.0-SNAPSHOT.426", + "reflect": "2.0.0-SNAPSHOT.202", + "testlib": "2.0.0-SNAPSHOT.215", + "tool-base": "2.0.0-SNAPSHOT.426" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "validation": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "logging", + "reflect", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "validationVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "validation-java" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.465", + "pin_vector": { + "ProtoTap": "0.17.3", + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "logging": "2.0.0-SNAPSHOT.426", + "reflect": "2.0.0-SNAPSHOT.202", + "testlib": "2.0.0-SNAPSHOT.215", + "tool-base": "2.0.0-SNAPSHOT.426" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "core-jvm-compiler": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "logging", + "reflect", + "testlib", + "tool-base", + "validation" + ], + "class": "library", + "version_property": "coreJvmCompilerVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "core-jvm-gradle-plugin" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.098", + "pin_vector": { + "ProtoTap": "0.17.3", + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "logging": "2.0.0-SNAPSHOT.426", + "reflect": "2.0.0-SNAPSHOT.202", + "testlib": "2.0.0-SNAPSHOT.215", + "tool-base": "2.0.0-SNAPSHOT.426", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "base-types": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-base-types" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.226", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "testlib": "2.0.0-SNAPSHOT.215", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "change": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-change" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.209", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "time": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "core-jvm-compiler", + "logging", + "testlib", + "tool-base", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-time" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.252", + "pin_vector": { + "ProtoTap": "0.17.3", + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "logging": "2.0.0-SNAPSHOT.426", + "testlib": "2.0.0-SNAPSHOT.215", + "tool-base": "2.0.0-SNAPSHOT.426", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "money": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-money" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.13", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "testlib": "2.0.0-SNAPSHOT.215", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "core-jvm": { + "upstreams": [ + "base-libraries", + "base-types", + "change", + "core-jvm-compiler", + "logging", + "reflect", + "testlib", + "time", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-core" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.571", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "base-types": "2.0.0-SNAPSHOT.226", + "change": "2.0.0-SNAPSHOT.209", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "logging": "2.0.0-SNAPSHOT.426", + "reflect": "2.0.0-SNAPSHOT.202", + "testlib": "2.0.0-SNAPSHOT.215", + "time": "2.0.0-SNAPSHOT.252", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "jdbc-storage": { + "upstreams": [ + "core-jvm", + "core-jvm-compiler", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-rdbms" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.131", + "pin_vector": { + "core-jvm": "2.0.0-SNAPSHOT.571", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "gcloud-jvm": { + "upstreams": [ + "base-libraries", + "base-types", + "compiler", + "core-jvm", + "core-jvm-compiler", + "logging", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/gcloud", + "artifact": "spine-datastore" + }, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.241", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.461", + "base-types": "2.0.0-SNAPSHOT.226", + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm": "2.0.0-SNAPSHOT.571", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "logging": "2.0.0-SNAPSHOT.426", + "testlib": "2.0.0-SNAPSHOT.215", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "delivery": { + "upstreams": [ + "compiler", + "core-jvm", + "core-jvm-compiler", + "logging", + "testlib", + "time", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/delivery", + "artifact": "spine-delivery-server" + }, + "state": "bumped", + "target_version": "0.24.1", + "pin_vector": { + "compiler": "2.0.0-SNAPSHOT.070", + "core-jvm": "2.0.0-SNAPSHOT.571", + "core-jvm-compiler": "2.0.0-SNAPSHOT.098", + "logging": "2.0.0-SNAPSHOT.426", + "testlib": "2.0.0-SNAPSHOT.215", + "time": "2.0.0-SNAPSHOT.252", + "validation": "2.0.0-SNAPSHOT.465" + }, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "BuildSpeed": { + "upstreams": [ + "core-jvm-compiler" + ], + "class": "verify-only", + "version_property": "", + "probe": { + "group_path": "", + "artifact": "" + }, + "state": "parked", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": "verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish" + } + }, + "excluded": {}, + "closing_pr": null +} diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/cascade-refresh-a0cbbbf.md new file mode 100644 index 0000000..616f1af --- /dev/null +++ b/.agents/tasks/cascade-refresh-a0cbbbf.md @@ -0,0 +1,38 @@ +--- +slug: cascade-refresh-a0cbbbf +branch: cascade-refresh-a0cbbbf +owner: cascade +status: in-progress +started: 2026-10-15 +--- + +# Wave `cascade-refresh-a0cbbbf` (refresh) + +Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). Park reasons and decisions land here. + +## Repos + +- [ ] base-libraries +- [ ] reflect +- [ ] logging +- [ ] testlib +- [ ] dokka-tools +- [ ] tool-base +- [ ] ProtoTap +- [ ] compiler +- [ ] validation +- [ ] core-jvm-compiler +- [ ] base-types +- [ ] change +- [ ] time +- [ ] money +- [ ] core-jvm +- [ ] jdbc-storage +- [ ] gcloud-jvm +- [ ] delivery +- [ ] BuildSpeed + +## Log + +- 2026-10-15 — wave planned. +- 2026-10-15 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish From 949f2d5afac1b7940922a7139ee5825c769df21f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 15 Oct 2026 20:16:15 +0100 Subject: [PATCH 04/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 53ddd7b..324b3a3 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -69,7 +69,10 @@ "head": "23d55db7a207c0df47ae5abf584d7cd2a89e75e8", "at": "2026-10-15T19:10:08Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/reflect/pull/15", + "head": "23d55db7a207c0df47ae5abf584d7cd2a89e75e8" + }, "parked": null }, "logging": { From 64f8326fd52c5115e2d519c699f8d1db3b80f28c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 15 Oct 2026 21:13:44 +0100 Subject: [PATCH 05/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 48 ++++++++++++++-------- .agents/tasks/cascade-refresh-a0cbbbf.md | 1 + 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 324b3a3..66964e2 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -39,7 +39,7 @@ "group_path": "io/spine", "artifact": "spine-base" }, - "state": "bumped", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.461", "pin_vector": {}, "adapt_rounds": 1, @@ -61,7 +61,7 @@ "group_path": "io/spine", "artifact": "spine-reflect" }, - "state": "bumped", + "state": "pr-open", "target_version": "2.0.0-SNAPSHOT.202", "pin_vector": {}, "adapt_rounds": 0, @@ -86,7 +86,7 @@ "group_path": "io/spine", "artifact": "spine-logging" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.426", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -110,7 +110,7 @@ "group_path": "io/spine/tools", "artifact": "base-testlib" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.215", "pin_vector": { "logging": "2.0.0-SNAPSHOT.426" @@ -133,7 +133,7 @@ "group_path": "io/spine/tools", "artifact": "dokka-extensions" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.11", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461" @@ -143,7 +143,10 @@ "head": "880762b8ff3472c17e02d3441c5d239d30da8825", "at": "2026-10-15T19:12:18Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/dokka-tools/pull/12", + "head": "880762b8ff3472c17e02d3441c5d239d30da8825" + }, "parked": null }, "tool-base": { @@ -158,7 +161,7 @@ "group_path": "io/spine/tools", "artifact": "jvm-tools" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.426", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -186,7 +189,7 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "bumped", + "state": "pr-ready", "target_version": "0.17.3", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -195,7 +198,10 @@ "tool-base": "2.0.0-SNAPSHOT.426" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "91eaaaad39c33ec1b0e6c61dcaf7a036a261c01d", + "at": "2026-10-15T19:21:02Z" + }, "pr": null, "parked": null }, @@ -214,7 +220,7 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.070", "pin_vector": { "ProtoTap": "0.17.3", @@ -224,8 +230,11 @@ "testlib": "2.0.0-SNAPSHOT.215", "tool-base": "2.0.0-SNAPSHOT.426" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "005cfa4be7bd78734885b8dad4a4466e28116c03", + "at": "2026-10-15T19:50:24Z" + }, "pr": null, "parked": null }, @@ -245,7 +254,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", @@ -256,8 +265,11 @@ "testlib": "2.0.0-SNAPSHOT.215", "tool-base": "2.0.0-SNAPSHOT.426" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "d5b98ece3ce0602eacc74626a0da15912404f942", + "at": "2026-10-15T19:53:41Z" + }, "pr": null, "parked": null }, @@ -278,7 +290,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "bumped", + "state": "parked", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", @@ -290,10 +302,10 @@ "tool-base": "2.0.0-SNAPSHOT.426", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, + "adapt_rounds": 2, "built": null, "pr": null, - "parked": null + "parked": "awaiting owner decision: 5 tests in tests/entity-queries (EntityQueryBuilderTest) assert FieldMask behavior that base-libraries#964 made a deprecated no-op ('Please remove the call'); deleting them was blocked as test removal" }, "base-types": { "upstreams": [ diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/cascade-refresh-a0cbbbf.md index 616f1af..c6d1dcc 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.md +++ b/.agents/tasks/cascade-refresh-a0cbbbf.md @@ -36,3 +36,4 @@ Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). P - 2026-10-15 — wave planned. - 2026-10-15 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish +- 2026-10-15 — **parked** `core-jvm-compiler`: awaiting owner decision: 5 tests in tests/entity-queries (EntityQueryBuilderTest) assert FieldMask behavior that base-libraries#964 made a deprecated no-op ('Please remove the call'); deleting them was blocked as test removal From d8afacc6d0f1a9e416504ba7c3b14899995c37ed Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 16:10:34 +0100 Subject: [PATCH 06/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 58 ++++++++++++++-------- .agents/tasks/cascade-refresh-a0cbbbf.md | 1 + 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 66964e2..692f493 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -61,7 +61,7 @@ "group_path": "io/spine", "artifact": "spine-reflect" }, - "state": "pr-open", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.202", "pin_vector": {}, "adapt_rounds": 0, @@ -97,7 +97,10 @@ "head": "79766b3c73d9c11ed13b1081a084d87bc21b12a7", "at": "2026-10-15T19:11:03Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/logging/pull/151", + "head": "79766b3c73d9c11ed13b1081a084d87bc21b12a7" + }, "parked": null }, "testlib": { @@ -133,7 +136,7 @@ "group_path": "io/spine/tools", "artifact": "dokka-extensions" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.11", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461" @@ -290,7 +293,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "parked", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", @@ -302,10 +305,13 @@ "tool-base": "2.0.0-SNAPSHOT.426", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 2, - "built": null, + "adapt_rounds": 0, + "built": { + "head": "dee4edfdbf4f356293623388bc4a6faf9a800e72", + "at": "2026-10-16T13:45:53Z" + }, "pr": null, - "parked": "awaiting owner decision: 5 tests in tests/entity-queries (EntityQueryBuilderTest) assert FieldMask behavior that base-libraries#964 made a deprecated no-op ('Please remove the call'); deleting them was blocked as test removal" + "parked": null }, "base-types": { "upstreams": [ @@ -321,7 +327,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -330,8 +336,11 @@ "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "4d96be22f8a04ef12fbab5983aed2cf46efb1c62", + "at": "2026-10-16T13:47:39Z" + }, "pr": null, "parked": null }, @@ -348,7 +357,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -356,8 +365,11 @@ "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 2, + "built": { + "head": "6d15a7d9caa8e9ecddbe9f0dca2a394be78a16db", + "at": "2026-10-16T13:50:18Z" + }, "pr": null, "parked": null }, @@ -378,7 +390,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.3", @@ -390,8 +402,11 @@ "tool-base": "2.0.0-SNAPSHOT.426", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 2, + "built": { + "head": "a33fac7d0b56b39916c41f6f2e2d4710fb522486", + "at": "2026-10-16T14:19:35Z" + }, "pr": null, "parked": null }, @@ -409,7 +424,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -418,8 +433,11 @@ "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "15e1b8d92b76be1711b4037f382a8422d85c383c", + "at": "2026-10-16T14:21:02Z" + }, "pr": null, "parked": null }, @@ -454,7 +472,7 @@ "time": "2.0.0-SNAPSHOT.252", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, + "adapt_rounds": 2, "built": null, "pr": null, "parked": null diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/cascade-refresh-a0cbbbf.md index c6d1dcc..f128413 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.md +++ b/.agents/tasks/cascade-refresh-a0cbbbf.md @@ -37,3 +37,4 @@ Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). P - 2026-10-15 — wave planned. - 2026-10-15 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish - 2026-10-15 — **parked** `core-jvm-compiler`: awaiting owner decision: 5 tests in tests/entity-queries (EntityQueryBuilderTest) assert FieldMask behavior that base-libraries#964 made a deprecated no-op ('Please remove the call'); deleting them was blocked as test removal +- 2026-10-16 — resumed `core-jvm-compiler`. From e93b8c202fea122e7240f3f6df5f167d848d2881 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 16:30:07 +0100 Subject: [PATCH 07/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 692f493..325fe14 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -86,7 +86,7 @@ "group_path": "io/spine", "artifact": "spine-logging" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.426", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -123,7 +123,10 @@ "head": "835b21d4587c265b49abb0f63ae4552f75175215", "at": "2026-10-15T19:11:35Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/testlib/pull/15", + "head": "835b21d4587c265b49abb0f63ae4552f75175215" + }, "parked": null }, "dokka-tools": { @@ -459,7 +462,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.571", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -473,7 +476,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": null, + "built": { + "head": "7e9d7ac69245c9aa8dfb2536f00d6ed23a73f618", + "at": "2026-10-16T15:20:18Z" + }, "pr": null, "parked": null }, @@ -489,15 +495,18 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "core-jvm": "2.0.0-SNAPSHOT.571", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "199ab027bb3a85524644587c925dc084bc762a27", + "at": "2026-10-16T15:25:43Z" + }, "pr": null, "parked": null }, @@ -530,7 +539,7 @@ "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, + "adapt_rounds": 1, "built": null, "pr": null, "parked": null From 9b17dda75680bbf2bdd6906516f2b70e84aa6cc6 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 16:31:00 +0100 Subject: [PATCH 08/65] Allow `./gradlew clean` without a permission prompt Cascade waves run clean builds routinely; the owner approved moving the rule from "ask" to "allow". Co-Authored-By: Claude Opus 5.5 --- .claude/settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index 7f8e7cc..460b219 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -5,6 +5,7 @@ "allow": [ "Edit(version.gradle.kts)", "Bash(./gradlew:*)", + "Bash(./gradlew clean:*)", "Bash(./config/gradlew:*)", "Bash(git status:*)", "Bash(git diff:*)", @@ -61,8 +62,7 @@ "Bash(git merge:*)", "Bash(git cherry-pick:*)", "Bash(./gradlew publish:*)", - "Bash(./gradlew uploadArtifacts:*)", - "Bash(./gradlew clean:*)" + "Bash(./gradlew uploadArtifacts:*)" ] }, "hooks": { From 9731f49a7f580ebcb8448385e864ff1b7435adb4 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 16:50:00 +0100 Subject: [PATCH 09/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 325fe14..a6f0058 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -113,7 +113,7 @@ "group_path": "io/spine/tools", "artifact": "base-testlib" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.215", "pin_vector": { "logging": "2.0.0-SNAPSHOT.426" @@ -179,7 +179,10 @@ "head": "b1071b8b25e87619031f011350887bd949c0875a", "at": "2026-10-15T19:14:48Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/tool-base/pull/195", + "head": "b1071b8b25e87619031f011350887bd949c0875a" + }, "parked": null }, "ProtoTap": { @@ -296,7 +299,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", @@ -330,7 +333,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -360,7 +363,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -393,7 +396,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.3", @@ -427,7 +430,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -462,7 +465,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.571", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -495,7 +498,7 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "core-jvm": "2.0.0-SNAPSHOT.571", @@ -527,7 +530,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -540,7 +543,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "0d4e1453e321c7b679a032eb3a6661687806fbd6", + "at": "2026-10-16T15:30:44Z" + }, "pr": null, "parked": null }, @@ -560,7 +566,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "bumped", + "state": "pr-ready", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.070", @@ -571,8 +577,11 @@ "time": "2.0.0-SNAPSHOT.252", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "1b997818116181a5d7b91bd4378162ad988982aa", + "at": "2026-10-16T15:44:02Z" + }, "pr": null, "parked": null }, From c3e5b4296cad207cd5265840393340ff90b560fa Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 17:03:52 +0100 Subject: [PATCH 10/65] Count `config`'s accessor aliases in the dependency graph MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cascade graph` saw local objects only as `Obj.member` or `io.spine.dependency.local.Obj.member`. Build scripts that load the Compiler through `config`'s accessors — `classpath(spineCompiler.pluginLib)` in `core-jvm` and `jdbc-storage` — therefore had no `compiler` edge, so waves never re-pinned the Compiler there. Those repos then built against the published Compiler and its transitive tool-base artifacts, which bundle an older Protobuf runtime. The derivation now treats `spineCompiler.member` and `coreJvmCompiler.member` like their objects (references in `force(...)` still create no edge), and `id(.pluginId)` as a plugin application. The regenerated graph gains `compiler -> core-jvm` and `compiler -> jdbc-storage`. Co-Authored-By: Claude Opus 5.5 --- cascade | 36 ++++++++++++++++++++++++++++++++---- docs/dependency-graph.md | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cascade b/cascade index aac68e8..8b431c6 100755 --- a/cascade +++ b/cascade @@ -150,6 +150,24 @@ obj_to_repo() { esac } +# `config`'s accessor aliases for local objects (`BuildExtensions.kt`), used +# where the objects are not imported, e.g. `classpath(spineCompiler.pluginLib)` +# in a `buildscript {}` block. +alias_of_obj() { + case "$1" in + Compiler) echo spineCompiler ;; + CoreJvmCompiler) echo coreJvmCompiler ;; + *) echo "" ;; + esac +} + +obj_of_alias() { + case "$1" in + spineCompiler) echo Compiler ;; + coreJvmCompiler) echo CoreJvmCompiler ;; + esac +} + # repo -> pin file (relative to a consumer's buildSrc local/ dir). repo_pin_file() { case "$1" in @@ -392,8 +410,12 @@ derive_scoped() { done [ -n "$files" ] || continue # shellcheck disable=SC2086 - objs="$(grep -hoE 'io\.spine\.dependency\.local\.[A-Z][A-Za-z]+' $files 2>/dev/null \ - | sed 's/.*\.//' | sort -u)" + objs="$( { grep -hoE 'io\.spine\.dependency\.local\.[A-Z][A-Za-z]+' $files 2>/dev/null \ + | sed 's/.*\.//' + grep -hoE '(^|[^.A-Za-z])(spineCompiler|coreJvmCompiler)\.[A-Za-z]' $files 2>/dev/null \ + | grep -oE 'spineCompiler|coreJvmCompiler' \ + | while read -r a; do obj_of_alias "$a"; done + } | sort -u)" # Block-aware classification: a reference creates an edge only where # it is a declared dependency. References inside version-management # constructs — force(...), constraints {...}, exclude(...) — create NO @@ -407,7 +429,7 @@ derive_scoped() { up="$(obj_to_repo "$o")" [ -n "$up" ] && [ "$up" != "$repo" ] || continue # shellcheck disable=SC2086 - scopes="$(awk -v obj="$o" ' + scopes="$(awk -v obj="$o" -v alias="$(alias_of_obj "$o")" ' function push(tag) { sp++; tags[sp] = tag; depths[sp] = depth } { line = $0 @@ -416,8 +438,10 @@ derive_scoped() { # and the fully-qualified `io.spine.dependency.local.Obj.member`, # which is the house style inside `buildscript {}` where # file-level imports do not apply. The leading guard still - # rejects an unrelated `Something.Obj.member`. + # rejects an unrelated `Something.Obj.member`. A `config` + # accessor alias (`spineCompiler.member`) counts the same way. use = match(line, "(^|[^.A-Za-z])(io\\.spine\\.dependency\\.local\\.)?" obj "\\.[A-Za-z]") + if (!use && alias != "") use = match(line, "(^|[^.A-Za-z])" alias "\\.[A-Za-z]") if (use) { if (line ~ /(^|[^A-Za-z])test[A-Za-z]*\(/) print "test" else if (line ~ /(^|[^A-Za-z])(api|implementation|compileOnly|compileOnlyApi|runtimeOnly|annotationProcessor|classpath|kapt|ksp)\(/) print "main" @@ -454,11 +478,15 @@ derive_scoped() { # coreJvmCompiler / io.spine.core-jvm -> core-jvm-compiler # io.spine.{artifact-meta,descriptor-set-file, # generated-sources} -> tool-base + # The accessors also apply as `id(spineCompiler.pluginId)`. # shellcheck disable=SC2086 { grep -hE '^[[:space:]]*(prototap|spineCompiler|coreJvmCompiler)[[:space:]]*$' $files 2>/dev/null \ | sed 's/[[:space:]]//g' | sort -u \ | sed 's/^prototap$/ProtoTap/; s/^spineCompiler$/compiler/; s/^coreJvmCompiler$/core-jvm-compiler/' + grep -hoE '(^|[^.A-Za-z])id\((spineCompiler|coreJvmCompiler)\.pluginId\)' $files 2>/dev/null \ + | grep -oE 'spineCompiler|coreJvmCompiler' | sort -u \ + | sed 's/^spineCompiler$/compiler/; s/^coreJvmCompiler$/core-jvm-compiler/' grep -hoE '"io\.spine\.(prototap|compiler|core-jvm|artifact-meta|descriptor-set-file|generated-sources)"' $files 2>/dev/null \ | tr -d '"' | sort -u \ | sed 's/^io\.spine\.prototap$/ProtoTap/; s/^io\.spine\.compiler$/compiler/; s/^io\.spine\.core-jvm$/core-jvm-compiler/; s/^io\.spine\..*$/tool-base/' diff --git a/docs/dependency-graph.md b/docs/dependency-graph.md index 20d0af4..221af17 100644 --- a/docs/dependency-graph.md +++ b/docs/dependency-graph.md @@ -255,6 +255,7 @@ compiler validation core-jvm base-libraries core-jvm base-types core-jvm change +core-jvm compiler core-jvm core-jvm-compiler core-jvm logging core-jvm reflect @@ -287,6 +288,7 @@ gcloud-jvm core-jvm-compiler gcloud-jvm logging gcloud-jvm testlib gcloud-jvm validation +jdbc-storage compiler jdbc-storage core-jvm jdbc-storage core-jvm-compiler jdbc-storage validation From 2108d3b59a13ba1ec3870b8670deadc84d297252 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 17:09:02 +0100 Subject: [PATCH 11/65] Tighten the comments added to `cascade` Address the documentation review: name the accessors that have a `pluginId` form, say what the false `prep` error is, and quote `delivery` as a name. Co-Authored-By: Claude Opus 5.5 --- cascade | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cascade b/cascade index 8b431c6..ebaf4c6 100755 --- a/cascade +++ b/cascade @@ -150,9 +150,10 @@ obj_to_repo() { esac } -# `config`'s accessor aliases for local objects (`BuildExtensions.kt`), used -# where the objects are not imported, e.g. `classpath(spineCompiler.pluginLib)` -# in a `buildscript {}` block. +# `config`'s accessor aliases for local objects (`BuildExtensions.kt`) that are +# dereferenced as `.member` where the objects are not imported, e.g. +# `classpath(spineCompiler.pluginLib)` in a `buildscript {}` block. +# `obj_of_alias` is the inverse. alias_of_obj() { case "$1" in Compiler) echo spineCompiler ;; @@ -204,7 +205,7 @@ repo_track_constants() { # marker-artifact: one definitely-published artifact used for registry probes. # class: library (full pipeline) | verify-only (no version/publishing steps). # registry: gcar (public europe-maven.pkg.dev) | github (GitHub Packages — -# delivery is proprietary and publishes only there; probes authenticate +# `delivery` is proprietary and publishes only there; probes authenticate # with `gh auth token`). repo_meta() { case "$1" in @@ -478,7 +479,8 @@ derive_scoped() { # coreJvmCompiler / io.spine.core-jvm -> core-jvm-compiler # io.spine.{artifact-meta,descriptor-set-file, # generated-sources} -> tool-base - # The accessors also apply as `id(spineCompiler.pluginId)`. + # `spineCompiler` and `coreJvmCompiler` (not `prototap`) also appear as + # `id(.pluginId)`. # shellcheck disable=SC2086 { grep -hE '^[[:space:]]*(prototap|spineCompiler|coreJvmCompiler)[[:space:]]*$' $files 2>/dev/null \ @@ -1249,8 +1251,9 @@ cmd_prep() { fi # Check `config` out at the commit the branch records: `git pull` moves the - # recorded pointer but not the checkout (a false "not clean" below), and an - # uninitialized one would pass for a repo that does not consume `config`. + # recorded pointer but not the checkout (a false "working tree not clean" error + # below), and an uninitialized `config` would be mistaken for a repo that does + # not consume it. if git config -f .gitmodules --get submodule.config.path >/dev/null 2>&1; then git submodule update --init --quiet -- config fi From b49a970c1f39e487890a3819788077720f237b43 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 17:18:43 +0100 Subject: [PATCH 12/65] Tolerate repositories without accessor aliases in `cascade graph` The alias scan's `grep` exits 1 when a repository references no `spineCompiler`/`coreJvmCompiler`, and `pipefail` turned that into a failed `objs` assignment. It only went unnoticed because `derive_scoped` runs inside command substitutions, where `errexit` is not inherited. Co-Authored-By: Claude Opus 5.5 --- cascade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cascade b/cascade index ebaf4c6..9a020d6 100755 --- a/cascade +++ b/cascade @@ -413,9 +413,11 @@ derive_scoped() { # shellcheck disable=SC2086 objs="$( { grep -hoE 'io\.spine\.dependency\.local\.[A-Z][A-Za-z]+' $files 2>/dev/null \ | sed 's/.*\.//' + # Optional: most repositories reference no alias, and `grep` + # exits 1 on no match, which `pipefail` would propagate. grep -hoE '(^|[^.A-Za-z])(spineCompiler|coreJvmCompiler)\.[A-Za-z]' $files 2>/dev/null \ | grep -oE 'spineCompiler|coreJvmCompiler' \ - | while read -r a; do obj_of_alias "$a"; done + | while read -r a; do obj_of_alias "$a"; done || true } | sort -u)" # Block-aware classification: a reference creates an edge only where # it is a declared dependency. References inside version-management From c0e407e14e51ba260fd5953156ad8156bac6c5d6 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 17:23:17 +0100 Subject: [PATCH 13/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index a6f0058..5e1b276 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -167,7 +167,7 @@ "group_path": "io/spine/tools", "artifact": "jvm-tools" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.426", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -211,7 +211,10 @@ "head": "91eaaaad39c33ec1b0e6c61dcaf7a036a261c01d", "at": "2026-10-15T19:21:02Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/ProtoTap/pull/23", + "head": "91eaaaad39c33ec1b0e6c61dcaf7a036a261c01d" + }, "parked": null }, "compiler": { @@ -229,8 +232,8 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "pr-ready", - "target_version": "2.0.0-SNAPSHOT.070", + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.072", "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", From eba8beec7192ee28b59e6aac89dc54110d1d7fe6 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 18:42:45 +0100 Subject: [PATCH 14/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 67 +++++++++++----------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 5e1b276..f2cfcc8 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -198,7 +198,7 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "0.17.3", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -244,10 +244,13 @@ }, "adapt_rounds": 1, "built": { - "head": "005cfa4be7bd78734885b8dad4a4466e28116c03", - "at": "2026-10-15T19:50:24Z" + "head": "0ebf947332a4521f15c5c232223529cf2f8fb805", + "at": "2026-10-16T16:42:26Z" + }, + "pr": { + "url": "https://github.com/SpineEventEngine/compiler/pull/91", + "head": "0ebf947332a4521f15c5c232223529cf2f8fb805" }, - "pr": null, "parked": null }, "validation": { @@ -271,7 +274,7 @@ "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "logging": "2.0.0-SNAPSHOT.426", "reflect": "2.0.0-SNAPSHOT.202", "testlib": "2.0.0-SNAPSHOT.215", @@ -279,8 +282,8 @@ }, "adapt_rounds": 1, "built": { - "head": "d5b98ece3ce0602eacc74626a0da15912404f942", - "at": "2026-10-15T19:53:41Z" + "head": "7c6c90e4a39cf76b409c61050d27ddfb62d47cfb", + "at": "2026-10-16T16:45:11Z" }, "pr": null, "parked": null @@ -307,7 +310,7 @@ "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "logging": "2.0.0-SNAPSHOT.426", "reflect": "2.0.0-SNAPSHOT.202", "testlib": "2.0.0-SNAPSHOT.215", @@ -316,8 +319,8 @@ }, "adapt_rounds": 0, "built": { - "head": "dee4edfdbf4f356293623388bc4a6faf9a800e72", - "at": "2026-10-16T13:45:53Z" + "head": "14802413eeeef3eaa7496da22a89765769dfe52d", + "at": "2026-10-16T16:49:19Z" }, "pr": null, "parked": null @@ -340,15 +343,15 @@ "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, "built": { - "head": "4d96be22f8a04ef12fbab5983aed2cf46efb1c62", - "at": "2026-10-16T13:47:39Z" + "head": "2a95dfc406846826d8d7af958326e5877b96858e", + "at": "2026-10-16T16:49:42Z" }, "pr": null, "parked": null @@ -370,14 +373,14 @@ "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, "built": { - "head": "6d15a7d9caa8e9ecddbe9f0dca2a394be78a16db", - "at": "2026-10-16T13:50:18Z" + "head": "41c092c16c96484e05afd02dc4baf2afd4f8884e", + "at": "2026-10-16T16:50:12Z" }, "pr": null, "parked": null @@ -404,7 +407,7 @@ "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", "testlib": "2.0.0-SNAPSHOT.215", @@ -413,8 +416,8 @@ }, "adapt_rounds": 2, "built": { - "head": "a33fac7d0b56b39916c41f6f2e2d4710fb522486", - "at": "2026-10-16T14:19:35Z" + "head": "8a671484a8782ce16f0e551dea322549d75c5919", + "at": "2026-10-16T16:51:56Z" }, "pr": null, "parked": null @@ -437,15 +440,15 @@ "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, "built": { - "head": "15e1b8d92b76be1711b4037f382a8422d85c383c", - "at": "2026-10-16T14:21:02Z" + "head": "36b807e1987543e260b2e08bdcf1d2a9e5cba83e", + "at": "2026-10-16T16:52:16Z" }, "pr": null, "parked": null @@ -483,8 +486,8 @@ }, "adapt_rounds": 2, "built": { - "head": "7e9d7ac69245c9aa8dfb2536f00d6ed23a73f618", - "at": "2026-10-16T15:20:18Z" + "head": "b0ea6626f1b11d74c254be3ffaa56f63068016d8", + "at": "2026-10-16T16:57:21Z" }, "pr": null, "parked": null @@ -510,8 +513,8 @@ }, "adapt_rounds": 1, "built": { - "head": "199ab027bb3a85524644587c925dc084bc762a27", - "at": "2026-10-16T15:25:43Z" + "head": "4041f0981bb8a768549e1f4d37203dcd67eb6099", + "at": "2026-10-16T16:58:50Z" }, "pr": null, "parked": null @@ -538,7 +541,7 @@ "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", "base-types": "2.0.0-SNAPSHOT.226", - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm": "2.0.0-SNAPSHOT.571", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", @@ -547,8 +550,8 @@ }, "adapt_rounds": 1, "built": { - "head": "0d4e1453e321c7b679a032eb3a6661687806fbd6", - "at": "2026-10-16T15:30:44Z" + "head": "585029b09743e3abdb098c662c9dc34e0821a3f1", + "at": "2026-10-16T17:01:20Z" }, "pr": null, "parked": null @@ -572,7 +575,7 @@ "state": "pr-ready", "target_version": "0.24.1", "pin_vector": { - "compiler": "2.0.0-SNAPSHOT.070", + "compiler": "2.0.0-SNAPSHOT.072", "core-jvm": "2.0.0-SNAPSHOT.571", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", @@ -582,8 +585,8 @@ }, "adapt_rounds": 1, "built": { - "head": "1b997818116181a5d7b91bd4378162ad988982aa", - "at": "2026-10-16T15:44:02Z" + "head": "b648666cd68a31b58ee79ed12d0cf0906f80c71a", + "at": "2026-10-16T17:14:02Z" }, "pr": null, "parked": null From fbb9e028c2dde246e7392b504872b8cc6bbd826d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 19:24:32 +0100 Subject: [PATCH 15/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index f2cfcc8..f7fa01d 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -232,7 +232,7 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "bumped", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.072", "pin_vector": { "ProtoTap": "0.17.3", @@ -285,7 +285,10 @@ "head": "7c6c90e4a39cf76b409c61050d27ddfb62d47cfb", "at": "2026-10-16T16:45:11Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/validation/pull/332", + "head": "7c6c90e4a39cf76b409c61050d27ddfb62d47cfb" + }, "parked": null }, "core-jvm-compiler": { From 7b195c110bda9d2662e8f472bb47da054b944e0f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 19:59:34 +0100 Subject: [PATCH 16/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index f7fa01d..3933df4 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", @@ -282,12 +282,12 @@ }, "adapt_rounds": 1, "built": { - "head": "7c6c90e4a39cf76b409c61050d27ddfb62d47cfb", - "at": "2026-10-16T16:45:11Z" + "head": "808b2a34f08951a57c376cdc0c1eeda71cafc4b1", + "at": "2026-10-16T18:59:02Z" }, "pr": { "url": "https://github.com/SpineEventEngine/validation/pull/332", - "head": "7c6c90e4a39cf76b409c61050d27ddfb62d47cfb" + "head": "808b2a34f08951a57c376cdc0c1eeda71cafc4b1" }, "parked": null }, @@ -474,7 +474,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.571", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", From c20e4ad390c5a691941b0592a17aea97fba9dd21 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 20:59:49 +0100 Subject: [PATCH 17/65] Detect partial publishes before treating a repo as published `cascade` took the registry serving a repo's marker artifact as proof of a complete publish. A `publish.yml` run that fails midway has already uploaded some modules: compiler `.072` reached the registry without `compiler-testlib`, `cascade` marked it `published-remote`, and `validation` shipped into a CI that could not resolve the missing module. `publish_verdict` now reads the conclusion of the `publish.yml` run for the merge commit of the repo's wave PR. A failed run yields the new state `publish-failed` (with the run linked in `status` and a `FIX-PUBLISH` action), a running one stays `merged`, and `ship` refuses an upstream whose publish failed. Without a recorded PR or run, the registry remains the evidence. Co-Authored-By: Claude Opus 5.5 --- cascade | 56 ++++++++++++++++++++++++++++++++++++++--- docs/rollout/rebuild.md | 17 +++++++++---- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/cascade b/cascade index 9a020d6..774a7fd 100755 --- a/cascade +++ b/cascade @@ -311,6 +311,32 @@ registry_has() { # marker_metadata "$1" | grep -q "$2" } +# The `publish.yml` run for the merge commit of the repo's wave PR, as +# " ": `ok`, `failed`, or `running`. The marker artifact alone +# cannot prove a publish completed: a run that fails midway has already uploaded +# some modules (compiler `.072` reached the registry without `compiler-testlib`). +# With no recorded PR, no merge commit, or no run (a seed published by hand, a +# repo without the workflow), the verdict is `ok` and the registry stays the +# only evidence, as before. +publish_verdict() { # + local url sha run + url="$(mget "$1" --arg r "$2" '.repos[$r].pr.url // empty')" + [ -n "$url" ] || { echo ok; return; } + sha="$(gh pr view "$url" --json mergeCommit --jq '.mergeCommit.oid // empty' 2>/dev/null || true)" + [ -n "$sha" ] || { echo ok; return; } + run="$(gh run list -R "$ORG/$2" --workflow publish.yml --commit "$sha" --limit 1 \ + --json status,conclusion,url \ + --jq '.[0] // empty | "\(.status) \(if (.conclusion // "") == "" then "none" else .conclusion end) \(.url)"' \ + 2>/dev/null || true)" + [ -n "$run" ] || { echo ok; return; } + set -- $run + case "$1 $2" in + "completed success") echo "ok $3" ;; + completed\ *) echo "failed $3" ;; + *) echo "running $3" ;; + esac +} + # File.kt -> repo (reverse of repo_pin_file); empty when not a repo pin file. pin_file_repo() { # local r @@ -1057,7 +1083,11 @@ derive_state() { # -> prints state # prep and rebuild a repository it has already shipped. local tvp; tvp="$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty')" if [ -n "$tvp" ] && registry_has "$repo" "$tvp"; then - echo published-remote; return + case "$(publish_verdict "$wave" "$repo")" in + failed\ *) echo publish-failed; return ;; + running\ *) echo merged; return ;; + *) echo published-remote; return ;; + esac fi local subjects @@ -1124,9 +1154,14 @@ derive_state() { # -> prints state *) echo pr-ready; return ;; esac - # published-remote (library): registry serves the target. + # published-remote (library): registry serves the target and the publish run + # completed. if [ "$cls" = library ]; then local tv; tv="$(mget "$wave" --arg r "$repo" '.repos[$r].target_version')" + case "$(publish_verdict "$wave" "$repo")" in + failed\ *) echo publish-failed; return ;; + running\ *) echo merged; return ;; + esac registry_has "$repo" "$tv" || { echo merged; return; } echo published-remote; return fi @@ -1154,10 +1189,13 @@ cmd_status() { done fi mset "$wave" '.repos[$r].state = $s' --arg r "$repo" --arg s "$st" + local note + note="$(mget "$wave" --arg r "$repo" '.repos[$r].parked // ""')" + [ "$st" = publish-failed ] && note="publish run failed: $(publish_verdict "$wave" "$repo" | cut -d' ' -f2)" printf '%-20s %-17s %-24s %s\n' "$repo" "${blocked:+blocked}${blocked:-$st}" \ "$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty' \ | grep . || version_of "$repo" "$wbranch" 2>/dev/null | grep . || echo "—")" \ - "${blocked:-$(mget "$wave" --arg r "$repo" '.repos[$r].parked // ""')}" + "${blocked:-$note}" done [ "$(mget "$wave" '.halted // empty')" != "" ] && warn "WAVE HALTED: $(mget "$wave" .halted)" return 0 @@ -1218,6 +1256,9 @@ cmd_next() { else actions="$actions WAIT-UPSTREAM:$repo"; fi ;; pr-open) actions="$actions WAIT-REVIEW:$repo" ;; merged) actions="$actions WAIT-PUBLISH:$repo" ;; + # The publish run failed after the merge; a human fixes the build + # and publishes a new version. Downstream repos keep waiting. + publish-failed) actions="$actions FIX-PUBLISH:$repo" ;; parked|blocked|published-remote) ;; esac done @@ -1455,6 +1496,15 @@ cmd_ship() { fi warn "waiting: $up $pv not yet in the registry"; exit 4 fi + # The marker alone may come from a publish that failed midway. + local verdict; verdict="$(publish_verdict "$wave" "$up")" + case "$verdict" in + failed\ *) + warn "upstream $up $pv: its publish run failed (${verdict#failed }), so some modules may be missing" + warn "fix and re-publish $up, re-pin with ./cascade refresh $repo, then ship again" + exit 3 ;; + running\ *) warn "waiting: $up $pv publish still running (${verdict#running })"; exit 4 ;; + esac done # Floor gate: every version pinned in this repo's own pin files must be diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 171d2eb..1487e4c 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -99,17 +99,24 @@ and execute what it prints, in order: repo — three adapt→rebuild rounds, then auto-park). Exit 5 = throttling halt. - `PREPR:` → run the `pre-pr` skill inside the repo (writes the sentinel). - `SHIP:` → `./cascade ship ` — sentinel gate, upstream-published - gate, floor gate (every version the repo pins — forward upstreams *and* - published floors — proven in the registry, derived from the pin files by - content, since floors never appear in the manifest), drift gate, push, PR. - Exit 4 means an upstream is not published yet: wait, don't force. + gate (the registry serves the upstream's version *and* the upstream's + `publish.yml` run for its merge commit succeeded), floor gate (every version + the repo pins — forward upstreams *and* published floors — proven in the + registry, derived from the pin files by content, since floors never appear in + the manifest), drift gate, push, PR. Exit 4 means an upstream is not + published yet: wait, don't force. +- `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR + merged. A run that fails midway may already have uploaded some modules, so + the registry's marker artifact proves nothing; `./cascade status` links the + run. Fix the build, publish a new version, and re-pin the downstream repos + (`./cascade refresh `). Downstream repos wait meanwhile. - `WAIT-*` only → `./cascade await` (background it) — exits the moment the action set changes; then run `next` again. - `CLOSE` → `./cascade close` — stages the final vector in `config` (floors included, now provably published), exit 3 → `pre-pr` in config → `./cascade close --ship` opens the closing PR. -Humans do exactly: review/merge PRs, resolve parks (`./cascade resume`), and +Humans do exactly: review/merge PRs, resolve parks (`./cascade resume`), fix failed publishes, and acknowledge throttle halts. Everything else is the loop. ## 3. Drift From e7166e0809c08015619a0fdb5543c4726419818a Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 22:45:18 +0100 Subject: [PATCH 18/65] Detect version collisions with the base branch A repo counted as published as soon as the registry served its wave target version. When the base branch takes the same version first, that copy is the base branch's build, not the wave's: core-jvm `.571` merged on master while the wave's `.571` was still unshipped, so `status` showed it published and downstream repos would have shipped against it. `cascade` now requires the wave's own PR to have merged. Otherwise the state is `collision`, and `next` asks to `REBUMP` the repo. `ship` refuses such an upstream, and also an upstream whose target moved past the recorded pin while the old pin stays public. Co-Authored-By: Claude Opus 5.5 --- cascade | 38 +++++++++++++++++++++++++++++++++++++- docs/rollout/rebuild.md | 12 ++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/cascade b/cascade index 774a7fd..bf02d0b 100755 --- a/cascade +++ b/cascade @@ -337,6 +337,24 @@ publish_verdict() { # esac } +# Has the wave's own PR for the repo merged? Without that, a registry serving the +# wave's target version serves someone else's build: the base branch took the +# same version first (core-jvm `.571`). A ripple seed is published by hand, and +# when `gh` itself fails, the registry stays the only evidence, as before. +wave_pr_merged() { # + local ref out + [ "$2" = "$(mget "$1" '.seed.repo // empty')" ] \ + && [ -n "$(mget "$1" '.seed.version // empty')" ] && return 0 + ref="$(mget "$1" --arg r "$2" '.repos[$r].pr.url // empty')" + [ -n "$ref" ] || ref="$(mget "$1" .branch)" + if out="$(gh pr view "$ref" -R "$ORG/$2" --json state --jq .state 2>&1)"; then + [ "$out" = MERGED ] + else + case "$out" in *"no pull requests found"*) return 1 ;; esac + return 0 + fi +} + # File.kt -> repo (reverse of repo_pin_file); empty when not a repo pin file. pin_file_repo() { # local r @@ -1080,9 +1098,12 @@ derive_state() { # -> prints state # the registry, this repository is done. Without this the derivation reads a # MERGED branch as `pending` -- after the merge `origin/$BASE..$branch` is # empty, so the branch looks like it never had work -- and the wave asks to - # prep and rebuild a repository it has already shipped. + # prep and rebuild a repository it has already shipped. Unless the wave's PR + # has not merged: then the registry's copy is the base branch's build of the + # same version, and the repository must re-bump. local tvp; tvp="$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty')" if [ -n "$tvp" ] && registry_has "$repo" "$tvp"; then + wave_pr_merged "$wave" "$repo" || { echo collision; return; } case "$(publish_verdict "$wave" "$repo")" in failed\ *) echo publish-failed; return ;; running\ *) echo merged; return ;; @@ -1192,6 +1213,7 @@ cmd_status() { local note note="$(mget "$wave" --arg r "$repo" '.repos[$r].parked // ""')" [ "$st" = publish-failed ] && note="publish run failed: $(publish_verdict "$wave" "$repo" | cut -d' ' -f2)" + [ "$st" = collision ] && note="$BASE published this version first — merge $BASE, then: ./cascade refresh $repo" printf '%-20s %-17s %-24s %s\n' "$repo" "${blocked:+blocked}${blocked:-$st}" \ "$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty' \ | grep . || version_of "$repo" "$wbranch" 2>/dev/null | grep . || echo "—")" \ @@ -1259,6 +1281,9 @@ cmd_next() { # The publish run failed after the merge; a human fixes the build # and publishes a new version. Downstream repos keep waiting. publish-failed) actions="$actions FIX-PUBLISH:$repo" ;; + # The base branch published the wave's target version first; the + # repo merges it and re-bumps. Downstream repos keep waiting. + collision) actions="$actions REBUMP:$repo" ;; parked|blocked|published-remote) ;; esac done @@ -1488,6 +1513,12 @@ cmd_ship() { for up in $(upstreams_of "$wave" "$repo"); do pv="$(mget "$wave" --arg r "$repo" --arg u "$up" '.repos[$r].pin_vector[$u] // empty')" [ -n "$pv" ] || continue + # Drift the registry cannot reveal: the upstream re-bumped after this repo + # was pinned (a collision or a failed publish), but the old pin is public. + local tvu; tvu="$(mget "$wave" --arg r "$up" '.repos[$r].target_version // empty')" + if [ -n "$tvu" ] && [ "$tvu" != "$pv" ]; then + warn "upstream $up re-bumped ($pv -> $tvu) — run: ./cascade refresh $repo"; exit 3 + fi if ! registry_has "$up" "$pv"; then # Drift check: did the upstream move past our pin (re-bump)? local upcur; upcur="$(version_of "$up" "$branch" 2>/dev/null || version_of "$up")" @@ -1496,6 +1527,11 @@ cmd_ship() { fi warn "waiting: $up $pv not yet in the registry"; exit 4 fi + # A copy the wave did not publish is the base branch's build of that version. + wave_pr_merged "$wave" "$up" || { + warn "upstream $up $pv: the registry serves $BASE's build of that version, not the wave's" + warn "re-bump $up first (REBUMP in ./cascade next), then: ./cascade refresh $repo" + exit 3; } # The marker alone may come from a publish that failed midway. local verdict; verdict="$(publish_verdict "$wave" "$up")" case "$verdict" in diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 1487e4c..772eef2 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -99,8 +99,9 @@ and execute what it prints, in order: repo — three adapt→rebuild rounds, then auto-park). Exit 5 = throttling halt. - `PREPR:` → run the `pre-pr` skill inside the repo (writes the sentinel). - `SHIP:` → `./cascade ship ` — sentinel gate, upstream-published - gate (the registry serves the upstream's version *and* the upstream's - `publish.yml` run for its merge commit succeeded), floor gate (every version + gate (the upstream has not re-bumped since the pin, the registry serves its + version *from the wave's merged PR*, and its `publish.yml` run for the merge + commit succeeded), floor gate (every version the repo pins — forward upstreams *and* published floors — proven in the registry, derived from the pin files by content, since floors never appear in the manifest), drift gate, push, PR. Exit 4 means an upstream is not @@ -110,6 +111,13 @@ and execute what it prints, in order: the registry's marker artifact proves nothing; `./cascade status` links the run. Fix the build, publish a new version, and re-pin the downstream repos (`./cascade refresh `). Downstream repos wait meanwhile. +- `REBUMP:` → the registry serves the repo's wave version, but the wave's + PR has not merged: the base branch took the same version first, so the + registry holds the base branch's build, not the wave's. Merge the base branch + into the wave branch (a `version.gradle.kts` conflict follows the + `bump-version` Conflict Rule), then `./cascade refresh ` bumps past it. + Rebuild it, and re-pin each downstream repo with + `./cascade refresh `. - `WAIT-*` only → `./cascade await` (background it) — exits the moment the action set changes; then run `next` again. - `CLOSE` → `./cascade close` — stages the final vector in `config` (floors From 548848985a92a3968b97fd6139ea038f87568f7e Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 22:45:18 +0100 Subject: [PATCH 19/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-a0cbbbf.json | 100 ++++++++------------- .agents/tasks/cascade-refresh-a0cbbbf.md | 3 + 2 files changed, 38 insertions(+), 65 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 3933df4..6e7c678 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -233,7 +233,7 @@ "artifact": "compiler-jvm" }, "state": "published-remote", - "target_version": "2.0.0-SNAPSHOT.072", + "target_version": "2.0.0-SNAPSHOT.074", "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", @@ -248,8 +248,8 @@ "at": "2026-10-16T16:42:26Z" }, "pr": { - "url": "https://github.com/SpineEventEngine/compiler/pull/91", - "head": "0ebf947332a4521f15c5c232223529cf2f8fb805" + "url": "https://github.com/SpineEventEngine/compiler/pull/92", + "head": "0ec7e51fc6f0cc8f6a83faee53672a16722021d2" }, "parked": null }, @@ -274,17 +274,14 @@ "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "logging": "2.0.0-SNAPSHOT.426", "reflect": "2.0.0-SNAPSHOT.202", "testlib": "2.0.0-SNAPSHOT.215", "tool-base": "2.0.0-SNAPSHOT.426" }, - "adapt_rounds": 1, - "built": { - "head": "808b2a34f08951a57c376cdc0c1eeda71cafc4b1", - "at": "2026-10-16T18:59:02Z" - }, + "adapt_rounds": 0, + "built": null, "pr": { "url": "https://github.com/SpineEventEngine/validation/pull/332", "head": "808b2a34f08951a57c376cdc0c1eeda71cafc4b1" @@ -308,12 +305,12 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "logging": "2.0.0-SNAPSHOT.426", "reflect": "2.0.0-SNAPSHOT.202", "testlib": "2.0.0-SNAPSHOT.215", @@ -321,10 +318,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 0, - "built": { - "head": "14802413eeeef3eaa7496da22a89765769dfe52d", - "at": "2026-10-16T16:49:19Z" - }, + "built": null, "pr": null, "parked": null }, @@ -342,20 +336,17 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "2a95dfc406846826d8d7af958326e5877b96858e", - "at": "2026-10-16T16:49:42Z" - }, + "built": null, "pr": null, "parked": null }, @@ -372,19 +363,16 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": { - "head": "41c092c16c96484e05afd02dc4baf2afd4f8884e", - "at": "2026-10-16T16:50:12Z" - }, + "built": null, "pr": null, "parked": null }, @@ -405,12 +393,12 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.3", "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", "testlib": "2.0.0-SNAPSHOT.215", @@ -418,10 +406,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": { - "head": "8a671484a8782ce16f0e551dea322549d75c5919", - "at": "2026-10-16T16:51:56Z" - }, + "built": null, "pr": null, "parked": null }, @@ -439,20 +424,17 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "compiler": "2.0.0-SNAPSHOT.072", + "compiler": "2.0.0-SNAPSHOT.074", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "36b807e1987543e260b2e08bdcf1d2a9e5cba83e", - "at": "2026-10-16T16:52:16Z" - }, + "built": null, "pr": null, "parked": null }, @@ -474,8 +456,8 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "published-remote", - "target_version": "2.0.0-SNAPSHOT.571", + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.572", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", "base-types": "2.0.0-SNAPSHOT.226", @@ -488,10 +470,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": { - "head": "b0ea6626f1b11d74c254be3ffaa56f63068016d8", - "at": "2026-10-16T16:57:21Z" - }, + "built": null, "pr": null, "parked": null }, @@ -507,18 +486,15 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { - "core-jvm": "2.0.0-SNAPSHOT.571", + "core-jvm": "2.0.0-SNAPSHOT.572", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "4041f0981bb8a768549e1f4d37203dcd67eb6099", - "at": "2026-10-16T16:58:50Z" - }, + "built": null, "pr": null, "parked": null }, @@ -539,23 +515,20 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "pr-ready", + "state": "bumped", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", "base-types": "2.0.0-SNAPSHOT.226", - "compiler": "2.0.0-SNAPSHOT.072", - "core-jvm": "2.0.0-SNAPSHOT.571", + "compiler": "2.0.0-SNAPSHOT.074", + "core-jvm": "2.0.0-SNAPSHOT.572", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", "testlib": "2.0.0-SNAPSHOT.215", "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "585029b09743e3abdb098c662c9dc34e0821a3f1", - "at": "2026-10-16T17:01:20Z" - }, + "built": null, "pr": null, "parked": null }, @@ -575,11 +548,11 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "pr-ready", + "state": "bumped", "target_version": "0.24.1", "pin_vector": { - "compiler": "2.0.0-SNAPSHOT.072", - "core-jvm": "2.0.0-SNAPSHOT.571", + "compiler": "2.0.0-SNAPSHOT.074", + "core-jvm": "2.0.0-SNAPSHOT.572", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", "testlib": "2.0.0-SNAPSHOT.215", @@ -587,10 +560,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "b648666cd68a31b58ee79ed12d0cf0906f80c71a", - "at": "2026-10-16T17:14:02Z" - }, + "built": null, "pr": null, "parked": null }, diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/cascade-refresh-a0cbbbf.md index f128413..5350d20 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.md +++ b/.agents/tasks/cascade-refresh-a0cbbbf.md @@ -38,3 +38,6 @@ Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). P - 2026-10-15 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish - 2026-10-15 — **parked** `core-jvm-compiler`: awaiting owner decision: 5 tests in tests/entity-queries (EntityQueryBuilderTest) assert FieldMask behavior that base-libraries#964 made a deprecated no-op ('Please remove the call'); deleting them was blocked as test removal - 2026-10-16 — resumed `core-jvm-compiler`. +- 2026-10-16 — **parked** `validation`: waiting for a complete compiler publish: compiler .072's publish aborted at test-env's PublicationChecksums (config#764) before compiler-testlib uploaded; a compiler fix + config update + new compiler version are in progress, after which validation, core-jvm-compiler and time re-pin to it +- 2026-10-16 — retargeted `compiler` to `2.0.0-SNAPSHOT.074`: the publish of the wave's `.072` (compiler#91) failed midway at test-env's PublicationChecksums, leaving `compiler-testlib` unpublished; compiler#92 fixed the attestation and published `.074` completely. The local wave branch was fast-forwarded to master; downstream repos re-pin to `.074`. +- 2026-10-16 — resumed `validation`. From 03cb883d7a06155e1ff0a69f8b96518a4ffa027f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 16 Oct 2026 22:50:01 +0100 Subject: [PATCH 20/65] Clarify the collision gate in docs and comments Name the repo whose wave PR must merge, document exit 3 from the upstream gate, and align the `FIX-PUBLISH` and `REBUMP` re-pin instructions. Co-Authored-By: Claude Opus 5.5 --- cascade | 28 +++++++++++++++++----------- docs/rollout/rebuild.md | 26 ++++++++++++++------------ 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/cascade b/cascade index bf02d0b..f4247f0 100755 --- a/cascade +++ b/cascade @@ -339,8 +339,9 @@ publish_verdict() { # # Has the wave's own PR for the repo merged? Without that, a registry serving the # wave's target version serves someone else's build: the base branch took the -# same version first (core-jvm `.571`). A ripple seed is published by hand, and -# when `gh` itself fails, the registry stays the only evidence, as before. +# same version first (core-jvm `.571`). A ripple seed given as `repo@version` is +# published by hand, and when `gh` itself fails the registry is the only +# evidence; both count as merged. wave_pr_merged() { # local ref out [ "$2" = "$(mget "$1" '.seed.repo // empty')" ] \ @@ -1098,9 +1099,10 @@ derive_state() { # -> prints state # the registry, this repository is done. Without this the derivation reads a # MERGED branch as `pending` -- after the merge `origin/$BASE..$branch` is # empty, so the branch looks like it never had work -- and the wave asks to - # prep and rebuild a repository it has already shipped. Unless the wave's PR - # has not merged: then the registry's copy is the base branch's build of the - # same version, and the repository must re-bump. + # prep and rebuild a repository it has already shipped. The exception is + # `collision`: while the wave's PR for the repository is unmerged, the + # registry's copy is the base branch's build of the same version, so the + # repository must re-bump. local tvp; tvp="$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty')" if [ -n "$tvp" ] && registry_has "$repo" "$tvp"; then wave_pr_merged "$wave" "$repo" || { echo collision; return; } @@ -1213,7 +1215,8 @@ cmd_status() { local note note="$(mget "$wave" --arg r "$repo" '.repos[$r].parked // ""')" [ "$st" = publish-failed ] && note="publish run failed: $(publish_verdict "$wave" "$repo" | cut -d' ' -f2)" - [ "$st" = collision ] && note="$BASE published this version first — merge $BASE, then: ./cascade refresh $repo" + [ "$st" = collision ] \ + && note="$BASE took this version first — merge $BASE, then: ./cascade refresh $repo" printf '%-20s %-17s %-24s %s\n' "$repo" "${blocked:+blocked}${blocked:-$st}" \ "$(mget "$wave" --arg r "$repo" '.repos[$r].target_version // empty' \ | grep . || version_of "$repo" "$wbranch" 2>/dev/null | grep . || echo "—")" \ @@ -1282,7 +1285,8 @@ cmd_next() { # and publishes a new version. Downstream repos keep waiting. publish-failed) actions="$actions FIX-PUBLISH:$repo" ;; # The base branch published the wave's target version first; the - # repo merges it and re-bumps. Downstream repos keep waiting. + # driver merges the base branch and re-bumps. Downstream repos keep + # waiting. collision) actions="$actions REBUMP:$repo" ;; parked|blocked|published-remote) ;; esac @@ -1513,8 +1517,9 @@ cmd_ship() { for up in $(upstreams_of "$wave" "$repo"); do pv="$(mget "$wave" --arg r "$repo" --arg u "$up" '.repos[$r].pin_vector[$u] // empty')" [ -n "$pv" ] || continue - # Drift the registry cannot reveal: the upstream re-bumped after this repo - # was pinned (a collision or a failed publish), but the old pin is public. + # Re-bump drift the registry cannot reveal: the upstream re-bumped after + # this repo was pinned (a collision or a failed publish), but the old + # pinned version is still public. local tvu; tvu="$(mget "$wave" --arg r "$up" '.repos[$r].target_version // empty')" if [ -n "$tvu" ] && [ "$tvu" != "$pv" ]; then warn "upstream $up re-bumped ($pv -> $tvu) — run: ./cascade refresh $repo"; exit 3 @@ -1527,9 +1532,10 @@ cmd_ship() { fi warn "waiting: $up $pv not yet in the registry"; exit 4 fi - # A copy the wave did not publish is the base branch's build of that version. + # A registry copy the wave did not publish is the base branch's build of + # that version. wave_pr_merged "$wave" "$up" || { - warn "upstream $up $pv: the registry serves $BASE's build of that version, not the wave's" + warn "upstream $up $pv: the registry serves $BASE's build, not the wave's" warn "re-bump $up first (REBUMP in ./cascade next), then: ./cascade refresh $repo" exit 3; } # The marker alone may come from a publish that failed midway. diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 772eef2..9bd48bc 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -99,25 +99,27 @@ and execute what it prints, in order: repo — three adapt→rebuild rounds, then auto-park). Exit 5 = throttling halt. - `PREPR:` → run the `pre-pr` skill inside the repo (writes the sentinel). - `SHIP:` → `./cascade ship ` — sentinel gate, upstream-published - gate (the upstream has not re-bumped since the pin, the registry serves its - version *from the wave's merged PR*, and its `publish.yml` run for the merge - commit succeeded), floor gate (every version + gate (the upstream has not re-bumped since this repo pinned it, the registry + serves its version *and* the upstream's wave PR for it has merged, and its + `publish.yml` run for the merge commit succeeded), floor gate (every version the repo pins — forward upstreams *and* published floors — proven in the registry, derived from the pin files by content, since floors never appear in the manifest), drift gate, push, PR. Exit 4 means an upstream is not - published yet: wait, don't force. + published yet: wait, don't force. Exit 3 from the upstream gate (the upstream + re-bumped, collided with the base branch, or failed to publish) means + re-pinning with `./cascade refresh ` once the upstream is fixed. - `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR merged. A run that fails midway may already have uploaded some modules, so the registry's marker artifact proves nothing; `./cascade status` links the - run. Fix the build, publish a new version, and re-pin the downstream repos - (`./cascade refresh `). Downstream repos wait meanwhile. -- `REBUMP:` → the registry serves the repo's wave version, but the wave's - PR has not merged: the base branch took the same version first, so the + run. Fix the build, publish a new version, and re-pin each downstream repo + with `./cascade refresh `. Downstream repos wait meanwhile. +- `REBUMP:` → the registry serves the repo's wave version, but the repo's + wave PR has not merged: the base branch took the same version first, so the registry holds the base branch's build, not the wave's. Merge the base branch - into the wave branch (a `version.gradle.kts` conflict follows the - `bump-version` Conflict Rule), then `./cascade refresh ` bumps past it. - Rebuild it, and re-pin each downstream repo with - `./cascade refresh `. + into the wave branch, resolving a `version.gradle.kts` conflict by the + `bump-version` Conflict Rule, then run `./cascade refresh ` to re-bump + past the base branch's version. Rebuild the repo, and re-pin each downstream + repo with `./cascade refresh `. Downstream repos wait meanwhile. - `WAIT-*` only → `./cascade await` (background it) — exits the moment the action set changes; then run `next` again. - `CLOSE` → `./cascade close` — stages the final vector in `config` (floors From 8b792b445c1471ce479d02c87424c1a68bdf8317 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 00:05:40 +0100 Subject: [PATCH 21/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 72 +++++++++++++++------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 6e7c678..e2e33c0 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", @@ -281,10 +281,13 @@ "tool-base": "2.0.0-SNAPSHOT.426" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "964398a378c866f769ce6f4cce850c8b20163d19", + "at": "2026-10-16T21:50:25Z" + }, "pr": { "url": "https://github.com/SpineEventEngine/validation/pull/332", - "head": "808b2a34f08951a57c376cdc0c1eeda71cafc4b1" + "head": "964398a378c866f769ce6f4cce850c8b20163d19" }, "parked": null }, @@ -317,8 +320,11 @@ "tool-base": "2.0.0-SNAPSHOT.426", "validation": "2.0.0-SNAPSHOT.465" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "50bbdfdc7b2f34d324495baff3b9ce02a1c2a310", + "at": "2026-10-16T23:04:25Z" + }, "pr": null, "parked": null }, @@ -336,7 +342,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -346,7 +352,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "6cfbcdef3b1bbc640fe588f8cf0f9c7939a59152", + "at": "2026-10-16T22:36:46Z" + }, "pr": null, "parked": null }, @@ -363,7 +372,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -372,7 +381,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": null, + "built": { + "head": "6f74f8b6afbb88088cd04b5d003df2048d90d086", + "at": "2026-10-16T22:37:21Z" + }, "pr": null, "parked": null }, @@ -393,7 +405,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.3", @@ -406,7 +418,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": null, + "built": { + "head": "d73aa1d78248b05880419143bddb3d83d116364c", + "at": "2026-10-16T22:38:44Z" + }, "pr": null, "parked": null }, @@ -424,7 +439,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -434,7 +449,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "d435a853f42a6aead6ed6733017d8a3f57690603", + "at": "2026-10-16T22:39:04Z" + }, "pr": null, "parked": null }, @@ -456,7 +474,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.572", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -470,7 +488,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": null, + "built": { + "head": "77ac8090e0e0e077de583977b7cf536bb59d0512", + "at": "2026-10-16T22:45:14Z" + }, "pr": null, "parked": null }, @@ -486,7 +507,7 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "core-jvm": "2.0.0-SNAPSHOT.572", @@ -494,7 +515,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "ccfb397ddda4df12acaf275ab019c0cb9e16c9d6", + "at": "2026-10-16T22:46:46Z" + }, "pr": null, "parked": null }, @@ -515,7 +539,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "bumped", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -528,7 +552,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "567a3173a80a2d7ec4005a6b10d137759f609352", + "at": "2026-10-16T22:48:56Z" + }, "pr": null, "parked": null }, @@ -548,7 +575,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "bumped", + "state": "published-local", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.074", @@ -560,7 +587,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "799a899d46648b5d5db6bfb0ef54ae9932440ded", + "at": "2026-10-16T23:00:09Z" + }, "pr": null, "parked": null }, From e87523c0edb72c4d38ef9cc0a7153e167c665f2f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 00:19:32 +0100 Subject: [PATCH 22/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-a0cbbbf.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index e2e33c0..cbd62eb 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "published-local", + "state": "pr-open", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", @@ -308,7 +308,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", @@ -342,7 +342,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.226", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -372,7 +372,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -405,7 +405,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.3", @@ -439,7 +439,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -474,7 +474,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.572", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -507,7 +507,7 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "core-jvm": "2.0.0-SNAPSHOT.572", @@ -539,7 +539,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -575,7 +575,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "published-local", + "state": "pr-ready", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.074", From 837e5a7b61b813d267f027efd80118f8a7e6d5e9 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 02:32:56 +0100 Subject: [PATCH 23/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index cbd62eb..8ebf1ff 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -282,12 +282,12 @@ }, "adapt_rounds": 0, "built": { - "head": "964398a378c866f769ce6f4cce850c8b20163d19", - "at": "2026-10-16T21:50:25Z" + "head": "24363727adb7222598dcef60b19304235afbc1d5", + "at": "2026-10-17T01:32:28Z" }, "pr": { "url": "https://github.com/SpineEventEngine/validation/pull/332", - "head": "964398a378c866f769ce6f4cce850c8b20163d19" + "head": "24363727adb7222598dcef60b19304235afbc1d5" }, "parked": null }, From aba4e9729caf7eb2cea9af424a3eab7ffafa4545 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 02:48:27 +0100 Subject: [PATCH 24/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 8ebf1ff..5b1b2de 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -282,12 +282,12 @@ }, "adapt_rounds": 0, "built": { - "head": "24363727adb7222598dcef60b19304235afbc1d5", - "at": "2026-10-17T01:32:28Z" + "head": "5f3f2ef48bece50a1511b036b50dc65381d12e04", + "at": "2026-10-17T01:47:54Z" }, "pr": { "url": "https://github.com/SpineEventEngine/validation/pull/332", - "head": "24363727adb7222598dcef60b19304235afbc1d5" + "head": "5f3f2ef48bece50a1511b036b50dc65381d12e04" }, "parked": null }, From 62bea88315684be16dda15f3085ce9ad5dea92df Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 08:33:13 +0100 Subject: [PATCH 25/65] Keep a merged repo out of `prep` while its publish is pending When a repo's wave PR has merged but the registry does not serve its target yet, `derive_state` fell through to the branch checks. A publish that failed before uploading anything (validation `.465` hit HTTP 429 while configuring) plus commits pushed to the branch after the merge then read as `pinned`, and `next` asked to `prep`, which would bump the repo again. Such a repo is now `merged`, or `publish-failed` once its publish run failed. Co-Authored-By: Claude Opus 5.5 --- cascade | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cascade b/cascade index f4247f0..2afd453 100755 --- a/cascade +++ b/cascade @@ -1113,6 +1113,19 @@ derive_state() { # -> prints state esac fi + # The wave's PR merged, but the registry does not serve the target yet: the + # publish run is pending, or it failed before uploading the marker (validation + # `.465` hit HTTP 429 while configuring). Commits pushed to the branch after + # the merge must not read as a fresh branch that needs `prep` again. + if [ -n "$tvp" ] && [ -n "$(mget "$wave" --arg r "$repo" '.repos[$r].pr.url // empty')" ] \ + && wave_pr_merged "$wave" "$repo"; then + case "$(publish_verdict "$wave" "$repo")" in + failed\ *) echo publish-failed ;; + *) echo merged ;; + esac + return + fi + local subjects subjects="$(git -C "$dir" log --format=%s "origin/$BASE..$branch" 2>/dev/null || true)" From ead23f75a9681bfe519996cb7c734f063072e3cd Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 08:33:13 +0100 Subject: [PATCH 26/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-a0cbbbf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 5b1b2de..6621d34 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "pr-open", + "state": "merged", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", From e734ffafd4d34d4fe5b86b2c2ff89714fbfb38e4 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Sat, 17 Oct 2026 08:46:34 +0100 Subject: [PATCH 27/65] Update cascade state --- .agents/tasks/cascade-refresh-a0cbbbf.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index 6621d34..bf32167 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "merged", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.465", "pin_vector": { "ProtoTap": "0.17.3", @@ -325,7 +325,10 @@ "head": "50bbdfdc7b2f34d324495baff3b9ce02a1c2a310", "at": "2026-10-16T23:04:25Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/core-jvm-compiler/pull/119", + "head": "50bbdfdc7b2f34d324495baff3b9ce02a1c2a310" + }, "parked": null }, "base-types": { From 751bd2a6fd57c80152441cb174be7aa08d6ef62b Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 19 Oct 2026 18:58:19 +0100 Subject: [PATCH 28/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-a0cbbbf.json | 25 +++++++--------------- .agents/tasks/cascade-refresh-a0cbbbf.md | 1 + 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index bf32167..e3d5dad 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -308,7 +308,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "pr-ready", + "state": "pr-open", "target_version": "2.0.0-SNAPSHOT.098", "pin_vector": { "ProtoTap": "0.17.3", @@ -345,8 +345,8 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "pr-ready", - "target_version": "2.0.0-SNAPSHOT.226", + "state": "collision", + "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", "compiler": "2.0.0-SNAPSHOT.074", @@ -355,10 +355,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "6cfbcdef3b1bbc640fe588f8cf0f9c7939a59152", - "at": "2026-10-16T22:36:46Z" - }, + "built": null, "pr": null, "parked": null }, @@ -481,7 +478,7 @@ "target_version": "2.0.0-SNAPSHOT.572", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "base-types": "2.0.0-SNAPSHOT.226", + "base-types": "2.0.0-SNAPSHOT.227", "change": "2.0.0-SNAPSHOT.209", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", "logging": "2.0.0-SNAPSHOT.426", @@ -491,10 +488,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": { - "head": "77ac8090e0e0e077de583977b7cf536bb59d0512", - "at": "2026-10-16T22:45:14Z" - }, + "built": null, "pr": null, "parked": null }, @@ -546,7 +540,7 @@ "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", - "base-types": "2.0.0-SNAPSHOT.226", + "base-types": "2.0.0-SNAPSHOT.227", "compiler": "2.0.0-SNAPSHOT.074", "core-jvm": "2.0.0-SNAPSHOT.572", "core-jvm-compiler": "2.0.0-SNAPSHOT.098", @@ -555,10 +549,7 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": { - "head": "567a3173a80a2d7ec4005a6b10d137759f609352", - "at": "2026-10-16T22:48:56Z" - }, + "built": null, "pr": null, "parked": null }, diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/cascade-refresh-a0cbbbf.md index 5350d20..1629eb3 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.md +++ b/.agents/tasks/cascade-refresh-a0cbbbf.md @@ -41,3 +41,4 @@ Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). P - 2026-10-16 — **parked** `validation`: waiting for a complete compiler publish: compiler .072's publish aborted at test-env's PublicationChecksums (config#764) before compiler-testlib uploaded; a compiler fix + config update + new compiler version are in progress, after which validation, core-jvm-compiler and time re-pin to it - 2026-10-16 — retargeted `compiler` to `2.0.0-SNAPSHOT.074`: the publish of the wave's `.072` (compiler#91) failed midway at test-env's PublicationChecksums, leaving `compiler-testlib` unpublished; compiler#92 fixed the attestation and published `.074` completely. The local wave branch was fast-forwarded to master; downstream repos re-pin to `.074`. - 2026-10-16 — resumed `validation`. +- 2026-10-19 — `base-types` collided: base-types#56 took `2.0.0-SNAPSHOT.226` on master. Merged master into the wave branch (the wave already carried its change) and re-bumped to `.227`; `core-jvm` and `gcloud-jvm` re-pinned. From 2157d5069e84ac14097cc5e96cf653e8f3dd1e38 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Mon, 19 Oct 2026 19:11:32 +0100 Subject: [PATCH 29/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-a0cbbbf.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/cascade-refresh-a0cbbbf.json index e3d5dad..a85fedb 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.json +++ b/.agents/tasks/cascade-refresh-a0cbbbf.json @@ -345,7 +345,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "collision", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.461", @@ -355,7 +355,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "8cfdadcb777933dd664588e1747a1a40dac388dd", + "at": "2026-10-19T17:59:49Z" + }, "pr": null, "parked": null }, @@ -488,7 +491,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 2, - "built": null, + "built": { + "head": "1e156115678edf65328bae253816bc60eed84e36", + "at": "2026-10-19T18:05:12Z" + }, "pr": null, "parked": null }, @@ -549,7 +555,10 @@ "validation": "2.0.0-SNAPSHOT.465" }, "adapt_rounds": 1, - "built": null, + "built": { + "head": "cbe4787e7e482cb2916b742cfa5064b99d82b26b", + "at": "2026-10-19T18:07:22Z" + }, "pr": null, "parked": null }, From f37afb861b33e7de925ef81ef3f8f4abf772f632 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 16:23:11 +0100 Subject: [PATCH 30/65] Archive the superseded `cascade-refresh-a0cbbbf` wave The wave restarts from `config@604420c`, which caps Kotlin at the version the Gradle in use embeds. Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/{ => archive}/cascade-refresh-a0cbbbf.json | 0 .agents/tasks/{ => archive}/cascade-refresh-a0cbbbf.md | 1 + 2 files changed, 1 insertion(+) rename .agents/tasks/{ => archive}/cascade-refresh-a0cbbbf.json (100%) rename .agents/tasks/{ => archive}/cascade-refresh-a0cbbbf.md (84%) diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.json b/.agents/tasks/archive/cascade-refresh-a0cbbbf.json similarity index 100% rename from .agents/tasks/cascade-refresh-a0cbbbf.json rename to .agents/tasks/archive/cascade-refresh-a0cbbbf.json diff --git a/.agents/tasks/cascade-refresh-a0cbbbf.md b/.agents/tasks/archive/cascade-refresh-a0cbbbf.md similarity index 84% rename from .agents/tasks/cascade-refresh-a0cbbbf.md rename to .agents/tasks/archive/cascade-refresh-a0cbbbf.md index 1629eb3..8976f84 100644 --- a/.agents/tasks/cascade-refresh-a0cbbbf.md +++ b/.agents/tasks/archive/cascade-refresh-a0cbbbf.md @@ -42,3 +42,4 @@ Machine state: [`cascade-refresh-a0cbbbf.json`](cascade-refresh-a0cbbbf.json). P - 2026-10-16 — retargeted `compiler` to `2.0.0-SNAPSHOT.074`: the publish of the wave's `.072` (compiler#91) failed midway at test-env's PublicationChecksums, leaving `compiler-testlib` unpublished; compiler#92 fixed the attestation and published `.074` completely. The local wave branch was fast-forwarded to master; downstream repos re-pin to `.074`. - 2026-10-16 — resumed `validation`. - 2026-10-19 — `base-types` collided: base-types#56 took `2.0.0-SNAPSHOT.226` on master. Merged master into the wave branch (the wave already carried its change) and re-bumped to `.227`; `core-jvm` and `gcloud-jvm` re-pinned. +- 2026-10-21 — superseded: the wave restarts as `cascade-refresh-604420c` with `config@604420c` (Gradle 9.8.2, Kotlin capped at the Gradle-embedded 2.4.10). Published here: base-libraries .461, reflect .202, logging .426, testlib .215, dokka-tools .11, tool-base .426, ProtoTap 0.17.3, compiler .074, validation .465. Unshipped branches carry over; core-jvm-compiler#119 closed. From 0a91ca31ad8dbb68f0ecb7a7d107286b3ec6740b Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 16:24:46 +0100 Subject: [PATCH 31/65] Update shared agent tooling and config (./config/pull) Brings `config` to `604420c` (Gradle 9.8.2, Kotlin capped at the Gradle-embedded 2.4.10) for the restarted wave, keeping the summit-only allow entries the template overwrite dropped: `./gradlew clean`, `./cascade`, `gh pr view`, `gh pr list`, `gh run list`. Co-Authored-By: Claude Opus 5.5 --- .claude/settings.json | 18 +++-- AGENTS.md | 34 ++++++--- config | 2 +- init-submodules | 168 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 180 insertions(+), 42 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index 460b219..e4b756f 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -15,6 +15,7 @@ "Bash(git switch:*)", "Bash(git checkout:*)", "Bash(git add:*)", + "Bash(git commit:*)", "Bash(git restore:*)", "Bash(git stash:*)", "Bash(git fetch:*)", @@ -39,7 +40,6 @@ "Bash(./config/migrate)", "Skill(pre-pr)", "Skill(pre-pr:*)", - "Bash(git commit:*)", "Bash(./cascade:*)", "Bash(gh pr view:*)", "Bash(gh pr list:*)", @@ -48,21 +48,27 @@ "deny": [ "Bash(git reset --hard:*)", "Bash(git clean -fdx:*)", - "Bash(git push --force:*)", - "Bash(git push -f:*)", - "Bash(git push --force-with-lease:*)", "Bash(rm -rf /:*)", "Bash(rm -rf ~:*)", "Bash(gh pr merge:*)", "Bash(gh release create:*)" ], "ask": [ + "Bash(git push --force*)", + "Bash(git push * --force*)", + "Bash(git push -f*)", + "Bash(git push * -f*)", + "Bash(git push -uf*)", + "Bash(git push * -uf*)", + "Bash(git push * +*)", + "Bash(git push --mirror*)", + "Bash(git push * --mirror*)", "Bash(git rebase:*)", - "Bash(git tag:*)", "Bash(git merge:*)", "Bash(git cherry-pick:*)", "Bash(./gradlew publish:*)", - "Bash(./gradlew uploadArtifacts:*)" + "Bash(./gradlew uploadArtifacts:*)", + "Bash(./gradlew clean:*)" ] }, "hooks": { diff --git a/AGENTS.md b/AGENTS.md index 8c5f619..dc6927f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,17 +20,29 @@ Shared skills, scripts, and guidelines come from the `.agents/shared` submodule (and some shallow clones / cloud checkouts) start with NO submodules checked out, so those symlinks dangle and no skills are found. Bootstrap such a tree with **`./init-submodules`** — a root script that materializes the missing -*config-managed* submodules at their pinned commits: `config` itself, plus every -submodule that declares a tracked `branch` in `.gitmodules` (`.agents/shared`, and -any shared submodule added later) — the same rule `./config/pull` uses to decide -what it floats. Submodules the consumer owns (a Hugo theme, a vendored library, -doc-example submodules, …) declare no tracked branch and are left untouched, so the -automatic `SessionStart` run never tries to clone — or fail on credentials for — a -submodule this project does not manage. It depends on no pre-existing `config` -submodule, so it works before `./config/pull` (which lives inside the `config` -submodule) can. Claude Code runs it automatically via a `SessionStart` hook; other -agents and humans run it by hand, then `./config/pull` to float the shared submodules -to their branch tips. +*config-managed* submodules at the tip of their branch (`master` for `config`, the +tracked `branch` for the rest): `config` itself, plus every submodule that declares +a tracked `branch` in `.gitmodules` (`.agents/shared`, and any shared submodule +added later) — the same rule `./config/pull` uses to decide what it floats. It +deliberately does not stop at the commit the superproject pins for such a +submodule: nothing keeps that pin current — `ignore = all` hides the submodule from +`git status`, and `./config/pull` floats the on-disk copy without committing the +moved gitlink — so materializing the pin as-is means months-old hook scripts, +skills, and guidelines. If the float fails — a branch the remote does not have, +say — a warning is printed and the submodule is left wherever the steps that +did succeed put it, at worst the pin, so a session still starts with a usable +tree; it is not retried on a later run, which is why that warning points at +`./config/pull`. With no network at all the clone itself fails and the +submodule is left uninitialized, as it was before. Submodules the consumer owns +(a Hugo theme, a vendored library, doc-example submodules, …) declare no tracked +branch and are left untouched, so the automatic `SessionStart` run never tries +to clone — or fail on credentials for — a submodule this project does not +manage. A submodule that is already checked out is left exactly as it is, which +keeps repeated runs cheap and offline-safe and never rewinds a tree someone +parked on a particular commit; run `./config/pull` to float those. It depends on +no pre-existing `config` submodule, so it works before `./config/pull` (which +lives inside the `config` submodule) can. Claude Code runs it automatically via +a `SessionStart` hook; other agents and humans run it by hand. ## Commit and history safety diff --git a/config b/config index 3409e7d..604420c 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit 3409e7dd193e8cb7da82467d01039140c79f84ab +Subproject commit 604420cd7eab82b382c9a5c1d812be454552c27c diff --git a/init-submodules b/init-submodules index 95b916b..64bb085 100755 --- a/init-submodules +++ b/init-submodules @@ -17,10 +17,10 @@ # (distributed by `config`), so `git worktree add` always checks it out — it can # therefore bring `config` itself into existence. # -# It initializes ONLY submodules that are BOTH: +# It acts ONLY on submodules that are BOTH: # -# * not yet checked out — those `git submodule status` marks with a leading `-`, -# at the commit the branch pins; and +# * not yet checked out — those `git submodule status` marks with a leading +# `-`; and # # * config-managed — `config` itself (the bootstrap target `pull` lives inside, # which carries no tracked `branch` in a consumer's `.gitmodules`), plus every @@ -28,6 +28,33 @@ # the rule `./config/pull` uses to decide what it floats, so the two scripts # can never disagree about what is shared. # +# Such a submodule is initialized and then advanced to the tip of its tracked +# branch, the way `./config/pull` floats it — NOT left at the commit the +# superproject pins. That pin is not a version anyone maintains: `.gitmodules` +# declares `ignore = all` for `.agents/shared`, which hides the submodule from +# `git status` and `git diff`, and `./config/pull` floats the on-disk copy without +# ever committing the moved gitlink. The pin therefore still holds the value it +# had on the day the submodule was adopted; an audit of all 19 Spine consumer +# repositories on 2026-10-16 found every one of them months stale. Materializing +# it hands a fresh worktree, CI checkout, or cloud session hook scripts, skills, +# and guidelines that are months out of date. +# +# A submodule may declare `branch = .`, which gitmodules(5) defines as the branch +# the superproject is on rather than a branch name. It is resolved before it +# reaches a refspec, because `git fetch origin .` is a `fatal: invalid refspec`. +# Nothing in Spine declares it today — `.agents/shared` tracks `agents`' `master` +# whatever branch the consumer is on — but it is valid in any `.gitmodules`. +# +# Neither the clone nor the float can fail the session start. With no network at +# all the clone is what fails: the submodule is left uninitialized and the +# symlinks keep dangling until a run that has a network, exactly as before this +# script floated anything. A float that fails after a successful clone — a branch +# the remote does not have, a fetch that dies midway, a local branch that is not +# a fast-forward — warns and leaves the submodule wherever the steps that did +# succeed put it: at worst the pin, a usable, if older, tree. The submodule is +# checked out by then, so later runs no longer see a `-` line for it and never +# retry the float — which is why the warning points at `./config/pull`. +# # Consumer-owned submodules (a Hugo theme, a vendored library, documentation # examples, ...) declare no tracked branch and are deliberately left untouched. # Because a `SessionStart` hook runs this script automatically on every session, @@ -35,15 +62,14 @@ # a submodule this project does not manage, on every single start. They are # skipped (noted on stderr). # -# Submodules already present are left exactly as they are, so a tree that floated -# `config` / `.agents/shared` to a branch tip via `./config/pull` is never -# silently rewound to the pin. That makes the script idempotent and safe to run on -# every session start. +# Submodules already present are left exactly as they are, neither rewound to the +# pin nor advanced. That keeps the script idempotent, keeps the runs that find +# nothing missing free of network access, and never disturbs a tree whose +# submodules someone deliberately parked on a particular commit. Run +# `./config/pull` to float those. # -# It does NOT float submodules to their branch tips — run `./config/pull` -# afterwards for that. Unlike `pull`, it depends on no pre-existing `config` -# submodule, so it can bootstrap a bare worktree where `./config/pull` does not -# yet exist. +# Unlike `pull`, this script depends on no pre-existing `config` submodule, so it +# can bootstrap a bare worktree where `./config/pull` does not yet exist. # ################################################################################ @@ -133,19 +159,29 @@ cd "$root" || exit 0 # Nothing to do in a repo without submodules. [ -f .gitmodules ] || exit 0 -# The set of config-managed submodule paths: `config` itself (handled specially — -# it carries no tracked branch, exactly as in `./config/pull`), plus every -# submodule declaring a tracked `branch` in `.gitmodules`. Mirrors `pull`'s rule. -config_managed_paths() { - printf '%s\n' 'config' +# The config-managed submodules, as `pathbranch` lines: every submodule that +# declares a tracked `branch` in `.gitmodules`, plus `config` itself — which +# carries no tracked branch in a consumer's `.gitmodules`, and which +# `./config/pull` floats to `master` in its step 1. Mirrors `pull`'s rule. The +# declared entries come first, so a `.gitmodules` that does give `config` a +# tracked branch wins over that default. +config_managed() { git config -f .gitmodules --get-regexp '^submodule\..*\.branch$' 2>/dev/null \ - | while read -r key _branch; do + | while read -r key branch; do name=${key#submodule.}; name=${name%.branch} - git config -f .gitmodules --get "submodule.$name.path" 2>/dev/null + path=$(git config -f .gitmodules --get "submodule.$name.path" 2>/dev/null) || continue + printf '%s\t%s\n' "$path" "$branch" done + printf '%s\t%s\n' 'config' 'master' } -managed=$(config_managed_paths | sort -u) +managed=$(config_managed) + +# The branch the submodule at `$1` tracks; empty when that path is not +# config-managed at all. The first match wins, as noted above. +tracked_branch() { + printf '%s\n' "$managed" | awk -F'\t' -v path="$1" '$1 == path { print $2; exit }' +} # `git submodule status` prefixes each uninitialized submodule with `-`; an # initialized one starts with a space (at the pinned commit) or `+` (ahead of it). @@ -153,13 +189,97 @@ managed=$(config_managed_paths | sort -u) # that path is config-managed. git submodule status 2>/dev/null | awk '$1 ~ /^-/ { print $2 }' | while read -r path; do [ -n "$path" ] || continue - if printf '%s\n' "$managed" | grep -qxF -- "$path"; then - echo "init-submodules: initializing '$path'" - git submodule update --init --recursive -- "$path" \ - || echo "init-submodules: WARNING — could not initialize '$path' (offline?)." >&2 - else + branch=$(tracked_branch "$path") + if [ -z "$branch" ]; then echo "init-submodules: skipping consumer-owned '$path' (not config-managed)." >&2 + continue + fi + echo "init-submodules: initializing '$path'" + git submodule update --init --recursive -- "$path" &2 + continue + } + # `.gitmodules` may declare `branch = .`, which gitmodules(5) defines as the + # branch the superproject itself is on. That is a sentinel, not a ref: passed + # through, it dies with `fatal: invalid refspec '.'`, and because the clone + # has already succeeded by then the submodule would keep the pin and never be + # retried. Resolve it to the current branch name. A detached superproject has + # no name to inherit, so the float is skipped and the pin kept — the one case + # where `./config/pull` is the only way forward, once on a branch. + if [ "$branch" = "." ]; then + # `git branch --show-current` prints the name exactly, and prints nothing + # when `HEAD` is detached. `git rev-parse --abbrev-ref HEAD` cannot stand + # in: it shortens to a *non-ambiguous* name, so a superproject carrying + # both a branch and a tag called `foo` yields `heads/foo`; the fetch + # then succeeds but the checkout fails, leaving this freshly + # initialized submodule stale and never retried. `./config/pull` + # resolves it the same way, for the same reason. + branch=$(git branch --show-current 2>/dev/null) + if [ -z "$branch" ]; then + echo "init-submodules: WARNING — '$path' tracks the superproject's" \ + "branch ('.'), which is detached here; left at the pin. Run" \ + "'./config/pull' from a branch to float it." >&2 + continue + fi fi + # What that just checked out is the superproject's pin, which nobody + # maintains (see the header). Advance the fresh checkout to the tip of its + # tracked branch, leaving it ON the branch rather than in a detached `HEAD` — + # the same three steps `./config/pull` takes in its step 2, both scripts + # naming the fetch destination and the checkout start point, for the two + # reasons below. A failure leaves the submodule wherever the steps that did + # succeed put it, so the warning promises no particular commit, as `pull`'s + # does not. + # + # The fetch names its destination. A bare `git fetch origin ` relies + # on the refspec configured for the remote to update + # `refs/remotes/origin/` opportunistically as well, which a full + # clone's does. But a submodule declaring `shallow = true` in `.gitmodules` + # is cloned single-branch (a shallow clone implies `--single-branch`), as + # `+refs/heads/:refs/remotes/origin/`, so any other tracked + # branch lands in `FETCH_HEAD` alone, `refs/remotes/origin/` never + # appears, and the checkout below fails. Spelling the refspec out makes the + # float work whatever refspec the clone carries, and the leading `+` matches + # what a default clone configures. + # + # The checkout asks whether the branch exists locally rather than letting Git + # work it out, because both answers are otherwise wrong in a reachable case. + # A fresh clone has a local branch only for the default branch, so `-b` alone + # would fail with `already exists` on the common path. And plain + # `git checkout ` is not a reliable substitute: with no local branch + # of that name it guesses one from a remote-tracking ref, considering only + # refs the remote's fetch refspec covers — so in the single-branch clone + # above it fails even though the explicit fetch did create + # `refs/remotes/origin/` — and if the submodule carries a *tag* of + # that name it quietly resolves the tag and detaches `HEAD` instead, which + # the `--ff-only` below then fast-forwards to the right commit on no branch + # at all. Naming the start point avoids both. + # + # `merge --ff-only` is kept after either path: a local branch that has + # diverged from `origin/` is reported rather than overwritten. + # Nothing here force-moves a ref except the remote-tracking ref the fetch + # owns, which a default clone force-updates anyway. + # + # It merges `refs/remotes/origin/`, not the `origin/` + # shorthand, for the reason the checkout above spells a ref out too. + # gitrevisions(7) resolves a bare name through `refs/tags/` BEFORE + # `refs/remotes/`, so a tag literally named `origin/` wins the + # shorthand — and then this merge would fast-forward the branch the + # checkout just placed exactly onto whatever that tag points at, reporting + # success. Every ref in the chain is therefore fully qualified. + echo "init-submodules: floating '$path' -> origin/$branch" + ( cd "$path" \ + && git fetch --quiet origin \ + "+refs/heads/$branch:refs/remotes/origin/$branch" \ + && if git show-ref --verify --quiet "refs/heads/$branch"; then \ + git checkout --quiet "$branch"; \ + else \ + git checkout --quiet -b "$branch" \ + "refs/remotes/origin/$branch"; \ + fi \ + && git merge --quiet --ff-only "refs/remotes/origin/$branch" ) &2 done # Route Git hooks to the shared hooks directory so the secret-scan `pre-commit` From 508e098740a3c9b544c4fd57ec478ed89649fbc2 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 16:25:39 +0100 Subject: [PATCH 32/65] Plan the `cascade-refresh-604420c` wave Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-604420c.json | 442 +++++++++++++++++++++ .agents/tasks/cascade-refresh-604420c.md | 37 ++ 2 files changed, 479 insertions(+) create mode 100644 .agents/tasks/cascade-refresh-604420c.json create mode 100644 .agents/tasks/cascade-refresh-604420c.md diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json new file mode 100644 index 0000000..d5ccb43 --- /dev/null +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -0,0 +1,442 @@ +{ + "schema": 1, + "wave": "cascade-refresh-604420c", + "kind": "refresh", + "created": "2026-10-21T15:25:26Z", + "base": "master", + "config_sha": "604420cd7eab82b382c9a5c1d812be454552c27c", + "seed": null, + "target": null, + "branch": "cascade-refresh-604420c", + "halted": null, + "order": [ + "base-libraries", + "reflect", + "logging", + "testlib", + "dokka-tools", + "tool-base", + "ProtoTap", + "compiler", + "validation", + "core-jvm-compiler", + "base-types", + "change", + "time", + "money", + "core-jvm", + "jdbc-storage", + "gcloud-jvm", + "delivery", + "BuildSpeed" + ], + "repos": { + "base-libraries": { + "upstreams": [], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-base" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "reflect": { + "upstreams": [], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-reflect" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "logging": { + "upstreams": [ + "base-libraries", + "reflect" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-logging" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "testlib": { + "upstreams": [ + "logging" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "base-testlib" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "dokka-tools": { + "upstreams": [ + "base-libraries" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "dokka-extensions" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "tool-base": { + "upstreams": [ + "base-libraries", + "logging", + "testlib" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "jvm-tools" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "ProtoTap": { + "upstreams": [ + "base-libraries", + "logging", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/tools", + "artifact": "prototap-gradle-plugin" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "compiler": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "logging", + "reflect", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "compilerVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "compiler-jvm" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "validation": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "logging", + "reflect", + "testlib", + "tool-base" + ], + "class": "library", + "version_property": "validationVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "validation-java" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "core-jvm-compiler": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "logging", + "reflect", + "testlib", + "tool-base", + "validation" + ], + "class": "library", + "version_property": "coreJvmCompilerVersion", + "probe": { + "group_path": "io/spine/tools", + "artifact": "core-jvm-gradle-plugin" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "base-types": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-base-types" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "change": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-change" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "time": { + "upstreams": [ + "ProtoTap", + "base-libraries", + "compiler", + "core-jvm-compiler", + "logging", + "testlib", + "tool-base", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-time" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "money": { + "upstreams": [ + "base-libraries", + "compiler", + "core-jvm-compiler", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-money" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "core-jvm": { + "upstreams": [ + "base-libraries", + "base-types", + "change", + "compiler", + "core-jvm-compiler", + "logging", + "reflect", + "testlib", + "time", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-core" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "jdbc-storage": { + "upstreams": [ + "compiler", + "core-jvm", + "core-jvm-compiler", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine", + "artifact": "spine-rdbms" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "gcloud-jvm": { + "upstreams": [ + "base-libraries", + "base-types", + "compiler", + "core-jvm", + "core-jvm-compiler", + "logging", + "testlib", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/gcloud", + "artifact": "spine-datastore" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "delivery": { + "upstreams": [ + "compiler", + "core-jvm", + "core-jvm-compiler", + "logging", + "testlib", + "time", + "validation" + ], + "class": "library", + "version_property": "versionToPublish", + "probe": { + "group_path": "io/spine/delivery", + "artifact": "spine-delivery-server" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + }, + "BuildSpeed": { + "upstreams": [ + "core-jvm-compiler" + ], + "class": "verify-only", + "version_property": "", + "probe": { + "group_path": "", + "artifact": "" + }, + "state": "pending", + "target_version": null, + "pin_vector": {}, + "adapt_rounds": 0, + "built": null, + "pr": null, + "parked": null + } + }, + "excluded": {}, + "closing_pr": null +} diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md new file mode 100644 index 0000000..49436d0 --- /dev/null +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -0,0 +1,37 @@ +--- +slug: cascade-refresh-604420c +branch: cascade-refresh-604420c +owner: cascade +status: in-progress +started: 2026-10-21 +--- + +# Wave `cascade-refresh-604420c` (refresh) + +Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). Park reasons and decisions land here. + +## Repos + +- [ ] base-libraries +- [ ] reflect +- [ ] logging +- [ ] testlib +- [ ] dokka-tools +- [ ] tool-base +- [ ] ProtoTap +- [ ] compiler +- [ ] validation +- [ ] core-jvm-compiler +- [ ] base-types +- [ ] change +- [ ] time +- [ ] money +- [ ] core-jvm +- [ ] jdbc-storage +- [ ] gcloud-jvm +- [ ] delivery +- [ ] BuildSpeed + +## Log + +- 2026-10-21 — wave planned. From 4ab5407052036b0a31e2bfb812a38b33ac64c8ec Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 16:40:21 +0100 Subject: [PATCH 33/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-604420c.json | 207 +++++++++++++++------ .agents/tasks/cascade-refresh-604420c.md | 1 + 2 files changed, 154 insertions(+), 54 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index d5ccb43..d5296ed 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -39,8 +39,8 @@ "group_path": "io/spine", "artifact": "spine-base" }, - "state": "pending", - "target_version": null, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.462", "pin_vector": {}, "adapt_rounds": 0, "built": null, @@ -55,8 +55,8 @@ "group_path": "io/spine", "artifact": "spine-reflect" }, - "state": "pending", - "target_version": null, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.203", "pin_vector": {}, "adapt_rounds": 0, "built": null, @@ -74,9 +74,12 @@ "group_path": "io/spine", "artifact": "spine-logging" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.427", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "reflect": "2.0.0-SNAPSHOT.203" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -92,9 +95,11 @@ "group_path": "io/spine/tools", "artifact": "base-testlib" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.216", + "pin_vector": { + "logging": "2.0.0-SNAPSHOT.427" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -110,9 +115,11 @@ "group_path": "io/spine/tools", "artifact": "dokka-extensions" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.12", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -130,9 +137,13 @@ "group_path": "io/spine/tools", "artifact": "jvm-tools" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.428", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "logging": "2.0.0-SNAPSHOT.427", + "testlib": "2.0.0-SNAPSHOT.216" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -151,9 +162,14 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "0.17.4", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "logging": "2.0.0-SNAPSHOT.427", + "testlib": "2.0.0-SNAPSHOT.216", + "tool-base": "2.0.0-SNAPSHOT.428" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -174,9 +190,16 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.080", + "pin_vector": { + "ProtoTap": "0.17.4", + "base-libraries": "2.0.0-SNAPSHOT.462", + "logging": "2.0.0-SNAPSHOT.427", + "reflect": "2.0.0-SNAPSHOT.203", + "testlib": "2.0.0-SNAPSHOT.216", + "tool-base": "2.0.0-SNAPSHOT.428" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -198,9 +221,17 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.469", + "pin_vector": { + "ProtoTap": "0.17.4", + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "logging": "2.0.0-SNAPSHOT.427", + "reflect": "2.0.0-SNAPSHOT.203", + "testlib": "2.0.0-SNAPSHOT.216", + "tool-base": "2.0.0-SNAPSHOT.428" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -223,9 +254,18 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.099", + "pin_vector": { + "ProtoTap": "0.17.4", + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "logging": "2.0.0-SNAPSHOT.427", + "reflect": "2.0.0-SNAPSHOT.203", + "testlib": "2.0.0-SNAPSHOT.216", + "tool-base": "2.0.0-SNAPSHOT.428", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -245,9 +285,15 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.227", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "testlib": "2.0.0-SNAPSHOT.216", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -266,9 +312,14 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.209", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -291,9 +342,18 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.252", + "pin_vector": { + "ProtoTap": "0.17.4", + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "logging": "2.0.0-SNAPSHOT.427", + "testlib": "2.0.0-SNAPSHOT.216", + "tool-base": "2.0.0-SNAPSHOT.428", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -313,9 +373,15 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.13", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "testlib": "2.0.0-SNAPSHOT.216", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -340,9 +406,20 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.577", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "base-types": "2.0.0-SNAPSHOT.227", + "change": "2.0.0-SNAPSHOT.209", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "logging": "2.0.0-SNAPSHOT.427", + "reflect": "2.0.0-SNAPSHOT.203", + "testlib": "2.0.0-SNAPSHOT.216", + "time": "2.0.0-SNAPSHOT.252", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -361,9 +438,14 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.131", + "pin_vector": { + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm": "2.0.0-SNAPSHOT.577", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -386,9 +468,18 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "2.0.0-SNAPSHOT.241", + "pin_vector": { + "base-libraries": "2.0.0-SNAPSHOT.462", + "base-types": "2.0.0-SNAPSHOT.227", + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm": "2.0.0-SNAPSHOT.577", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "logging": "2.0.0-SNAPSHOT.427", + "testlib": "2.0.0-SNAPSHOT.216", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -410,9 +501,17 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "pending", - "target_version": null, - "pin_vector": {}, + "state": "bumped", + "target_version": "0.24.1", + "pin_vector": { + "compiler": "2.0.0-SNAPSHOT.080", + "core-jvm": "2.0.0-SNAPSHOT.577", + "core-jvm-compiler": "2.0.0-SNAPSHOT.099", + "logging": "2.0.0-SNAPSHOT.427", + "testlib": "2.0.0-SNAPSHOT.216", + "time": "2.0.0-SNAPSHOT.252", + "validation": "2.0.0-SNAPSHOT.469" + }, "adapt_rounds": 0, "built": null, "pr": null, @@ -428,13 +527,13 @@ "group_path": "", "artifact": "" }, - "state": "pending", + "state": "parked", "target_version": null, "pin_vector": {}, "adapt_rounds": 0, "built": null, "pr": null, - "parked": null + "parked": "verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish" } }, "excluded": {}, diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index 49436d0..0733826 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -35,3 +35,4 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P ## Log - 2026-10-21 — wave planned. +- 2026-10-21 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish From 11e8f62e7d76fed6ea4764bca6b0a17c3f551a1a Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 17:33:45 +0100 Subject: [PATCH 34/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 58 ++++++++++++++++------ .agents/tasks/cascade-refresh-604420c.md | 1 + 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index d5296ed..697eea2 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -43,8 +43,14 @@ "target_version": "2.0.0-SNAPSHOT.462", "pin_vector": {}, "adapt_rounds": 0, - "built": null, - "pr": null, + "built": { + "head": "e6ce655acb5683b3e475deb7bed0d8971195bea3", + "at": "2026-10-21T15:43:07Z" + }, + "pr": { + "url": "https://github.com/SpineEventEngine/base-libraries/pull/968", + "head": "e6ce655acb5683b3e475deb7bed0d8971195bea3" + }, "parked": null }, "reflect": { @@ -59,7 +65,10 @@ "target_version": "2.0.0-SNAPSHOT.203", "pin_vector": {}, "adapt_rounds": 0, - "built": null, + "built": { + "head": "867d9cf05a0224a6c9dc3768785ae9a82d56458b", + "at": "2026-10-21T15:43:26Z" + }, "pr": null, "parked": null }, @@ -80,8 +89,11 @@ "base-libraries": "2.0.0-SNAPSHOT.462", "reflect": "2.0.0-SNAPSHOT.203" }, - "adapt_rounds": 0, - "built": null, + "adapt_rounds": 1, + "built": { + "head": "ecacc07a6bd1130faa5b5302f6deecd0469d9760", + "at": "2026-10-21T15:55:46Z" + }, "pr": null, "parked": null }, @@ -101,7 +113,10 @@ "logging": "2.0.0-SNAPSHOT.427" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "b8018f38dc4cbdbe1322c91f97652ef535d779d1", + "at": "2026-10-21T15:56:18Z" + }, "pr": null, "parked": null }, @@ -121,7 +136,10 @@ "base-libraries": "2.0.0-SNAPSHOT.462" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "bae4036811749421871d065a0bf842b6bd249749", + "at": "2026-10-21T15:56:40Z" + }, "pr": null, "parked": null }, @@ -145,7 +163,10 @@ "testlib": "2.0.0-SNAPSHOT.216" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "513bc9e6e8e3d77f027eaf75e031bd987acfc9d2", + "at": "2026-10-21T15:59:24Z" + }, "pr": null, "parked": null }, @@ -171,7 +192,10 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac", + "at": "2026-10-21T16:00:23Z" + }, "pr": null, "parked": null }, @@ -201,7 +225,10 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "d2ae7b61ae233b7f647df249fb51b2355bb13f36", + "at": "2026-10-21T16:07:22Z" + }, "pr": null, "parked": null }, @@ -233,7 +260,10 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "d126ad45889823e8a71eb0378eef0af441cf1f72", + "at": "2026-10-21T16:10:01Z" + }, "pr": null, "parked": null }, @@ -254,7 +284,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "bumped", + "state": "parked", "target_version": "2.0.0-SNAPSHOT.099", "pin_vector": { "ProtoTap": "0.17.4", @@ -266,10 +296,10 @@ "tool-base": "2.0.0-SNAPSHOT.428", "validation": "2.0.0-SNAPSHOT.469" }, - "adapt_rounds": 0, + "adapt_rounds": 1, "built": null, "pr": null, - "parked": null + "parked": "CoreJvmPluginIgTest: applying the published plugin by ID in plugins{} with Compiler .080 on the buildscript classpath fails on Gradle's embedded-Kotlin pin (org.jetbrains:annotations strictly 13.0); worked with Compiler .074" }, "base-types": { "upstreams": [ diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index 0733826..0edc0cf 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -36,3 +36,4 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — wave planned. - 2026-10-21 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish +- 2026-10-21 — **parked** `core-jvm-compiler`: CoreJvmPluginIgTest: applying the published plugin by ID in plugins{} with Compiler .080 on the buildscript classpath fails on Gradle's embedded-Kotlin pin (org.jetbrains:annotations strictly 13.0); worked with Compiler .074 From fab201b12f46f8e2d0dbbcaad66c3f76b197f9f8 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 17:34:02 +0100 Subject: [PATCH 35/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 697eea2..a0f8afb 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -69,7 +69,10 @@ "head": "867d9cf05a0224a6c9dc3768785ae9a82d56458b", "at": "2026-10-21T15:43:26Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/reflect/pull/16", + "head": "867d9cf05a0224a6c9dc3768785ae9a82d56458b" + }, "parked": null }, "logging": { From 84c8fd1a7513bd50b2c8b1b9196c8a85bf9aa601 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 17:35:07 +0100 Subject: [PATCH 36/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-604420c.json | 4 ++-- .agents/tasks/cascade-refresh-604420c.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index a0f8afb..1f64e85 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -299,10 +299,10 @@ "tool-base": "2.0.0-SNAPSHOT.428", "validation": "2.0.0-SNAPSHOT.469" }, - "adapt_rounds": 1, + "adapt_rounds": 0, "built": null, "pr": null, - "parked": "CoreJvmPluginIgTest: applying the published plugin by ID in plugins{} with Compiler .080 on the buildscript classpath fails on Gradle's embedded-Kotlin pin (org.jetbrains:annotations strictly 13.0); worked with Compiler .074" + "parked": null }, "base-types": { "upstreams": [ diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index 0edc0cf..56cf749 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -37,3 +37,5 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — wave planned. - 2026-10-21 — **parked** `BuildSpeed`: verify-only: SDK versions arrive as CI environment variables substituted into settings.gradle.kts.template, so there are no file pins to apply, no version to bump, and no artifact to publish - 2026-10-21 — **parked** `core-jvm-compiler`: CoreJvmPluginIgTest: applying the published plugin by ID in plugins{} with Compiler .080 on the buildscript classpath fails on Gradle's embedded-Kotlin pin (org.jetbrains:annotations strictly 13.0); worked with Compiler .074 +- 2026-10-21 — resumed `core-jvm-compiler`. +- 2026-10-21 — `core-jvm-compiler` unparked. Root cause of the `CoreJvmPluginIgTest` failure: stale local builds from the abandoned `a0cbbbf` wave in `~/.m2` (core-jvm `.571`/`.572`, base-types `.226`, built with Kotlin 2.4.21 and endorsing `kotlin-bom` 2.4.21) shadowed the registry artifacts of the same versions, because the TestKit project lists `mavenLocal()` first; their graph cannot be reconciled with Gradle's strict embedded-Kotlin pins (`kotlin-stdlib` 2.4.10, `annotations` 13.0). Moved them to the session scratchpad; CI never sees them. From f59fee78403a9f2699d2a33447fd030953f9e9ce Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 18:16:03 +0100 Subject: [PATCH 37/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 86 +++++++++++++++------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 1f64e85..7668181 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -39,7 +39,7 @@ "group_path": "io/spine", "artifact": "spine-base" }, - "state": "bumped", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.462", "pin_vector": {}, "adapt_rounds": 0, @@ -61,7 +61,7 @@ "group_path": "io/spine", "artifact": "spine-reflect" }, - "state": "bumped", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.203", "pin_vector": {}, "adapt_rounds": 0, @@ -86,7 +86,7 @@ "group_path": "io/spine", "artifact": "spine-logging" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.427", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -97,7 +97,10 @@ "head": "ecacc07a6bd1130faa5b5302f6deecd0469d9760", "at": "2026-10-21T15:55:46Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/logging/pull/152", + "head": "ecacc07a6bd1130faa5b5302f6deecd0469d9760" + }, "parked": null }, "testlib": { @@ -110,7 +113,7 @@ "group_path": "io/spine/tools", "artifact": "base-testlib" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.216", "pin_vector": { "logging": "2.0.0-SNAPSHOT.427" @@ -133,7 +136,7 @@ "group_path": "io/spine/tools", "artifact": "dokka-extensions" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.12", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462" @@ -158,7 +161,7 @@ "group_path": "io/spine/tools", "artifact": "jvm-tools" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.428", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -186,7 +189,7 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "bumped", + "state": "pr-ready", "target_version": "0.17.4", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -217,7 +220,7 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.080", "pin_vector": { "ProtoTap": "0.17.4", @@ -251,7 +254,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.469", "pin_vector": { "ProtoTap": "0.17.4", @@ -287,7 +290,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "parked", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.099", "pin_vector": { "ProtoTap": "0.17.4", @@ -300,7 +303,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "f992efd399ed1434c432100dce21ad4362807ba0", + "at": "2026-10-21T16:38:48Z" + }, "pr": null, "parked": null }, @@ -318,7 +324,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -328,7 +334,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "c92ef3af0a25f55a98c4bd156221c6ba50537add", + "at": "2026-10-21T16:39:18Z" + }, "pr": null, "parked": null }, @@ -345,7 +354,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -354,7 +363,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "1a0ede3d66ec34b7c26ad2c1992327cef18ae2cd", + "at": "2026-10-21T16:39:55Z" + }, "pr": null, "parked": null }, @@ -375,7 +387,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.4", @@ -388,7 +400,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "23d8a493b585db7f8e09324c9f162e3f1e2992af", + "at": "2026-10-21T16:41:51Z" + }, "pr": null, "parked": null }, @@ -406,7 +421,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -416,7 +431,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "88b1d0dcbee9f31a0e53180b539e7b1ffb657ef2", + "at": "2026-10-21T16:42:19Z" + }, "pr": null, "parked": null }, @@ -439,7 +457,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.577", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -454,7 +472,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "bd49bb92e90ca6764fa2668320ba527ae2ffc5c4", + "at": "2026-10-21T16:48:46Z" + }, "pr": null, "parked": null }, @@ -471,7 +492,7 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.080", @@ -480,7 +501,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "97f3ac4b0e7be0d957b198bf1b20d40a35210c22", + "at": "2026-10-21T16:50:25Z" + }, "pr": null, "parked": null }, @@ -501,7 +525,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "bumped", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -514,7 +538,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "256093ac3921b3044617172e1a9b068d6a6b728d", + "at": "2026-10-21T16:52:47Z" + }, "pr": null, "parked": null }, @@ -534,7 +561,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "bumped", + "state": "published-local", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.080", @@ -546,7 +573,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "26ef46fe4400fc678b21dce152739d9ab28a9335", + "at": "2026-10-21T17:04:50Z" + }, "pr": null, "parked": null }, From 6ff2c8906ff217faf4e8b09cb05b2e20f54fbbd1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 18:16:21 +0100 Subject: [PATCH 38/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 7668181..2f2ea34 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -146,7 +146,10 @@ "head": "bae4036811749421871d065a0bf842b6bd249749", "at": "2026-10-21T15:56:40Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/dokka-tools/pull/13", + "head": "bae4036811749421871d065a0bf842b6bd249749" + }, "parked": null }, "tool-base": { From 2e8f4411aece83c5d3d4fccc878656cf22990c8c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 18:24:38 +0100 Subject: [PATCH 39/65] Open wave PRs as drafts The organization's ruleset requests a Copilot review for every pull request opened as ready, so each `ship` paid for a review before CI had run. Draft PRs are exempt. `ship` now opens the PR as a draft; the driver marks it ready once all its checks pass, which requests the one review then. Co-Authored-By: Claude Opus 5.5 --- cascade | 5 ++++- docs/rollout/rebuild.md | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cascade b/cascade index 2afd453..7403906 100755 --- a/cascade +++ b/cascade @@ -1592,7 +1592,10 @@ EOF note "PR already open: $(gh pr view "$branch" -R "$ORG/$repo" --json url --jq .url)" else git push -u origin "$branch" - gh pr create --base "$BASE" --head "$branch" \ + # A draft: the organization's ruleset requests a Copilot review for every + # pull request opened as ready, before CI has run. The driver marks the + # draft ready once all its checks pass, which requests that review then. + gh pr create --draft --base "$BASE" --head "$branch" \ --title "$(pr_title)" \ --body-file "$SUMMIT/docs/rollout/rebuild-pr-body.md" fi diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 9bd48bc..792a8a3 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -108,6 +108,10 @@ and execute what it prints, in order: published yet: wait, don't force. Exit 3 from the upstream gate (the upstream re-bumped, collided with the base branch, or failed to publish) means re-pinning with `./cascade refresh ` once the upstream is fixed. + The PR opens as a draft, because the organization's ruleset requests a + Copilot review for every PR opened as ready, before CI has run. Once all its + checks pass, mark it ready (`gh pr ready `), which requests that review + then, and enable auto-merge. - `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR merged. A run that fails midway may already have uploaded some modules, so the registry's marker artifact proves nothing; `./cascade status` links the From 6f505c95d99273eecdf6f8eac299c4f67123197f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 19:02:07 +0100 Subject: [PATCH 40/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 2f2ea34..1b33347 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -86,7 +86,7 @@ "group_path": "io/spine", "artifact": "spine-logging" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.427", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -123,7 +123,10 @@ "head": "b8018f38dc4cbdbe1322c91f97652ef535d779d1", "at": "2026-10-21T15:56:18Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/testlib/pull/16", + "head": "b8018f38dc4cbdbe1322c91f97652ef535d779d1" + }, "parked": null }, "dokka-tools": { @@ -136,7 +139,7 @@ "group_path": "io/spine/tools", "artifact": "dokka-extensions" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.12", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462" @@ -564,7 +567,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "published-local", + "state": "pr-ready", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.080", From 2ba538af9ea11829f4160a09d9ad75a6da5d304a Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 19:08:05 +0100 Subject: [PATCH 41/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-604420c.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index 56cf749..c397475 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -39,3 +39,4 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — **parked** `core-jvm-compiler`: CoreJvmPluginIgTest: applying the published plugin by ID in plugins{} with Compiler .080 on the buildscript classpath fails on Gradle's embedded-Kotlin pin (org.jetbrains:annotations strictly 13.0); worked with Compiler .074 - 2026-10-21 — resumed `core-jvm-compiler`. - 2026-10-21 — `core-jvm-compiler` unparked. Root cause of the `CoreJvmPluginIgTest` failure: stale local builds from the abandoned `a0cbbbf` wave in `~/.m2` (core-jvm `.571`/`.572`, base-types `.226`, built with Kotlin 2.4.21 and endorsing `kotlin-bom` 2.4.21) shadowed the registry artifacts of the same versions, because the TestKit project lists `mavenLocal()` first; their graph cannot be reconciled with Gradle's strict embedded-Kotlin pins (`kotlin-stdlib` 2.4.10, `annotations` 13.0). Moved them to the session scratchpad; CI never sees them. +- 2026-10-21 — follow-up after the wave: config#813 (merged as `a53eca4b2e`) declares `OpenTelemetryKotlin.exportersCore`/`exportersOtlp`; once `logging` pulls a config at or past it, `otel-backend-bootstrap/build.gradle.kts` can drop the inline coordinates from `0bf9a733`. From f35e26988dc29232c49a6dcbff39eaaf0dd25100 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 19:17:26 +0100 Subject: [PATCH 42/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 1b33347..282f5a6 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -113,7 +113,7 @@ "group_path": "io/spine/tools", "artifact": "base-testlib" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.216", "pin_vector": { "logging": "2.0.0-SNAPSHOT.427" @@ -179,7 +179,10 @@ "head": "513bc9e6e8e3d77f027eaf75e031bd987acfc9d2", "at": "2026-10-21T15:59:24Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/tool-base/pull/197", + "head": "513bc9e6e8e3d77f027eaf75e031bd987acfc9d2" + }, "parked": null }, "ProtoTap": { From bd85ec6ddcae6fd060fa07edc297fa8283691542 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 20:35:17 +0100 Subject: [PATCH 43/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 282f5a6..fa64d78 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -167,7 +167,7 @@ "group_path": "io/spine/tools", "artifact": "jvm-tools" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.428", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -211,7 +211,10 @@ "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac", "at": "2026-10-21T16:00:23Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/ProtoTap/pull/24", + "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac" + }, "parked": null }, "compiler": { From 7e1e84b75c7729c9288d8cd2a2373658cdbaba56 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 20:40:52 +0100 Subject: [PATCH 44/65] Update cascade state Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/cascade-refresh-604420c.json | 64 +++++++--------------- .agents/tasks/cascade-refresh-604420c.md | 1 + 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index fa64d78..f714771 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -87,7 +87,7 @@ "artifact": "spine-logging" }, "state": "published-remote", - "target_version": "2.0.0-SNAPSHOT.427", + "target_version": "2.0.0-SNAPSHOT.428", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", "reflect": "2.0.0-SNAPSHOT.203" @@ -98,8 +98,8 @@ "at": "2026-10-21T15:55:46Z" }, "pr": { - "url": "https://github.com/SpineEventEngine/logging/pull/152", - "head": "ecacc07a6bd1130faa5b5302f6deecd0469d9760" + "url": "https://github.com/SpineEventEngine/logging/pull/153", + "head": "9f75c7f2c5e304ea358c4304caf4d495ac20f81a" }, "parked": null }, @@ -198,19 +198,16 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "pr-ready", + "state": "pr-open", "target_version": "0.17.4", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": { - "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac", - "at": "2026-10-21T16:00:23Z" - }, + "built": null, "pr": { "url": "https://github.com/SpineEventEngine/ProtoTap/pull/24", "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac" @@ -237,16 +234,13 @@ "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": { - "head": "d2ae7b61ae233b7f647df249fb51b2355bb13f36", - "at": "2026-10-21T16:07:22Z" - }, + "built": null, "pr": null, "parked": null }, @@ -272,16 +266,13 @@ "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", "compiler": "2.0.0-SNAPSHOT.080", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": { - "head": "d126ad45889823e8a71eb0378eef0af441cf1f72", - "at": "2026-10-21T16:10:01Z" - }, + "built": null, "pr": null, "parked": null }, @@ -308,17 +299,14 @@ "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", "compiler": "2.0.0-SNAPSHOT.080", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", "tool-base": "2.0.0-SNAPSHOT.428", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": { - "head": "f992efd399ed1434c432100dce21ad4362807ba0", - "at": "2026-10-21T16:38:48Z" - }, + "built": null, "pr": null, "parked": null }, @@ -406,16 +394,13 @@ "base-libraries": "2.0.0-SNAPSHOT.462", "compiler": "2.0.0-SNAPSHOT.080", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", "tool-base": "2.0.0-SNAPSHOT.428", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": { - "head": "23d8a493b585db7f8e09324c9f162e3f1e2992af", - "at": "2026-10-21T16:41:51Z" - }, + "built": null, "pr": null, "parked": null }, @@ -477,17 +462,14 @@ "change": "2.0.0-SNAPSHOT.209", "compiler": "2.0.0-SNAPSHOT.080", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", "time": "2.0.0-SNAPSHOT.252", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": { - "head": "bd49bb92e90ca6764fa2668320ba527ae2ffc5c4", - "at": "2026-10-21T16:48:46Z" - }, + "built": null, "pr": null, "parked": null }, @@ -545,15 +527,12 @@ "compiler": "2.0.0-SNAPSHOT.080", "core-jvm": "2.0.0-SNAPSHOT.577", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": { - "head": "256093ac3921b3044617172e1a9b068d6a6b728d", - "at": "2026-10-21T16:52:47Z" - }, + "built": null, "pr": null, "parked": null }, @@ -579,16 +558,13 @@ "compiler": "2.0.0-SNAPSHOT.080", "core-jvm": "2.0.0-SNAPSHOT.577", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", - "logging": "2.0.0-SNAPSHOT.427", + "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", "time": "2.0.0-SNAPSHOT.252", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": { - "head": "26ef46fe4400fc678b21dce152739d9ab28a9335", - "at": "2026-10-21T17:04:50Z" - }, + "built": null, "pr": null, "parked": null }, diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index c397475..fb298d5 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -40,3 +40,4 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — resumed `core-jvm-compiler`. - 2026-10-21 — `core-jvm-compiler` unparked. Root cause of the `CoreJvmPluginIgTest` failure: stale local builds from the abandoned `a0cbbbf` wave in `~/.m2` (core-jvm `.571`/`.572`, base-types `.226`, built with Kotlin 2.4.21 and endorsing `kotlin-bom` 2.4.21) shadowed the registry artifacts of the same versions, because the TestKit project lists `mavenLocal()` first; their graph cannot be reconciled with Gradle's strict embedded-Kotlin pins (`kotlin-stdlib` 2.4.10, `annotations` 13.0). Moved them to the session scratchpad; CI never sees them. - 2026-10-21 — follow-up after the wave: config#813 (merged as `a53eca4b2e`) declares `OpenTelemetryKotlin.exportersCore`/`exportersOtlp`; once `logging` pulls a config at or past it, `otel-backend-bootstrap/build.gradle.kts` can drop the inline coordinates from `0bf9a733`. +- 2026-10-21 — retargeted `logging` to `2.0.0-SNAPSHOT.428` (logging#153, on the latest `config` with the named OpenTelemetry exporter accessors) at the owner's request; the wave branch was fast-forwarded to master. Unshipped downstream repos re-pin to `.428`; the already-published testlib `.216` and tool-base `.428` keep `.427` as a floor. From 49b37fd0c8fb9310d1990a402b78872d0298f4ce Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 21 Oct 2026 21:25:18 +0100 Subject: [PATCH 45/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 57 ++++++++++++++++------ .agents/tasks/cascade-refresh-604420c.md | 1 + 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index f714771..335b6f2 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -198,7 +198,7 @@ "group_path": "io/spine/tools", "artifact": "prototap-gradle-plugin" }, - "state": "pr-open", + "state": "published-remote", "target_version": "0.17.4", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -207,7 +207,10 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "c1a526d3e9d6e97b633b779b0f019e9ba223d3d2", + "at": "2026-10-21T19:42:33Z" + }, "pr": { "url": "https://github.com/SpineEventEngine/ProtoTap/pull/24", "head": "08b843a3068eedaf80ba7912c1d2b529df7a45ac" @@ -240,8 +243,14 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, - "pr": null, + "built": { + "head": "b3c6d2929617ef92b5547b6ba5c5aad8ac5f342a", + "at": "2026-10-21T19:48:38Z" + }, + "pr": { + "url": "https://github.com/SpineEventEngine/compiler/pull/96", + "head": "b3c6d2929617ef92b5547b6ba5c5aad8ac5f342a" + }, "parked": null }, "validation": { @@ -272,7 +281,10 @@ "tool-base": "2.0.0-SNAPSHOT.428" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "450ba7c993c1f9d75b080843653ea0db5b4409fa", + "at": "2026-10-21T19:50:50Z" + }, "pr": null, "parked": null }, @@ -293,7 +305,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "pr-ready", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.099", "pin_vector": { "ProtoTap": "0.17.4", @@ -306,7 +318,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "54ceff1984e1c1fbcdc41e4d21111df5b86009cd", + "at": "2026-10-21T19:55:46Z" + }, "pr": null, "parked": null }, @@ -387,7 +402,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "pr-ready", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.4", @@ -400,7 +415,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "571f412341962c1a24869db001f200bee2a48a42", + "at": "2026-10-21T19:57:26Z" + }, "pr": null, "parked": null }, @@ -454,7 +472,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "pr-ready", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.577", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -469,7 +487,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "cf277daf8649bfa1d1af3982afcca15de64d9e4c", + "at": "2026-10-21T20:07:09Z" + }, "pr": null, "parked": null }, @@ -519,7 +540,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "pr-ready", + "state": "published-local", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -532,7 +553,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "2b051dd0181fd70317525171d7aade2d3e3a27c3", + "at": "2026-10-21T20:09:29Z" + }, "pr": null, "parked": null }, @@ -552,7 +576,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "pr-ready", + "state": "published-local", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.080", @@ -564,7 +588,10 @@ "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, - "built": null, + "built": { + "head": "5d24d3e68b751857b220b68357b69de0063a954d", + "at": "2026-10-21T20:20:49Z" + }, "pr": null, "parked": null }, diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/cascade-refresh-604420c.md index fb298d5..566a682 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/cascade-refresh-604420c.md @@ -41,3 +41,4 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — `core-jvm-compiler` unparked. Root cause of the `CoreJvmPluginIgTest` failure: stale local builds from the abandoned `a0cbbbf` wave in `~/.m2` (core-jvm `.571`/`.572`, base-types `.226`, built with Kotlin 2.4.21 and endorsing `kotlin-bom` 2.4.21) shadowed the registry artifacts of the same versions, because the TestKit project lists `mavenLocal()` first; their graph cannot be reconciled with Gradle's strict embedded-Kotlin pins (`kotlin-stdlib` 2.4.10, `annotations` 13.0). Moved them to the session scratchpad; CI never sees them. - 2026-10-21 — follow-up after the wave: config#813 (merged as `a53eca4b2e`) declares `OpenTelemetryKotlin.exportersCore`/`exportersOtlp`; once `logging` pulls a config at or past it, `otel-backend-bootstrap/build.gradle.kts` can drop the inline coordinates from `0bf9a733`. - 2026-10-21 — retargeted `logging` to `2.0.0-SNAPSHOT.428` (logging#153, on the latest `config` with the named OpenTelemetry exporter accessors) at the owner's request; the wave branch was fast-forwarded to master. Unshipped downstream repos re-pin to `.428`; the already-published testlib `.216` and tool-base `.428` keep `.427` as a floor. +- 2026-10-21 — ProtoTap#24 merged on its pre-re-pin head (`08b843a`), so ProtoTap `0.17.4` pins logging `.427` (a floor, like testlib and tool-base); its local re-pin commits stay unpushed, and the local rebuild of `0.17.4` was moved out of `~/.m2`. From 4e14603046f01a41427cf7c3538f4f4be3bc4f46 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 15:09:53 +0100 Subject: [PATCH 46/65] Re-ship a repository whose publish failed `./cascade refresh ` on a `publish-failed` repository now starts it over from the base branch (the wave branch has merged), so `prep` pulls `config` again and bumps past the partly published version. `ship` and `derive_state` look for the wave branch's open PR, not any PR from that branch name, which would find the merged one. `prep` reads its earlier pull commit through a here-string: under `pipefail`, `git log | grep -q` could read the SIGPIPE `git log` takes as "not pulled" and pull `config` a second time. Co-Authored-By: Claude Opus 5.5 --- cascade | 45 ++++++++++++++++++++++++++++++++++------- docs/rollout/rebuild.md | 4 +++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/cascade b/cascade index 7403906..cf0cca6 100755 --- a/cascade +++ b/cascade @@ -356,6 +356,14 @@ wave_pr_merged() { # fi } +# The open PR from the wave branch, or nothing. Unlike `gh pr view `, it +# ignores a merged PR from the same branch name, which a repository re-shipped +# after a failed publish already has. +open_pr_url() { # + gh pr list -R "$ORG/$1" --head "$2" --state open --json url --jq '.[0].url // empty' \ + 2>/dev/null || true +} + # File.kt -> repo (reverse of repo_pin_file); empty when not a repo pin file. pin_file_repo() { # local r @@ -1181,9 +1189,15 @@ derive_state() { # -> prints state s_status="$(sed -n 's/^status=//p' "$gitdir/pre-pr.ok" 2>/dev/null || true)" { [ "$s_status" = PASS ] && [ "$s_head" = "$head" ]; } || { echo published-local; return; } - # pr-open / merged. - local prstate - prstate="$(gh pr view "$branch" -R "$ORG/$repo" --json state --jq .state 2>/dev/null || true)" + # pr-open / merged. A PR merged from another head is the previous ship of + # the reused wave branch (a new version after a failed publish): the + # current head has no PR yet. + local prstate prhead + read -r prstate prhead </dev/null || true) +EOF + [ "$prstate" = MERGED ] && [ "$prhead" != "$head" ] && prstate="" case "$prstate" in MERGED) ;; OPEN) echo pr-open; return ;; @@ -1348,7 +1362,9 @@ cmd_prep() { # nothing to pull; skipping keeps it a wave participant instead of a hard error. if [ ! -x ./config/pull ]; then note "$repo does not consume \`config\` — no pull step" - elif ! git log --format=%s "origin/$BASE..HEAD" | grep -q '^Update shared agent tooling'; then + # A here-string, not a pipe: `grep -q` exits at the first match, and under + # `pipefail` the SIGPIPE `git log` may then take reads as "not pulled yet". + elif ! grep -q '^Update shared agent tooling' <<<"$(git log --format=%s "origin/$BASE..HEAD")"; then [ -z "$(git status --porcelain)" ] \ || die "working tree not clean before ./config/pull at $repo — commit or stash first" ./config/pull @@ -1587,9 +1603,10 @@ EOF fi git checkout -- docs/dependencies/ 2>/dev/null || true - if gh pr view "$branch" -R "$ORG/$repo" --json url >/dev/null 2>&1; then + local url; url="$(open_pr_url "$repo" "$branch")" + if [ -n "$url" ]; then git push -q origin "$branch" - note "PR already open: $(gh pr view "$branch" -R "$ORG/$repo" --json url --jq .url)" + note "PR already open: $url" else git push -u origin "$branch" # A draft: the organization's ruleset requests a Copilot review for every @@ -1598,9 +1615,11 @@ EOF gh pr create --draft --base "$BASE" --head "$branch" \ --title "$(pr_title)" \ --body-file "$SUMMIT/docs/rollout/rebuild-pr-body.md" + url="$(open_pr_url "$repo" "$branch")" fi + [ -n "$url" ] || die "no open PR from '$branch' in $ORG/$repo after ship" mset "$wave" '.repos[$r].pr = {url: $u, head: $h}' --arg r "$repo" \ - --arg u "$(gh pr view "$branch" -R "$ORG/$repo" --json url --jq .url)" --arg h "$head" + --arg u "$url" --arg h "$head" checkpoint_state "$wave" || true } @@ -1619,6 +1638,18 @@ pr_title() { cmd_refresh() { local repo="${1:?usage: cascade refresh }" wave wave="$(active_wave)" + # After a failed publish the wave branch has merged: start the repository + # over from the base branch, so prep pulls `config` again and bumps past the + # partly published version. + if [ "$(derive_state "$wave" "$repo")" = publish-failed ]; then + local dir="$SUMMIT/$repo" branch + branch="$(mget "$wave" .branch)" + git -C "$dir" fetch --quiet origin "$BASE" + git -C "$dir" checkout -q "$BASE" + git -C "$dir" pull --ff-only --quiet origin "$BASE" + git -C "$dir" branch -d "$branch" # refuses a branch the base lacks + mset "$wave" '.repos[$r].pr = null | .repos[$r].target_version = null' --arg r "$repo" + fi # Clear the recorded pins so prep re-reads the upstreams' current versions, # then invalidate the build record (the branch will gain commits). mset "$wave" '.repos[$r].pin_vector = {} | .repos[$r].built = null' --arg r "$repo" diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 792a8a3..c5faa6b 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -115,7 +115,9 @@ and execute what it prints, in order: - `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR merged. A run that fails midway may already have uploaded some modules, so the registry's marker artifact proves nothing; `./cascade status` links the - run. Fix the build, publish a new version, and re-pin each downstream repo + run. Fix the cause (often in `config`), then run `./cascade refresh `: + it branches again from the base branch, pulls `config`, and bumps to a new + version. Build, pre-pr, and ship it as usual, and re-pin each downstream repo with `./cascade refresh `. Downstream repos wait meanwhile. - `REBUMP:` → the registry serves the repo's wave version, but the repo's wave PR has not merged: the base branch took the same version first, so the From bffd46009e3948753ca5697adc72477d8fd01faf Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 16:06:30 +0100 Subject: [PATCH 47/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 80 +++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 335b6f2..17f6933 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -233,7 +233,7 @@ "artifact": "compiler-jvm" }, "state": "pr-ready", - "target_version": "2.0.0-SNAPSHOT.080", + "target_version": "2.0.0-SNAPSHOT.081", "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", @@ -244,12 +244,12 @@ }, "adapt_rounds": 0, "built": { - "head": "b3c6d2929617ef92b5547b6ba5c5aad8ac5f342a", - "at": "2026-10-21T19:48:38Z" + "head": "b5d8b3d69301fd527f35080b165e22e42e68c18d", + "at": "2026-10-22T14:16:20Z" }, "pr": { - "url": "https://github.com/SpineEventEngine/compiler/pull/96", - "head": "b3c6d2929617ef92b5547b6ba5c5aad8ac5f342a" + "url": "https://github.com/SpineEventEngine/compiler/pull/97", + "head": "b5d8b3d69301fd527f35080b165e22e42e68c18d" }, "parked": null }, @@ -274,7 +274,7 @@ "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", @@ -282,8 +282,8 @@ }, "adapt_rounds": 0, "built": { - "head": "450ba7c993c1f9d75b080843653ea0db5b4409fa", - "at": "2026-10-21T19:50:50Z" + "head": "c9855b75bf1f382c1c27f91afe9facdcb8803a48", + "at": "2026-10-22T14:18:38Z" }, "pr": null, "parked": null @@ -305,12 +305,12 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.099", "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", @@ -319,8 +319,8 @@ }, "adapt_rounds": 0, "built": { - "head": "54ceff1984e1c1fbcdc41e4d21111df5b86009cd", - "at": "2026-10-21T19:55:46Z" + "head": "b27f8ab9e26fa4069239482781fa94ad8996a264", + "at": "2026-10-22T14:22:58Z" }, "pr": null, "parked": null @@ -343,15 +343,15 @@ "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "testlib": "2.0.0-SNAPSHOT.216", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "c92ef3af0a25f55a98c4bd156221c6ba50537add", - "at": "2026-10-21T16:39:18Z" + "head": "e3078e44252217f0591e2dc538179389ac57b3da", + "at": "2026-10-22T14:23:35Z" }, "pr": null, "parked": null @@ -373,14 +373,14 @@ "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "1a0ede3d66ec34b7c26ad2c1992327cef18ae2cd", - "at": "2026-10-21T16:39:55Z" + "head": "bc59e6ed9ee2b39459472e6882fc09d35212fce6", + "at": "2026-10-22T14:24:06Z" }, "pr": null, "parked": null @@ -402,12 +402,12 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.252", "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", @@ -416,8 +416,8 @@ }, "adapt_rounds": 0, "built": { - "head": "571f412341962c1a24869db001f200bee2a48a42", - "at": "2026-10-21T19:57:26Z" + "head": "b2993f29f31f068e4cf8667c2a0701eedf667a5f", + "at": "2026-10-22T14:25:39Z" }, "pr": null, "parked": null @@ -440,15 +440,15 @@ "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "testlib": "2.0.0-SNAPSHOT.216", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "88b1d0dcbee9f31a0e53180b539e7b1ffb657ef2", - "at": "2026-10-21T16:42:19Z" + "head": "88e65d7661352fe9ab7ae284230f511ff98a28ab", + "at": "2026-10-22T14:26:01Z" }, "pr": null, "parked": null @@ -472,13 +472,13 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.577", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", "base-types": "2.0.0-SNAPSHOT.227", "change": "2.0.0-SNAPSHOT.209", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", @@ -488,8 +488,8 @@ }, "adapt_rounds": 0, "built": { - "head": "cf277daf8649bfa1d1af3982afcca15de64d9e4c", - "at": "2026-10-21T20:07:09Z" + "head": "394864b3ebc852edf26b1d2b406c638f2d568996", + "at": "2026-10-22T14:33:00Z" }, "pr": null, "parked": null @@ -510,15 +510,15 @@ "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm": "2.0.0-SNAPSHOT.577", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "97f3ac4b0e7be0d957b198bf1b20d40a35210c22", - "at": "2026-10-21T16:50:25Z" + "head": "cb74cdf074e4b6e4bbffd483a9349b217636028d", + "at": "2026-10-22T14:34:08Z" }, "pr": null, "parked": null @@ -540,12 +540,12 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "published-local", + "state": "pr-ready", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", "base-types": "2.0.0-SNAPSHOT.227", - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm": "2.0.0-SNAPSHOT.577", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "logging": "2.0.0-SNAPSHOT.428", @@ -554,8 +554,8 @@ }, "adapt_rounds": 0, "built": { - "head": "2b051dd0181fd70317525171d7aade2d3e3a27c3", - "at": "2026-10-21T20:09:29Z" + "head": "f8fbbe9d7d84e04bc3af1063a11400bb62796537", + "at": "2026-10-22T14:36:09Z" }, "pr": null, "parked": null @@ -576,10 +576,10 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "published-local", + "state": "pr-ready", "target_version": "0.24.1", "pin_vector": { - "compiler": "2.0.0-SNAPSHOT.080", + "compiler": "2.0.0-SNAPSHOT.081", "core-jvm": "2.0.0-SNAPSHOT.577", "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "logging": "2.0.0-SNAPSHOT.428", @@ -589,8 +589,8 @@ }, "adapt_rounds": 0, "built": { - "head": "5d24d3e68b751857b220b68357b69de0063a954d", - "at": "2026-10-21T20:20:49Z" + "head": "54c8e1fa6271d1ed78ac6753b20900c4ad222213", + "at": "2026-10-22T14:47:10Z" }, "pr": null, "parked": null From f2238db70ac15866dd6e8515ef00ac777297cc0e Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 17:04:09 +0100 Subject: [PATCH 48/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 17f6933..4b8f16d 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -232,7 +232,7 @@ "group_path": "io/spine/tools", "artifact": "compiler-jvm" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.081", "pin_vector": { "ProtoTap": "0.17.4", @@ -285,7 +285,10 @@ "head": "c9855b75bf1f382c1c27f91afe9facdcb8803a48", "at": "2026-10-22T14:18:38Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/validation/pull/338", + "head": "c9855b75bf1f382c1c27f91afe9facdcb8803a48" + }, "parked": null }, "core-jvm-compiler": { From aca6e31a0ee198da4633af33b8d6231b32f25f30 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 17:52:56 +0100 Subject: [PATCH 49/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 4b8f16d..a0a230d 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -269,7 +269,7 @@ "group_path": "io/spine/tools", "artifact": "validation-java" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.469", "pin_vector": { "ProtoTap": "0.17.4", @@ -325,7 +325,10 @@ "head": "b27f8ab9e26fa4069239482781fa94ad8996a264", "at": "2026-10-22T14:22:58Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/core-jvm-compiler/pull/121", + "head": "b27f8ab9e26fa4069239482781fa94ad8996a264" + }, "parked": null }, "base-types": { From da60d1d58be325e1578856c90c7467d3e935bc60 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 19:05:36 +0100 Subject: [PATCH 50/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index a0a230d..de91f20 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -308,7 +308,7 @@ "group_path": "io/spine/tools", "artifact": "core-jvm-gradle-plugin" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.099", "pin_vector": { "ProtoTap": "0.17.4", @@ -359,7 +359,10 @@ "head": "e3078e44252217f0591e2dc538179389ac57b3da", "at": "2026-10-22T14:23:35Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/base-types/pull/57", + "head": "e3078e44252217f0591e2dc538179389ac57b3da" + }, "parked": null }, "change": { From 6a016f451626d938a19ae0d6c43e8c9afd919925 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 19:06:02 +0100 Subject: [PATCH 51/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index de91f20..829bd5e 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -345,7 +345,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "pr-ready", + "state": "pr-open", "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -391,7 +391,10 @@ "head": "bc59e6ed9ee2b39459472e6882fc09d35212fce6", "at": "2026-10-22T14:24:06Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/change/pull/10", + "head": "bc59e6ed9ee2b39459472e6882fc09d35212fce6" + }, "parked": null }, "time": { From 9a5ed0b203d547fb31cd1b1835e6a42c8bd41c53 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 19:06:38 +0100 Subject: [PATCH 52/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 829bd5e..6f701a4 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -431,7 +431,10 @@ "head": "b2993f29f31f068e4cf8667c2a0701eedf667a5f", "at": "2026-10-22T14:25:39Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/time/pull/201", + "head": "b2993f29f31f068e4cf8667c2a0701eedf667a5f" + }, "parked": null }, "money": { From cdae417003da123f991b922d8d74ecf003023694 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 19:07:09 +0100 Subject: [PATCH 53/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 6f701a4..53bce6f 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -465,7 +465,10 @@ "head": "88e65d7661352fe9ab7ae284230f511ff98a28ab", "at": "2026-10-22T14:26:01Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/money/pull/33", + "head": "88e65d7661352fe9ab7ae284230f511ff98a28ab" + }, "parked": null }, "core-jvm": { From a8b8234e7b719b34c706bd1449c2916a78dbe28d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 19:47:47 +0100 Subject: [PATCH 54/65] Treat a merge without a Publish run as a failed publish GitHub dropped the push event of the time `.252` merge, so no workflow started for the merge commit, and the wave read the repository as `merged` forever. Ten minutes after a merge without a `publish.yml` run, `publish_verdict` now reports a failure, which routes the repository to `FIX-PUBLISH` and lets `./cascade refresh` re-ship it. Co-Authored-By: Claude Opus 5.5 --- cascade | 23 ++++++++++++++++++++--- docs/rollout/rebuild.md | 3 ++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/cascade b/cascade index cf0cca6..da65c12 100755 --- a/cascade +++ b/cascade @@ -318,17 +318,34 @@ registry_has() { # # With no recorded PR, no merge commit, or no run (a seed published by hand, a # repo without the workflow), the verdict is `ok` and the registry stays the # only evidence, as before. +iso_epoch() { # -> seconds since the epoch (BSD or GNU `date`) + date -j -u -f '%Y-%m-%dT%H:%M:%SZ' "$1" +%s 2>/dev/null || date -u -d "$1" +%s +} + publish_verdict() { # - local url sha run + local url sha merged run url="$(mget "$1" --arg r "$2" '.repos[$r].pr.url // empty')" [ -n "$url" ] || { echo ok; return; } - sha="$(gh pr view "$url" --json mergeCommit --jq '.mergeCommit.oid // empty' 2>/dev/null || true)" + read -r sha merged </dev/null || true) +EOF [ -n "$sha" ] || { echo ok; return; } run="$(gh run list -R "$ORG/$2" --workflow publish.yml --commit "$sha" --limit 1 \ --json status,conclusion,url \ --jq '.[0] // empty | "\(.status) \(if (.conclusion // "") == "" then "none" else .conclusion end) \(.url)"' \ 2>/dev/null || true)" - [ -n "$run" ] || { echo ok; return; } + if [ -z "$run" ]; then + # GitHub can drop the push event of a merge, and then no workflow starts for the + # merge commit at all (time `.252`). Publish runs start within seconds of a merge, so + # ten minutes on, the publication never happened. + if [ -n "$merged" ] && [ $(( $(date +%s) - $(iso_epoch "$merged") )) -gt 600 ]; then + echo "failed https://github.com/$ORG/$2/commit/$sha (no publish run started)" + else + echo ok + fi + return + fi set -- $run case "$1 $2" in "completed success") echo "ok $3" ;; diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index c5faa6b..72afa53 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -113,7 +113,8 @@ and execute what it prints, in order: checks pass, mark it ready (`gh pr ready `), which requests that review then, and enable auto-merge. - `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR - merged. A run that fails midway may already have uploaded some modules, so + merged, or never started: GitHub can drop a merge's push event, and ten + minutes without a run counts as a failure. A run that fails midway may already have uploaded some modules, so the registry's marker artifact proves nothing; `./cascade status` links the run. Fix the cause (often in `config`), then run `./cascade refresh `: it branches again from the base branch, pulls `config`, and bumps to a new From a836e63ccc20e78572c1b72360e82dc8a723aa74 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 20:23:10 +0100 Subject: [PATCH 55/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 53bce6f..0e25f84 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -345,7 +345,7 @@ "group_path": "io/spine", "artifact": "spine-base-types" }, - "state": "pr-open", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.227", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -378,7 +378,7 @@ "group_path": "io/spine", "artifact": "spine-change" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.209", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -415,7 +415,7 @@ "artifact": "spine-time" }, "state": "pr-ready", - "target_version": "2.0.0-SNAPSHOT.252", + "target_version": "2.0.0-SNAPSHOT.253", "pin_vector": { "ProtoTap": "0.17.4", "base-libraries": "2.0.0-SNAPSHOT.462", @@ -426,14 +426,14 @@ "tool-base": "2.0.0-SNAPSHOT.428", "validation": "2.0.0-SNAPSHOT.469" }, - "adapt_rounds": 0, + "adapt_rounds": 1, "built": { - "head": "b2993f29f31f068e4cf8667c2a0701eedf667a5f", - "at": "2026-10-22T14:25:39Z" + "head": "ba06ebe4d758bf84de64e14660304d64a3ab6a6c", + "at": "2026-10-22T18:52:59Z" }, "pr": { - "url": "https://github.com/SpineEventEngine/time/pull/201", - "head": "b2993f29f31f068e4cf8667c2a0701eedf667a5f" + "url": "https://github.com/SpineEventEngine/time/pull/202", + "head": "ba06ebe4d758bf84de64e14660304d64a3ab6a6c" }, "parked": null }, @@ -451,7 +451,7 @@ "group_path": "io/spine", "artifact": "spine-money" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.13", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -501,13 +501,13 @@ "logging": "2.0.0-SNAPSHOT.428", "reflect": "2.0.0-SNAPSHOT.203", "testlib": "2.0.0-SNAPSHOT.216", - "time": "2.0.0-SNAPSHOT.252", + "time": "2.0.0-SNAPSHOT.253", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "394864b3ebc852edf26b1d2b406c638f2d568996", - "at": "2026-10-22T14:33:00Z" + "head": "ee9be9d3fa7a1bccea910243e3becc8da2099f32", + "at": "2026-10-22T18:59:00Z" }, "pr": null, "parked": null @@ -602,13 +602,13 @@ "core-jvm-compiler": "2.0.0-SNAPSHOT.099", "logging": "2.0.0-SNAPSHOT.428", "testlib": "2.0.0-SNAPSHOT.216", - "time": "2.0.0-SNAPSHOT.252", + "time": "2.0.0-SNAPSHOT.253", "validation": "2.0.0-SNAPSHOT.469" }, "adapt_rounds": 0, "built": { - "head": "54c8e1fa6271d1ed78ac6753b20900c4ad222213", - "at": "2026-10-22T14:47:10Z" + "head": "a672c6955d146c9f1ef2496166bf9f01428c3da0", + "at": "2026-10-22T19:10:50Z" }, "pr": null, "parked": null From 153d31b0ffd18307c5628bf3f1a941d8a9b7ac3f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 20:37:32 +0100 Subject: [PATCH 56/65] Wait an hour for a Publish run before calling it failed The push event of the time `.252` merge arrived 17 minutes late, during a GitHub incident, so its Publish run did start and succeed; ten minutes was too short to tell a dropped event from a delayed one. Co-Authored-By: Claude Opus 5.5 --- cascade | 8 ++++---- docs/rollout/rebuild.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cascade b/cascade index da65c12..f325bc4 100755 --- a/cascade +++ b/cascade @@ -336,10 +336,10 @@ EOF --jq '.[0] // empty | "\(.status) \(if (.conclusion // "") == "" then "none" else .conclusion end) \(.url)"' \ 2>/dev/null || true)" if [ -z "$run" ]; then - # GitHub can drop the push event of a merge, and then no workflow starts for the - # merge commit at all (time `.252`). Publish runs start within seconds of a merge, so - # ten minutes on, the publication never happened. - if [ -n "$merged" ] && [ $(( $(date +%s) - $(iso_epoch "$merged") )) -gt 600 ]; then + # GitHub can delay the push event of a merge, or drop it, and then no workflow starts + # for the merge commit. The time `.252` run started 17 minutes late, during an + # incident; an hour without a run means the publication never happened. + if [ -n "$merged" ] && [ $(( $(date +%s) - $(iso_epoch "$merged") )) -gt 3600 ]; then echo "failed https://github.com/$ORG/$2/commit/$sha (no publish run started)" else echo ok diff --git a/docs/rollout/rebuild.md b/docs/rollout/rebuild.md index 72afa53..7d1c1dc 100644 --- a/docs/rollout/rebuild.md +++ b/docs/rollout/rebuild.md @@ -113,8 +113,8 @@ and execute what it prints, in order: checks pass, mark it ready (`gh pr ready `), which requests that review then, and enable auto-merge. - `FIX-PUBLISH:` → the repo's `publish.yml` run failed after its PR - merged, or never started: GitHub can drop a merge's push event, and ten - minutes without a run counts as a failure. A run that fails midway may already have uploaded some modules, so + merged, or never started: GitHub can delay or drop a merge's push event, and + an hour without a run counts as a failure. A run that fails midway may already have uploaded some modules, so the registry's marker artifact proves nothing; `./cascade status` links the run. Fix the cause (often in `config`), then run `./cascade refresh `: it branches again from the base branch, pulls `config`, and bumps to a new From 25229746cd96a47f5398be38d4aa85479a91cb9c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 21:04:50 +0100 Subject: [PATCH 57/65] Keep concurrent runs from emptying the wave manifest Two `cascade` runs at once (the driver's `next` and a manual one) shared `.tmp`: one truncated the other's output, and an empty manifest was moved into place, which `next` then read as a finished wave (CLOSE). `mset` now writes through a private temp file and never moves an empty result into place, and `next` and `close` refuse a manifest that lists no repos. Co-Authored-By: Claude Opus 5.5 --- cascade | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/cascade b/cascade index f325bc4..6583b69 100755 --- a/cascade +++ b/cascade @@ -896,6 +896,12 @@ active_wave() { basename "$m" .json } +# A manifest that lists no repos reads as a finished wave, so `next` would say CLOSE. +require_intact() { # + [ "$(mget "$1" '(.repos // {}) | length > 0' 2>/dev/null)" = true ] \ + || die "the manifest of '$1' lists no repos — restore it: git checkout -- $(manifest_path "$1")" +} + # mget [jq-args...] — the program is always the LAST argument. mget() { local wave="$1"; shift @@ -907,8 +913,15 @@ mget() { } mset() { # [--arg k v ...] local wave="$1" prog="$2"; shift 2 - local p tmp; p="$(manifest_path "$wave")"; tmp="$p.tmp" - jq "$@" "$prog" "$p" > "$tmp" && mv "$tmp" "$p" + local p tmp; p="$(manifest_path "$wave")" + # A private temp file: with a shared one, concurrent runs (the driver and a manual + # call) truncated each other's output and moved an empty manifest into place. + tmp="$(mktemp "$p.XXXXXX")" + if jq "$@" "$prog" "$p" > "$tmp" && [ -s "$tmp" ]; then + mv "$tmp" "$p" + else + rm -f "$tmp"; die "could not update $p" + fi } wave_repos() { mget "$1" '.repos | keys[]'; } @@ -1277,6 +1290,7 @@ cmd_status() { cmd_next() { local wave json=0 wave="$(active_wave)" + require_intact "$wave" [ "${1:-}" = "--json" ] && json=1 cmd_status "$wave" >/dev/null # refresh derived states first @@ -1732,6 +1746,7 @@ cmd_await() { cmd_close() { local wave ship=0 wave="$(active_wave)" + require_intact "$wave" [ "${1:-}" = "--ship" ] && ship=1 local cfg="$SUMMIT/config" vbranch repo tv pf c cur cur_re vbranch="$(mget "$wave" .wave)-vector" From 4b0e06410909f524dd4a965f3ba014d7841daba1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 22 Oct 2026 21:06:23 +0100 Subject: [PATCH 58/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 0e25f84..918bbc6 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -414,7 +414,7 @@ "group_path": "io/spine", "artifact": "spine-time" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.253", "pin_vector": { "ProtoTap": "0.17.4", @@ -509,7 +509,10 @@ "head": "ee9be9d3fa7a1bccea910243e3becc8da2099f32", "at": "2026-10-22T18:59:00Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/core-jvm/pull/1697", + "head": "ee9be9d3fa7a1bccea910243e3becc8da2099f32" + }, "parked": null }, "jdbc-storage": { From cf56390d9ec50468dceb120ff155ee4dd3b7a0da Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 14:24:46 +0100 Subject: [PATCH 59/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 918bbc6..f52aa6b 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -490,7 +490,7 @@ "group_path": "io/spine", "artifact": "spine-core" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.577", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -506,8 +506,8 @@ }, "adapt_rounds": 0, "built": { - "head": "ee9be9d3fa7a1bccea910243e3becc8da2099f32", - "at": "2026-10-22T18:59:00Z" + "head": "8e7ff830d518fa74e67ece6ccb53cee6ccd8af38", + "at": "2026-10-22T20:24:42Z" }, "pr": { "url": "https://github.com/SpineEventEngine/core-jvm/pull/1697", @@ -538,10 +538,13 @@ }, "adapt_rounds": 0, "built": { - "head": "cb74cdf074e4b6e4bbffd483a9349b217636028d", - "at": "2026-10-22T14:34:08Z" + "head": "0e1e71f937700f9c49946517de7e817d48d0a604", + "at": "2026-10-22T20:25:52Z" + }, + "pr": { + "url": "https://github.com/SpineEventEngine/jdbc-storage/pull/186", + "head": "0e1e71f937700f9c49946517de7e817d48d0a604" }, - "pr": null, "parked": null }, "gcloud-jvm": { @@ -575,8 +578,8 @@ }, "adapt_rounds": 0, "built": { - "head": "f8fbbe9d7d84e04bc3af1063a11400bb62796537", - "at": "2026-10-22T14:36:09Z" + "head": "ddb61bfe239c56f0bd8d5fabf869104ce19dfff9", + "at": "2026-10-22T20:28:03Z" }, "pr": null, "parked": null @@ -610,8 +613,8 @@ }, "adapt_rounds": 0, "built": { - "head": "a672c6955d146c9f1ef2496166bf9f01428c3da0", - "at": "2026-10-22T19:10:50Z" + "head": "75bb56c07fe6c354816a9762ee504d1c31f7e535", + "at": "2026-10-22T20:48:29Z" }, "pr": null, "parked": null From 4c732b1019b9a936ba1876bae7cace48a51c68bd Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 14:25:20 +0100 Subject: [PATCH 60/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index f52aa6b..f5a22fc 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -581,7 +581,10 @@ "head": "ddb61bfe239c56f0bd8d5fabf869104ce19dfff9", "at": "2026-10-22T20:28:03Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/gcloud-jvm/pull/210", + "head": "ddb61bfe239c56f0bd8d5fabf869104ce19dfff9" + }, "parked": null }, "delivery": { From f99465a89f52dbae5bea54de4d14dc1027073e56 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 14:25:51 +0100 Subject: [PATCH 61/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index f5a22fc..0b61f9e 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -619,7 +619,10 @@ "head": "75bb56c07fe6c354816a9762ee504d1c31f7e535", "at": "2026-10-22T20:48:29Z" }, - "pr": null, + "pr": { + "url": "https://github.com/SpineEventEngine/delivery/pull/85", + "head": "75bb56c07fe6c354816a9762ee504d1c31f7e535" + }, "parked": null }, "BuildSpeed": { From 1fda0b28b6c863b0e565545f2570214021651464 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 15:12:09 +0100 Subject: [PATCH 62/65] Map dokka-tools to its DokkaTools.kt pin file Without the mapping, `close` skipped `DokkaTools.kt` and left `config` pinning `2.0.0-SNAPSHOT.10` after the wave published `.12`, and the floor gate could not tell which repo a `DokkaTools` pin belongs to. Co-Authored-By: Claude Opus 5.5 --- cascade | 1 + 1 file changed, 1 insertion(+) diff --git a/cascade b/cascade index 6583b69..d762914 100755 --- a/cascade +++ b/cascade @@ -178,6 +178,7 @@ repo_pin_file() { compiler) echo Compiler.kt ;; core-jvm) echo CoreJvm.kt ;; core-jvm-compiler) echo CoreJvmCompiler.kt ;; + dokka-tools) echo DokkaTools.kt ;; logging) echo Logging.kt ;; ProtoTap) echo ProtoTap.kt ;; reflect) echo Reflect.kt ;; From cf6dc28fc44ee06643dc002323c21a69e3a889a2 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 15:17:09 +0100 Subject: [PATCH 63/65] Update cascade state --- .agents/tasks/cascade-refresh-604420c.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/cascade-refresh-604420c.json index 0b61f9e..574aa4d 100644 --- a/.agents/tasks/cascade-refresh-604420c.json +++ b/.agents/tasks/cascade-refresh-604420c.json @@ -528,7 +528,7 @@ "group_path": "io/spine", "artifact": "spine-rdbms" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.131", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.081", @@ -564,7 +564,7 @@ "group_path": "io/spine/gcloud", "artifact": "spine-datastore" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "2.0.0-SNAPSHOT.241", "pin_vector": { "base-libraries": "2.0.0-SNAPSHOT.462", @@ -603,7 +603,7 @@ "group_path": "io/spine/delivery", "artifact": "spine-delivery-server" }, - "state": "pr-ready", + "state": "published-remote", "target_version": "0.24.1", "pin_vector": { "compiler": "2.0.0-SNAPSHOT.081", @@ -645,5 +645,5 @@ } }, "excluded": {}, - "closing_pr": null + "closing_pr": "https://github.com/SpineEventEngine/config/pull/818" } From 4eef83e8fe142df42d8a11fc77549994bf90fda1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 15:17:56 +0100 Subject: [PATCH 64/65] Open the closing config PR as a draft `close --ship` still opened the closing PR as ready, so the organization's ruleset requested a Copilot review before CI had run, as `ship` already avoids. Mark it ready once all its checks pass. Co-Authored-By: Claude Opus 5.5 --- cascade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cascade b/cascade index d762914..b401ccd 100755 --- a/cascade +++ b/cascade @@ -1808,7 +1808,9 @@ cmd_close() { { [ "$s_status" = PASS ] && [ "$s_head" = "$chead" ]; } \ || { warn "no PASS pre-pr sentinel for HEAD in config — run the pre-pr skill there, then: ./cascade close --ship"; exit 3; } git push -u origin "$vbranch" - gh pr create -R "$ORG/config" --base "$BASE" --head "$vbranch" \ + # A draft, as in `ship`: the ruleset requests a Copilot review for every PR + # opened as ready. Mark it ready once all its checks pass. + gh pr create --draft -R "$ORG/config" --base "$BASE" --head "$vbranch" \ --title "Record the \`$wave\` version vector" \ --body "Advances \`io.spine.dependency.local\` pins to the versions published by wave \`$wave\`. All versions verified present in the registry before this PR was opened." mset "$wave" '.closing_pr = $u' --arg u "$(gh pr view "$vbranch" -R "$ORG/config" --json url --jq .url)" From f80b0d0fb13717e3f7b7b0a4020b350698a757ae Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 23 Oct 2026 15:38:28 +0100 Subject: [PATCH 65/65] Archive the completed `cascade-refresh-604420c` wave config#818 (merged as `fcd68830`) records the version vector the wave published; the log ends with the events since 2026-10-21. Co-Authored-By: Claude Opus 5.5 --- .agents/tasks/{ => archive}/cascade-refresh-604420c.json | 0 .agents/tasks/{ => archive}/cascade-refresh-604420c.md | 5 +++++ 2 files changed, 5 insertions(+) rename .agents/tasks/{ => archive}/cascade-refresh-604420c.json (100%) rename .agents/tasks/{ => archive}/cascade-refresh-604420c.md (69%) diff --git a/.agents/tasks/cascade-refresh-604420c.json b/.agents/tasks/archive/cascade-refresh-604420c.json similarity index 100% rename from .agents/tasks/cascade-refresh-604420c.json rename to .agents/tasks/archive/cascade-refresh-604420c.json diff --git a/.agents/tasks/cascade-refresh-604420c.md b/.agents/tasks/archive/cascade-refresh-604420c.md similarity index 69% rename from .agents/tasks/cascade-refresh-604420c.md rename to .agents/tasks/archive/cascade-refresh-604420c.md index 566a682..4d27f0e 100644 --- a/.agents/tasks/cascade-refresh-604420c.md +++ b/.agents/tasks/archive/cascade-refresh-604420c.md @@ -42,3 +42,8 @@ Machine state: [`cascade-refresh-604420c.json`](cascade-refresh-604420c.json). P - 2026-10-21 — follow-up after the wave: config#813 (merged as `a53eca4b2e`) declares `OpenTelemetryKotlin.exportersCore`/`exportersOtlp`; once `logging` pulls a config at or past it, `otel-backend-bootstrap/build.gradle.kts` can drop the inline coordinates from `0bf9a733`. - 2026-10-21 — retargeted `logging` to `2.0.0-SNAPSHOT.428` (logging#153, on the latest `config` with the named OpenTelemetry exporter accessors) at the owner's request; the wave branch was fast-forwarded to master. Unshipped downstream repos re-pin to `.428`; the already-published testlib `.216` and tool-base `.428` keep `.427` as a floor. - 2026-10-21 — ProtoTap#24 merged on its pre-re-pin head (`08b843a`), so ProtoTap `0.17.4` pins logging `.427` (a floor, like testlib and tool-base); its local re-pin commits stay unpushed, and the local rebuild of `0.17.4` was moved out of `~/.m2`. +- 2026-10-22 — `compiler` `.080` published partly (GitHub Packages answered 409 Conflict on an already uploaded checksum). Re-shipped as `.081` (compiler#97) on `config` `ad3dff08`, the hardened publishing of config#814; the ten repos without PRs pulled the same `config` and re-pinned to `.081`. +- 2026-10-22 — four PRs shipped together hit the Artifact Registry's HTTP 429 rate limit in CI; the driver now re-runs jobs that failed on 429 only. +- 2026-10-22 — the push event of the time#201 merge arrived 17 minutes late, so `.252` did publish; `time` was re-shipped anyway as `.253` (time#202) to try `config` `58cd2d4a` (config#815, `publishApiDocs`), whose rename broke consumers' own Gradle scripts until config#817 taught `migrate` to rewrite them. `core-jvm` and `delivery` re-pinned to `.253`. +- 2026-10-23 — core-jvm#1697 merged master (`.576`, from core-jvm#1696) and kept `.577`; `core-jvm`, `jdbc-storage`, `gcloud-jvm` and `delivery` shipped on `config` `c5d6e5b2`, whose `migrate` rewrote their scripts. +- 2026-10-23 — **closed**: config#818 (merged as `fcd68830`) records the wave's version vector.