Skip to content

API drift guard

API drift guard #77

Workflow file for this run

# Drift guard — asserts the live API, the OpenAPI spec, and the skill docs
# still agree. Created after a downstream consumer (2026-06-20) found the three
# had silently diverged as endpoints/params were added. Runs daily + on demand.
#
# A red at this step is the drift detector reporting a finding, not the lane
# breaking. Deliberately NOT declared: the field-population and skill-reference
# steps — a red there flags the lane (read by scripts/check-workflow-health.ts):
# workflow-health: signal-steps: ^Propagate the red$
name: API drift guard
on:
schedule:
- cron: "17 13 * * *" # daily ~13:17 UTC
workflow_dispatch:
inputs:
base:
description: "Base URL to check"
required: false
default: "https://stellarlight.xyz"
permissions:
contents: read
issues: write
jobs:
drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Run API drift guard
id: drift
continue-on-error: true
env:
SCOUT_BASE: ${{ github.event.inputs.base || 'https://stellarlight.xyz' }}
# shell: bash = pipefail; GitHub's default bash -e has none, so `| tee`
# masked this step's exit code (2026-08-12 lesson).
shell: bash
run: npx -y tsx scripts/check-api-drift.ts 2>&1 | tee drift.log
- name: Field-population guard (values arrive, not just shape)
if: always()
run: npx -y tsx scripts/check-field-population.ts
- name: Skill-reference coverage (sk-009 — served skill must not lag the contract)
if: always()
run: npx -y tsx scripts/check-skill-reference.ts
- name: Track the signal (rolling issue)
uses: ./.github/actions/rolling-issue
with:
title-prefix: "API drift guard red"
outcome: ${{ steps.drift.outcome }}
body-file: drift.log
- name: Propagate the red
if: steps.drift.outcome == 'failure'
run: exit 1