S³AI Brain CI — "Functional MRI" Gate #805
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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." |