For: DevOps Engineer Generated: 2026-03-09 Version: v0.9.0 (30 epics shipped)
IntentCAD is a Drawing Intelligence Platform for AEC professionals. Users upload architectural drawings (DXF or PDF), describe what they need in plain English — an edit, a compliance check, a quantity takeoff, a health report — and the platform classifies intent on two axes, selects the right processing pipeline, and delivers structured results. Original files are never modified — every save produces a new file.
The system has shipped 30 epics across 9 phases, evolving from a local-first DXF editor into a multi-capability platform with compliance validation, health reports, quantity takeoff, drawing summaries, RFI generation, zone detection, revision comparison, agent mode, and user accounts with persistent workspaces. It ships as both a PySide6 desktop app (Windows/Linux) and a React + FastAPI web app deployed on Google Cloud (Firebase Hosting + Cloud Run). The LLM backend is Gemini via Vertex AI, with a mock provider for CI determinism.
The core architectural invariant: the LLM never touches DXF directly. It returns structured JSON operations (13 op types) which are validated against protected-layer rules before a deterministic edit engine applies them. This design eliminates a class of LLM hallucination risks at the architecture level.
Current risk profile: the system is well-tested (4,494 tests across 10 tiers, 65% coverage threshold) with green CI, automated deploys via WIF, and comprehensive security scanning. Primary operational risks are single-region deployment and the external ODA File Converter dependency for DWG support.
| Environment | Status | Uptime Target | Release Cadence |
|---|---|---|---|
| Production (Web) | Active | Best-effort (Cloud Run default SLA) | Merge-to-main auto-deploy |
| Desktop | Builds available | N/A (local) | Tag-triggered (v* tags) |
| CI | Green (main) | N/A | Every push/PR |
| Staging | None (direct-to-prod) | N/A | N/A |
| Category | Technology | Version | Purpose |
|---|---|---|---|
| Language | Python | 3.11 / 3.12 | Core pipeline, backend |
| DXF Engine | ezdxf | >=1.3.0 | DXF read/write/entity manipulation |
| Data Models | Pydantic | >=2.0 | Schema validation, serialization |
| LLM | Gemini (Vertex AI) | gemini-2.5-flash | Edit planning, vision, agent tool-use |
| Backend | FastAPI + Uvicorn | >=0.115.0 | REST API for web frontend |
| Frontend | React 18 + Vite | 18.3.1 / 6.0.5 | SPA interface |
| DXF Viewer | dxf-viewer + Three.js | 1.0.46 / 0.183.2 | WebGL drawing preview |
| Auth | Firebase Authentication | 11.0.0 | Google Sign-In |
| Hosting | Firebase Hosting | — | Static SPA delivery |
| Compute | Cloud Run | — | Containerized backend (8Gi/4CPU) |
| Storage | GCS + Firestore | — | Document persistence, user profiles, tenants |
| Registry | Artifact Registry | — | Docker images (us-central1) |
| Tracing | OpenTelemetry → Cloud Trace | >=1.21 | Pipeline span instrumentation |
| Desktop UI | PySide6 | >=6.6 | Qt-based desktop shell |
| CI/CD | GitHub Actions | — | Lint, test, deploy (WIF auth) |
| Linting | Ruff | >=0.5 | Lint + format |
| Type Check | Mypy | >=1.10 | Static type analysis |
| Security | Bandit + pip-audit | — | SAST + dependency audit |
| Build | Hatchling + PyInstaller | — | Package + desktop executable |
┌─────────────────────────┐
│ Firebase Hosting │
│ (React SPA) │
│ cad-dxf-agent.web.app │
└────────┬────────────────┘
│ /api/* rewrite
▼
┌─────────────────────────┐
│ Cloud Run │
│ cad-dxf-web │
│ FastAPI (8Gi/4CPU) │
│ us-central1 │
└────────┬────────────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Pipeline Core │ │ Vertex AI │ │ Firebase/GCP │
│ (ezdxf, 41 │ │ Gemini API │ │ Auth, Firestore │
│ core modules, │ │ (WIF auth) │ │ GCS (documents) │
│ validators, │ │ │ │ Cloud Trace │
│ edit engine) │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Pipeline Flow (Two-Axis Classification):
User Prompt → ObjectiveClassifier (RequestClass × ObjectiveTag)
→ StrategyRegistry (maps to StagePipelineDefinition)
→ StageExecutor (ordered stages: deterministic + LLM)
→ ResponseBuilder (PlatformResponse envelope)
Edit Pipeline:
Planner(Gemini) → ChangeSet → Validator → Preview → EditEngine → Save-As DXF
│
RevisionNotes (deterministic)
Analysis Pipeline (compliance, health, takeoff, summary, RFI, zones):
Deterministic extractors → structured results (no edit flow)
Agent Mode (complex requests):
Prompt + context + tools → Gemini → tool calls → ToolExecutor
→ results fed back → next iteration (max 10 turns)
→ final ChangeSet from accumulated tool calls
Desktop variant:
PySide6 UI → same pipeline → local file I/O
| Domain | Impact | Mitigation |
|---|---|---|
| Gemini API down | No edit planning (read/compare/analysis still work) | Mock provider fallback in CI; timeout + retry with backoff |
| Cloud Run cold start | 5-15s latency spike | 8Gi memory, min-instances=0 (cost tradeoff) |
| Firebase Hosting | Frontend unavailable | CDN-backed, rarely fails |
| ODA binary missing | DWG uploads return 422 | DXF and PDF uploads unaffected; size-validated download in CI |
| Firestore down | User profiles/tenant creation fails | Cached in-process (5min/10min TTL); existing sessions unaffected |
| GCS down | Document persistence fails | Session-local copies still work; uploads/downloads degrade |
cad-dxf-agent/
├── src/cad_dxf_agent/ # Core Python package (124 .py files, 23k LOC)
│ ├── models/ # 30 Pydantic schemas (cad, ops, config, zone, compliance, etc.)
│ ├── core/ # 41 modules — DXF I/O, validation, editing, analysis
│ │ └── comparison/ # Revision diff engine (alignment, matching, changelog, bundle)
│ ├── llm/ # 22 modules — intent classification, planning, agent loop
│ │ └── stage_handlers/ # Stage pipeline handlers (analyze, comply, health, summarize, etc.)
│ ├── cli/ # cad-revision CLI (diff/align/bundle/explain)
│ ├── ui/ # PySide6 desktop GUI
│ ├── settings.py # Env-based configuration (all CAD_* prefixed)
│ ├── otel.py # OpenTelemetry bootstrap (off by default)
│ └── app.py # Desktop entry point
├── web/
│ ├── backend/ # FastAPI on Cloud Run
│ │ ├── main.py # ~2850 lines — all API routes (20+ endpoints)
│ │ ├── api_v1.py # /api/v1 router
│ │ ├── auth.py # Firebase token validation
│ │ ├── session.py # SessionManager for ephemeral work
│ │ ├── Dockerfile # Production image (Python 3.12-slim + ODA)
│ │ └── requirements.txt # Backend-specific deps
│ ├── frontend/ # React 18 + Vite SPA
│ │ ├── src/pages/ # Upload, Editor, Compare, RevisionWizard, Documents
│ │ ├── src/components/ # Reusable UI components
│ │ └── package.json # Frontend deps
│ ├── firebase.json # Hosting config + /api/** → Cloud Run rewrite
│ ├── firestore.rules # Client reads/writes denied (server-side only)
│ └── .firebaserc # Project: cad-dxf-agent
├── proxy/ # Cloud Run proxy for desktop licensing
│ ├── main.py # FastAPI, rate-limited Gemini forwarder
│ └── Dockerfile # Minimal image
├── tests/ # 224 test modules, 4,494 tests across 10 tiers
│ ├── unit/ # ~3,618 tests — schemas, validators, reader, writer, engine, etc.
│ ├── integration/ # ~102 tests — full pipeline, agent loop (ScriptedAgentProvider)
│ ├── web/ # ~418 tests — FastAPI TestClient endpoint tests
│ ├── eval/ # ~238 tests — intent classification scorecard
│ ├── live/ # ~42 tests — real Gemini API tests (WIF in CI)
│ ├── e2e/ # ~33 tests — end-to-end with real DXF files
│ ├── benchmark/ # ~19 tests — pytest-benchmark micro-benchmarks
│ ├── gui/ # ~10 tests — PySide6 tests (QT_QPA_PLATFORM=offscreen)
│ ├── property/ # ~7 tests — fuzz/property tests (randomized, bounded)
│ ├── smoke/ # ~7 tests — end-to-end mock pipeline
│ ├── fixtures/ # DXF zoo, revision cases, trajectories, prompt bank
│ └── helpers/ # DXF factory, changeset factory, scripted provider
├── scripts/ # Build, smoke test, eval runner, fixture downloads
├── 000-docs/ # 64 architectural/planning documents
├── .github/workflows/ # 8 CI/CD workflows
├── Makefile # 67-line task runner
├── pyproject.toml # Build config, tool settings, dep groups
└── .pre-commit-config.yaml # Ruff, trailing whitespace, .env block, main protection
| Language | Files | Code Lines | Comments | Blanks |
|---|---|---|---|---|
| Python | 360 | 77,795 | 3,897 | 16,383 |
| JSON | 44 | 9,726 | 0 | 8 |
| JSX | 24 | 4,190 | 220 | 320 |
| JavaScript | 24 | 3,429 | 650 | 717 |
| CSS | 6 | 1,807 | 62 | 301 |
| Other | 95 | 1,730 | 11,533 | 3,991 |
| Total | 553 | 98,677 | 16,362 | 21,720 |
- Prerequisites: Python 3.11+, Node.js 22+,
gcloudCLI - Setup:
# Python backend pip install -e ".[dev]" pre-commit install gcloud auth application-default login # One-time GCP auth # Create .env (gitignored) echo 'CAD_LLM_PROVIDER=gemini' > .env echo 'CAD_GCP_PROJECT=cad-dxf-agent' >> .env # Frontend cd web/frontend && npm ci
- Run:
# Backend on :8322 CAD_WEB_DEV_MODE=1 uvicorn web.backend.main:app --port 8322 # Frontend on :3000 cd web/frontend && npm run dev
- Verification:
make check(lint → format → typecheck → test → smoke)
Normal path (automated): Merge PR to main touching web/** or src/** → GitHub Actions deploy-web.yml fires → builds Docker image → pushes to Artifact Registry → deploys Cloud Run → deploys Firebase Hosting. No manual steps.
Pre-flight checklist:
- All CI checks green on PR
-
make checkpasses locally - PR reviewed and approved
- No secrets in diff
Manual deploy (emergency only):
# ALWAYS specify --project (local gcloud may point elsewhere)
cd web/frontend && npm run build
firebase deploy --only hosting --project cad-dxf-agent
gcloud run deploy cad-dxf-web \
--source . --dockerfile web/backend/Dockerfile \
--region us-central1 --project cad-dxf-agent \
--allow-unauthenticated --memory 8Gi --cpu 4 --timeout 600 \
--service-account cad-dxf-web-run@cad-dxf-agent.iam.gserviceaccount.com \
--set-env-vars CAD_LLM_PROVIDER=gemini,CAD_GCP_PROJECT=cad-dxf-agent,OTEL_ENABLED=1,OTEL_EXPORTER=gcp-traceDo NOT use: gcloud builds submit --config cloudbuild.yaml — $SHORT_SHA is only set by triggers, not manual submits.
Rollback protocol:
# List recent revisions
gcloud run revisions list --service cad-dxf-web --region us-central1 --project cad-dxf-agent
# Route traffic to previous revision
gcloud run services update-traffic cad-dxf-web \
--to-revisions=PREVIOUS_REVISION=100 \
--region us-central1 --project cad-dxf-agent- Cloud Trace: All pipeline stages emit OTel spans (
cad.load_dxf,cad.run_planner,cad.validate,cad.build_context, etc.). Enabled viaOTEL_ENABLED=1+OTEL_EXPORTER=gcp-trace. - Cloud Run Logs:
gcloud run services logs read cad-dxf-web --region us-central1 --project cad-dxf-agent - CI Status:
gh run list --workflow=ci.ymlandgh run list --workflow=deploy-web.yml - SLIs: No formal SLOs defined yet. Cloud Run provides built-in request latency, error rate, and instance count metrics.
- Dashboards: GCP Console → Cloud Run → cad-dxf-web service page (built-in metrics)
- On-call: No rotation — single-developer project.
| Severity | Definition | Response | Playbook |
|---|---|---|---|
| P0 | Web app completely down | Immediate — check Cloud Run status, rollback if deploy broke it | gcloud run revisions list → route traffic to last-good |
| P1 | Gemini API failures (edit planning broken) | 15 min — check Vertex AI status page, verify ADC credentials | Read-only features still work; users see "planning unavailable" |
| P2 | ODA converter missing (DWG uploads 422) | Next business day — rebuild with ODA .deb from GCS | DXF and PDF uploads unaffected |
| P3 | Test failures on main | Same day — fix or revert the breaking commit | gh run list --workflow=ci.yml → investigate |
| Role | Purpose | Permissions | Where |
|---|---|---|---|
cad-dxf-web-run SA |
Cloud Run runtime | Vertex AI API, Cloud Trace, GCS, Firestore | GCP IAM |
| WIF (GitHub Actions) | CI/CD deploy | Cloud Run deploy, Artifact Registry push, Firebase deploy, GCS read | Federated via WIF_PROVIDER / WIF_SERVICE_ACCOUNT (GitHub vars, not secrets) |
| Firebase Admin SDK | Token validation + Firestore | Firebase Auth read, Firestore read/write | Initialized in backend startup |
- No stored secrets: WIF provides tokenless authentication from GitHub Actions to GCP. No API keys, service account JSON files, or secrets in GitHub.
- Firebase API keys: Public-safe client config (hardcoded in
deploy-web.yml). These are designed to be public per Firebase documentation. - Local dev:
gcloud auth application-default loginprovides ADC credentials..envfile is gitignored. - Break-glass: If WIF breaks, manual deploy uses developer's own
gcloud authcredentials with--project cad-dxf-agent.
detect-private-key: Blocks commits containing private keysforbid-env-files: Blocks.envfile commitsno-commit-to-branch: Prevents direct commits tomaincheck-added-large-files: Blocks files >1MB (catches accidental binary commits)bandit: Python SAST on every CI runpip-audit: Dependency vulnerability scan on every CI run
- Cloud Run: ~$5-20/mo (low traffic, scale-to-zero, 8Gi/4CPU per request)
- Vertex AI (Gemini): ~$10-50/mo (depends on request volume; gemini-2.5-flash pricing)
- Firebase Hosting: Free tier (SPA CDN)
- Firebase Auth: Free tier (<50k MAU)
- Firestore: Free tier (user profiles, tenants, allowlist)
- GCS: ~$1-5/mo (document storage)
- Artifact Registry: ~$1/mo (container storage)
- Cloud Trace: Free tier (first 5M spans/mo)
- Total: ~$20-80/mo at current usage
- DXF load: <100ms for 200-entity drawings, ~500ms for 1000-entity (benchmarked in
tests/benchmark/) - Gemini planning: 2-8s per edit prompt (network + inference)
- Agent mode: 5-30s (multi-turn, up to 10 iterations)
- Validation: <1ms per operation
- Edit engine: <10ms per changeset application
- Cloud Run cold start: 5-15s (Python image + ODA libraries)
- Web API P95: ~3-10s end-to-end (dominated by Gemini latency)
- Comprehensive CI: Lint (ruff), format, typecheck (mypy), 4,494 tests across 10 tiers, security scans — all automated on push/PR
- Automated deploys: Merge to main → GitHub Actions deploys both frontend + backend via WIF. Zero manual steps.
- Multi-capability platform: Edit, compliance, health, takeoff, summary, RFI, zone detection, revision comparison, agent mode — all production-ready
- Two-axis intent classification: Every prompt classified by RequestClass (what) × ObjectiveTag (why), routed to the right pipeline
- User accounts: Firebase Auth (Google Sign-In), Firestore tenants/profiles, GCS document persistence with work progress
- Safety architecture: LLM never touches DXF directly; protected layers enforced at validator + ToolExecutor; deterministic revision notes; save-as workflow
- Agent mode: Iterative tool-use loop (20+ tools, max 10 turns) for complex multi-step requests
- Modern tooling: 30 Pydantic schemas, Ruff linting, syrupy snapshots, pytest-benchmark, OpenTelemetry tracing
- Strong documentation: 64 docs covering architecture decisions, specs, audit reports, and epic AARs
- WIF authentication: No secrets stored anywhere — tokenless GCP access from CI
- No staging environment: Production deploys go direct-to-prod. A staging Cloud Run service would catch deploy issues before users see them.
- Single-region: Cloud Run only in
us-central1. No multi-region failover. - No CODEOWNERS: No automated review assignment for critical paths.
- Proxy service: Not deployed via CI — ad-hoc manual deploys. No monitoring.
- ODA dependency: External binary downloaded from GCS. If the bucket or file is lost, DWG support breaks.
- Desktop build: Windows-only PyInstaller builds. Linux desktop builds not automated.
- No dependency pinning:
pyproject.tomluses>=ranges. No lock file for reproducible builds.
| Capability | Command | Notes |
|---|---|---|
| Install + setup | pip install -e ".[dev]" && pre-commit install |
Editable install with all dev deps |
| All quality checks | make check |
lint → format → typecheck → test → smoke |
| Lint only | make lint |
ruff check src/ tests/ |
| Format only | make format |
ruff format src/ tests/ |
| Type check | make typecheck |
mypy src/ |
| All tests | .venv/bin/python -m pytest -v |
System pytest may lack ezdxf |
| Unit tests | make test-unit |
~3,618 tests |
| Integration tests | make test-integration |
~102 tests |
| Web API tests | make test-web |
~418 tests, FastAPI TestClient |
| E2E tests | make test-e2e |
~33 tests, real DXF files |
| Live Gemini tests | make test-live |
~42 tests, requires ADC |
| Eval scorecard | make scorecard |
~238 tests, mock mode |
| Coverage report | make test-cov |
Threshold: 65% |
| Security scan | make security |
bandit -r src/ -ll && pip-audit |
| Smoke test | make smoke |
Full pipeline with mock provider |
| Local backend | CAD_WEB_DEV_MODE=1 uvicorn web.backend.main:app --port 8322 |
Skips Firebase auth |
| Local frontend | cd web/frontend && npm run dev |
Vite on :3000 |
| Desktop app | make run |
Requires pip install -e ".[gui]" |
| Build executable | make build |
PyInstaller → dist/cad-dxf-agent/ |
| Revision CLI | cad-revision diff master.dxf rev.dxf --output-dir ./out |
Compare two DXFs |
| Deploy status | gh run list --workflow=deploy-web.yml |
Latest deploy results |
| Cloud Run logs | gcloud run services logs read cad-dxf-web --region us-central1 --project cad-dxf-agent |
Recent request logs |
| Rollback | See Section 4 rollback protocol | Traffic splitting to previous revision |
- Production: https://cad-dxf-agent.web.app
- Cloud Run service:
gcloud run services describe cad-dxf-web --region us-central1 --project cad-dxf-agent - CI/CD: https://github.com/jeremylongshore/cad-dxf-agent/actions
- Artifact Registry:
us-central1-docker.pkg.dev/cad-dxf-agent/cad-dxf-agent/web-backend - Firebase Console: https://console.firebase.google.com/project/cad-dxf-agent
- GCP Console: https://console.cloud.google.com/run?project=cad-dxf-agent
- Cloud Trace: https://console.cloud.google.com/traces?project=cad-dxf-agent
- GCP access granted (
gcloud auth loginwith projectcad-dxf-agent) - GitHub repo access (push to branches, not main)
-
gcloud auth application-default loginfor local Gemini access -
pip install -e ".[dev]"+pre-commit install -
make checkpasses locally (all green) - Understood two-axis classification: RequestClass × ObjectiveTag → pipeline
- Run
make smoketo see full pipeline execute with mock provider - Reviewed CLAUDE.md (project conventions, commit format, PR template)
- Read 000-docs/000-INDEX.md for doc inventory
- Completed a local web dev session (upload DXF → prompt → preview → apply)
- Reviewed
deploy-web.ymlto understand the auto-deploy pipeline - Understood WIF authentication (no secrets — vars in GitHub repo settings)
| Variable | Default | Purpose |
|---|---|---|
CAD_LLM_PROVIDER |
mock |
gemini for prod/dev, mock for CI |
CAD_GCP_PROJECT |
(none) | GCP project ID (required for Vertex AI) |
CAD_GCP_LOCATION |
us-central1 |
Vertex AI region |
CAD_GEMINI_MODEL |
gemini-2.5-flash |
Gemini model for planning |
CAD_VISION_MODEL |
gemini-2.5-flash |
Gemini model for vision description |
CAD_PROTECTED_LAYERS |
TITLE,TITLEBLOCK,SEAL,REVISION |
Layers the LLM cannot edit |
CAD_REVISION_NOTES_ENABLED |
true |
Insert deterministic revision notes |
CAD_REVISION_NOTES_LAYER |
AI_REV_NOTES |
Layer for revision notes |
CAD_LLM_TEMPERATURE |
0.0 |
Gemini temperature (0 = deterministic) |
CAD_LLM_MAX_OUTPUT_TOKENS |
4096 |
Max response tokens |
CAD_PLANNER_TIMEOUT |
60 |
Planner timeout (seconds) |
CAD_PLANNER_MAX_RETRIES |
2 |
Retry count on planner failure |
CAD_RENDER_DPI |
150 |
PNG render resolution |
CAD_MAX_UNDO_SNAPSHOTS |
50 |
Edit history depth |
CAD_VISION_ENABLED |
true |
Enable DXF → image → description pipeline |
CAD_ODA_PATH |
(auto) | ODA File Converter path (DWG support) |
CAD_WEB_DEV_MODE |
(unset) | Skip Firebase auth for local dev (1) |
CAD_WEB_CORS_ORIGIN |
(unset) | Additional CORS origin |
CAD_ALLOWED_EMAILS |
(unset) | Semicolon-separated emails for auto-provisioning |
CAD_PROXY_URL |
(unset) | Cloud Run proxy for desktop |
CAD_LICENSE_KEY |
(unset) | Proxy authentication key |
OTEL_ENABLED |
(unset) | Enable tracing (1, true, yes) |
OTEL_EXPORTER |
console |
console, otlp, or gcp-trace |
OTEL_EXPORTER_OTLP_ENDPOINT |
(unset) | OTLP collector URL |
| Workflow | Trigger | Jobs | Duration |
|---|---|---|---|
ci.yml |
Push to main, all PRs | lint, typecheck, test (matrix 3.11+3.12), benchmark (main only), live-test (main only) | ~3-5 min |
deploy-web.yml |
Push to main (web/src changes), manual | deploy-backend (Docker → Cloud Run), deploy-frontend (npm → Firebase) | ~5-8 min |
security.yml |
Push to main, all PRs | bandit, pip-audit | ~2 min |
build-windows.yml |
Tag push (v*), manual | PyInstaller build, Inno Setup installer, upload artifacts | ~10 min |
gemini-review.yml |
PRs | AI code review | ~2 min |
canary-monitoring.yml |
Scheduled/manual | Production canary checks | ~2 min |
publish-pypi.yml |
Manual | PyPI publish | ~2 min |
release-dryrun.yml |
Manual | Validate release artifacts | ~3 min |
| Tier | Location | Count | Runner | Notes |
|---|---|---|---|---|
| Unit | tests/unit/ |
~3,618 | make test-unit |
Fast, mocked, all CI runs |
| Integration | tests/integration/ |
~102 | make test-integration |
Full pipeline, ScriptedAgentProvider |
| Web API | tests/web/ |
~418 | make test-web |
FastAPI TestClient |
| Eval | tests/eval/ |
~238 | make scorecard |
Intent classification scorecard |
| Live API | tests/live/ |
~42 | CI (main only) | Real Gemini via WIF |
| E2E | tests/e2e/ |
~33 | make test-e2e |
End-to-end with real DXF files |
| Benchmark | tests/benchmark/ |
~19 | CI (main only) | pytest-benchmark, JSON artifacts |
| GUI | tests/gui/ |
~10 | Manual | Requires QT_QPA_PLATFORM=offscreen |
| Property | tests/property/ |
~7 | CI | Randomized, bounded runtime |
| Smoke | tests/smoke/ |
~7 | make smoke |
End-to-end mock pipeline |
| Total | ~4,494 |
| Term | Meaning |
|---|---|
| DrawingContext | Normalized Pydantic model of a loaded DXF (entities, layers, blocks, metadata) |
| EntityRef | Single DXF entity reference (handle, type, layer, position, text, block) |
| ChangeSet | Batch of EditOperations from a single user prompt |
| OpType | Edit operation type enum (13 values: move, edit_text, delete, add_block, rotate, copy, scale, mirror, add_line, add_polyline, add_circle, add_arc, add_text) |
| RequestClass | Classification axis 1 — what: edit, analyze, compare, query, generate |
| ObjectiveTag | Classification axis 2 — why: compliance, coordination, documentation, estimation, quality, general |
| StagePipelineDefinition | Ordered list of StageHandlers selected by StrategyRegistry for a (RequestClass, ObjectiveTag) pair |
| PlatformResponse | Response envelope with TaskFamily, ResponseType, RiskLevel, AuditMetadata |
| AgentProvider | Iterative tool-use loop (max 10 turns) for complex multi-step requests |
| ToolExecutor | Dispatches 20+ query and edit tools with protected-layer enforcement |
| Protected layer | Layer that cannot be edited (TITLE, TITLEBLOCK, SEAL, REVISION) |
| TaskFamily | Intent category (QNA, EDIT_PLAN, COMPARE, SUMMARY, COMPLIANCE, HEALTH, TAKEOFF, RFI, etc.) |
| WIF | Workload Identity Federation — GCP's secretless auth for CI/CD |
| ADC | Application Default Credentials — local GCP auth via gcloud auth application-default login |
| ODA | Open Design Alliance File Converter — DWG → DXF conversion tool |
| Save-as | Architectural invariant: original files are never modified; edits produce new files |
Tests fail with ModuleNotFoundError: No module named 'ezdxf':
System pytest doesn't have project deps. Use .venv/bin/python -m pytest -v instead of bare pytest.
Cloud Run deploy fails:
- Check
gh run list --workflow=deploy-web.ymlfor the failing step - Verify WIF vars are set:
gh variable list(should showWIF_PROVIDER,WIF_SERVICE_ACCOUNT,GCP_PROJECT_ID) - Check Artifact Registry permissions: the WIF service account needs
roles/artifactregistry.writer
ODA .deb download fails in CI:
- Check GCS bucket:
gsutil ls gs://cad-dxf-agent-deps/oda/ - If missing, DWG support is unavailable but DXF/PDF uploads work fine
- Size validation catches corrupt downloads (<1MB = skip install)
User login fails:
- Check Firebase Auth console for the user's email
- Verify
CAD_ALLOWED_EMAILSenv var or Firestoreallowlistcollection includes the email - Check Cloud Run logs for auth validation errors
Document persistence fails:
- Check GCS bucket access:
gsutil ls gs://cad-dxf-agent-documents/ - Verify Cloud Run SA has
roles/storage.objectAdminon the bucket - Check Firestore for tenant/user records