Skip to content

merge: integrate repository-centered desktop workflow into dev #2707

merge: integrate repository-centered desktop workflow into dev

merge: integrate repository-centered desktop workflow into dev #2707

Workflow file for this run

name: CI
on:
push:
branches:
- dev
- feat/keiko-editor
- feat/keiko-agent-native-editor-foundation-and-runtime
- feat/prompt-enhancer-1307
- feat/keiko-establish-governed-end-to-end-git-delivery
- feat/keiko-voice-digital-twin
- feat/keiko-isolated-task-workspaces
- feat/keiko-colleague-like-voice-dialogue-mode
- feat/keiko-repository-centered-desktop-workflow
- "release/**"
pull_request:
branches:
- dev
- feat/keiko-editor
- feat/keiko-agent-native-editor-foundation-and-runtime
- feat/prompt-enhancer-1307
- feat/keiko-establish-governed-end-to-end-git-delivery
- feat/keiko-voice-digital-twin
- feat/keiko-isolated-task-workspaces
- feat/keiko-colleague-like-voice-dialogue-mode
- feat/keiko-repository-centered-desktop-workflow
- "release/**"
workflow_dispatch:
permissions: {}
jobs:
protected-branch-gate:
name: Protected branch gate
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Confirm dev branch gate
run: |
case "${{ github.ref }}:${{ github.base_ref }}" in
refs/heads/dev: | refs/heads/feat/keiko-editor: | refs/heads/feat/keiko-agent-native-editor-foundation-and-runtime: | refs/heads/feat/prompt-enhancer-1307: | refs/heads/feat/keiko-establish-governed-end-to-end-git-delivery: | refs/heads/feat/keiko-voice-digital-twin: | refs/heads/feat/keiko-isolated-task-workspaces: | refs/heads/feat/keiko-colleague-like-voice-dialogue-mode: | refs/heads/feat/keiko-repository-centered-desktop-workflow: | refs/heads/release/*: | *:dev | *:feat/keiko-editor | *:feat/keiko-agent-native-editor-foundation-and-runtime | *:feat/prompt-enhancer-1307 | *:feat/keiko-establish-governed-end-to-end-git-delivery | *:feat/keiko-voice-digital-twin | *:feat/keiko-isolated-task-workspaces | *:feat/keiko-colleague-like-voice-dialogue-mode | *:feat/keiko-repository-centered-desktop-workflow | *:release/*)
echo "Protected or integration branch gate satisfied."
;;
*)
echo "This gate is only valid for protected dev, integration, and release branches."
exit 1
;;
esac
ci:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Install sandbox isolation backend (bubblewrap)
run: |
sudo apt-get update
sudo apt-get install -y bubblewrap
# Ubuntu 24.04 restricts unprivileged user namespaces via AppArmor; bubblewrap (and the
# unshare fallback) need them to create the network namespace. Relax it for the runner so
# the enforced-egress proof below actually exercises the isolation boundary (ADR-0043).
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
- name: Enforced sandbox egress proof (ADR-0043 / #1202)
# NOT gated by the feat/keiko-editor branch skip: the assured pre-filter executes untrusted
# model-generated code, so the deny-by-default egress boundary must be proven on every run.
# The egress test fails the job if an outbound connection from inside network:"none" succeeds.
run: npm --workspace @oscharko-dev/keiko-sandbox test
- name: Verify Keiko Editor package
run: |
npm --workspace @oscharko-dev/keiko-editor run build
npm --workspace @oscharko-dev/keiko-editor run typecheck
npm --workspace @oscharko-dev/keiko-editor test
- run: npm run typecheck
- run: npm run check:version-consistency
- run: npm run check:git-client-evidence
- run: npm run lint
- run: npm run arch:check
- run: npm run arch:check:negative
- name: Quality Intelligence supply-chain gate
run: npm run check:qi-supply-chain
- name: Retrieval latency gate (enterprise retrieval M3)
# Runs after `npm run typecheck` (which builds packages), so the compiled keiko-workspace
# dist the gate imports is present. Deterministic fixture + generous p95 ceiling.
run: npm run check:retrieval-latency
- name: Retrieval quality gate (enterprise retrieval M4)
# Same compiled workspace surface as the latency gate; evaluates top-k quality, line-level
# evidence, and generated-artifact leakage over fixed synthetic enterprise fixtures.
run: npm run check:retrieval-quality
- name: Context quality gate (ADR-0052, context-engineering PR1)
# Runs after `npm run typecheck` (which builds packages), so the compiled keiko-contracts,
# keiko-workflows, keiko-workspace, and keiko-security dist the gate imports are present —
# the same build dependency the retrieval gates above rely on. Drives the deterministic lane
# allocator over a fixed offline corpus and enforces context-quality invariants.
run: npm run check:context-quality
- name: Keiko Editor static-export bundle gate
run: |
npm run build:ui
npm run check:editor-bundle-size -- --require-static-export
- name: Package surface and installable smoke
run: |
npm run build
npm run prepare:bin
npm run prune:package-native-optionals
npm run check:package-surface
KEIKO_SMOKE_PACK_IGNORE_SCRIPTS=1 npm run smoke:install
- name: Coverage quality gates
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run test:coverage:quality
actionlint:
name: actionlint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download and verify actionlint
run: |
curl -sSfL "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz" -o actionlint.tar.gz
echo "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 actionlint.tar.gz" | sha256sum --check
tar -xzf actionlint.tar.gz actionlint
chmod +x actionlint
- name: Run actionlint
run: ./actionlint -color .github/workflows/*.yml
verify-pinned-shas:
name: Verify pinned action SHAs
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Assert all action references are pinned to 40-hex SHAs
run: |
set -euo pipefail
violations=$(grep -rnE '^\s*-?\s*uses:' .github/workflows/ \
| grep -vE 'uses:\s*\./' \
| grep -vE 'uses:\s*docker://' \
| grep -vE 'uses:\s*[A-Za-z0-9._/-]+@[0-9a-f]{40}([[:space:]]|$|#)' || true)
if [ -n "$violations" ]; then
echo "Unpinned action references (must pin to a full 40-hex commit SHA):"
echo "$violations"
exit 1
fi
echo "All action references are pinned to full commit SHAs."
build-scan-sbom-smoke:
name: Build, scan, SBOM, smoke
# Keep early feature-branch PRs fast. These release/package gates still run on merges to
# feat/keiko-editor, on dev/release PRs, and on manual workflow_dispatch runs.
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Build
run: npm run build
- name: Prepare packaged CLI and UI assets
run: |
npm run prepare:bin
npm run build:ui
- name: Installable-package smoke (Issue #169 AC2)
run: npm run smoke:install
- name: Installable memory smoke (Issue #216)
run: npm run smoke:install:memory
- name: Smoke - offline evaluate exits 0
run: KEIKO_EVIDENCE_DIR="$(mktemp -d)" node dist/cli/index.js evaluate --suite all
- name: Security audit (high and above)
run: npm audit --audit-level=high
- name: Generate CycloneDX SBOM
run: npm sbom --sbom-format cyclonedx --omit dev > sbom.cdx.json
- name: Workspace SBOM and license gate (Issue #169 AC4)
run: npm run check:workspace-supply-chain
- name: Smoke - help exits 0
run: node dist/cli/index.js --help
- name: Smoke - version exits 0
run: node dist/cli/index.js --version
- name: Smoke - unknown command exits 2
run: |
set +e
node dist/cli/index.js definitely-not-a-command
code=$?
if [ "$code" -ne 2 ]; then echo "expected exit 2, got $code"; exit 1; fi
echo "unknown-command exit code correct: $code"
- name: Upload SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-cyclonedx
path: sbom.cdx.json
retention-days: 90
- name: Upload workspace SBOMs (Issue #169 AC4)
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: workspace-sboms-cyclonedx
path: sbom/
retention-days: 90
cross-platform-smoke:
name: Cross-platform smoke (${{ matrix.os }})
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
# Issue #284 AC4: the packed Keiko artifact must work on macOS, Windows, and Linux via the
# normal start path. Linux is already exercised by `build-scan-sbom-smoke`; this job runs the
# same installable-package smoke (pack -> install -> CLI -> packaged `keiko ui` -> health,
# launch project, QI runs read route, home shell) on Windows and macOS so AC4 portability is
# EXECUTED, not only portable by construction. Intentionally NOT a required/gating check yet —
# the `ci` job remains the merge gate; promote this to a required check once it has proven
# stable across several runs (native optional deps + the Next static export are the parts most
# likely to need per-OS attention). fail-fast:false so one OS result never masks the other.
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Build
run: npm run build
# Two separate steps (not one multi-line run): on the Windows runner the default shell is
# PowerShell, which only surfaces the exit code of the LAST line of a multi-line `run`; as
# discrete steps each command's failure fails the job on every OS.
- name: Prepare packaged CLI
run: npm run prepare:bin
- name: Build UI (static export)
run: npm run build:ui
- name: Installable-package smoke (Issue #169 AC2 / #284 AC4 cross-platform)
env:
# Pack the dist already built by the steps above instead of re-running the Linux-oriented
# `prepack` publish gate (arch-check / package-surface / supply-chain shell out to npx/npm
# in ways that are not Windows-portable — a separate concern from artifact portability).
# The gating `build-scan-sbom-smoke` job keeps the full prepack pack on Linux.
KEIKO_SMOKE_PACK_IGNORE_SCRIPTS: "1"
run: npm run smoke:install
ui:
name: ui
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- name: Install workspaces (single root lockfile after #167)
run: npm ci
- name: Build internal packages so contracts dist resolves for UI tsc
run: npm run build:packages
- name: Security audit UI dependencies (moderate and above)
run: npm audit --audit-level=moderate --workspace @oscharko-dev/keiko-ui
- name: Lint UI
run: npm run lint --workspace @oscharko-dev/keiko-ui
- name: Typecheck UI
run: npm run typecheck --workspace @oscharko-dev/keiko-ui
- name: Build UI (static export)
run: npm run build --workspace @oscharko-dev/keiko-ui
- name: Generate UI CycloneDX SBOM
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm sbom --sbom-format cyclonedx --omit dev --workspace @oscharko-dev/keiko-ui > ui-sbom.cdx.json
- name: Test UI with coverage (jsdom + axe a11y)
run: npm run test:coverage:ui
- name: UI coverage ratchet
run: npm run check:coverage:ui
- name: Install Playwright browser
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npx playwright install --with-deps chromium
- name: Release smoke E2E
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run test:e2e:smoke
- name: Build package and UI assets
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: |
npm run build
npm run prepare:bin
npm run build:ui
npm run prune:package-native-optionals
- name: Verify package surface
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run check:package-surface
- name: Smoke - keiko ui serves /api/health
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: |
set -euo pipefail
node dist/cli/index.js ui --port 4399 &
ui_pid=$!
trap 'kill "$ui_pid" 2>/dev/null || true' EXIT
body=$(curl --retry 10 --retry-connrefused --retry-delay 1 -fsS http://127.0.0.1:4399/api/health)
echo "health: $body"
echo "$body" | grep -q '"status":"ok"'
- name: Upload UI SBOM
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ui-sbom-cyclonedx
path: ui-sbom.cdx.json
retention-days: 90