Project-level guidance for AI coding assistants (Cortex Code, Cursor, Copilot, etc.) working in this repository.
Cortex Code skills that deploy routing, fleet intelligence, and geospatial analytics on Snowflake — powered by the OpenRouteService (ORS) App on Snowpark Container Services (SPCS).
Skills live in .cortex/skills/. Each is a self-contained deployment playbook an AI agent follows step-by-step.
.cortex/skills/ # All Cortex Code skills
├── <skill-name>/
│ ├── SKILL.md # Skill definition (frontmatter + instructions)
│ ├── references/ # Detailed SQL, code, docs (loaded on demand)
│ └── assets/ # Notebooks and other deployable artifacts
├── evals/ # Eval framework (trigger, quality, xref)
build-routing-solution/ # ORS app build artifacts (Dockerfiles, configs)
docs/ # Documentation (dev/ and guides/)
archive/ # Archived materials
# Run skill evals (trigger accuracy, quality checks, cross-ref validation)
python3 .cortex/skills/evals/run_evals.py
# Audit a single skill interactively
# Invoke the skill-optimiser skill in Cortex Code: "audit skill <name>"
# Validate ORS services are running
snow sql -q "SHOW SERVICES IN DATABASE OPENROUTESERVICE_APP;"No global build/lint step — each skill is independently deployable via its own SKILL.md workflow.
| Skill | Category | Purpose |
|---|---|---|
build-routing-solution |
infrastructure | Builds and deploys the ORS app on SPCS |
routing-prerequisites |
infrastructure | Checks local build prerequisites (Docker, Snow CLI) |
routing-customization |
configuration | Router with 3 subskills for ORS config changes |
route-optimization |
demo | VRP demo with Marketplace data + notebook |
fleet-intelligence-taxis |
fleet-intelligence | Taxi GPS telemetry generation + React dashboard |
fleet-intelligence-food-delivery |
fleet-intelligence | Food delivery courier telemetry + React app |
retail-catchment |
demo | Retail location analysis with isochrone catchment zones |
route-deviation |
demo | Detour detection ETL pipeline + React dashboard |
dwell-analysis |
demo | 12-step Dynamic Table pipeline for dwell/congestion |
routing-agent |
advanced | Snowflake Intelligence agent wrapping ORS functions |
skill-optimiser |
developer-tools | Audits and optimizes skills per Anthropic best practices |
routing-solution-cleanup |
developer-tools | Discovers and removes skill-created Snowflake objects via COMMENT tag |
backload-matching |
demo | DHL Freight backload VRP demo: solves trailer<->load assignment via OPENROUTESERVICE_APP.CORE.OPTIMIZATION, with internal-first priority and Cortex rationale |
For the full rule set, read .cortex/skills/skill-optimiser/SKILL.md and its references/ directory. That skill encodes all conventions from "The Complete Guide to Building Skills for Claude" (Anthropic, Jan 2026).
Key rules:
- Folder name: kebab-case, must match
namein YAML frontmatter - Main file: exactly
SKILL.md(case-sensitive). NoREADME.mdinside skill folders. - Description: under 1024 chars, formula:
[What] + [When] + [Triggers] + [Do NOT use for] - Body: under 5,000 words. Move detailed content to
references/ - No XML angle brackets in frontmatter. No "claude" or "anthropic" in skill names.
- Cross-skill references use full relative paths from repo root:
> Read and follow `.cortex/skills/routing-customization/SKILL.md` - Subskills nest as child folders; parent SKILL.md acts as a router
- All skills use
metadata.author: Snowflake SIT-ISandmetadata.version: 1.0.0 - Deployment skills must include
depends_onin frontmatter listing prerequisite skills - Deployment skills must include a
## Configurationtable with parameterized defaults - Deployment skills must include a
## Required Privilegestable (no ACCOUNTADMIN assumptions) - Deployment skills must include a
## Cleanupsection with DROP statements
When any step fails or produces unexpected results (SQL errors, missing objects, wrong row counts, service failures, deployment issues), log the issue to logs/ following the format in logs/README.md. Create one log file per execution: <skill-name>_{YYYY-MM-DD}_{HH-MM}.md. Continue execution where possible, logging all issues encountered. If execution completes with no issues, do not create a log file.
MANDATORY: After each logical change is completed and verified, create a new git commit on the user's single shared branch AND push it immediately. Do not batch unrelated changes into a single commit, and do not leave commits unpushed at the end of a turn.
- NEVER commit directly to
main.mainis protected — changes only land via merged PRs fromdev. - NEVER commit directly to
dev.devis the integration branch — changes only land via merged PRs from per-user branches. - All work happens on ONE per-user long-lived branch named
feat/<GITHUB_LOGIN>-feat. The GitHub login MUST be detected dynamically at the start of every session — never hardcoded.Example: for loginGITHUB_LOGIN=$(gh api user --jq .login) USER_BRANCH="feat/${GITHUB_LOGIN}-feat"
sfc-gh-preszkethe branch isfeat/sfc-gh-preszke-feat. This single branch is shared by all parallel Cortex Code chats on the user's machine, so no branch switching is ever needed mid-session. - Do NOT create additional branches. No
<username>/work, no<username>/<topic>, nofeat/*/fix/*/docs/*per-change branches. One user, one branch. Multiple parallel chats sharing one working tree cannot each own their own branch — that causes constantgit checkoutthrashing and lost work. Commit straight onto the user's branch instead. - All PRs target
dev(notmain). Only release/promotion PRs go fromdev→main, and those are opened by humans, not assistants. - Before starting work, detect the user branch and verify you are on it:
If
GITHUB_LOGIN=$(gh api user --jq .login) USER_BRANCH="feat/${GITHUB_LOGIN}-feat" CURRENT=$(git branch --show-current) if [ "$CURRENT" != "$USER_BRANCH" ]; then git checkout "$USER_BRANCH" 2>/dev/null || git checkout -b "$USER_BRANCH" fi
ghis not authenticated, stop and ask the user to rungh auth login— never fall back to a hardcoded branch name. - After EVERY commit, push the branch immediately. Do not leave local commits unpushed:
git push -u origin "$USER_BRANCH" - Open / update a single PR into
devfor the branch when there is reviewable work:gh pr create --base dev --head "$USER_BRANCH" --title "..." --body "..."
- A PR may include several commits from the branch. Keep PRs scoped to one logical theme — open a new PR rather than piling unrelated commits into one.
- One commit per logical change (one skill edit, one bug fix, one doc update, one refactor)
- Commits land on
$USER_BRANCH(i.e.feat/<GITHUB_LOGIN>-feat). Never on a fresh per-change branch. - After every commit, run
git push origin "$USER_BRANCH"immediately. A change is not "done" until it is pushed to remote.- CRITICAL: Plain
git pushwill fail with SSH permission denied. Before your first push in a session, ALWAYS read/memories/git-push-method.mdfor the working command (usesgh auth token+GIT_CONFIG_GLOBAL=/dev/nullto bypass the global SSHinsteadOfrule). Do NOT attemptgit push origin <branch>directly — it always fails for this repo.
- CRITICAL: Plain
- Verify the change works (SQL compiles, skill evals pass, notebook runs) BEFORE committing
- Stage only files related to the current change — never use blanket
git add .if unrelated edits exist - Commit message format:
<type>(<scope>): <subject>where type is one offeat,fix,docs,refactor,chore,test- Examples:
feat(fleet-intelligence-taxis): add H3 resolution config parameterfix(build-routing-solution): handle ARM Mac esbuild segfaultdocs(AGENTS.md): add commit discipline rule
- Examples:
- If a change spans multiple skills, prefer multiple smaller commits over one large one
- Never amend or force-push commits the user has not explicitly authorized
- Never push directly to
mainordev— push only to$USER_BRANCH(feat/<GITHUB_LOGIN>-feat)
MANDATORY: After every build-routing-solution execution (regardless of success or failure), generate a friction log in logs/. This is NOT optional — every run produces a friction log, even if everything went smoothly.
File name: friction-log_{YYYY-MM-DD}_{HH-MM}.md
Follow the friction log template in logs/README.md. The log must capture:
- Exact wall-clock duration of each step
- Any friction points (confusing instructions, slow operations, unexpected behavior)
- For each friction point: what was done to resolve it during this run, and a recommendation for how to prevent it in future runs (e.g., skill wording change, new validation step, default change)
- A step-by-step status table showing OK/FAILED/SKIPPED for each workflow step
- Final summary with total execution time and overall outcome
If no friction was encountered, the log should still be created with "No friction points" and the step timing table.
- Create folder:
.cortex/skills/my-new-skill/ - Create
SKILL.mdwith YAML frontmatter + body (useskill-optimiserfor the template) - Add
references/for detailed SQL/code if body would exceed 5,000 words - Add
assets/for notebooks or other deployable artifacts - Audit: invoke
skill-optimiseror runpython3 .cortex/skills/evals/run_evals.py - Update the Skills Inventory table above
- Inline large SQL blocks in SKILL.md — put them in
references/*.mdand link - Skip the query tag — every skill must set the session query tag for attribution tracking:
ALTER SESSION SET query_tag = '{"origin":"sf_sit-is-fleet","name":"oss-<skill-name>","version":{"major":1,"minor":0},"attributes":{"is_quickstart":1,"source":"sql"}}';
- Skip the object COMMENT — every CREATE statement must include a COMMENT tracking tag (or
ALTER ... SET COMMENTfor CTAS):COMMENT = '{"origin":"sf_sit-is-fleet","name":"oss-<skill-name>","version":{"major":1,"minor":0},"attributes":{"is_quickstart":1,"source":"<sql|notebook|app>"}}';
- Assume ORS is running — always verify with
SHOW SERVICES IN DATABASE OPENROUTESERVICE_APP;(all 5 services must be RUNNING) - Hardcode city/region — skills must be configurable via parameters, not baked-in coordinates
- Add README.md inside skill folders — all docs go in SKILL.md or
references/ - Duplicate conventions — point to
skill-optimiserreferences instead of repeating rules - Require ACCOUNTADMIN — document minimum privileges in
## Required Privileges; never assume ACCOUNTADMIN - Skip cleanup instructions — every deployment skill must have a
## Cleanupsection with DROP statements - Skip committing AND pushing after a completed change — every verified change must result in a commit AND a push to
feat/<GITHUB_LOGIN>-featbefore the turn ends (see## Commit Discipline) - Commit directly to
mainordev— both are protected. All work goes onfeat/<GITHUB_LOGIN>-featwith PRs targetingdev. Only humans promotedev→main. - Hardcode the user branch name — always derive it from
gh api user --jq .loginat session start. Do not paste a literal branch likefeat/sfc-gh-preszke-featinto AGENTS.md, skill files, or scripts. - Create a new branch per change or per topic — there is exactly one branch per user (
feat/<GITHUB_LOGIN>-feat). No<username>/work, no<username>/<topic>, nofeat/*/fix/*/docs/*per-change branches. Multiple Cortex Code chats running in parallel against the same working tree must all commit to the same branch. - Create any Snowflake object or run any query without tracking tags — this is a hard requirement with no exceptions. Every new Snowflake object (TABLE, VIEW, PROCEDURE, FUNCTION, STAGE, SCHEMA, DATABASE, WAREHOUSE, TASK, DYNAMIC TABLE, STREAMLIT, SERVICE, AGENT) MUST have a COMMENT tracking tag. Every SQL session MUST set
query_tagbefore executing statements. This applies to all skills, notebooks, stored procedures, dynamic SQL inside procedure bodies, ORS control app server code, and any other code path that creates objects or runs queries. For objects created via CTAS or dynamic SQL, useALTER ... SET COMMENTimmediately after creation. For service functions (SERVICE=...clause) that do not support COMMENT, document the limitation and ensure the parent procedure has a COMMENT tag.
When changing any source file (src/, server/, or config), rebuild and push the Docker image.
The multi-stage Dockerfile.runtime compiles both the React frontend and the server automatically —
no manual dist/ or dist-server/ edits are needed.
IMPORTANT: Always use Dockerfile.runtime (multi-stage build). Never create a "prebuilt" Dockerfile that copies dist/ from the host — this conflicts with .dockerignore and creates fragile host-build dependencies. The .dockerignore intentionally excludes dist and dist-server because the multi-stage build generates them inside the container. Do not remove those exclusions.
ARM Mac + Podman: If esbuild crashes with a QEMU segfault during the build stage, build locally first (npm run build && npx tsc -p tsconfig.server.json), then use --ignorefile .dockerignore.prebuilt when building the image. See references/troubleshooting.md for full instructions. Do NOT rename or edit .dockerignore.
APP_DIR=.cortex/skills/build-routing-solution/openrouteservice_app/services/ors_control_app
snow spcs image-registry login -c <connection>
REPO_URL=$(snow spcs image-repository url OPENROUTESERVICE_APP.core.image_repository -c <connection>)
# 1. Edit source files only:
# - src/components/... (React frontend)
# - server/index.ts (Express backend)
# 2. Build (bump version from current):
docker build --platform linux/amd64 \
-f $APP_DIR/Dockerfile.runtime \
-t $REPO_URL/openrouteservice_app/core/image_repository/ors_control_app:vX.Y.Z \
$APP_DIR
# 3. Push:
docker push $REPO_URL/openrouteservice_app/core/image_repository/ors_control_app:vX.Y.Z
# 3b. If `docker push` hangs (single layer stuck at "Waiting" forever):
# This is a known SPCS registry token-refresh bug — the bearer token
# issued by `snow spcs image-registry login` expires mid-PUT and the
# registry rejects the upload with 401. Docker daemon retries auth
# silently → re-queues the blob → the layer "Waits" indefinitely.
# Symptoms: 8 of 9 layers report "Layer already exists", 1 sits on
# "Waiting". Podman shows the explicit error
# "unable to retrieve auth token: invalid username/password".
#
# Workaround: use `crane` (from go-containerregistry), which handles
# registry token refresh correctly:
brew install crane
snow spcs image-registry login -c <connection> # refreshes ~/.docker/config.json + keychain
docker save $REPO_URL/openrouteservice_app/core/image_repository/ors_control_app:vX.Y.Z -o /tmp/img.tar
crane push /tmp/img.tar $REPO_URL/openrouteservice_app/core/image_repository/ors_control_app:vX.Y.Z
# Expected output: `pushed blob: sha256:<hash>` followed by
# `<image>:<tag>: digest: sha256:... size: 1729`. Total ~5 minutes
# for a typical 139 MB image with one new layer.
#
# `docker save | podman load | podman push` does NOT help here —
# both daemons hit the same registry-side bug. Restarting Docker
# Desktop and re-logging in does not help either. Only crane works.
# 4. Update version:
# - $APP_DIR/ors_control_app_service.yaml (image tag)
# 5. Upload updated spec to stage:
snow stage copy $APP_DIR/ors_control_app_service.yaml \
@OPENROUTESERVICE_APP.CORE.ORS_SPCS_STAGE/services/ors_control_app/ \
-c <connection> --overwrite
# 6. Apply new spec and restart:
# IMPORTANT: ALTER SERVICE while RUNNING does not reliably cycle the container.
# Always use the suspend → update spec → resume pattern to guarantee the new image loads.
```sql
ALTER SERVICE OPENROUTESERVICE_APP.CORE.ORS_CONTROL_APP SUSPEND;
ALTER SERVICE OPENROUTESERVICE_APP.CORE.ORS_CONTROL_APP
FROM @OPENROUTESERVICE_APP.CORE.ORS_SPCS_STAGE/services/ors_control_app/
SPECIFICATION_FILE = 'ors_control_app_service.yaml';
-- The service does NOT auto-resume after a spec update. Always resume manually:
ALTER SERVICE OPENROUTESERVICE_APP.CORE.ORS_CONTROL_APP RESUME;SHOW ENDPOINTS IN SERVICE OPENROUTESERVICE_APP.CORE.ORS_CONTROL_APP;
SELECT 'https://' || ingress_url AS control_app_url
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
WHERE name = 'ors-control-app';graph TD
RP[routing-prerequisites] --> BRS[build-routing-solution]
BRS --> RC[routing-customization]
BRS --> RO[route-optimization]
BRS --> FIT[fleet-intelligence-taxis]
BRS --> FIFD[fleet-intelligence-food-delivery]
BRS --> RET[retail-catchment]
BRS --> RD[route-deviation]
BRS --> RA[routing-agent]
RO --> BM[backload-matching]
BRS --> BM
RC --> FIT
RC --> FIFD
RC --> RD
RD --> DA[dwell-analysis]
style BRS fill:#f96,stroke:#333
style RP fill:#9cf,stroke:#333
style RC fill:#9cf,stroke:#333
Legend: Orange = core infrastructure. Blue = configuration/prerequisites. White = demo/feature skills.
Deploy order (top → bottom). Teardown order (bottom → top).
- ORS dependency: most demo skills require 4 running ORS services. Use
routing-prerequisitesto verify. - Overture Maps POI data: fleet skills use Overture Maps for realistic locations. Fallback: synthetic points within configured bounding boxes.
- ORS Control App deployment: Edit source →
docker build(multi-stage, no manual dist/ step) →docker push→ update YAML version →snow stage copyspec to stage →ALTER SERVICE FROM @stage SPECIFICATION_FILE=.... - Object tracking: Two tracking mechanisms — session
query_tag(tracks queries) and objectCOMMENT(tracks created objects). Both are required. For CTAS (CREATE TABLE ... AS SELECT), useALTER TABLE ... SET COMMENTafter creation since CTAS doesn't support inline COMMENT. - REBUILD_GRAPHS management (Issue #59): Routing graphs are persisted on
@ORS_GRAPHS_SPCS_STAGE/<region>/and MUST be reused across suspend/resume cycles. Thecreate_region_ors_serviceproc probes the stage and setsREBUILD_GRAPHS="false"if graphs already exist. After first-time provisioning completes (service_ready=true),PROVISION_REGION_WRAPPERauto-callsSET_REBUILD_GRAPHS_FLAG(region, 'false')so the next resume is instant (~1–2 min). For forced rebuilds (PBF update / corruption), callREBUILD_REGION_GRAPHS(region). - Per-region VROOM (multi-region OPTIMIZATION): Each provisioned region gets its own
VROOM_SERVICE_<REGION>co-located inORS_POOL_<REGION>(same compute pool as the region's ORS). The VROOM image (vroom-docker:v1.0.4) readsORS_HOSTfrom env and substitutes it into/conf/config.ymlat startup, so the same image serves any region without rebuild.BUILD_VROOM_SERVICE_SPEC(region)+create_region_vroom_service(region)mirror the ORS pattern;PROVISION_REGION_WRAPPERcallscreate_region_vroom_serviceafter the ORS service is up. The routing gateway'sresolve_vroom_host(region)returnsvroom-service-<region>and routes/optimizationthere, so VROOM's internal ORS calls land on the right regional graph. To add a new region, no code change is needed — the existing provisioning flow auto-deploys the per-region VROOM. Drop withdrop_region_vroom(region)(also called bydrop_region_ors). v1.1.0 unification: there is NO globalORS_SERVICE/VROOM_SERVICEanymore — even the default region (SanFrancisco) is served byORS_SERVICE_SANFRANCISCO+VROOM_SERVICE_SANFRANCISCOinORS_POOL_SANFRANCISCO. The gateway resolves a missing/NULLregionto the env varDEFAULT_REGION_NAME(default:SanFrancisco) so callers may still omit the argument; both omitted and explicit-region paths land on the same per-region service. Passingregionis recommended in all multi-region payloads to be self-documenting and to avoid relying on the DEFAULT_REGION_NAME setting. The_OPTIMIZATION_TABULAR_RAW(jobs, vehicles, matrices, region)form requires region as the 4th arg (do not passNULL). VROOM'sconfig.ymlbody-parser limit is set to50mbto fit pre-computed matrices for VRPs up to ~1000 locations. - AUTO_SUSPEND_SECS invariant (per-stage contract): Only services strictly involved in the active build are pinned at
AUTO_SUSPEND_SECS=0. Every other service stays at the steady-state default. Active build = a row inREGION_PROVISION_JOBSwithSTATUS IN ('PENDING','RUNNING')at a specificSTAGE, OR a row inMATRIX_BUILD_JOBSwithSTATUS IN ('PENDING','RUNNING')andSTAGE NOT IN ('COMPLETE','ERROR'). The contract:STAGE = 'DOWNLOADING'→ pinDOWNLOADER,ORS_SERVICE_<REGION>, andORS_POOL_<REGION>to 0.STAGE IN ('CONFIGURING','STARTING_SERVICE','WAITING_FOR_SERVICE','BUILDING_GRAPH')→ pinORS_SERVICE_<REGION>andORS_POOL_<REGION>to 0;DOWNLOADERreturns to 14400 (the PBF is already on stage).- Matrix job
STATUS IN ('PENDING','RUNNING')→ pinrouting_gateway_service,ORS_SERVICE_<REGION>,VROOM_SERVICE_<REGION>, andORS_POOL_<REGION>to 0. - All other times → services =
14400(4h), per-region pools =3600(1h).OPENROUTERSERVICE_APP_COMPUTE_POOLis unrelated to this invariant (its default is600). ors_control_apphas public endpoints and therefore noAUTO_SUSPEND_SECS— it is excluded.- Every procedure that flips a value to
0is responsible for restoring its default on ALL exits (happy path, timeout, early return, exception). - The idempotent safety net
OPENROUTESERVICE_APP.CORE.RECONCILE_AUTO_SUSPEND()is the single source of truth and now reconcilesrouting_gateway_service,ORS_SERVICE_%,VROOM_SERVICE_%,DOWNLOADER, andORS_POOL_%. Auto-called bySUSPEND_ALL_SERVICESandSUSPEND_SERVICE; safe to call at any time.
- v1.1.4 default-sentinel retirement: The legacy
region:'default'sentinel returned by/api/regions/provisionedwas retired.LIST_REGIONS()now returns SanFrancisco as a regular row inREGION_ORS_MAP(with newIS_DEFAULT BOOLEANcolumn, seededTRUEfor the canonical default). The control-app server no longer synthesizes aregion:'default'entry, no longer makes 0-argORS_STATUS()calls, and no longer special-cases'default'in studio job pool scaling, ors-readiness, or stage probing. TheisDefaultboolean is preserved as a pure UI hint (dropdown auto-selection + "(Default)" badge) but is decoupled from SQL routing. Inbound API requests passing'default'or empty region are still resolved at the gateway boundary vianormalizeRegion()->DEFAULT_REGION_NAME, but internal contracts assume real region keys.
- Store point locations as
GEOGRAPHYcolumns (not separate FLOAT lat/lon). - Construct via
ST_MAKEPOINT(longitude, latitude)— note: longitude first. - Line/polygon geometries: use
TO_GEOGRAPHY('LINESTRING(lon lat, ...)')orST_MAKELINE. - Keep redundant FLOAT lat/lon only when required (CLUSTER BY, ORS ARRAY_CONSTRUCT API args, bounding-box configs).
| Instead of | Use |
|---|---|
H3_LATLNG_TO_CELL(lat, lon, res) |
H3_POINT_TO_CELL_STRING(geography, res) |
HAVERSINE(lat1, lon1, lat2, lon2) (returns km) |
ST_DISTANCE(geog_a, geog_b) / 1000 (meters→km) |
ST_DISTANCE + filter |
ST_DWITHIN(geog_a, geog_b, meters) (uses spatial index) |
| Separate FLOAT lat/lon in WHERE | ST_WITHIN, ST_INTERSECTS, ST_CONTAINS |
- Always store H3 indices as
VARCHAR(string format, e.g.'8928308280fffff'). - Use
H3_POINT_TO_CELL_STRING(returns VARCHAR directly) — notH3_LATLNG_TO_CELLwhich returns NUMBER. - Never cast H3 between NUMBER and STRING at query time — store as string from the start.
- COPY INTO with transform: use
ST_MAKEPOINT($col_lon, $col_lat)orTO_GEOGRAPHY($col_wkb)in the SELECT. - INSERT via SELECT…UNION ALL: compute
ST_MAKEPOINT(lon, lat)inline (VALUES clauses cannot contain function calls). MATCH_BY_COLUMN_NAMEcannot be used when adding computed columns — switch to explicit transform SELECT.
All tables are created with GEOGRAPHY columns from the start. Reference them directly:
t.POINT_GEOM -- telemetry point
t.ORIGIN -- trip origin
t.DESTINATION -- trip destination| Layer | Data format | Extraction |
|---|---|---|
ScatterplotLayer |
[lng, lat] array |
ST_X(geog) / ST_Y(geog) in SQL |
H3HexagonLayer |
H3 string index | H3_POINT_TO_CELL_STRING(geog, res) in SQL |
GeoJsonLayer |
GeoJSON string | ST_ASGEOJSON(geog)::STRING in SQL |
PathLayer |
coordinate array | ST_ASGEOJSON(geog) → parse coords client-side |
- ORS function arguments (
ARRAY_CONSTRUCTof numeric coords for DIRECTIONS/MATRIX) - Bounding-box configs (REGION_REGISTRY, city provisioner)
CLUSTER BYexpressions (GEOGRAPHY not supported in CLUSTER BY)- Direct deck.gl
getPositioncallbacks expecting[Number, Number]
docs/guides/QUICKSTART.md— End-to-end deployment quickstartdocs/dev/server-architecture.md— One-page map ofors_control_appserver modules (server/{lib,routes,studio}/) and decision tree for "where do I add X?"docs/README.md— Full index