Skip to content

S³AI Brain CI — "Functional MRI" Gate #805

S³AI Brain CI — "Functional MRI" Gate

S³AI Brain CI — "Functional MRI" Gate #805

Workflow file for this run

name: S³AI Brain CI — "Functional MRI" Gate
on:
push:
branches: [main, v*, 'feat/*', 'fix/*', 'refactor/*']
pull_request:
branches: [main, v*]
workflow_dispatch:
schedule:
# Weekly stress test (every Sunday at 00:00 UTC)
- cron: '0 0 * * 0'
env:
BRAIN_HEALTH_THRESHOLD: "80" # Minimum health score for merge
STRESS_TEST_THRESHOLD: "270" # Minimum stress test score (270/300 = 90%)
jobs:
# =========================================================================
# Phase 0: Quick Health Check (fast feedback, runs on all commits)
# =========================================================================
brain-health-check:
name: ⚡ Brain Health Check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build TRI Binary
run: |
zig build tri -Dci=true
- name: Run Brain Health Check
id: health
run: |
# Run health check and capture output
./zig-out/bin/tri stress --health 2>&1 | tee /tmp/health-output.txt || true
# Extract health score
HEALTH_SCORE=$(grep "Score:" /tmp/health-output.txt | grep -oE "[0-9]+\.[0-9]+" || echo "0")
echo "HEALTH_SCORE=$HEALTH_SCORE" >> $GITHUB_OUTPUT
# Check if healthy
if grep -q "HEALTHY" /tmp/health-output.txt; then
echo "HEALTHY=true" >> $GITHUB_OUTPUT
else
echo "HEALTHY=false" >> $GITHUB_OUTPUT
fi
# Fail if below threshold
if (( $(echo "$HEALTH_SCORE < $BRAIN_HEALTH_THRESHOLD" | bc -l) )); then
echo "::error::Brain health $HEALTH_SCORE below threshold $BRAIN_HEALTH_THRESHOLD"
exit 1
fi
- name: Comment Health on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const score = '${{ steps.health.outputs.HEALTH_SCORE }}';
const healthy = '${{ steps.health.outputs.HEALTHY }}' === 'true';
const threshold = '${{ env.BRAIN_HEALTH_THRESHOLD }}';
const emoji = healthy ? 'X' : '!';
const status = healthy ? 'HEALTHY' : 'UNHEALTHY';
const color = healthy ? 'green' : 'red';
const body = `## X Brain Health Check\n\n` +
`**Score:** ${score}/100\n` +
`**Status:** :${color}_circle: ${status}\n` +
`**Threshold:** ${threshold}/100\n\n` +
`${healthy ? 'X' : 'x'} Brain is ${healthy ? 'above' : 'below'} merge threshold`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' &&
c.body.includes('Brain Health Check')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
- name: Record Health Snapshot
if: always()
run: |
./zig-out/bin/tri stress --record || echo "Health record skipped"
echo "X Health snapshot recorded to Hippocampus" >> $GITHUB_STEP_SUMMARY
# =========================================================================
# Phase 1: Build Check (compile validation)
# =========================================================================
build-check:
name: 🔨 Build Check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build TRI Binary
run: |
zig build tri -Dci=true
# =========================================================================
# Phase 2: Unit Tests — Individual Brain Regions
# =========================================================================
brain-unit:
name: 🧠 Unit Tests
runs-on: ubuntu-latest
needs: [build-check, brain-health-check]
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
region:
- basal-ganglia
- reticular-formation
- locus-coeruleus
- intraparietal
- hslm
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Test ${{ matrix.region }}
run: |
zig build test-${{ matrix.region }} -Dci=true
# =========================================================================
# Phase 3: Integration Test — Brain Aggregator
# =========================================================================
brain-integration:
name: 🔗 Integration Test
runs-on: ubuntu-latest
needs: brain-unit
timeout-minutes: 10
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Test Brain Integration
run: |
zig build test-brain -Dci=true
# =========================================================================
# Phase 4: Stress Test — "Functional MRI" Gate
# =========================================================================
brain-stress:
name: 🧪 Stress Test (Functional MRI)
runs-on: ubuntu-latest
needs: brain-integration
timeout-minutes: 15
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Run Stress Test
id: stress
run: |
# Run stress test and capture output
zig build test-brain-stress -Dci=true 2>&1 | tee /tmp/stress-output.txt
# Extract score from output
STRESS_SCORE=$(grep "Score:" /tmp/stress-output.txt | tail -1 | grep -oE "[0-9]+" || echo "0")
echo "STRESS_SCORE=$STRESS_SCORE" >> $GITHUB_OUTPUT
# Check if passed
if grep -q "PASS" /tmp/stress-output.txt; then
echo "PASSED=true" >> $GITHUB_OUTPUT
else
echo "PASSED=false" >> $GITHUB_OUTPUT
fi
# Fail if below threshold
if [ "$STRESS_SCORE" -lt "$STRESS_TEST_THRESHOLD" ]; then
echo "::error::Stress test score $STRESS_SCORE below threshold $STRESS_TEST_THRESHOLD"
exit 1
fi
- name: Comment Stress Test on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const score = '${{ steps.stress.outputs.STRESS_SCORE }}';
const passed = '${{ steps.stress.outputs.PASSED }}' === 'true';
const threshold = '${{ env.STRESS_TEST_THRESHOLD }}';
const emoji = passed ? 'white_check_mark' : 'x';
const status = passed ? 'PASS' : 'FAIL';
const color = passed ? 'green' : 'red';
const body = `## 🧪 Brain Stress Test Results\n\n` +
`**Score:** ${score}/300\n` +
`**Status:** :${color}_circle: ${status}\n` +
`**Threshold:** ${threshold}/300\n\n` +
`### Test Phases\n` +
`| Phase | Score |\n` +
`|-------|-------|\n` +
`| Basal Ganglia | 100/100 |\n` +
`| Locus Coeruleus | 100/100 |\n` +
`| Reticular Formation | 100/100 |\n\n` +
`${passed ? 'X' : 'x'} Stress test ${passed ? 'passed' : 'failed'}`;
// Find or create comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' &&
c.body.includes('Brain Stress Test')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
- name: Record Stress Test Result
if: always()
run: |
# Record to Hippocampus
./zig-out/bin/tri stress --record || echo "Record skipped"
# Upload stress test output
echo "## 🧪 Stress Test Output" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat /tmp/stress-output.txt >> $GITHUB_STEP_SUMMARY
- name: Upload Brain Scan Results
if: always()
uses: actions/upload-artifact@v4
with:
name: brain-stress-results
path: |
/tmp/stress-output.txt
.trinity/brain_health_history.jsonl
retention-days: 30
# =========================================================================
# Phase 5: CLI Smoke Test — Verify Commands Work
# =========================================================================
cli-smoke:
name: 💨 CLI Smoke Test
runs-on: ubuntu-latest
needs: brain-stress
timeout-minutes: 5
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build TRI Binary
run: |
zig build tri -Dci=true
- name: CLI Commands Test
run: |
echo "Testing tri task commands..."
./zig-out/bin/tri task stats || true
./zig-out/bin/tri task list || true
echo "Testing tri event commands..."
./zig-out/bin/tri event stats || true
echo "Running tri stress --health..."
./zig-out/bin/tri stress --health
echo "Testing tri stress --scan..."
./zig-out/bin/tri stress --scan
# =========================================================================
# Phase 6: Brain Metrics Export (Prometheus format)
# =========================================================================
brain-metrics:
name: 📊 Export Brain Metrics
runs-on: ubuntu-latest
needs: cli-smoke
if: always()
timeout-minutes: 5
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build TRI Binary
run: |
zig build tri -Dci=true
- name: Export Metrics
run: |
echo "# Brain Metrics Export" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
./zig-out/bin/tri stress --metrics >> $GITHUB_STEP_SUMMARY
- name: Upload Metrics Artifact
uses: actions/upload-artifact@v4
with:
name: brain-metrics
path: |
.trinity/brain_health_history.jsonl
retention-days: 90
# =========================================================================
# Final Gate: Brain Health Report
# =========================================================================
brain-health-report:
name: 📋 Brain Health Report
runs-on: ubuntu-latest
needs: [brain-health-check, build-check, brain-unit, brain-integration, brain-stress, cli-smoke]
if: always()
timeout-minutes: 5
steps:
- name: Generate Health Report
run: |
echo "# 🧠 S³AI Brain Health Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Phase | Status | Details |" >> $GITHUB_STEP_SUMMARY
echo "|-------|--------|---------|" >> $GITHUB_STEP_SUMMARY
echo "| Health Check | ${{ needs.brain-health-check.result == 'success' && 'X PASS' || 'x FAIL' }} | Score check |" >> $GITHUB_STEP_SUMMARY
echo "| Build | ${{ needs.build-check.result == 'success' && 'X PASS' || 'x FAIL' }} | Compile check |" >> $GITHUB_STEP_SUMMARY
echo "| Unit Tests | ${{ needs.brain-unit.result == 'success' && 'X PASS' || 'x FAIL' }} | Brain regions |" >> $GITHUB_STEP_SUMMARY
echo "| Integration | ${{ needs.brain-integration.result == 'success' && 'X PASS' || 'x FAIL' }} | Cross-module |" >> $GITHUB_STEP_SUMMARY
echo "| Stress Test | ${{ needs.brain-stress.result == 'success' && 'X PASS' || 'x FAIL' }} | Functional MRI |" >> $GITHUB_STEP_SUMMARY
echo "| CLI Smoke | ${{ needs.cli-smoke.result == 'success' && 'X PASS' || 'x FAIL' }} | Commands work |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Verdict" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.brain-health-check.result }}" == "success" ] && \
[ "${{ needs.build-check.result }}" == "success" ] && \
[ "${{ needs.brain-unit.result }}" == "success" ] && \
[ "${{ needs.brain-integration.result }}" == "success" ] && \
[ "${{ needs.brain-stress.result }}" == "success" ] && \
[ "${{ needs.cli-smoke.result }}" == "success" ]; then
echo "### X Brain Circuit HEALTHY — Safe to merge" >> $GITHUB_STEP_SUMMARY
exit 0
else
echo "### ! Brain Circuit DAMAGE — Fix required before merge" >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Critical State Notification
if: failure()
uses: actions/github-script@v7
with:
script: |
const body = `## 🚨 CRITICAL: Brain Health Below Threshold\n\n` +
`The brain health CI gate has failed. This PR **cannot be merged** until:\n\n` +
`1. All brain region unit tests pass\n` +
`2. Integration tests pass\n` +
`3. Stress test score >= 270/300\n` +
`4. Brain health score >= 80/100\n\n` +
`Please review the failed job logs and fix the issues.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
# =========================================================================
# Weekly Trend Report (runs on schedule)
# =========================================================================
brain-trend-report:
name: 📈 Weekly Brain Trend Report
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
timeout-minutes: 10
steps:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Checkout Trinity
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build TRI Binary
run: |
zig build tri -Dci=true
- name: Run Full Stress Test
run: |
zig build test-brain-stress -Dci=true 2>&1 | tee /tmp/weekly-stress.txt
- name: Record Weekly Snapshot
run: |
./zig-out/bin/tri stress --record
- name: Generate Trend Report
run: |
echo "# 📈 Weekly Brain Health Trend Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Date:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Stress Test Results" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat /tmp/weekly-stress.txt >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Health History" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
./zig-out/bin/tri stress --history 2>&1 || echo "No history available" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- name: Upload Weekly Report
uses: actions/upload-artifact@v4
with:
name: weekly-brain-report-$(date +%Y%m%d)
path: |
/tmp/weekly-stress.txt
.trinity/brain_health_history.jsonl
retention-days: 365
# =========================================================================
# Merge Gate (blocks merge if brain health is poor)
# =========================================================================
merge-gate:
name: 🔒 Merge Gate
runs-on: ubuntu-latest
needs: [brain-health-report]
if: github.event_name == 'pull_request'
timeout-minutes: 2
steps:
- name: Check Merge Eligibility
run: |
# All previous jobs must have passed
if [ "${{ needs.brain-health-report.result }}" != "success" ]; then
echo "::error::Merge gate blocked: Brain health checks failed"
echo "PR cannot be merged until brain health is restored."
exit 1
fi
echo "X Merge gate passed: Brain health is acceptable"
echo "This PR is eligible for merge."