build(deps-dev): Bump the studio-dependencies group across 1 directory with 9 updates #170
Workflow file for this run
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, dev] | |
| pull_request: | |
| jobs: | |
| core: | |
| name: Core (Node ${{ matrix.node }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # The zero-dependency core + packages must run on every supported Node (engines: >=18). | |
| # This matrix is what catches version-specific breakage (e.g. an unref'd timer that only the | |
| # Node 20 test runner flags). Coverage/freshness/pack gates run once, on the newest Node. | |
| node: ['18', '20', '22', '24'] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| - name: Syntax check (zero-dep, every source file parses) | |
| run: | | |
| find tools packages tests -name '*.mjs' -not -path '*/node_modules/*' -print0 \ | |
| | xargs -0 -n1 node --check | |
| # The runtime stays zero-dependency; the test suite uses devDependencies (fast-check for the | |
| # frontmatter property tests). `.npmrc` (legacy-peer-deps) handles the optional self-peer. | |
| - name: Install dev toolchain (tests only) | |
| run: npm ci | |
| - name: Run core, CLI and package tests | |
| run: node --test tests/*.test.mjs packages/base-ranker-semantic/tests/*.test.mjs packages/base-index-local/tests/*.test.mjs packages/base-llm/tests/*.test.mjs packages/base-eval/tests/*.test.mjs | |
| - name: Validate the BASE project | |
| run: node tools/base.mjs validate --root . | |
| - name: Corpus health (doctor — fail on any error-severity finding) | |
| run: node tools/base.mjs doctor --root . | |
| - name: Routing fixtures stay stable | |
| run: node tools/base.mjs route-test --root . | |
| - name: Routing example fixtures stay stable | |
| run: | | |
| node tools/base.mjs route-test --root exemples/routage-pme | |
| node tools/base.mjs route-test --root exemples/assistant-devis | |
| node tools/base.mjs route-test --root exemples/assistant-devis-demo | |
| node tools/base.mjs route-test --root exemples/assistant-communication | |
| node tools/base.mjs route-test --root exemples/assistant-rh | |
| node tools/base.mjs route-test --root exemples/assistant-projet | |
| node tools/base.mjs route-test --root exemples/assistant-courrier | |
| node tools/base.mjs route-test --root exemples/assistant-reunion | |
| node tools/base.mjs route-test --root exemples/assistant-reflexion | |
| node tools/base.mjs route-test --root exemples/assistant-enseignant | |
| node tools/base.mjs route-test --root exemples/veytaux-tourisme | |
| node tools/base.mjs route-test --root exemples/starter-perso | |
| node tools/base.mjs route-test --root exemples/agence-multi-clients/clients/dupont-conseil | |
| node tools/base.mjs route-test --root exemples/agence-multi-clients/clients/martin-digital | |
| - name: Index benchmark smoke (no fragile thresholds) | |
| run: npm run bench:index -- --sizes 100,1000 | |
| - name: Validate each example in isolation | |
| run: | | |
| for ex in exemples/*/; do | |
| echo "validate $ex" | |
| node tools/base.mjs validate --root "$ex" || exit 1 | |
| done | |
| # --- gates that run once, on the newest Node --- | |
| # Coverage uses the node:test coverage-threshold flags, which exist only on Node 22+. | |
| - name: Coverage gate | |
| if: matrix.node == '24' | |
| run: npm run test:coverage | |
| - name: Manifest is a derived artifact (regenerate + diff) | |
| if: matrix.node == '24' | |
| run: | | |
| node tools/base.mjs index --root . | |
| git diff --exit-code base.manifest.json \ | |
| || (echo "::error::base.manifest.json is stale. Run 'npm run index' and commit." && exit 1) | |
| - name: Projected artifacts are derived (regenerate + diff) | |
| if: matrix.node == '24' | |
| run: | | |
| node tools/base.mjs build --write --root . | |
| git diff --exit-code AGENTS.md .ai/tools.md CLAUDE.md BASE_BOOTSTRAP.md .cursor/rules/assistant.mdc \ | |
| || (echo "::error::Generated artifacts are stale. Run 'base build --write' and commit." && exit 1) | |
| - name: Routing index is a derived artifact (regenerate + diff) | |
| if: matrix.node == '24' | |
| # Distinct from `build --write` above: routing-index is an opt-in target it does not generate. | |
| run: | | |
| node tools/base.mjs build routing-index --write --root . | |
| git diff --exit-code .ai/routing/index.md '.ai/agents/*/index.md' \ | |
| || (echo "::error::Routing index is stale. Run 'base build routing-index --write' and commit." && exit 1) | |
| - name: Package install smoke test | |
| if: matrix.node == '24' | |
| run: npm run smoke:pack | |
| windows-smoke: | |
| name: Windows smoke (core) | |
| # The docs onboard native Windows users (PowerShell install, ZIP extraction); this leg keeps the | |
| # zero-dependency core honest on the OS the ubuntu matrix never sees (paths, line endings — | |
| # the CRLF silent-frontmatter-loss class of defect). Lean by design: parser + CLI + one example. | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - name: Install dev toolchain (tests only) | |
| run: npm ci | |
| - name: Parser, core and init tests | |
| run: node --test tests/base-frontmatter.test.mjs tests/base-frontmatter-serialize.test.mjs tests/base-core.test.mjs tests/base-cli-init.test.mjs | |
| - name: Validate the BASE project and one example | |
| run: | | |
| node tools/base.mjs validate --root . | |
| node tools/base.mjs validate --root exemples/assistant-devis | |
| typecheck: | |
| name: Static type-check (JS) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| # Installs the type-checking toolchain only (typescript + @types/node devDeps); the core stays | |
| # zero-dependency at runtime. `.npmrc` (legacy-peer-deps) handles the optional self-peer. | |
| - name: Install toolchain | |
| run: npm ci | |
| - name: tsc --checkJs over tools/ + packages/ (zero errors) | |
| run: npm run typecheck | |
| studio-ui: | |
| name: Studio UI (test + build) | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: tools/studio/ui | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| cache-dependency-path: tools/studio/ui/package-lock.json | |
| - name: Install | |
| run: npm ci | |
| # The UI is the repo's largest third-party surface (React + Vite + their tree): audit what | |
| # ships in the built bundle, same gate as the MCP job. Dev tooling stays out of scope here. | |
| - name: Dependency audit | |
| run: npm audit --omit=dev --audit-level=high | |
| - name: Component + hook tests (Vitest, jsdom) with coverage gate | |
| run: npm run test:coverage | |
| - name: Build (tsc strict + vite) | |
| run: npm run build | |
| studio-e2e: | |
| name: Studio UI (E2E + a11y) | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: tools/studio/ui | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| cache-dependency-path: tools/studio/ui/package-lock.json | |
| # The Playwright webServer boots the real Studio API server, which reaches the eval | |
| # orchestration; that imports @ai-swiss/base-llm through the root workspace links, so the | |
| # root install is required in addition to the UI install. | |
| - name: Install root workspaces (API server dependencies) | |
| run: npm ci | |
| working-directory: . | |
| - name: Install | |
| run: npm ci | |
| # Uses the "chrome" channel. GitHub ubuntu runners ship Google Chrome preinstalled, and | |
| # `playwright install chrome` refuses to overwrite a system Chrome, so only install when absent. | |
| - name: Ensure Google Chrome for the e2e run | |
| run: | | |
| if command -v google-chrome >/dev/null 2>&1; then | |
| echo "Using preinstalled Google Chrome: $(google-chrome --version)" | |
| else | |
| npx playwright install --with-deps chrome | |
| fi | |
| # serve.mjs boots the real UI + API + broker against a throwaway copy of the example, on | |
| # isolated ports. Ollama is absent in CI, so the "invalid launch" journey still fails preflight | |
| # deterministically (cannot reach Ollama -> problems). | |
| - name: End-to-end journeys + axe accessibility (Playwright) | |
| run: npm run e2e | |
| mcp: | |
| name: MCP server (Node ${{ matrix.node }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # The MCP server ships on the same engines surface as the core (>=18); matrix it so a | |
| # version-specific break is caught here too, not only in the core job. | |
| node: ['18', '20', '22', '24'] | |
| defaults: | |
| run: | |
| working-directory: mcp | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| cache-dependency-path: mcp/package-lock.json | |
| - name: Install | |
| run: npm ci | |
| - name: Dependency audit | |
| run: npm audit --omit=dev --audit-level=high | |
| - name: Build (tsc typecheck + bundle) | |
| run: npm run build | |
| - name: Test (with coverage gate) | |
| run: npm run test:coverage | |
| - name: Package install smoke test | |
| if: matrix.node == '24' | |
| run: npm run smoke:pack | |
| spec: | |
| name: Spec & docs discipline | |
| runs-on: ubuntu-latest | |
| # Run only after the test suites are green, so a fresh proof matrix can never sit on top of a red | |
| # suite ("a test cites it" and "the suite passes" hold together). | |
| needs: [core, mcp] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # Full history so the ID-immutability, ratchet and spec-sync gates can diff against the base. | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| # Every gate below is a zero-dependency Node script: no install step needed. | |
| - name: Requirements matrix is fresh + no phantom citations | |
| run: node tools/spec/requirements-matrix.mjs --check | |
| - name: Proof quality may not regress (weak/gap ratchet) | |
| run: node tools/spec/requirements-matrix.mjs --ratchet --base origin/main | |
| - name: Requirement IDs are immutable (never renumbered, reused, or deleted) | |
| run: node tools/spec/check-ids.mjs --base origin/main | |
| - name: Spec leaves are bounded, statusless and routed | |
| run: node tools/spec/check-leaf.mjs | |
| - name: Marker vocabulary is one closed set | |
| run: node tools/spec/check-markers.mjs | |
| - name: Reference docs state the present (no roadmap leak) | |
| run: node tools/docs/check-statusless.mjs | |
| - name: No em-dash in authoritative French content | |
| run: node tools/docs/check-emdash.mjs | |
| - name: French is authoritative; translations link their source | |
| run: node tools/docs/check-translations.mjs | |
| - name: Documentation model has no broken links | |
| run: node tools/base.mjs docs validate --root . | |
| - name: spec-sync — a code change touches specs/ or declares [SPEC-NEUTRAL] | |
| if: github.event_name == 'pull_request' | |
| env: | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| run: | | |
| # Honour a [SPEC-NEUTRAL: …] declared in the PR description, not only in commit messages. | |
| printf '%s' "$PR_BODY" > "$RUNNER_TEMP/pr-body.txt" | |
| node tools/spec/spec-sync-check.mjs --range "origin/${{ github.base_ref }}..HEAD" --pr-body-file "$RUNNER_TEMP/pr-body.txt" | |
| - name: changelog-sync — a visible change adds a CHANGELOG line or declares [CHANGELOG-SKIP] | |
| if: github.event_name == 'pull_request' | |
| env: | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| run: | | |
| printf '%s' "$PR_BODY" > "$RUNNER_TEMP/pr-body.txt" | |
| node tools/spec/changelog-sync-check.mjs --range "origin/${{ github.base_ref }}..HEAD" --pr-body-file "$RUNNER_TEMP/pr-body.txt" | |
| - name: Spec-neutral watch (informational, published to the run summary) | |
| if: github.event_name == 'pull_request' | |
| run: node tools/spec/spec-neutral-report.mjs --range "origin/${{ github.base_ref }}..HEAD" | |
| dco: | |
| name: DCO (Signed-off-by on every commit) | |
| runs-on: ubuntu-latest | |
| # The Developer Certificate of Origin is documented in CONTRIBUTING.md; this turns it from a | |
| # request into a mechanism. Provenance held by goodwill is not provenance. | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # Full history so the PR commit range can be walked against the base branch. | |
| fetch-depth: 0 | |
| - name: Every PR commit carries a Signed-off-by trailer | |
| run: | | |
| range="origin/${{ github.base_ref }}..HEAD" | |
| missing=$(git rev-list --no-merges "$range" | while read -r sha; do | |
| git show -s --format=%B "$sha" | grep -qiE '^Signed-off-by: .+ <[^>]+@[^>]+>' \ | |
| || git show -s --format=' %h %s' "$sha" | |
| done) | |
| if [ -n "$missing" ]; then | |
| echo "::error::DCO: these commits lack a Signed-off-by trailer. Sign with 'git commit -s' (or repair the branch with 'git rebase --signoff'):" | |
| echo "$missing" | |
| exit 1 | |
| fi | |
| echo "DCO ok: every non-merge commit in the range is signed off." |