NEXUS Session #74
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: NEXUS Session | |
| on: | |
| schedule: | |
| # Weekday sessions (Mon-Fri) | |
| - cron: '0 0 * * 1-5' # 00:00 UTC (01:00 CET) — Asia session open | |
| - cron: '0 8 * * 1-5' # 08:00 UTC (09:00 CET) — London open | |
| - cron: '0 13 * * 1-5' # 13:00 UTC (14:00 CET) — NY open | |
| # Weekend sessions (Sat-Sun) — crypto only | |
| - cron: '0 0 * * 0,6' # 00:00 UTC — weekend crypto session 1 | |
| - cron: '0 8 * * 0,6' # 08:00 UTC — weekend crypto session 2 | |
| - cron: '0 16 * * 0,6' # 16:00 UTC — weekend crypto session 3 | |
| # Manual trigger — always runs, no weekday restriction | |
| workflow_dispatch: | |
| jobs: | |
| run-session: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # push commits | |
| issues: write # open and close self-tasks | |
| pull-requests: write # FORGE opens PRs for code changes | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run NEXUS session | |
| id: attempt1 | |
| continue-on-error: true | |
| run: | | |
| # Manual triggers always force-run, scheduled runs respect weekday guard | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "Manual trigger — bypassing weekday guard" | |
| npm run run:session -- --force | |
| else | |
| npm run run:session | |
| fi | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| FRED_API_KEY: ${{ secrets.FRED_API_KEY }} | |
| ALPHA_VANTAGE_API_KEY: ${{ secrets.ALPHA_VANTAGE_API_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| - name: Retry session after 2 minutes | |
| if: steps.attempt1.outcome == 'failure' | |
| run: | | |
| echo "First attempt failed, retrying after 2 minutes..." | |
| sleep 120 | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| npm run run:session -- --force | |
| else | |
| npm run run:session | |
| fi | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| FRED_API_KEY: ${{ secrets.FRED_API_KEY }} | |
| ALPHA_VANTAGE_API_KEY: ${{ secrets.ALPHA_VANTAGE_API_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| - name: Commit memory & journal to main | |
| run: | | |
| git config user.name "NEXUS" | |
| git config user.email "nexus-bot@users.noreply.github.com" | |
| git pull --rebase --autostash origin main | |
| # Safety: revert any changes to protected files that shouldn't be modified by sessions | |
| git checkout HEAD -- NEXUS_IDENTITY.md 2>/dev/null || true | |
| # Check if FORGE changed any src/ files | |
| FORGE_CHANGES=$(git diff --name-only src/ 2>/dev/null || true) | |
| if [ -n "$FORGE_CHANGES" ]; then | |
| echo "FORGE changed source files — will open PR" | |
| echo "FORGE_CHANGED=true" >> "$GITHUB_ENV" | |
| # Stash src/ changes before committing memory to main | |
| git stash push -- src/ | |
| else | |
| echo "FORGE_CHANGED=false" >> "$GITHUB_ENV" | |
| fi | |
| # Commit memory/journal/docs/README to main (always) | |
| git add memory/ journal/ docs/ README.md | |
| git diff --staged --quiet || git commit -m "session: $(date -u +'%Y-%m-%d %H:%M UTC') [${{ github.event_name }}]" | |
| git push | |
| - name: Open PR for FORGE code changes | |
| if: env.FORGE_CHANGED == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Get session number from latest sessions.json entry | |
| SESSION_NUM=$(node -e "const s=require('./memory/sessions.json'); console.log(s[s.length-1]?.sessionNumber ?? 'unknown')") | |
| BRANCH="forge/session-${SESSION_NUM}-$(date -u +'%Y%m%d-%H%M')" | |
| # Create branch from current main | |
| git checkout -b "$BRANCH" | |
| # Apply the stashed FORGE changes | |
| git stash pop | |
| # Commit src/ changes | |
| git add src/ | |
| git diff --staged --quiet && { echo "No src/ changes after unstash"; exit 0; } | |
| # Build commit message from changed files | |
| CHANGED_FILES=$(git diff --staged --name-only | tr '\n' ', ' | sed 's/,$//') | |
| git commit -m "forge: code evolution from session #${SESSION_NUM} | |
| Files changed: ${CHANGED_FILES} | |
| This PR was created automatically by NEXUS FORGE." | |
| # Push branch and open PR | |
| git push -u origin "$BRANCH" | |
| # Ensure labels exist (no-op if they already do) | |
| gh label create "forge" --description "Code changes by NEXUS FORGE" --color "0e8a16" 2>/dev/null || true | |
| gh label create "automated" --description "Created automatically by NEXUS" --color "bfdadc" 2>/dev/null || true | |
| gh pr create \ | |
| --title "FORGE: Code evolution from session #${SESSION_NUM}" \ | |
| --label "forge" --label "automated" \ | |
| --body "## FORGE Code Evolution | |
| This PR contains source code changes made by NEXUS FORGE during session #${SESSION_NUM}. | |
| FORGE receives change requests from AXIOM (the self-reflection engine), patches source files | |
| using Claude, and validates with TypeScript before committing. Protected files (\`security.ts\`, | |
| \`forge.ts\`) can never be modified. | |
| ### Review checklist | |
| - [ ] Changes are sensible and improve the system | |
| - [ ] No security regressions | |
| - [ ] TypeScript compiles clean | |
| - [ ] No unintended side effects | |
| --- | |
| *This PR was created automatically by NEXUS. Review before merging.*" | |
| echo "PR created for FORGE changes on branch $BRANCH" |