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 f78c7f9a2e
783 changed files with 221663 additions and 0 deletions
+335
View File
@@ -0,0 +1,335 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# teardown.sh Clean removal of Claude Code Agent Monitor infrastructure
#
# Usage:
# ./teardown.sh --env dev --method helm
# ./teardown.sh --env production --method terraform
# ./teardown.sh --help
# ─────────────────────────────────────────────────────────────────────────────
# @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
set -euo pipefail
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
readonly DEPLOY_DIR="${PROJECT_ROOT}/deployments"
readonly APP_NAME="agent-monitor"
# ── Colors & logging ───────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
log() { echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*"; }
info() { echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} ${BLUE}${NC} $*"; }
ok() { echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} ${GREEN}${NC} $*"; }
warn() { echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} ${YELLOW}${NC} $*" >&2; }
err() { echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} ${RED}${NC} $*" >&2; }
fatal() { err "$@"; exit 1; }
# ── Defaults ────────────────────────────────────────────────────────────────
ENVIRONMENT=""
METHOD=""
NAMESPACE=""
HELM_RELEASE="${APP_NAME}"
SKIP_BACKUP=false
FORCE=false
DELETE_NAMESPACE=false
DELETE_PVC=false
# ── Usage ───────────────────────────────────────────────────────────────────
usage() {
cat <<EOF
${BOLD}Usage:${NC}
$(basename "$0") --env <environment> --method <method> [options]
${BOLD}Required:${NC}
--env, -e Environment: dev, staging, production
--method, -m Method: helm, kustomize, terraform
${BOLD}Options:${NC}
--namespace, -n Kubernetes namespace (default: agent-monitor-<env>)
--release Helm release name (default: ${APP_NAME})
--delete-namespace Also delete the Kubernetes namespace
--delete-pvc Also delete PersistentVolumeClaims (data loss!)
--skip-backup Skip data backup before teardown
--force Skip all confirmation prompts
--help, -h Show this help message
${BOLD}Examples:${NC}
$(basename "$0") --env dev --method helm
$(basename "$0") --env staging --method kustomize --delete-namespace
$(basename "$0") --env production --method terraform
EOF
exit 0
}
# ── Argument parsing ────────────────────────────────────────────────────────
parse_args() {
[[ $# -eq 0 ]] && usage
while [[ $# -gt 0 ]]; do
case "$1" in
--env|-e) ENVIRONMENT="$2"; shift 2 ;;
--method|-m) METHOD="$2"; shift 2 ;;
--namespace|-n) NAMESPACE="$2"; shift 2 ;;
--release) HELM_RELEASE="$2"; shift 2 ;;
--delete-namespace) DELETE_NAMESPACE=true; shift ;;
--delete-pvc) DELETE_PVC=true; shift ;;
--skip-backup) SKIP_BACKUP=true; shift ;;
--force) FORCE=true; shift ;;
--help|-h) usage ;;
*) fatal "Unknown option: $1" ;;
esac
done
[[ -z "$ENVIRONMENT" ]] && fatal "Missing required argument: --env"
[[ -z "$METHOD" ]] && fatal "Missing required argument: --method"
[[ -z "$NAMESPACE" ]] && NAMESPACE="agent-monitor-${ENVIRONMENT}"
}
# ── Confirm teardown ───────────────────────────────────────────────────────
confirm_teardown() {
if [[ "$FORCE" == true ]]; then
return
fi
echo ""
echo -e " ${RED}${BOLD}╔══════════════════════════════════════════╗${NC}"
echo -e " ${RED}${BOLD}║ ⚠ TEARDOWN WARNING ⚠ ║${NC}"
echo -e " ${RED}${BOLD}╚══════════════════════════════════════════╝${NC}"
echo ""
echo -e " This will ${RED}${BOLD}DESTROY${NC} the following resources:"
echo -e " • Environment: ${BOLD}${ENVIRONMENT}${NC}"
echo -e " • Method: ${BOLD}${METHOD}${NC}"
echo -e " • Namespace: ${BOLD}${NAMESPACE}${NC}"
[[ "$DELETE_NAMESPACE" == true ]] && echo -e "${RED}Namespace will be deleted${NC}"
[[ "$DELETE_PVC" == true ]] && echo -e "${RED}PVCs will be deleted (DATA LOSS!)${NC}"
echo ""
if [[ "$ENVIRONMENT" == "production" ]]; then
echo -e " ${RED}${BOLD}THIS IS A PRODUCTION ENVIRONMENT!${NC}"
echo ""
read -r -p "$(echo -e "${RED}Type 'destroy ${ENVIRONMENT}' to confirm:${NC} ")" confirm
[[ "$confirm" == "destroy ${ENVIRONMENT}" ]] || fatal "Teardown cancelled."
# Second confirmation for production
echo ""
read -r -p "$(echo -e "${RED}Are you absolutely sure? Type 'YES' in caps:${NC} ")" confirm2
[[ "$confirm2" == "YES" ]] || fatal "Teardown cancelled."
else
read -r -p "$(echo -e "${YELLOW}Type 'yes' to confirm:${NC} ")" confirm
[[ "$confirm" == "yes" ]] || fatal "Teardown cancelled."
fi
}
# ── Pre-teardown backup ────────────────────────────────────────────────────
backup_data() {
if [[ "$SKIP_BACKUP" == true ]]; then
info "Skipping pre-teardown backup (--skip-backup)"
return
fi
info "Creating backup before teardown..."
if [[ -x "${SCRIPT_DIR}/db-backup.sh" ]]; then
local backup_dir="${PROJECT_ROOT}/data/pre-teardown-backups"
"${SCRIPT_DIR}/db-backup.sh" \
--env "${ENVIRONMENT}" \
--output "${backup_dir}" \
--namespace "${NAMESPACE}" \
&& ok "Pre-teardown backup created" \
|| warn "Backup failed continuing with teardown"
else
warn "db-backup.sh not found skipping backup"
fi
}
# ── Show current resources ──────────────────────────────────────────────────
show_resources() {
info "Current resources in namespace '${NAMESPACE}':"
echo ""
kubectl get all -n "${NAMESPACE}" 2>/dev/null || warn "Could not list resources"
if [[ "$METHOD" != "terraform" ]]; then
echo ""
info "PersistentVolumeClaims:"
kubectl get pvc -n "${NAMESPACE}" 2>/dev/null || warn "No PVCs found"
fi
echo ""
}
# ── Helm teardown ──────────────────────────────────────────────────────────
teardown_helm() {
info "Uninstalling Helm release '${HELM_RELEASE}'..."
if helm status "${HELM_RELEASE}" -n "${NAMESPACE}" &>/dev/null; then
helm uninstall "${HELM_RELEASE}" -n "${NAMESPACE}" --wait --timeout 300s \
|| fatal "Helm uninstall failed"
ok "Helm release '${HELM_RELEASE}' uninstalled"
else
warn "Helm release '${HELM_RELEASE}' not found in namespace '${NAMESPACE}'"
fi
# Also try uninstalling blue/green releases
for color in blue green; do
if helm status "${HELM_RELEASE}-${color}" -n "${NAMESPACE}" &>/dev/null; then
info "Uninstalling ${color} slot release..."
helm uninstall "${HELM_RELEASE}-${color}" -n "${NAMESPACE}" --wait --timeout 300s \
&& ok "Release '${HELM_RELEASE}-${color}' uninstalled" \
|| warn "Failed to uninstall ${color} release"
fi
done
}
# ── Kustomize teardown ─────────────────────────────────────────────────────
teardown_kustomize() {
local overlay_dir="${DEPLOY_DIR}/kubernetes/overlays/${ENVIRONMENT}"
if [[ -d "$overlay_dir" ]]; then
info "Deleting Kustomize resources..."
kubectl delete -k "${overlay_dir}" --ignore-not-found=true --wait=true --timeout=300s \
&& ok "Kustomize resources deleted" \
|| warn "Some resources may not have been deleted"
else
warn "Kustomize overlay not found at ${overlay_dir}"
info "Deleting resources by label..."
kubectl delete all -l "app.kubernetes.io/name=${APP_NAME}" -n "${NAMESPACE}" --wait=true \
|| warn "Could not delete resources by label"
fi
}
# ── Terraform teardown ─────────────────────────────────────────────────────
teardown_terraform() {
local tf_dir="${DEPLOY_DIR}/terraform"
local env_vars_file="${tf_dir}/environments/${ENVIRONMENT}/terraform.tfvars"
info "Destroying Terraform-managed infrastructure..."
pushd "${tf_dir}" > /dev/null
terraform init -input=false
local destroy_args=(-input=false -auto-approve)
if [[ -f "$env_vars_file" ]]; then
destroy_args+=(-var-file="$env_vars_file")
fi
# Need to provide required variables that may not have defaults
destroy_args+=(-var "environment=${ENVIRONMENT}")
if ! terraform destroy "${destroy_args[@]}"; then
popd > /dev/null
fatal "Terraform destroy failed! Review state manually."
fi
popd > /dev/null
ok "Terraform infrastructure destroyed"
}
# ── Cleanup PVCs ────────────────────────────────────────────────────────────
cleanup_pvcs() {
if [[ "$DELETE_PVC" != true ]]; then
local pvc_count
pvc_count=$(kubectl get pvc -n "${NAMESPACE}" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [[ "$pvc_count" -gt 0 ]]; then
warn "PersistentVolumeClaims still exist. Use --delete-pvc to remove them."
kubectl get pvc -n "${NAMESPACE}" 2>/dev/null
fi
return
fi
info "Deleting PersistentVolumeClaims..."
kubectl delete pvc --all -n "${NAMESPACE}" --wait=true \
&& ok "PVCs deleted" \
|| warn "Some PVCs could not be deleted"
}
# ── Cleanup namespace ──────────────────────────────────────────────────────
cleanup_namespace() {
if [[ "$DELETE_NAMESPACE" != true ]]; then
return
fi
if [[ "$ENVIRONMENT" == "production" ]]; then
warn "Refusing to delete production namespace automatically."
warn "Delete manually: kubectl delete namespace ${NAMESPACE}"
return
fi
info "Deleting namespace '${NAMESPACE}'..."
kubectl delete namespace "${NAMESPACE}" --ignore-not-found=true --wait=true --timeout=120s \
&& ok "Namespace '${NAMESPACE}' deleted" \
|| warn "Namespace deletion may be stuck. Check: kubectl get namespace ${NAMESPACE}"
}
# ── Verify teardown ────────────────────────────────────────────────────────
verify_teardown() {
info "Verifying teardown..."
if [[ "$METHOD" == "terraform" ]]; then
ok "Terraform state should reflect no resources"
return
fi
local remaining
remaining=$(kubectl get all -n "${NAMESPACE}" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [[ "$remaining" -eq 0 ]]; then
ok "No resources remaining in namespace '${NAMESPACE}'"
else
warn "${remaining} resources still exist in namespace '${NAMESPACE}':"
kubectl get all -n "${NAMESPACE}" 2>/dev/null
fi
}
# ── Main ────────────────────────────────────────────────────────────────────
main() {
echo ""
echo -e "${BOLD}${RED}╔══════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}${RED}║ Claude Code Agent Monitor Teardown ║${NC}"
echo -e "${BOLD}${RED}╚══════════════════════════════════════════════════╝${NC}"
echo ""
parse_args "$@"
info "Teardown configuration:"
echo -e " ${BOLD}Environment:${NC} ${ENVIRONMENT}"
echo -e " ${BOLD}Method:${NC} ${METHOD}"
echo -e " ${BOLD}Namespace:${NC} ${NAMESPACE}"
echo ""
if [[ "$METHOD" != "terraform" ]]; then
show_resources
fi
confirm_teardown
backup_data
case "$METHOD" in
helm) teardown_helm ;;
kustomize) teardown_kustomize ;;
terraform) teardown_terraform ;;
*) fatal "Invalid method: ${METHOD}" ;;
esac
if [[ "$METHOD" != "terraform" ]]; then
cleanup_pvcs
cleanup_namespace
verify_teardown
fi
echo ""
ok "${BOLD}Teardown complete!${NC}"
echo -e " ${BOLD}Environment:${NC} ${ENVIRONMENT}"
echo -e " ${BOLD}Method:${NC} ${METHOD}"
echo -e " ${BOLD}Timestamp:${NC} $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo ""
}
main "$@"