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
@@ -0,0 +1,15 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: agent-monitor-config
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: config
app.kubernetes.io/managed-by: kustomize
data:
NODE_ENV: "production"
DASHBOARD_PORT: "4820"
LOG_LEVEL: "info"
+147
View File
@@ -0,0 +1,147 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: server
app.kubernetes.io/managed-by: kustomize
spec:
replicas: 2
revisionHistoryLimit: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
template:
metadata:
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: server
app.kubernetes.io/managed-by: kustomize
annotations:
# Force rollout on configmap changes via kustomize hash
checksum/config: "placeholder"
spec:
serviceAccountName: agent-monitor
automountServiceAccountToken: false
terminationGracePeriodSeconds: 30
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- agent-monitor
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: agent-monitor
containers:
- name: agent-monitor
image: ${IMAGE_REGISTRY}/agent-monitor:${IMAGE_TAG}
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 4820
protocol: TCP
envFrom:
- configMapRef:
name: agent-monitor-config
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
startupProbe:
httpGet:
path: /api/health
port: http
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 15
periodSeconds: 15
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: data
mountPath: /app/data
- name: tmp
mountPath: /tmp
lifecycle:
preStop:
exec:
# Allow in-flight requests to drain before SIGTERM
command: ["sh", "-c", "sleep 5"]
volumes:
- name: data
persistentVolumeClaim:
claimName: agent-monitor-data
- name: tmp
emptyDir:
sizeLimit: 100Mi
+49
View File
@@ -0,0 +1,49 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: autoscaling
app.kubernetes.io/managed-by: kustomize
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: agent-monitor
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60
selectPolicy: Min
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Pods
value: 2
periodSeconds: 60
- type: Percent
value: 50
periodSeconds: 60
selectPolicy: Max
+51
View File
@@ -0,0 +1,51 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: ingress
app.kubernetes.io/managed-by: kustomize
annotations:
# NGINX Ingress Controller annotations
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
# WebSocket upgrade support
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Sticky sessions for WebSocket
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent
nginx.ingress.kubernetes.io/session-cookie-name: agent-monitor-affinity
nginx.ingress.kubernetes.io/session-cookie-max-age: "10800"
nginx.ingress.kubernetes.io/session-cookie-samesite: Strict
nginx.ingress.kubernetes.io/session-cookie-secure: "true"
# Security headers
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- agent-monitor.example.com
secretName: agent-monitor-tls
rules:
- host: agent-monitor.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: agent-monitor
port:
name: http
@@ -0,0 +1,23 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: agent-monitor-base
commonLabels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: kustomize
resources:
- namespace.yaml
- configmap.yaml
- serviceaccount.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- hpa.yaml
- pdb.yaml
- networkpolicy.yaml
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Namespace
metadata:
name: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: namespace
app.kubernetes.io/managed-by: kustomize
# Enable Pod Security Standards (restricted)
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: latest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
@@ -0,0 +1,53 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: network
app.kubernetes.io/managed-by: kustomize
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
policyTypes:
- Ingress
- Egress
ingress:
# Allow traffic from ingress controller
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
- podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 4820
# Allow intra-namespace traffic (pod-to-pod)
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: agent-monitor
ports:
- protocol: TCP
port: 4820
egress:
# Allow DNS resolution (required for service discovery)
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Allow outbound HTTPS (for external API calls if needed)
- ports:
- port: 443
protocol: TCP
# Allow internal communication within the namespace (pod-to-pod)
- to:
- podSelector: {}
+17
View File
@@ -0,0 +1,17 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: availability
app.kubernetes.io/managed-by: kustomize
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
+17
View File
@@ -0,0 +1,17 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: agent-monitor-data
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: storage
app.kubernetes.io/managed-by: kustomize
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
+29
View File
@@ -0,0 +1,29 @@
apiVersion: v1
kind: Service
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: server
app.kubernetes.io/managed-by: kustomize
annotations:
# Document the WebSocket requirement
service.kubernetes.io/topology-mode: Auto
spec:
type: ClusterIP
# Sticky sessions for WebSocket support
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
selector:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
@@ -0,0 +1,12 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: agent-monitor
namespace: agent-monitor
labels:
app.kubernetes.io/name: agent-monitor
app.kubernetes.io/instance: agent-monitor
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: serviceaccount
app.kubernetes.io/managed-by: kustomize
automountServiceAccountToken: false