GloriousFlywheel JS Bazel Package V2 Rollout 2026-04-17

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:

Owner surfaces:

  • #210
  • #213

Current Surface

Current shared workflow:

  • tinyland-inc/ci-templates/.github/workflows/js-bazel-package.yml

Current downstream consumers:

  • tinyland-inc/tinyvectors
  • Jesssullivan/scheduling-kit
  • Jesssullivan/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
  • acuity-middleware
    • has live PRIMARY_LINUX_RUNNER_LABELS_JSON
    • package CI and publish lanes are self-hosted
    • deploy-modal.yml remains hosted
  • 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/checkout with clean: false
  • cleanup paths
  • best-effort chmod plus rm -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

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_TEMP or equivalent
  • avoid clean: false and repo-local cleanup reliance in the normal contract
  • retain persistent_compat only 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_mode
  • workspace_mode
  • workdir or scratch_subdir if needed for isolated staging
  • optional publish_mode: same_runner | hosted_exception

Validation Job Changes

  1. resolve runner intent from runner_mode
  2. use normal checkout behavior
  3. if self-hosted:
    • call setup-flywheel
    • stage work in an isolated path
  4. install and build as before
  5. validate Bazel package as before

Publish Job Changes

  1. make publication authority explicit
  2. if publish_mode is same_runner
    • publish from the self-hosted lane
  3. if publish_mode is hosted_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-kit becomes 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 README if 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.yml as 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-flywheel for self-hosted modes
  • V2 no longer depends on clean: false in the normal path

Downstream Pilots

  • scheduling-kit is a clean dedicated-lane proof
  • acuity-middleware is a clean hybrid proof with one named hosted exception
  • tinyvectors is 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:

  1. confirm runner labels used at runtime
  2. confirm workspace isolation path is actually used
  3. confirm setup-flywheel effects are visible on self-hosted runs
  4. 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.

GloriousFlywheel