GloriousFlywheel JS Bazel Package V2 Rollout 2026-04-17
Snapshot date: 2026-04-17
Purpose
Define the smallest credible V2 of the shared JS and Bazel package workflow and the downstream pilot sequence for adopting it.
Companion notes:
- gloriousflywheel-contract-remediation-packages-2026-04-17.md
- gloriousflywheel-tier-scorecard-and-template-remediation-2026-04-17.md
- gloriousflywheel-exception-register-and-promotion-rules-2026-04-17.md
- gloriousflywheel-js-bazel-package-v2-contract-spec-2026-04-17.md
Owner surfaces:
#210#213
Current Surface
Current shared workflow:
tinyland-inc/ci-templates/.github/workflows/js-bazel-package.yml
Current downstream consumers:
tinyland-inc/tinyvectorsJesssullivan/scheduling-kitJesssullivan/acuity-middleware
Verified runner-intent reality:
scheduling-kit- has live
PRIMARY_LINUX_RUNNER_LABELS_JSON - current CI and publish paths use the shared template with a repo-owned dedicated lane
- has live
acuity-middleware- has live
PRIMARY_LINUX_RUNNER_LABELS_JSON - package CI and publish lanes are self-hosted
deploy-modal.ymlremains hosted
- has live
tinyvectors- imports the shared template
- does not currently show repo-level runner variables
- remains the clean hosted-template control case
V1 Problems
1. Hosted Fallback Is The Default
The template treats self-hosted use as optional by defaulting
runner_labels_json to ["ubuntu-latest"].
That is acceptable for migration.
It is weak as a long-term platform contract because the workflow alone does not say whether a repo is meant to be hosted or self-hosted.
2. Persistent Workspace Hygiene Is Encoded Directly
The template currently uses:
actions/checkoutwithclean: false- cleanup paths
- best-effort
chmodplusrm -rf
That means the workflow assumes the old persistent self-hosted workspace model.
3. Self-Hosted Platform Behavior Is Implicit
The workflow does not call:
setup-flywheel
So even when the job runs on a real self-hosted lane, the template is not expressing the GloriousFlywheel contract explicitly.
4. Build And Publish Policy Are Intertwined
The workflow mixes:
- build validation
- Bazel packaging
- npm dry-run validation
- GitHub Packages validation
- real publish behavior
That is workable, but the contract boundary is unclear:
- what should always run on self-hosted
- what may need hosted publication authority
V2 Design Goals
Goal 1: Runner Intent Must Be Explicit
The reusable workflow should make the repo choose one policy:
- hosted
- shared self-hosted
- repo-owned dedicated lane
Suggested new input:
runner_mode: hosted | shared | repo_owned
Suggested follow-on behavior:
hosted- require hosted labels or default to hosted intentionally
shared- use a documented shared label set
repo_owned- require
runner_labels_json
- require
Goal 2: Workspace Intent Must Be Explicit
Suggested new input:
workspace_mode: isolated | persistent_compat
Expected default:
isolated
Expected behavior:
- create a per-job workspace under
$RUNNER_TEMPor equivalent - avoid
clean: falseand repo-local cleanup reliance in the normal contract - retain
persistent_compatonly as a temporary migration switch
Goal 3: Self-Hosted Modes Must Express The Platform Contract
When runner_mode is shared or repo_owned, the workflow should:
- call
setup-flywheel - make cache behavior visible in the job
- treat missing contract wiring as a workflow bug, not as invisible drift
Goal 4: Build Validation Must Be Separable From Publication Authority
V2 should clearly separate:
- self-hosted build and package validation
- hosted publish authority when provenance or registry behavior still needs it
That does not require separate reusable workflows yet, but it does require clearer job boundaries.
Proposed V2 Patch Shape
New Inputs
runner_modeworkspace_modeworkdirorscratch_subdirif needed for isolated staging- optional
publish_mode: same_runner | hosted_exception
Validation Job Changes
- resolve runner intent from
runner_mode - use normal checkout behavior
- if self-hosted:
- call
setup-flywheel - stage work in an isolated path
- call
- install and build as before
- validate Bazel package as before
Publish Job Changes
- make publication authority explicit
- if
publish_modeissame_runner- publish from the self-hosted lane
- if
publish_modeishosted_exception- download validated artifacts on hosted
- publish there intentionally
Pilot Sequence
Pilot 1: scheduling-kit
Why first:
- verified dedicated self-hosted lane
- no inspected hosted authority in CI and publish path
- cleanest current downstream proof point
Success means:
scheduling-kitbecomes a documented Tier 4 contract example- the new template can carry a real dedicated-lane repo without hosted drift
Pilot 2: acuity-middleware
Why second:
- verified dedicated self-hosted package lane
- explicit hosted deploy exception already exists
- exposed the current hygiene defect directly
Success means:
- one repo can use the self-hosted package contract cleanly
- while preserving a named hosted deploy exception
Pilot 3: tinyvectors
Why third:
- clean hosted-template control case
- will show whether V2 can promote a repo into verified self-hosted use without additional workflow sprawl
Success means either:
- the repo gets verified runner labels and promotes cleanly
- or it remains explicitly hosted with no ambiguity
Both are acceptable. Ambiguity is not.
Exact Files Expected To Change
In tinyland-inc/ci-templates
.github/workflows/js-bazel-package.yml
Potentially:
- add comments or docs in
READMEif that repo uses one
In Pilot Repos
scheduling-kit
.github/workflows/ci.yml.github/workflows/publish.yml
acuity-middleware
.github/workflows/ci.yml.github/workflows/publish.yml- document
deploy-modal.ymlas hosted exception if needed
tinyvectors
.github/workflows/ci.yml.github/workflows/publish.yml- optionally repo variable setup if promotion is chosen
Acceptance Criteria
Shared Template
- V2 makes runner intent explicit
- V2 makes workspace intent explicit
- V2 uses
setup-flywheelfor self-hosted modes - V2 no longer depends on
clean: falsein the normal path
Downstream Pilots
scheduling-kitis a clean dedicated-lane proofacuity-middlewareis a clean hybrid proof with one named hosted exceptiontinyvectorsis either promoted cleanly or left explicitly hosted
Risks
1. Trying To Solve Too Many Repo Differences In The Template
Mitigation:
- keep V2 focused on runner intent, workspace intent, and contract wiring
2. Breaking Existing Consumers During Migration
Mitigation:
- keep a temporary compatibility mode
- migrate pilots first
- only then make stricter defaults
3. Confusing Hosted Publish Requirements With Build Requirements
Mitigation:
- make publish authority a named choice in the template
- do not bury it in shell conditionals
Verification
Expected verification per pilot:
- confirm runner labels used at runtime
- confirm workspace isolation path is actually used
- confirm
setup-flywheeleffects are visible on self-hosted runs - confirm published artifacts still derive from validated Bazel output
Rollback
If V2 causes downstream churn:
- retain V1 compatibility mode temporarily
- keep pilot repos on the explicit mode they were validated against
- do not return to ambiguous hosted fallback as the default explanation
Rollback should preserve explicitness, not recover ambiguity.