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
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>
94 lines
3.8 KiB
YAML
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
|