diff --git a/.github/scripts/next-version.sh b/.github/scripts/next-version.sh index 27fce0e..a0c3758 100755 --- a/.github/scripts/next-version.sh +++ b/.github/scripts/next-version.sh @@ -2,7 +2,7 @@ # next-version.sh — compute THIS repo's next release tag for release-on-upstream.yml. # # Single source of truth for the version math, exercised in CI by release-selftest.yml so the -# release automation can't silently rot (guard #135.8). Prints "v.." to stdout. +# release automation can't silently rot. Prints "v.." to stdout. # # Inputs (env, all optional): # INPUT_VERSION explicit version to cut (leading "v" tolerated) -> used verbatim. diff --git a/.github/workflows/docker-bundle.yml b/.github/workflows/docker-bundle.yml index 1a550a3..168e3e6 100644 --- a/.github/workflows/docker-bundle.yml +++ b/.github/workflows/docker-bundle.yml @@ -15,9 +15,8 @@ name: Docker (bundle) # this repo already declares busbarAI as a path dependency for busbar-plugin-sdk (see Cargo.toml), # so the sibling-checkout layout is already the convention. The build mirrors EXACTLY what # busbarAI's own docker.yml used to do when it bundled headroom into its own image, before that -# responsibility moved to this repo (see busbarAI commit ed61aae "ci/docker: stop bundling -# headroom into busbar's own release and image" — its PARENT commit has the full original logic -# this workflow was transcribed from): same PGO-mandatory fail-closed release build, same +# responsibility moved to this repo (busbarAI stopped bundling headroom into busbar's own release +# and image at that point): same PGO-mandatory fail-closed release build, same # musl-native `rust:alpine` container trick, exact-ABI-matched runtime libs extracted from the # same container so dlopen() succeeds in a FROM-scratch image with no libc at all. # @@ -35,8 +34,8 @@ name: Docker (bundle) # # Needs real `DOCKERHUB_USERNAME`/`DOCKERHUB_TOKEN` secrets on THIS repo to push. As of this # workflow's authoring both are provisioned (`gh secret list --repo GetBusbar/headroom-hook` -# shows DOCKERHUB_TOKEN + DOCKERHUB_USERNAME) — verify the push step yourself before relying on -# it; it was not (and cannot be) exercised by the agent that authored this file. +# shows DOCKERHUB_TOKEN + DOCKERHUB_USERNAME). The push step is only exercised by a real tagged +# run, so confirm it once against this repo's credentials before relying on it. on: push: @@ -96,20 +95,14 @@ jobs: ref: ${{ env.BUSBARAI_REF }} path: busbarAI - # headroom-hook's Cargo.toml currently declares busbar-plugin-sdk (and its dev-dependency) - # as an ABSOLUTE local path (/Users/matthew/Developer/busbarAI/busbarAI/crates/...) — a - # stopgap documented in Cargo.toml pending busbarAI going public. Despite a comment - # elsewhere claiming this is already a sibling-relative path, it is NOT, as of this - # workflow's authoring (verified by reading the checked-out Cargo.toml directly) — so this - # step patches it for CI, exactly the workaround busbarAI's own release.yml used to carry - # before headroom-hook was (incorrectly, per that same verification) believed to no longer - # need it. Remove this step once headroom-hook's Cargo.toml itself switches to a real - # sibling-relative path (`../busbarAI/crates/...`). - - name: Patch headroom-hook's interim path dependencies for CI + # headroom-hook's Cargo.toml declares busbar-plugin-sdk (and its dev-dependency) as + # SIBLING-RELATIVE path dependencies (`../busbarAI/crates/...`), which is exactly the layout + # the two checkout steps above produce. An absolute or otherwise non-sibling path here would + # not resolve against this job's tree, and cargo's failure for it is a confusing one, so + # assert the shape up front rather than letting the build step report it. + - name: Assert headroom-hook's path dependencies are sibling-relative run: | set -euo pipefail - sed -i.bak 's#/Users/matthew/Developer/busbarAI/busbarAI/crates#../busbarAI/crates#g' headroom-hook/Cargo.toml - rm -f headroom-hook/Cargo.toml.bak grep 'path = "\.\./busbarAI' headroom-hook/Cargo.toml - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6f39ff1..4a328cb 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,13 +1,13 @@ -# STALE since "Port headroom-hook to busbar's signed dlopen plugin ABI" (commit c37b798): this +# STALE since "Port headroom-hook to busbar's signed dlopen plugin ABI": this # workflow builds a standalone `headroom-hook` BINARY for the RETIRED Unix-socket transport, but the # crate has been `crate-type = ["cdylib", "rlib"]` only since that port — no `[[bin]]`, no `fn main` # — so `cargo build --release` here can no longer produce a binary at all. `release.yml` is the real # release workflow now (builds the cdylib, packs+signs it as a busbar plugin tarball). # # The automatic `push: tags: v*` trigger is REMOVED below so this doesn't fail on every release tag. -# Kept as `workflow_dispatch` only, and NOT deleted outright: whether to revive this as a Docker -# image build for the standalone-plugin-loaded-into-busbar use case (see busbar-headroom bundled -# image work) or retire it entirely is a product call, not made unilaterally here. +# Kept as `workflow_dispatch` only, and NOT deleted outright: reviving it as a Docker image build +# for the standalone-plugin-loaded-into-busbar use case (see busbar-headroom bundled image work) +# and retiring it entirely are both still open options. # # Build the headroom-hook image for amd64 + arm64 and publish to Docker Hub, # tagged with the pushed vX.Y.Z tag and `latest`. Binaries are built on @@ -15,7 +15,7 @@ # # DEPRECATED / CURRENTLY BROKEN: this workflow builds `target//release/headroom-hook`, # a binary that no longer exists — since "Port headroom-hook to busbar's signed dlopen plugin -# ABI" (commit c37b798) this crate is `crate-type = ["cdylib", "rlib"]` only (no `[[bin]]`, no +# ABI" this crate is `crate-type = ["cdylib", "rlib"]` only (no `[[bin]]`, no # `fn main`). `cargo build --release` here builds fine (the lib target), but there is no # `headroom-hook` executable to `file`/upload/COPY into the Dockerfile — this workflow would # fail partway through if it ran. The automatic `push: tags: v*` trigger has been REMOVED (see @@ -24,9 +24,9 @@ # headroom-release-publish.yml used to `gh workflow run docker.yml` after every merge to main # (dispatching a guaranteed-failing run on every real release, since this workflow was already # broken) — that call was retargeted to docker-bundle.yml instead, the actual current release -# path. Use getbusbar/busbar-headroom (.github/workflows/docker-bundle.yml) instead — see -# README.md's "Two ways to run" section. Fixing or retiring this file for good is a product call -# for a human, not made unilaterally here. +# path. Use getbusbar/busbar-headroom (.github/workflows/docker-bundle.yml) instead - see +# README.md's "Two ways to run" section. This file is neither fixed nor deleted: it stays as a +# manual-dispatch-only record of the retired transport. # # NOTE (see Dockerfile): on Linux, headroom-core's default tree links the ONNX # runtime at build time. The FIRST run of this workflow is the validation point diff --git a/.github/workflows/release-selftest.yml b/.github/workflows/release-selftest.yml index a6aafb6..9cfa502 100644 --- a/.github/workflows/release-selftest.yml +++ b/.github/workflows/release-selftest.yml @@ -1,4 +1,4 @@ -# CI self-test for the release-on-upstream version-compute logic (guard #135.8). +# CI self-test for the release-on-upstream version-compute logic. # Runs the REAL .github/scripts/next-version.sh against synthetic repos and asserts it produces a # valid next version for BOTH the has-prior-tag and no-prior-tag cases — WITHOUT publishing anything. # This is what keeps the release automation from silently rotting before the fleet fan-out is armed. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b144c3..8c9ed9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ # # REPLACES the old `release-headroom` workflow, which built a standalone binary for the # RETIRED Unix-socket transport (`headroom-hook` executable, triggered by a `headroom-v*` tag). -# Since "Port headroom-hook to busbar's signed dlopen plugin ABI" (commit c37b798) this crate is +# Since "Port headroom-hook to busbar's signed dlopen plugin ABI" this crate is # `crate-type = ["cdylib", "rlib"]` only — no `[[bin]]`, no `fn main` — so that old workflow can no # longer build anything. This workflow builds the cdylib instead, packed the same way every other # first-party plugin's Release tarball is. @@ -110,17 +110,14 @@ jobs: ref: ${{ steps.ref.outputs.sha }} path: busbarAI - # headroom-hook's Cargo.toml currently declares busbar-plugin-sdk as an ABSOLUTE local path - # (/Users/matthew/Developer/busbarAI/busbarAI/crates/...) — a stopgap the crate's own - # Cargo.toml documents, pending busbarAI going public. Patch it to the sibling-relative path - # this job's checkout layout actually produces (same patch - # .github/workflows/docker-bundle.yml already carries for the same reason). - - name: Patch headroom-hook's interim path dependencies for CI + # headroom-hook's Cargo.toml declares busbar-plugin-sdk as a SIBLING-RELATIVE path + # dependency (`../busbarAI/crates/...`), which is the layout the checkout step above + # produces. Assert that shape up front (the same assertion + # .github/workflows/docker-bundle.yml carries) rather than letting cargo report it. + - name: Assert headroom-hook's path dependencies are sibling-relative shell: bash run: | set -euo pipefail - sed -i.bak 's#/Users/matthew/Developer/busbarAI/busbarAI/crates#../busbarAI/crates#g' headroom-hook/Cargo.toml - rm -f headroom-hook/Cargo.toml.bak grep 'path = "\.\./busbarAI' headroom-hook/Cargo.toml - uses: dtolnay/rust-toolchain@stable diff --git a/Dockerfile b/Dockerfile index 34309a3..666a4a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # # This Dockerfile describes the RETIRED pre-dlopen-ABI architecture: a standalone # `headroom-hook` binary serving busbar's old Unix-socket hook wire. Since "Port -# headroom-hook to busbar's signed dlopen plugin ABI" (commit c37b798), this crate +# headroom-hook to busbar's signed dlopen plugin ABI", this crate # builds ONLY a cdylib (`crate-type = ["cdylib", "rlib"]`, no `[[bin]]`, no `fn main`) # that busbar dlopen's in-process — there is no more standalone binary for this # Dockerfile's `COPY binaries/${TARGETARCH}/headroom-hook /headroom-hook` line to copy, @@ -17,10 +17,9 @@ # .github/workflows/docker-bundle.yml) — see README.md's "Two ways to run" section. # Alternatively, release.yml's signed plugin tarball (drop into an existing busbar's # plugins.dir) is the other real release path — see README.md "Install and run". -# Whether this standalone image concept is still worth reviving (e.g. as a from-source -# dlopen sidecar loader) or should simply be deleted is a product call for a human to -# make, not something fixed unilaterally here — this header only documents why the file -# as it stands no longer describes anything buildable. +# Whether this standalone image concept is revived (e.g. as a from-source dlopen sidecar +# loader) or simply deleted is still open; this header only documents why the file as it +# stands no longer describes anything buildable. # # ---- Everything below this point is the ORIGINAL (stale) socket-transport content, # ---- left as-is / historical reference. Do not trust it against the current code. diff --git a/docker-compose.yml b/docker-compose.yml index c1741c5..6870387 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ # This file composes two containers around a shared Unix socket — the RETIRED # pre-dlopen-ABI transport. headroom-hook has not shipped a standalone binary (and so # no getbusbar/headroom-hook image build has succeeded) since "Port headroom-hook to -# busbar's signed dlopen plugin ABI" (commit c37b798): the plugin is now an in-process +# busbar's signed dlopen plugin ABI": the plugin is now an in-process # cdylib busbar dlopen's itself, not a second process with a socket to connect to. # # For "one container, zero config, busbar + headroom together" today, use diff --git a/docker/bundle/Dockerfile b/docker/bundle/Dockerfile index d0559f1..46907b9 100644 --- a/docker/bundle/Dockerfile +++ b/docker/bundle/Dockerfile @@ -56,9 +56,8 @@ # musl-native container, so the ABI matches) is what makes dlopen() succeed in a FROM-scratch # image that otherwise has no libc at all. This whole mechanism — the musl-native rust:alpine # build container, crt-static disabled, runtime-lib extraction — is ported verbatim from -# busbarAI's git history (its Dockerfile/docker.yml used to bundle headroom this exact way, -# before that responsibility moved to this repo; see busbarAI commit ed61aae's parent for the -# original, already-solved implementation this was transcribed from). +# busbarAI's own image build, which used to bundle headroom this exact way before that +# responsibility moved to this repo. # # Run (zero-config quickstart — headroom active, one provider): # docker run -d -p 8080:8080 \ diff --git a/tests/e2e.rs b/tests/e2e.rs index d701197..d1ad599 100644 --- a/tests/e2e.rs +++ b/tests/e2e.rs @@ -164,6 +164,13 @@ fn load(settings: &str) -> Arc { fn req_with_history(history: String, ask: &str) -> RoutingRequest<'static> { let total_chars = history.len() + ask.len(); RoutingRequest { + // A fixed correlation id: these fixtures assert on the gate's DECISION, and nothing in the + // headroom policy reads the id, so a constant keeps two otherwise-identical requests + // comparable instead of introducing a value that differs run to run. + request_id: 1, + // No signals: the engine only populates the bag for signals a hook asked for, and the + // headroom policy asks for none — an empty bag is what it is really handed in production. + signals: Default::default(), pool: "p", ingress_protocol: "anthropic", requested_model: None, @@ -188,6 +195,8 @@ fn req_with_history(history: String, ask: &str) -> RoutingRequest<'static> { /// A request with NO prompt (grant absent): the projector carries no prompt keys → the gate abstains. fn req_without_prompt() -> RoutingRequest<'static> { RoutingRequest { + request_id: 2, + signals: Default::default(), pool: "p", ingress_protocol: "anthropic", requested_model: None, @@ -217,6 +226,7 @@ fn cand(idx: usize) -> Candidate<'static> { available_concurrency: 1, budget_remaining: None, rate_headroom: None, + signals: Default::default(), } }