docs(agent): add hard rules for AC mode inference logic and usage #418
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: ci | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: {} | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run lint | |
| typecheck: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run typecheck | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - run: npm ci | |
| - run: npm test | |
| format: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run format -- --check | |
| # Non-blocking dependency audit: surfaces high/critical advisories in | |
| # runtime deps without gating the pipeline (advisories can appear with no | |
| # code change, so a hard gate would break unrelated pushes). | |
| audit: | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - run: npm audit --omit=dev --audit-level=high | |
| audit-web: | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| defaults: | |
| run: | |
| working-directory: web | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| cache-dependency-path: web/package-lock.json | |
| - run: npm audit --omit=dev --audit-level=high | |
| # Lint the web/ Nuxt project with its own ESLint (@nuxt/eslint). `npm ci` | |
| # runs `nuxt prepare` (postinstall), which generates the .nuxt/eslint config | |
| # that web/eslint.config.mjs extends. | |
| lint-web: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: web | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| cache-dependency-path: web/package-lock.json | |
| - run: npm ci | |
| - run: npm run lint | |
| # Type-check the web/ Nuxt project (nuxt typecheck → vue-tsc). `npm ci` runs | |
| # `nuxt prepare`, generating the .nuxt types the check relies on. | |
| typecheck-web: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: web | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| cache-dependency-path: web/package-lock.json | |
| - run: npm ci | |
| - run: npm run typecheck | |
| build: | |
| needs: [lint, typecheck, test, format] | |
| if: github.event_name != 'pull_request' | |
| # Native arm64 runner — the image targets a Pi 5; building natively | |
| # avoids QEMU emulation for npm ci and everything else. | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute short SHA | |
| id: sha | |
| run: echo "short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | |
| - uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| platforms: linux/arm64 | |
| push: true | |
| tags: | | |
| ghcr.io/maxmaxme/voice-assistant:latest | |
| ghcr.io/maxmaxme/voice-assistant:sha-${{ steps.sha.outputs.short }} | |
| # Standard OCI labels — `revision` (full git SHA) lets the host-side | |
| # update.sh ask GitHub's compare API for the commit list between the | |
| # old and new image. `source` tells it which repo to ask. | |
| labels: | | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| org.opencontainers.image.source=https://github.com/${{ github.repository }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Config web panel (web/) — a separate Nuxt SSR image consumed by home-infra | |
| # as ghcr.io/maxmaxme/voice-assistant-config-web. Built in its own job so it | |
| # runs in parallel with the main image (independent caches + failures). | |
| build-web: | |
| needs: [lint-web, typecheck-web] | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute short SHA | |
| id: sha | |
| run: echo "short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | |
| - uses: docker/build-push-action@v7 | |
| with: | |
| context: web | |
| file: web/Dockerfile | |
| platforms: linux/arm64 | |
| push: true | |
| tags: | | |
| ghcr.io/maxmaxme/voice-assistant-config-web:latest | |
| ghcr.io/maxmaxme/voice-assistant-config-web:sha-${{ steps.sha.outputs.short }} | |
| labels: | | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| org.opencontainers.image.source=https://github.com/${{ github.repository }} | |
| cache-from: type=gha,scope=web | |
| cache-to: type=gha,mode=max,scope=web | |
| # Telegram ping once the main build settles — green or red. Runs only on | |
| # main (push / manual), never on PRs. `if: always()` so a failed upstream | |
| # job still triggers it; we inspect needs.*.result to pick the message. | |
| notify: | |
| needs: [lint, typecheck, test, format, lint-web, typecheck-web, build, build-web] | |
| if: always() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Notify Telegram | |
| env: | |
| TG_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TG_CHAT: ${{ secrets.TELEGRAM_CHAT_ID }} | |
| FAILED: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} | |
| COMMIT_MSG: ${{ github.event.head_commit.message }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| if [ "$FAILED" = "true" ]; then | |
| status="❌ voice-assistant CI failed" | |
| else | |
| status="✅ voice-assistant CI passed — image pushed to ghcr" | |
| fi | |
| first_line=$(printf '%s' "$COMMIT_MSG" | head -n1) | |
| text=$(printf '%s\nmain @ %s — %s\n%s' "$status" "${GITHUB_SHA:0:7}" "$first_line" "$RUN_URL") | |
| curl -sS --fail -X POST \ | |
| "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \ | |
| --data-urlencode "chat_id=${TG_CHAT}" \ | |
| --data-urlencode "text=${text}" \ | |
| --data-urlencode "disable_web_page_preview=true" |