Files
molecule-core/.gitea/workflows/lint-schedule-budget.yml
T
hongmingandClaude Opus 5 556d9aa981
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 12s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 12s
CI / Python Lint & Test (pull_request) Successful in 13s
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 16s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 13s
Harness Replays / detect-changes (pull_request) Successful in 15s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 17s
ci-required-drift / drift (pull_request) Successful in 23s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 17s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 18s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 18s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Successful in 22s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 25s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 13s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 16s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 28s
lint-phantom-gate / lint-phantom-gate (pull_request) Successful in 27s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 23s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 19s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 5s
sdk-route-milestone-contract-drift / SDK route + milestone derive-gates (pull_request) Successful in 17s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 13s
sdk-pin-drift / SDK consumer pin vs molecule-ai-sdk main (pull_request) Successful in 19s
E2E API Smoke Test / detect-changes (pull_request) Successful in 47s
lint-staging-tenant-cd-gate-chain / lint-staging-tenant-cd-gate-chain (pull_request) Successful in 27s
Lint workflow YAML (repository compatibility policy) / Lint workflow YAML for repository compatibility policy (pull_request) Successful in 30s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 36s
Lint schedule budget / Zero-cron ratchet (pull_request) Successful in 33s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 6s
lint-env-coupling-dismissal / lint-env-coupling-dismissal (pull_request) Successful in 55s
CI / Detect changes (pull_request) Successful in 1m5s
E2E Ephemeral CP Happy Path / detect (pull_request) Successful in 1m3s
template-delivery-e2e / detect-changes (pull_request) Successful in 35s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 4s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 56s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 59s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 59s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 48s
E2E Chat / E2E Chat (pull_request) Successful in 2m14s
E2E Ephemeral CP Happy Path / E2E Ephemeral CP Happy Path (pull_request) Failing after 1m18s
Harness Replays / Harness Replays (pull_request) Successful in 2m30s
CI / Canvas (Next.js) (pull_request) Successful in 4m40s
CI / Canvas Deploy Status (pull_request) Successful in 3s
CI / Platform (Go) (pull_request) Successful in 5m46s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 6m7s
CI / all-required (pull_request) Successful in 5s
fix(ci): correct the "not required" claim on the zero-cron ratchet, and close the review gaps
Review of #5117 found one false claim in the repo and three gaps in the
instrumentation. All four are addressed here; none of them change what the
diagnostic asserts, only what it can distinguish and what it admits.

THE FALSE CLAIM. lint-schedule-budget.yml said it is "NOT a
branch-protection-required context (kept out of .gitea/required-contexts.txt)
so a future violation surfaces loudly ... without wedging the merge queue".
Absence from that file exempts a lane from the merge queue's step-4b PRESENCE
check and NOTHING else. main's branch protection is status_check_contexts=['*'],
and since #4363 the queue reads that glob with Gitea's real semantics — see
gitea-merge-queue.py::required_contexts_green, "a GLOB pattern is a SUPERSET
check ... requires all matches to be `success`". So the moment this lane posts,
it is required to be green. A red here DOES wedge the queue. The comment is
replaced with the two-mechanism version, because it is what made a red on #5117
read as non-blocking.

GAP 1 — the browser side alone cannot separate the two forks core#5106 is stuck
on. A connection REFUSED (never reached the server) and one RESET BEFORE
HEADERS (reached a server that dropped it) settle to byte-identical CSSOM and
Resource Timing: THREW SecurityError / status=0 firstByte=NEVER transfer=0B.
Only the net error and the server probe's silence-vs-"CONNECTION DIED" separate
them. Documented where it matters — in the timing block that would otherwise
be read as sufficient, and in net-evidence.ts as the argument for why that
channel is load-bearing rather than a second opinion.

GAP 2 — a graceful FIN that stops short of Content-Length gives the SAME CSSOM
shape and the SAME timing as a mid-body RST (status=200, bytes on the wire,
readable 0-rule sheet) and a different net error, ERR_CONTENT_LENGTH_MISMATCH.
Measured, then added to the fixture as /short-fin.css and asserted alongside
/truncated.css so the pair cannot be read as one shape.

GAP 3 — the Resource Timing buffer holds 250 entries and drops NEW ones when
full. Verified: a 400-request flood after the stylesheets left both stylesheet
entries intact and lost the tail. So a late flood cannot turn "this sheet died"
into "this sheet never settled". Recorded, because the opposite eviction policy
would have silently inverted a diagnosis.

RESIDUAL — "the server never saw the request" was an INFERENCE from the absence
of a probe line, and absence is the exact reading that got this issue stuck: a
fast complete response is silent, and so is a request that never arrived. The
probe now emits a 5s heartbeat with `served=` and `inflight=` counters, so the
claim is positive. `inflight > 0` is direct evidence for "accepted and could not
answer"; a flat `served` with `inflight == 0` while the browser waits is
evidence for "it never got here". Unconditional on purpose — a heartbeat that
printed only on change would restore the ambiguity it exists to remove.

Refs #5106

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 09:35:27 -07:00

94 lines
3.8 KiB
YAML

name: Lint schedule budget
# The zero-cron ratchet (principal's rule: NO nightly/scheduled CI).
#
# Every test/gate in molecule-core runs PER-PR and/or as the prod-merge gate
# (push:main/staging) — never on a `schedule:`/`cron:` timer. A scheduled run
# is how breakage reaches prod uncaught: a red nightly sits unwatched, where a
# green PR-gate would have frozen the merge. This lint fails the build if ANY
# `.gitea/workflows/*.yml` declares a live `schedule:` trigger, locking in the
# zero-schedule state after #3344 (the bulk schedule strip) and the staging-
# e2e consolidation (this change retired staging-smoke.yml + continuous-synth-
# e2e.yml into the single e2e-staging-saas full-journey gate).
#
# It parses YAML, so commented-out `# schedule:` cruft and prose mentioning
# "cron" do NOT trip it — only a parser-visible, actually-firing trigger does.
#
# Triggers (mirrors lint-workflow-yaml.yml):
# - pull_request: pre-merge gate — block a re-added cron before it lands.
# - push:main/staging: post-merge regression detection for direct edits.
# - workflow_dispatch: manual re-run.
#
# Kept out of .gitea/required-contexts.txt.
#
# That does NOT make this lane optional, and the comment here used to say it
# did ("NOT a branch-protection-required context ... without wedging the merge
# queue for unrelated changes"). It is false, and it cost real time on core#5117
# where a red here was read as non-blocking.
#
# Two independent mechanisms, and the exclusion only touches one of them:
#
# * ABSENT from required-contexts.txt -> exempt from the merge queue's
# step-4b PRESENCE check. This lane is paths-filtered, so on a PR that
# touches no workflow it never posts at all; listing it would make that
# silence a merge blocker. THAT is what the exclusion buys.
#
# * main's branch protection is status_check_contexts=['*'], and since #4363
# the queue reads that glob with Gitea's real semantics — see
# gitea-merge-queue.py::required_contexts_green: "a GLOB pattern is a
# SUPERSET check ... it matches every posted context ... and requires all
# matches to be `success`". So the instant this lane POSTS, it is required
# to be green. Nothing in required-contexts.txt can exempt it from that.
#
# Net: a red here DOES wedge the merge queue. The lane is a hard gate whenever
# it runs, which is the intent — it is just not a gate that has to run.
on:
pull_request:
paths:
- '.gitea/workflows/**'
- '.gitea/scripts/lint_schedule_budget.py'
- 'tests/test_lint_schedule_budget.py'
push:
branches: [main, staging]
paths:
- '.gitea/workflows/**'
- '.gitea/scripts/lint_schedule_budget.py'
- 'tests/test_lint_schedule_budget.py'
workflow_dispatch:
# Belt-and-suspenders against runner default
# (feedback_act_runner_github_server_url).
env:
GITHUB_SERVER_URL: https://git.moleculesai.app
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ratchet:
name: Zero-cron ratchet
runs-on: ubuntu-latest
# Hard gate (no continue-on-error mask — mc#2654): a re-added schedule
# MUST go red. The job is green today (0 active schedule triggers).
continue-on-error: false
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.11'
- name: Install PyYAML
run: pip install --quiet 'PyYAML>=6.0'
- name: Zero-cron ratchet (no active schedule triggers)
run: python3 .gitea/scripts/lint_schedule_budget.py
- name: Run lint_schedule_budget unit tests
run: |
pip install --quiet pytest
python3 -m pytest tests/test_lint_schedule_budget.py -v