Canonical source: docs/claude/operations.md. This page is generated by docs/scripts/sync-handbook.mjs. Edit the source file in the repo; changes appear here on the next build.
Operations Guide — Autonomous Development & Deployment
This document describes how the Basis platform's automated development pipeline, monitoring, and deployment processes work together. It is the single source of truth for the end-to-end flow from bug report to production.
System Overview
Client reports bug ──► Slack Support Agent ──► GitHub Issue (agent:triage)
│
Sentry error ──► error-to-bug workflow ────────────────┤
│
ROADMAP.md task ──► Nightly Orchestrator ───────────────┤
▼
Triage Agent (Haiku)
Classifies P0-P3, area, complexity
│
┌────────────┴────────────┐
▼ ▼
Low complexity High/sensitive
auto: agent:build label: needs-human
│
▼
Build Agent (Sonnet)
Creates branch, applies fix
Runs lint/typecheck/build
│
▼
Opens PR (auto-generated)
│
┌───────────┼───────────┐
▼ ▼ ▼
QA Agent Risk Review Staging Deploy
(Haiku) (pr-risk) (Firebase preview)
│ │ │
└───────────┴───────────┘
│
▼
Human Review + Merge
│
▼
Production Deploy
(firebase-hosting-merge.yml)
│
▼
Health Check (every 30 min)
PostHog analytics
Sentry error tracking
1. Issue Sources — How Work Enters the Pipeline
A. Client Support (Slack → GitHub)
The Slack support agent monitors client messages. When it identifies a bug or feature request:
- It creates a GitHub issue using the
bug-report.ymltemplate - The template auto-applies labels
['bug', 'agent:triage'] - The
agent:triagelabel triggers the Triage Agent
B. Error Monitoring (Sentry → GitHub)
Sentry captures Python Cloud Function errors. Sentry's GitHub integration links errors to commits and source code.
For automated issue creation, external systems can call:
curl -X POST https://api.github.com/repos/OWNER/basis/dispatches \
-H "Authorization: token $PAT" \
-d '{"event_type":"error_alert","client_payload":{"title":"...","error":"...","severity":"P1"}}'
This triggers error-to-bug.yml, which creates a deduplicated GitHub issue with ['bug', 'auto-error', 'agent:triage'] labels.
C. Nightly Orchestrator (ROADMAP → GitHub)
Schedule: Every night at 2:00 AM UTC (9 PM EST)
Workflow: nightly-orchestrator.yml → nightly_orchestrator.py
- Parses
ROADMAP.mdfor YAML task blocks - Filters tasks:
agent: true, status not complete/in_progress/skipped, dependencies met - Sorts by priority (P0 > P1 > P2 > P3), then phase, then ID
- Checks budget: pauses if 5+ open
auto-generatedissues exist - Creates 1 GitHub issue per night with labels
['agent:triage', 'auto-generated']
ROADMAP.md task format:
- id: "1.3"
title: "Add loading skeletons to dashboard"
phase: 1
status: pending
agent: true
priority: P2
area: frontend
description: "Replace spinner with skeleton loaders"
files: ["hybrid/basisflow-web/app/(main)/dashboard/page.tsx"]
depends_on: ["1.1"]
D. Manual Issues
Anyone can create a GitHub issue. To enter the automated pipeline, add the agent:triage label.
2. Triage Agent
Workflow: triage-agent.yml → triage_agent.py
Trigger: agent:triage label added to an issue
Model: Claude Haiku (~$0.003/run)
What it does:
- Reads the issue title + body + CLAUDE.md context
- Classifies: severity (P0-P3), area, complexity (LOW/MEDIUM/HIGH), affected files, acceptance criteria
- Posts a detailed triage comment with a ready-to-copy Claude Code prompt
- Auto-escalation: Forces
needs-humanfor sensitive areas (auth, billing, permissions, stripe, HIPAA) or sensitive files (firestore.rules, storage.rules, payment functions) - Auto-build: If LOW/MEDIUM complexity + not sensitive → adds
agent:buildlabel
Labels applied: severity (P0-P3), area:{area}, complexity:{level}, status:ready
3. Build Agent
Workflow: build-agent.yml → anthropics/claude-code-action@v1 (the old build_agent.py single-call script was DELETED)
Trigger: agent:build label added to an issue (applied by the Triage Agent's suitability gate or by George — never self-applied)
Model: --model claude-sonnet-4-6 --max-turns 150
Timeout: 30 minutes
Branch: agent/issue-{number}-{timestamp} (prefix agent/ only — the action appends issue-<n>-<ts>)
What it does:
- Mark building: adds
agent:building+status:in-progress; sets the board Status field to In Progress (needsAGENT_PATprojectscope) - Runs the full Claude Code CLI autonomously — reads CLAUDE.md, explores, implements, verifies (
py_compile/npm run build), commits, and pushes the branch (up to 150 turns) - On success: the action pushes the branch but does NOT open a PR itself — the workflow finds the pushed branch and runs
gh pr create→ labelsauto-generated,agent:qa, sets the issuestatus:in-review+buildoutcome:success, moves the board card to Human Review - On failure: categorizes the failure (
buildfail:<max-turns|python-compile|frontend-build|no-changes|api-error|other>), posts a scope-instead-of-fail handoff (root cause + files + step plan), labelsneeds-human,agent:build-failed - Queue-drain (always): kicks the next eligible
agent:buildissue so work doesn't stall behind the concurrency lock
Merged ≠ live: merging the PR closes the issue (board → Done) but the code still needs a ship.sh deploy.
Important: uses AGENT_PAT (not GITHUB_TOKEN) so its pushes/PRs trigger downstream workflows and it can move the project board. Weekly agent-learning-digest.yml clusters buildfail:* outcomes back into classifier fixes.
4. PR Review Pipeline
When a PR is opened (manually or by the build agent), three checks run in parallel:
A. QA Agent
Workflow: qa-agent.yml → qa_agent.py
Trigger: PR with label agent:qa or auto-generated
Model: Claude Haiku (~$0.005/run)
- Analyzes the diff for issues, HIPAA violations, and sensitive file changes
- Verdict:
PASS→ approves PR +qa:passlabel;FAIL→ requests changes +qa:fail;NEEDS_HUMAN→needs-human-review - Always forces
NEEDS_HUMANif sensitive files are touched
B. PR Risk Review
Workflow: pr-risk-review.yml → pr_risk_review.py
Trigger: All PRs (opened/synchronized/reopened)
- Scores changed files against risk weights (sensitive paths +3, protected files +5, secrets patterns +3, etc.)
- Posts a risk summary comment and adds a risk label
- Sends to Slack if high risk
C. Staging Deploy
Workflow: staging-deploy.yml
Trigger: PRs with label auto-generated or deploy:staging
- Builds basisflow-web and deploys to a Firebase preview channel (
staging-pr-{number}, 7-day expiry) - Posts preview URL as a PR comment
- Runs Python syntax verification on all Cloud Functions
D. CI Checks
Workflow: ci.yml
Trigger: All PRs + pushes to master
- Runs lint + typecheck + build for both basisflow-web and basisweb
5. Human Review & Merge
Every PR requires human review before merging. The automated pipeline assists but never auto-merges.
Merge checklist (from QA_GUIDE.md):
- QA Agent passed (
qa:passlabel) - Risk review posted (check risk level)
- Staging preview tested (if applicable)
- CI checks green
- At least 1 human approval
- No
needs-humanorneeds-human-reviewlabels remaining
For agent-generated PRs: Always review the diff manually. The build agent can make mistakes — treat its output like a junior developer's PR.
6. Production Deployment
Automatic (Frontend Only)
Workflow: firebase-hosting-merge.yml (auto-generated by Firebase CLI)
Trigger: Push/merge to master branch
- Builds basisflow-web (
npm ci && npm run build) - Deploys to Firebase Hosting
livechannel
Also: production-deploy.yml sends Slack notifications on deploy success/failure.
Manual (Cloud Functions)
Cloud Functions are never auto-deployed. Always deploy individually:
cd /Users/G/basis/basis-functions
firebase deploy --only functions:function_name --force
Manual (Firestore/Storage Rules)
firebase deploy --only firestore:rules
firebase deploy --only storage
Manual (basisweb / Client Portal)
basisweb deploys to Netlify automatically on git push to the deployed branch. Ensure Netlify env vars are up to date.
7. When You Deploy Manually
If you build and deploy locally (outside git/CI), follow this process to keep everything in sync:
- Before deploying: Ensure your local changes are committed (or at least stashed) so git reflects what's live
- After deploying frontend manually:
- Commit the changes to git
- Push to the remote so the build agent, CI, and other workflows operate on the correct code
- After deploying Cloud Functions manually:
- Commit any Python changes to git
- Note: Function deploys don't trigger GitHub workflows, but the code must be in git for the build agent to read
- After deploying Firestore/Storage rules:
- Commit rule changes to git
- Hard-refresh (Cmd+Shift+R) any open browser tabs to clear cached permission denials
Why this matters: The build agent reads source code from GitHub. If git is behind production, the agent will propose changes against stale code, causing conflicts or regressions.
8. Monitoring & Alerting
Health Checks (Synthetic)
Workflow: health-check.yml
Schedule: Every 30 minutes
Checks three endpoints:
https://platform.basishealth.io— HTTP 200https://web.basishealth.io— HTTP 200https://us-central1-basis-hybrid.cloudfunctions.net/health_check— non-000
On failure: Creates P0 GitHub issue with health-check-failure label
On recovery: Auto-closes the issue
Sentry (Error Tracking)
DSN: Configured in Firebase Secret Manager (SENTRY_DSN)
Platform: Python (Vanilla) — captures Cloud Function errors
GitHub Integration: Links errors to commits and source code (free plan)
PostHog (Product Analytics)
Project Key: Set via NEXT_PUBLIC_POSTHOG_KEY env var
Integrated in: basisflow-web (staff platform) + basisweb (client portal)
HIPAA-safe config: All inputs masked, $ip stripped, identified_only person profiles
Tracked events:
- Automatic pageviews on route changes
- Signup funnel:
signup_clinic_created,signup_billing_started,signup_billing_complete - User identification on login (UID only, no PII)
Slack Notifications
Webhook: Stored in both Firebase Secret Manager and GitHub Secrets as SLACK_WEBHOOK_URL
Channel: #bug-channel
Sends notifications for:
- Production deploy success/failure
- High-risk PR alerts
- Cloud Function errors (via
error_reporter.py)
9. GitHub Secrets & Variables Reference
Secrets (Settings → Secrets → Actions)
| Secret | Used by | Purpose |
|---|---|---|
AGENT_PAT | build-agent.yml | GitHub PAT for pushing branches + creating PRs |
ANTHROPIC_API_KEY | triage/build/qa agents | Claude API access |
SLACK_WEBHOOK_URL | production-deploy, pr-risk | Slack notifications |
FIREBASE_SERVICE_ACCOUNT | staging-deploy, ci | Firebase preview deploys |
FIREBASE_SERVICE_ACCOUNT_BASIS_HYBRID | firebase-hosting-*.yml | Firebase CLI auto-generated deploys |
Variables (Settings → Variables → Actions)
| Variable | Used by | Purpose |
|---|---|---|
BUILD_AGENT_BASE_BRANCH | build-agent.yml | Branch to base agent work on (default: master) |
Firebase Secrets (Secret Manager)
| Secret | Used by | Purpose |
|---|---|---|
SENTRY_DSN | Cloud Functions | Sentry error reporting |
SLACK_WEBHOOK_URL | 14+ Cloud Functions | Slack error/notification posting |
10. Key Labels Reference
| Label | Meaning | Triggers |
|---|---|---|
agent:triage | Needs AI triage | triage-agent.yml |
agent:build | Ready for AI implementation | build-agent.yml |
agent:building | Build agent is working (concurrency lock) | — |
agent:qa | Needs AI QA review | qa-agent.yml |
auto-generated | Created by automated pipeline | staging-deploy.yml, budget checks |
needs-human | Requires human decision | Blocks auto-build |
needs-human-review | QA flagged for human review | — |
qa:pass | QA agent approved | — |
qa:fail | QA agent rejected | — |
agent:build-failed | Build agent couldn't fix it | — |
deploy:staging | Request staging preview | staging-deploy.yml |
health-check-failure | Uptime check failed | health-check.yml |
auto-error | Created from error alert | error-to-bug.yml |
11. Cost Estimates
| Component | Cost | Frequency |
|---|---|---|
| Triage Agent (Haiku) | ~$0.003/issue | Per issue |
| Build Agent (Sonnet) | ~$0.05-$0.30/issue | Per agent:build issue |
| QA Agent (Haiku) | ~$0.005/PR | Per PR |
| Nightly Orchestrator | ~$0.003/night | Daily |
| GitHub Actions | Free tier (2000 min/mo) | — |
| Firebase Hosting previews | Free | 7-day expiry |
| Sentry | Free (Developer plan) | — |
| PostHog | Free tier + credits | — |
Monthly budget cap: ~$300 for build agent (configurable via issue volume + the 5-open-issue budget gate in the nightly orchestrator).