CI Quality Gates

Audience: engineers and release owners who need to understand which automated gates can block a merge or a release, what each gate measures, and how to run or update them.

Overview

Beyond the per-module test lanes (see CI Lane Integration), Stella Ops runs a set of quality gates in CI that enforce product-level guarantees rather than individual test outcomes:

Quality gates run after the main test suite completes. The example workflow steps below were authored against build-test-deploy.yml, which has since been archived to .gitea/workflows-archived/build-test-deploy.yml; new gate wiring should plug into the live workflows. Verify the gate scripts referenced below against scripts/ci/ before relying on them.

Quality Gate Jobs

Reachability Quality Gate

Script: .gitea/scripts/metrics/compute-reachability-metrics.sh
Config: .gitea/scripts/metrics/reachability-thresholds.yaml

Validates that the scanner meets recall/precision thresholds against the ground-truth corpus.

Metrics Computed

MetricDescriptionThreshold
runtime_dependency_recall% of runtime dep vulns detected≥ 95%
unreachable_false_positivesFP rate for unreachable findings≤ 5%
reachability_underreportUnderreporting rate≤ 10%
os_package_recall% of OS package vulns detected≥ 92%
code_vuln_recall% of code vulns detected≥ 88%
config_vuln_recall% of config vulns detected≥ 85%

Running Locally

# Dry run (no enforcement)
./.gitea/scripts/metrics/compute-reachability-metrics.sh --dry-run

# Full run against corpus
./.gitea/scripts/metrics/compute-reachability-metrics.sh

TTFS Regression Gate

Script: .gitea/scripts/metrics/compute-ttfs-metrics.sh
Baseline: src/__Tests/__Benchmarks/baselines/ttfs-baseline.json

Detects performance regressions in Time-to-First-Signal.

Metrics Computed

MetricDescriptionThreshold
ttfs_p50_msP50 time to first signal≤ baseline + 10%
ttfs_p95_msP95 time to first signal≤ baseline + 15%
ttfs_max_msMaximum TTFS≤ baseline + 25%

Baseline Format

{
  "ttfs_p50_ms": 450,
  "ttfs_p95_ms": 1200,
  "ttfs_max_ms": 3000,
  "measured_at": "2025-12-16T00:00:00Z",
  "sample_count": 1000
}

Performance SLO Gate

Script: .gitea/scripts/metrics/enforce-performance-slos.sh
Config: .gitea/scripts/metrics/performance-slos.yaml

Enforces scan time and compute budget SLOs.

SLOs Enforced

SLODescriptionTarget
scan_time_p50_msP50 scan time≤ 120,000ms (2 min)
scan_time_p95_msP95 scan time≤ 300,000ms (5 min)
memory_peak_mbPeak memory usage≤ 2048 MB
cpu_secondsTotal CPU time≤ 120 seconds

Workflow Integration

Quality gates are integrated into the main CI workflow:

# Illustrative quality-gates job (modelled on the archived build-test-deploy.yml)

quality-gates:
  runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }}
  needs: build-test
  steps:
    - name: Reachability quality gate
      run: ./.gitea/scripts/metrics/compute-reachability-metrics.sh

    - name: TTFS regression gate
      run: ./.gitea/scripts/metrics/compute-ttfs-metrics.sh

    - name: Performance SLO gate
      run: ./.gitea/scripts/metrics/enforce-performance-slos.sh --warn-only

Failure Modes

Hard Failure (Blocks Merge)

Soft Failure (Warning Only)

Adding New Quality Gates

  1. Create computation script under .gitea/scripts/metrics/ (alongside the existing gate scripts)
  2. Add threshold configuration (YAML or JSON)
  3. Integrate into workflow as a new step
  4. Update this documentation
  5. Add to sprint tracking

Troubleshooting

Gate Fails on PR but Passes on Main

Check for:

Baseline Drift

If baselines become stale:

# Regenerate baselines
./.gitea/scripts/metrics/compute-ttfs-metrics.sh --update-baseline
./.gitea/scripts/metrics/compute-reachability-metrics.sh --update-baseline

Turn #6 Quality Gates (2026-01-27)

Source: Testing Enhancements (Automation Turn #6) Sprint: docs/implplan/SPRINT_0127_002_DOCS_testing_enhancements_turn6.md

Verify before wiring. The gate scripts named in this section (check-intent-violations.sh, check-observability-contracts.sh, check-evidence-chain.sh, run-longevity-gate.sh, run-interop-gate.sh, check-post-incident-tests.sh) describe the intended design from the Turn #6 sprint and may not yet be committed. Confirm each script exists under .gitea/scripts/ before relying on it in a workflow.

Intent Violation Gate

Purpose: Detect test changes that violate declared intent categories.

Script: scripts/ci/check-intent-violations.sh

CheckDescriptionAction
Intent missingNon-trivial test without Intent traitWarning (regulatory modules: Error)
Intent contradictionTest behavior contradicts declared intentError
Intent coverage dropModule intent coverage decreasedWarning

Enforcement:

Observability Contract Gate

Purpose: Validate OTel spans, structured logs, and metrics contracts.

Script: scripts/ci/check-observability-contracts.sh

CheckDescriptionThreshold
Required spans missingCore operation spans not emittedError
Span attribute missingRequired attributes not presentError
High cardinality attributeLabel cardinality exceeds limitWarning (> 50), Error (> 100)
PII in logsSensitive data patterns in log outputError
Missing log fieldsRequired fields not presentWarning

Enforcement:

Evidence Chain Gate

Purpose: Verify requirement -> test -> artifact traceability.

Script: scripts/ci/check-evidence-chain.sh

CheckDescriptionAction
Orphaned testRegulatory test without Requirement attributeWarning
Artifact hash driftArtifact hash changed unexpectedlyError
Artifact non-deterministicMultiple runs produce different artifactsError
Traceability gapRequirement without test coverageWarning

Enforcement:

Longevity Gate (Release Gating)

Purpose: Detect memory leaks, connection leaks, and counter drift under sustained load.

Script: scripts/ci/run-longevity-gate.sh Cadence: Nightly + pre-release

MetricDescriptionThreshold
Memory growth rateMemory increase per hour≤ 1%
Connection pool leaksUnreturned connections0
Counter driftCounter value outside expected rangeError
GC pressureGen2 collections per hour≤ 10

Enforcement:

Interop Gate (Release Gating)

Purpose: Validate cross-version and environment compatibility.

Script: scripts/ci/run-interop-gate.sh Cadence: Weekly + pre-release

CheckDescriptionThreshold
N-1 compatibilityCurrent server with previous clientMust pass
N+1 compatibilityPrevious server with current clientMust pass
Environment equivalenceSame results across infra profiles≤ 5% deviation

Profiles Tested:

Enforcement:

Post-Incident Gate

Purpose: Ensure incident-derived tests are maintained and passing.

Script: scripts/ci/check-post-incident-tests.sh

CheckDescriptionAction
Incident test failingPostIncident test not passingError (P1/P2), Warning (P3)
Incident test missing metadataMissing IncidentId or RootCauseWarning
Incident coverageP1/P2 incidents without testsError

Enforcement:


Gate Summary by Gating Level

PR-Gating (Must Pass for Merge)

GateScope
Reachability QualityAll
TTFS RegressionAll
Intent ViolationRegulatory modules
Observability ContractW1 modules
Evidence ChainRegulatory modules
Post-Incident (P1/P2)All

Release-Gating (Must Pass for Release)

GateScope
All PR gatesAll
LongevityWorker modules
InteropSchema/API-dependent modules
Post-Incident (all)All
Performance SLOAll

Warning-Only (Informational)

GateScope
Intent missingNon-regulatory modules
Intent coverage dropAll
Orphaned testAll
Traceability gapAll