feat: Claude Code Monitor — lanes, pipelines and a merged workspace

Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
This commit is contained in:
2026-07-29 17:07:45 +07:00
commit 57dc91585d
783 changed files with 221743 additions and 0 deletions
+250
View File
@@ -0,0 +1,250 @@
# ─────────────────────────────────────────────────────────────────────────────
# GitHub Actions CI Pipeline Claude Code Agent Monitor
#
# Triggers on push to main and PRs. Runs linting, tests, builds Docker
# images, and scans for security vulnerabilities.
# ─────────────────────────────────────────────────────────────────────────────
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
packages: write
security-events: write
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "22"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/agent-monitor
MCP_IMAGE_NAME: ${{ github.repository }}/agent-monitor-mcp
jobs:
# ── Lint & Format Check ─────────────────────────────────────────────────
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Check formatting
run: npm run format:check
# ── Server Tests ────────────────────────────────────────────────────────
test-server:
name: Server Tests
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run server tests
run: npm run test:server
# ── Client Tests ────────────────────────────────────────────────────────
test-client:
name: Client Tests
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install root dependencies
run: npm ci
- name: Install client dependencies
run: cd client && npm ci
- name: Run client tests
run: npm run test:client
# ── MCP Tests ───────────────────────────────────────────────────────────
test-mcp:
name: MCP Sidecar Tests
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install MCP dependencies
run: npm run mcp:install
- name: Type check MCP
run: npm run mcp:typecheck
- name: Run MCP tests
run: npm run mcp:test
# ── Build Docker Images ────────────────────────────────────────────────
build-image:
name: Build Docker Images
runs-on: ubuntu-latest
needs: [test-server, test-client, test-mcp]
# Only push images on main branch
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
outputs:
image-tag: ${{ steps.meta.outputs.version }}
image-digest: ${{ steps.build-app.outputs.digest }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (app)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
- name: Build & push app image
id: build-app
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
- name: Extract metadata (MCP)
id: meta-mcp
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.MCP_IMAGE_NAME }}
tags: |
type=ref,event=branch
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build & push MCP image
id: build-mcp
uses: docker/build-push-action@v5
with:
context: .
file: ./mcp/Dockerfile
push: true
tags: ${{ steps.meta-mcp.outputs.tags }}
labels: ${{ steps.meta-mcp.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
# ── Security Scan ──────────────────────────────────────────────────────
security-scan:
name: Security Scan
runs-on: ubuntu-latest
needs: build-image
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run Trivy vulnerability scanner (app)
uses: aquasecurity/trivy-action@master
with:
image-ref: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build-image.outputs.image-tag }}"
format: "sarif"
output: "trivy-app-results.sarif"
severity: "CRITICAL,HIGH"
exit-code: "1"
- name: Run Trivy vulnerability scanner (MCP)
uses: aquasecurity/trivy-action@master
with:
image-ref: "${{ env.REGISTRY }}/${{ env.MCP_IMAGE_NAME }}:${{ needs.build-image.outputs.image-tag }}"
format: "sarif"
output: "trivy-mcp-results.sarif"
severity: "CRITICAL,HIGH"
exit-code: "1"
- name: Upload Trivy SARIF (app)
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: "trivy-app-results.sarif"
category: "trivy-app"
- name: Upload Trivy SARIF (MCP)
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: "trivy-mcp-results.sarif"
category: "trivy-mcp"
- name: Run npm audit
run: npm audit --production --audit-level=high
- name: Trivy filesystem scan (IaC)
uses: aquasecurity/trivy-action@master
with:
scan-type: "fs"
scan-ref: "./deployments"
format: "table"
severity: "CRITICAL,HIGH"
exit-code: "1"