Files
molecule-core/.gitea/workflows/sdk-pin-drift.yml
T
hongming 3f3f832ad6
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 8s
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 11s
CI / Python Lint & Test (pull_request) Successful in 16s
ci-required-drift / drift (pull_request) Successful in 25s
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 22s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 12s
CI / Detect changes (pull_request) Successful in 37s
E2E API Smoke Test / detect-changes (pull_request) Successful in 37s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 7s
E2E Ephemeral CP Happy Path / detect (pull_request) Successful in 21s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 9s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 7s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 19s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 33s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Successful in 43s
lint-phantom-gate / lint-phantom-gate (pull_request) Successful in 30s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 30s
lint-env-coupling-dismissal / lint-env-coupling-dismissal (pull_request) Successful in 37s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 6s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 28s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 28s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 15s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 16s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 12s
lint-staging-tenant-cd-gate-chain / lint-staging-tenant-cd-gate-chain (pull_request) Successful in 17s
Lint schedule budget / Zero-cron ratchet (pull_request) Successful in 21s
sdk-route-milestone-contract-drift / SDK route + milestone derive-gates (pull_request) Successful in 17s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 4s
sdk-pin-drift / SDK consumer pin vs molecule-ai-sdk main (pull_request) Successful in 19s
template-delivery-e2e / detect-changes (pull_request) Successful in 21s
Lint workflow YAML (repository compatibility policy) / Lint workflow YAML for repository compatibility policy (pull_request) Successful in 27s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 49s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 48s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 3s
CI / Platform (Go) (pull_request) Has been cancelled
CI / Canvas (Next.js) (pull_request) Has been cancelled
CI / Shellcheck (E2E scripts) (pull_request) Has been cancelled
CI / Canvas Deploy Status (pull_request) Has been cancelled
CI / all-required (pull_request) Has been cancelled
E2E Ephemeral CP Happy Path / E2E Ephemeral CP Happy Path (pull_request) Has been cancelled
E2E Chat / E2E Chat (pull_request) Successful in 2m2s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 54s
ci(sdk-pin): move bp-exempt directive within 3 lines of the job key
lint-required-context-exists-in-bp (Tier 2g) scans a 3-line window above the
job key; my directive sat 4 lines up behind its own rationale, so the new
sdk-pin-drift emissions read as undeclared. Rationale moved above the marker,
marker moved adjacent. Same fix applied pre-emptively to sdk-pin-bump.
2026-08-05 00:43:53 -07:00

108 lines
5.1 KiB
YAML

name: sdk-pin-drift
# SDK consumer-pin drift gate — the DETECTOR leg of the SDK -> molecule-core pin
# pipeline (the sibling of workspace-runtime's check_consumer_runtime_drift.py on
# the runtime -> template axis).
#
# SSOT: molecule-ai-sdk@main, module `go.moleculesai.app/sdk/gen/go`.
# CONSUMER PIN: workspace-server/go.mod.
#
# WHAT WAS MISSING. The runtime -> template axis has an opener, a merger and a
# detector. The SDK -> core axis had none of the three: nothing opened a bump PR
# on an SDK merge, nothing merged one, and nothing ever went red when the pin
# fell behind. The two gates that look adjacent do NOT cover staleness:
# * sync_canonical_test.go pins the sha of whatever the binary ALREADY embeds —
# hermetic and inverted, it fires on an unexpected change, never on lag.
# * verify-providers-gen.yml asserts the projection matches THE PINNED MODULE,
# whatever version that is. Also green on a stale pin.
# On 2026-08-05 core sat on sdk#203 (platform arms narrowed to minimax-only)
# while sdk#204 had already restored five healthy model ids. Five ids were
# unselectable for new workspaces and every check in the repo was green.
#
# WHY IT IS NOT "RED ON ANY LAG". Branch protection on main is
# `status_check_contexts: ["*"]`, so any context this workflow posts blocks EVERY
# PR in the repo. Going red on a routine SDK merge would wedge molecule-core. The
# script therefore mirrors classify_pin_drift's disposition and is RED only in
# the one case a human must act on:
# pin == head -> OK (exit 0)
# lagging within the window -> ADVISORY (exit 0)
# lagging beyond window, bump PR in flight -> ADVISORY (exit 0)
# lagging beyond window, NO bump PR = STUCK -> BLOCKING (exit 1)
# undeterminable (API/network/token) -> ADVISORY (exit 0)
# The window is SDK_PIN_MAX_LAG_HOURS (default 72h — spans a weekend, so a Friday
# SDK merge does not go red on Saturday).
#
# Proof the gate fires: tests/test_check_sdk_pin_drift.py exercises the BLOCKING
# row explicitly (`test_lag_beyond_window_with_no_bump_pr_BLOCKS`,
# `test_main_returns_1_on_stuck_pin`), not just the happy path. A gate that has
# never been observed to fail is not a gate.
#
# NO schedule/cron: molecule-core enforces a zero-cron ratchet
# (lint_schedule_budget.py). PR + push + dispatch is strictly better here anyway —
# drift is reported on every PR rather than once a night.
#
# NO paths: filter. This gate's verdict depends on the STATE OF ANOTHER REPO, so
# it can change without any file in this PR changing. A paths filter would make
# it structurally incapable of noticing the very drift it exists to catch. (It is
# also a prerequisite for promoting it into required-contexts.txt later —
# lint-required-no-paths forbids paths on required contexts.)
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [main, staging]
workflow_dispatch:
env:
GITHUB_SERVER_URL: https://git.moleculesai.app
permissions:
contents: read
concurrency:
group: sdk-pin-drift-${{ github.ref }}
cancel-in-progress: true
jobs:
# Soak-then-promote posture, same as cron-fixtures-ssot-drift and
# verify-providers-gen: this reports on every PR and push immediately, but
# promoting it into branch protection is a follow-up once it has soaked —
# a cross-repo signal that can gate all of core needs operator GO.
# bp-exempt: standalone soak-then-promote drift gate, not a declared BP context
drift:
name: SDK consumer pin vs molecule-ai-sdk main
runs-on: ubuntu-latest
timeout-minutes: 8
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.11'
- name: Check SDK pin drift
env:
# The SDK repo is public, so the HEAD read needs no credential. The
# open-bump-PR query is same-repo, which the run-scoped token covers —
# so the gate is ARMED by default rather than permanently advisory. If
# the token is ever absent the script degrades to ADVISORY and says so
# (it never blocks on a signal it could not read).
SDK_PIN_DRIFT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SDK_PIN_MAX_LAG_HOURS: ${{ vars.SDK_PIN_MAX_LAG_HOURS || '72' }}
GITEA_HOST: https://git.moleculesai.app
run: |
set -euo pipefail
python3 .gitea/scripts/check_sdk_pin_drift.py \
--go-mod workspace-server/go.mod
- name: Self-test the gate's own disposition matrix
run: |
set -euo pipefail
# Runs in the same job deliberately: if the classifier regresses into
# "never blocks", THIS step goes red even though the step above is
# green. Without it a broken gate is indistinguishable from a healthy
# pin — the vacuous-pass failure mode this repo keeps re-learning.
python3 -m pip install --quiet pytest
python3 -m pytest tests/test_check_sdk_pin_drift.py -q