Files
molecule-core/.gitea/workflows/lint-continue-on-error-tracking.yml
T
hongming-ceo-delegated e79d1ae12b
sop-checklist / all-items-acked (pull_request) ack advisory until agent-team — would be failure: acked: 0/10 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +7 — body
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request_target) Successful in 5s
ci-required-drift / drift (pull_request) Successful in 31s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 36s
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 36s
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 23s
CI / Python Lint & Test (pull_request) Successful in 25s
boot-to-registration-e2e / Minimal cell (claude-code + molecules-server + SSOT default model) (pull_request) Failing after 38s
design-token-drift / Canvas ↔ app design-token SSOT drift (pull_request) Successful in 24s
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Successful in 18s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Successful in 18s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 24s
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 28s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Successful in 25s
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Successful in 50s
E2E Staging SaaS (full lifecycle) / E2E Staging Plugin Install Lifecycle (pull_request) Successful in 46s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Successful in 50s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Successful in 53s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Successful in 54s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 49s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Successful in 33s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 43s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 41s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 53s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 49s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 36s
E2E Chat / detect-changes (pull_request) Successful in 2m20s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 2m20s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 47s
lint-phantom-gate / lint-phantom-gate (pull_request) Failing after 53s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 54s
CI / Detect changes (pull_request) Successful in 3m40s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 46s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 56s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 58s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 16s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 18s
Lint schedule budget / Zero-cron ratchet (pull_request) Successful in 37s
E2E API Smoke Test / detect-changes (pull_request) Successful in 3m32s
lint-staging-tenant-cd-gate-chain / lint-staging-tenant-cd-gate-chain (pull_request) Successful in 28s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 21s
qa-review / approved (pull_request_target) Failing after 13s
sop-checklist / review-refire (pull_request_target) Successful in 3s
gate-check-v3 / gate-check (pull_request_target) Successful in 23s
reserved-path-review / reserved-path-review (pull_request_target) Failing after 12s
security-review / approved (pull_request_target) Failing after 19s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 50s
E2E Staging External Runtime / E2E Staging External Runtime (pull_request) Successful in 4m4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 4s
E2E Chat / E2E Chat (pull_request) Successful in 5s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 11s
PR Diff Guard / PR diff guard (pull_request_target) Successful in 53s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 5s
CI / Platform (Go) (pull_request) Successful in 4s
E2E Staging SaaS (full lifecycle) / Prune stale e2e DNS records (pull_request) Successful in 18s
CI / Canvas (Next.js) (pull_request) Successful in 5s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 4s
CI / Canvas Deploy Status (pull_request) Successful in 3s
CI / all-required (pull_request) Successful in 7s
lint-env-coupling-dismissal / lint-env-coupling-dismissal (pull_request) Successful in 3m18s
template-delivery-e2e / detect-changes (pull_request) Successful in 1m23s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 3s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 2m38s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 37s
audit-force-merge / audit (pull_request_target) Successful in 8s
ci(workflows): per-SHA concurrency for per-commit e2e gates + unmask keystone coe-tracking lint
Three CI-hygiene fixes on one branch.

(1) PER-SHA CONCURRENCY. On Gitea 1.22.6 a superseded same-group run is
CANCELLED (not queued) even with cancel-in-progress:false (documented in
status-reaper.yml 69-72, DB-verified 2026-05-12), so a static concurrency
group on a per-commit-on-main workflow stamps a cancel-red on the older
commit and wedges the [*] merge queue. The four per-commit e2e GATES each
provision their OWN isolated org/tenant (E2E_RUN_ID = github.run_id), so
overlapping runs never corrupt each other — the shared staging quota is a
throttling cost, not corruption. Flipped them to per-SHA groups (mirrors
e2e-api.yml / local-provision-e2e.yml), keeping cancel-in-progress:false:
  - e2e-staging-saas, e2e-staging-external, e2e-staging-reconciler,
    boot-to-registration-e2e
LEFT SERIALIZED (static group + cancel-in-progress:false) because each
mutates ONE genuinely-shared resource where concurrency = corruption:
  - staging-tenant-cd / redeploy-tenants-on-main  (single shared tenant FLEET
    roll + DB pin write)
  - runtime-default-flip-gate  (single shared Infisical MOLECULE_DEFAULT_RUNTIME
    secret write)
  - ci-required-drift  (singleton [ci-drift] issue create/update)
These already carried cancel-in-progress:false; no change needed.

(2) UN-MASK THE KEYSTONE. lint-continue-on-error-tracking was itself
continue-on-error:true (mc#3436), so the meta-gate that forces every mask to
carry an open <=14d tracker could rot undetected. Flipped it true->false
(BLOCKING). Verified green-when-enforcing: all 22 remaining job-level
continue-on-error:true directives on main reference an OPEN, <=14d tracker
(mc#3436 / mc#3616 / mc#3617 / mc#3760).

To keep the flip from wedging the queue, bumped lint-pre-flip-continue-on-error's
RECENT_COMMITS_N 5->12: that gate FAILS CLOSED when it finds zero runs of the
flipped job's (push) context in the window, and the keystone is paths-filtered
(runs on push only when .gitea/workflows/** changes) so its last green main run
was 9 commits back. A 12-commit window reaches it; verified locally the gate
then reports "flip is safe, no FAIL markers" (EXIT 0).

(3) mc#2654 RENEWALS + past-deadline masks. mc#2654 is CLOSED (superseded by
mc#3436); the keystone already renewed onto mc#3436. The two named
past-deadline advisory renewals — local-provision-e2e (lifecycle-real) and
design-token-drift-gate (drift) — are GENUINELY still advisory and cannot be
confirmed green (per-workflow run history is API-blind on Gitea 1.22.6), so
they are RE-TRACKED onto their fresh 2026-07-09 renewals (mc#3617 / mc#3616,
both open, expire 2026-07-23) rather than unmasked. Trimmed the stale
mc#3230/mc#3232/mc#3175/mc#3177 tracker numbers out of the +-2 line window so
lint-continue-on-error-tracking matches the CURRENT tracker first.

Verify: yaml.safe_load all 83 workflows OK; lint-workflow-yaml.py 0 warnings;
lint_continue_on_error_tracking.py EXIT 0 (22 masks valid); lint_no_coe_on_required
OK (14 required contexts, none masked); lint_pre_flip_continue_on_error EXIT 0
(keystone flip verified safe against the green run 9 commits back).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 17:59:38 -07:00

157 lines
7.4 KiB
YAML

name: lint-continue-on-error-tracking
# Tier 2e hard-gate lint (per mc#1982) — every
# `continue-on-error: true` in `.gitea/workflows/*.yml` must carry a
# `# mc#NNNN` or `# internal#NNNN` tracker comment within 2 lines,
# the referenced issue must be OPEN, and ≤14 days old.
#
# Why this exists
# ---------------
# `continue-on-error: true` on `platform-build` had been hiding
# mc#1982-class regressions for ~3 weeks before #656 surfaced them on
# 2026-05-12. A 14-day cap on tracker age forces a review cycle and
# surfaces mask-drift within at most 14 days of the original defect.
# Each `continue-on-error: true` gets a paper trail — close or renew.
#
# How the gate works
# ------------------
# 1. Walk `.gitea/workflows/*.yml` via PyYAML's line-tracking loader
# (per `feedback_behavior_based_ast_gates`) and find every job
# whose `continue-on-error` evaluates truthy (`true` or string
# `"true"` — Gitea's evaluator coerces strings).
# 2. For each, scan ±2 lines of the directive's source line for a
# `# mc#NNNN` or `# internal#NNNN` comment. Inline-trailing
# comments on the directive line count.
# 3. For each tracker reference, GET the issue from the Gitea API.
# Validate: exists, `state == open`, `created_at` ≤ MAX_AGE_DAYS.
# 4. Aggregate ALL violations (not short-circuit) and exit 1 if any.
#
# Triggers
# --------
# Runs on PR events (paths-filter on `.gitea/workflows/**`) AND on
# a daily schedule. PR runs catch the violation at introduction time.
# Schedule runs catch the AGE-EXPIRY class: a tracker that was ≤14d
# old when the PR landed but is now 20d old, with the underlying
# defect still unfixed. Per `feedback_chained_defects_in_never_tested_workflows`,
# scheduled drift detection is the second half of the gate.
#
# Phase contract (RFC internal#219 §1 ladder)
# -------------------------------------------
# Now at Phase 4 (`continue-on-error: false` — BLOCKING). The Phase-3
# burndown is complete: every job-level `continue-on-error: true` on
# `main` carries an OPEN, ≤14-day tracker, so this lint runs green when
# enforcing. A future mask that lands untracked, closes its tracker, or
# lets it age past 14 days will now RED the run and block merge — which
# is the whole point of the meta-gate. Tracking: mc#1982.
#
# Cross-links
# -----------
# - mc#1982 (the RFC that specs this lint)
# - mc#1982 (the empirical masked-3-weeks case)
# - feedback_chained_defects_in_never_tested_workflows
# - feedback_behavior_based_ast_gates
# - feedback_strict_root_only_after_class_a
#
# Auth: DRIFT_BOT_TOKEN — same persona used by ci-required-drift.yml
# (provisioned under internal#329). Auto-injected GITHUB_TOKEN is
# insufficient because `internal#NNN` references cross repositories
# (molecule-core → molecule-ai/internal).
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.gitea/workflows/**'
- '.gitea/scripts/lint_continue_on_error_tracking.py'
- 'tests/test_lint_continue_on_error_tracking.py'
push:
branches: [main, staging]
paths:
- '.gitea/workflows/**'
- '.gitea/scripts/lint_continue_on_error_tracking.py'
workflow_dispatch:
env:
GITHUB_SERVER_URL: https://git.moleculesai.app
permissions:
contents: read
concurrency:
group: lint-coe-tracking-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# bp-exempt: meta-lint for masked jobs; tracked separately until masks are burned down.
lint:
name: lint-continue-on-error-tracking
runs-on: ubuntu-latest
timeout-minutes: 20
# Phase 4 (RFC #219 §1): the keystone is now BLOCKING. Every job-level
# `continue-on-error: true` on main currently carries an OPEN, ≤14-day
# tracker (verified 2026-07-11: all 23 masks reference mc#3436 / mc#3616 /
# mc#3617 / mc#3760, each open and within the 14d cap), so this lint passes
# green when enforcing. Keeping it masked would let the meta-gate itself rot
# undetected — the exact class it exists to prevent. Flipped true→false.
continue-on-error: false
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
- name: Install PyYAML
run: python -m pip install --quiet 'PyYAML==6.0.2'
# KMS consolidation (#971/#3274 pattern): the lint below previously read
# the per-bot Gitea Actions secret `DRIFT_BOT_TOKEN`. We now fetch the
# consolidated DRIFT_BOT_TOKEN from the Infisical SSOT (prod
# /shared/drift-bot) via the CI machine identity and export it to
# $GITHUB_ENV. The lint keeps reading it under the GITEA_TOKEN env var
# name it already expects, so the script is unchanged. The old
# DRIFT_BOT_TOKEN Gitea secret is left in place until a green run
# validates this path (validate-before-delete).
#
# Trust boundary: molecule-core PRs are same-repo (not forks), so the
# INFISICAL_CI_* machine-identity secrets are present on pull_request /
# push — the same assumption the prior direct consumption made.
- name: Fetch DRIFT_BOT_TOKEN from Infisical SSOT
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("accessToken"); sys.stdout.write(v if isinstance(v,str) else "")')
if [ -z "$TOK" ]; then echo "::error::Infisical accessToken empty - failing closed"; exit 1; fi
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
DRIFT_BOT_TOKEN=$(read_secret DRIFT_BOT_TOKEN %2Fshared%2Fdrift-bot)
echo "::add-mask::$DRIFT_BOT_TOKEN"
if [ -z "$DRIFT_BOT_TOKEN" ]; then
echo "::error::Infisical returned empty DRIFT_BOT_TOKEN at prod /shared/drift-bot — failing closed."
exit 1
fi
echo "DRIFT_BOT_TOKEN=$DRIFT_BOT_TOKEN" >> "$GITHUB_ENV"
echo "DRIFT_BOT_TOKEN loaded from Infisical (len=${#DRIFT_BOT_TOKEN})"
- name: Run lint-continue-on-error-tracking
env:
# KMS consolidation: now arrives via $GITHUB_ENV from the fetch step
# above (was secrets.DRIFT_BOT_TOKEN).
GITEA_TOKEN: ${{ env.DRIFT_BOT_TOKEN }}
GITEA_HOST: git.moleculesai.app
REPO: ${{ github.repository }}
INTERNAL_REPO: molecule-ai/internal
WORKFLOWS_DIR: .gitea/workflows
MAX_AGE_DAYS: '14'
run: python3 .gitea/scripts/lint_continue_on_error_tracking.py
- name: Run lint-continue-on-error-tracking unit tests
run: |
python -m pip install --quiet pytest
python3 -m pytest tests/test_lint_continue_on_error_tracking.py -v