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
+323
View File
@@ -0,0 +1,323 @@
# ─────────────────────────────────────────────────────────────────────────────
# GitLab CI/CD Pipeline Claude Code Agent Monitor
#
# Stages: test → build → deploy-staging → deploy-production
# ─────────────────────────────────────────────────────────────────────────────
# ── Global settings ─────────────────────────────────────────────────────────
default:
image: node:22-alpine
interruptible: true
retry:
max: 1
when:
- runner_system_failure
- stuck_or_timeout_failure
variables:
NODE_VERSION: "22"
REGISTRY: "${CI_REGISTRY}"
IMAGE_NAME: "${CI_REGISTRY_IMAGE}/agent-monitor"
MCP_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/agent-monitor-mcp"
HELM_CHART_PATH: "deployments/helm/agent-monitor"
APP_NAME: "agent-monitor"
# Kaniko cache
KANIKO_CACHE_ARGS: "--cache=true --cache-repo=${CI_REGISTRY_IMAGE}/cache"
stages:
- test
- build
- deploy-staging
- deploy-production
- rollback
# ── Cache configuration ────────────────────────────────────────────────────
.node_cache: &node_cache
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull-push
# ── Test stage ──────────────────────────────────────────────────────────────
lint:
stage: test
<<: *node_cache
script:
- npm ci --prefer-offline
- npm run format:check
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
test:server:
stage: test
<<: *node_cache
script:
- npm ci --prefer-offline
- npm run test:server
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
artifacts:
when: on_failure
paths:
- server/__tests__/
expire_in: 7 days
test:client:
stage: test
<<: *node_cache
script:
- npm ci --prefer-offline
- cd client && npm ci --prefer-offline
- npm run test:client
cache:
key:
files:
- client/package-lock.json
paths:
- client/node_modules/
policy: pull-push
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
test:mcp:
stage: test
<<: *node_cache
script:
- npm run mcp:install
- npm run mcp:typecheck
- npm run mcp:test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# ── Build stage ─────────────────────────────────────────────────────────────
.kaniko_build: &kaniko_build
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.22.0-debug
entrypoint: [""]
before_script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64)\"}}}" > /kaniko/.docker/config.json
build:app:
<<: *kaniko_build
script:
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
--destination "${IMAGE_NAME}:${CI_COMMIT_REF_SLUG}"
--destination "${IMAGE_NAME}:latest"
${KANIKO_CACHE_ARGS}
--label "org.opencontainers.image.revision=${CI_COMMIT_SHA}"
--label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
--label "org.opencontainers.image.source=${CI_PROJECT_URL}"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
build:mcp:
<<: *kaniko_build
script:
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/mcp/Dockerfile"
--destination "${MCP_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
--destination "${MCP_IMAGE_NAME}:${CI_COMMIT_REF_SLUG}"
--destination "${MCP_IMAGE_NAME}:latest"
${KANIKO_CACHE_ARGS}
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
# Security scan
security:scan:
stage: build
needs: ["build:app", "build:mcp"]
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL --format table "${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
- trivy image --exit-code 1 --severity HIGH,CRITICAL --format table "${MCP_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
- trivy image --exit-code 1 --severity CRITICAL --format json --output trivy-app-report.json "${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
- trivy image --exit-code 1 --severity CRITICAL --format json --output trivy-mcp-report.json "${MCP_IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
artifacts:
paths:
- trivy-app-report.json
- trivy-mcp-report.json
expire_in: 30 days
allow_failure: false
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
# ── Deploy Staging ──────────────────────────────────────────────────────────
deploy:staging:
stage: deploy-staging
image:
name: alpine/helm:3.14.0
entrypoint: [""]
needs:
- build:app
- build:mcp
environment:
name: staging
url: https://staging.agent-monitor.example.com
on_stop: stop:staging
before_script:
- apk add --no-cache curl aws-cli kubectl
- aws eks update-kubeconfig --region "${AWS_REGION:-us-west-2}" --name "${EKS_CLUSTER_STAGING:-agent-monitor-staging}"
script:
- |
helm upgrade --install ${APP_NAME} ${HELM_CHART_PATH} \
--namespace agent-monitor-staging \
--create-namespace \
--set image.repository=${IMAGE_NAME} \
--set image.tag=${CI_COMMIT_SHORT_SHA} \
--set mcp.image.repository=${MCP_IMAGE_NAME} \
--set mcp.image.tag=${CI_COMMIT_SHORT_SHA} \
--set environment=staging \
--values ${HELM_CHART_PATH}/values-staging.yaml \
--wait \
--atomic \
--timeout 600s
- |
echo "Running health check..."
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=${APP_NAME} \
-n agent-monitor-staging \
--timeout=300s
echo "✔ Staging deployment successful"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
stop:staging:
stage: deploy-staging
image:
name: alpine/helm:3.14.0
entrypoint: [""]
environment:
name: staging
action: stop
before_script:
- apk add --no-cache aws-cli kubectl
- aws eks update-kubeconfig --region "${AWS_REGION:-us-west-2}" --name "${EKS_CLUSTER_STAGING:-agent-monitor-staging}"
script:
- helm uninstall ${APP_NAME} -n agent-monitor-staging --wait || true
when: manual
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# ── Deploy Production ───────────────────────────────────────────────────────
deploy:production:
stage: deploy-production
image:
name: alpine/helm:3.14.0
entrypoint: [""]
needs:
- deploy:staging
environment:
name: production
url: https://agent-monitor.example.com
before_script:
- apk add --no-cache curl aws-cli kubectl
- aws eks update-kubeconfig --region "${AWS_REGION:-us-west-2}" --name "${EKS_CLUSTER_PRODUCTION:-agent-monitor-production}"
script:
# Pre-deploy backup
- |
POD=$(kubectl get pods -n agent-monitor-production \
-l app.kubernetes.io/name=${APP_NAME} \
--field-selector=status.phase=Running \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
if [ -n "$POD" ]; then
echo "Creating pre-deploy backup..."
kubectl exec "$POD" -n agent-monitor-production -- \
sh -c "cp /app/data/dashboard.db /tmp/pre-deploy-backup.db" 2>/dev/null || true
fi
# Deploy
- |
helm upgrade --install ${APP_NAME} ${HELM_CHART_PATH} \
--namespace agent-monitor-production \
--create-namespace \
--set image.repository=${IMAGE_NAME} \
--set image.tag=${CI_COMMIT_SHORT_SHA} \
--set mcp.image.repository=${MCP_IMAGE_NAME} \
--set mcp.image.tag=${CI_COMMIT_SHORT_SHA} \
--set environment=production \
--values ${HELM_CHART_PATH}/values-production.yaml \
--wait \
--atomic \
--timeout 600s
# Health check
- |
echo "Running production health check..."
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=${APP_NAME} \
-n agent-monitor-production \
--timeout=300s
echo "✔ Production deployment successful"
when: manual
allow_failure: false
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
# ── Rollback ────────────────────────────────────────────────────────────────
rollback:staging:
stage: rollback
image:
name: alpine/helm:3.14.0
entrypoint: [""]
environment:
name: staging
before_script:
- apk add --no-cache aws-cli kubectl
- aws eks update-kubeconfig --region "${AWS_REGION:-us-west-2}" --name "${EKS_CLUSTER_STAGING:-agent-monitor-staging}"
script:
- echo "Rolling back staging..."
- helm rollback ${APP_NAME} ${ROLLBACK_REVISION:-0} -n agent-monitor-staging --wait --timeout 300s
- |
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=${APP_NAME} \
-n agent-monitor-staging \
--timeout=300s
- echo "✔ Staging rollback complete"
when: manual
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
rollback:production:
stage: rollback
image:
name: alpine/helm:3.14.0
entrypoint: [""]
environment:
name: production
before_script:
- apk add --no-cache aws-cli kubectl
- aws eks update-kubeconfig --region "${AWS_REGION:-us-west-2}" --name "${EKS_CLUSTER_PRODUCTION:-agent-monitor-production}"
script:
- echo "⚠ Rolling back PRODUCTION..."
- helm history ${APP_NAME} -n agent-monitor-production --max 5
- helm rollback ${APP_NAME} ${ROLLBACK_REVISION:-0} -n agent-monitor-production --wait --timeout 300s
- |
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=${APP_NAME} \
-n agent-monitor-production \
--timeout=300s
- echo "✔ Production rollback complete"
when: manual
allow_failure: false
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH