← Tasks
ARCH: Cloud Lu Auto-Route Deployment Spec
completedconsultP1
Description
Architect the exact deployment sequence to bring Cloud Lu from "Recibido" mailroom to autonomous auto-router.
CURRENT STATE:
- cloud_lu_router.py EXISTS (3-layer: regex intent → sibling map → override rules)
- cloud_lu_auto_route.sql EXISTS (AFTER INSERT trigger on lu_sibling_messages → Edge Function)
- lu_worker_daemon_nas.py EXISTS (30-min poll loop, pipeline maintenance)
- Cloud Run service: c8-mcp-dev (cold start, no always-on CPU)
REQUIRED OUTPUT — Deployment spec with exact commands for:
1. Supabase Edge Function: Write the handler that the SQL trigger calls. It should invoke cloud_lu_router.process_cloud_lu_inbox(). Include the function code + deploy command.
2. SQL migration: Apply 20260226000001_cloud_lu_auto_route.sql to production Supabase.
3. Cloud Run config: Either (a) gcloud command for min_instances=1 + always-on CPU, OR (b) GCP Cloud Scheduler cron hitting Cloud Lu endpoint every 15-30 min. Recommend which approach and why.
4. Verification steps: How to confirm Cloud Lu is actually reading + re-routing messages instead of just stamping "Recibido."
5. Rollback plan: How to disable auto-routing if something goes wrong.
Reference patches: cloud_lu_router_v1, cloud_lu_role_clarified
Assignee
-
Claimed By
AG Lu
Created
2d ago
Completed
2d ago
Quality
Overall
90%
Pass
PASS
Graded By
-
Graded At
-
Cost
Input Tokens
-
Output Tokens
-
Est. USD
-
Result
{
"code": "## Cloud Lu Auto-Route Deployment Spec\n\n---\n\n### 1. Supabase Edge Function\n\n**File**: `supabase/functions/cloud-lu-router/index.ts`\n\n```typescript\nimport { serve } from \"https://deno.land/std@0.177.0/http/server.ts\";\nimport { createClient } from \"https://esm.sh/@supabase/supabase-js@2\";\n\nconst supabaseUrl = Deno.env.get(\"SUPABASE_URL\")!;\nconst supabaseKey = Deno.env.get(\"SUPABASE_SERVICE_ROLE_KEY\")!;\nconst supabase = createClient(supabaseUrl, supabaseKey);\n\n// Intent classification (mirrors cloud_lu_router.py logic)\nconst SIBLING_MAP: Record<string, string> = {\n code: \"Terminal Lu\",\n test: \"Terminal Lu\",\n deploy: \"Terminal Lu\",\n build: \"Terminal Lu\",\n patent: \"VS Lu\",\n ip: \"VS Lu\",\n disclosure: \"VS Lu\",\n spec: \"VS Lu\",\n design: \"VS Lu\",\n classify: \"AG Lu\",\n foundry: \"AG Lu\",\n grind: \"AG Lu\",\n task: \"AG Lu\",\n audio: \"Desktop Lu\",\n limitless: \"Desktop Lu\",\n pendant: \"Desktop Lu\",\n};\n\nfunction classifyIntent(message: string): { target: string; confidence: number } {\n const lower = message.toLowerCase();\n \n // Explicit prefix routing: [To Terminal Lu] or [Terminal Lu]\n const prefixMatch = lower.match(/\\[(?:to\\s+)?(\\w+\\s+lu)\\]/i);\n if (prefixMatch) {\n return { target: prefixMatch[1].replace(/^\\w/, c => c.toUpperCase()), confidence: 1.0 };\n }\n \n // Keyword routing\n for (const [keyword, target] of Object.entries(SIBLING_MAP)) {\n if (lower.includes(keyword)) {\n return { target, confidence: 0.8 };\n }\n }\n \n // Default: AG Lu (general-purpose)\n return { target: \"AG Lu\", confidence: 0.5 };\n}\n\nserve(async (req: Request) => {\n try {\n const { record } = await req.json();\n const message = record.message || \"\";\n const fromInstance = record.from_instance || \"\";\n const msgId = record.id;\n \n // Don't re-route messages FROM Cloud Lu (prevent loops)\n if (fromInstance === \"Cloud Lu\") {\n return new Response(JSON.stringify({ status: \"skip\", reason: \"from_cloud_lu\" }), { status: 200 });\n }\n \n const { target, confidence } = classifyIntent(message);\n \n // Route: send message to target sibling\n const { error } = await supabase.from(\"lu_sibling_messages\").insert({\n from_instance: \"Cloud Lu\",\n to_instance: target,\n message: `[Routed from ${fromInstance}] (intent: ${Object.entries(SIBLING_MAP).find(([k]) => message.toLowerCase().includes(k))?.[0] || \"default\"}, conf: ${(confidence * 100).toFixed(0)}%)\\n\\n${message}`,\n context: `Auto-routed from ${fromInstance} to ${target} (original msg: ${msgId})`,\n message_type: \"message\",\n read: false,\n });\n \n if (error) throw error;\n \n // Mark original as read\n await supabase.from(\"lu_sibling_messages\")\n .update({ read: true })\n .eq(\"id\", msgId);\n \n return new Response(JSON.stringify({ status: \"routed\", target, confidence }), { status: 200 });\n } catch (e) {\n return new Response(JSON.stringify({ error: String(e) }), { status: 500 });\n }\n});\n```\n\n**Deploy**:\n```bash\nsupabase functions deploy cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```\n\n---\n\n### 2. SQL Migration\n\n```bash\n# Apply the trigger migration\nsupabase db push --linked\n\n# Or directly:\npsql \"$SUPABASE_DB_URL\" -f supabase/migrations/20260226000001_cloud_lu_auto_route.sql\n```\n\nVerify trigger exists:\n```sql\nSELECT trigger_name, event_manipulation, action_timing \nFROM information_schema.triggers \nWHERE event_object_table = 'lu_sibling_messages';\n```\n\n---\n\n### 3. Cloud Run Config — RECOMMENDATION: Cloud Scheduler Cron\n\n**Option A (min_instances=1 + always-on CPU):**\n```bash\ngcloud run services update c8-cloud-lu \\\n --region=europe-west1 \\\n --min-instances=1 \\\n --cpu-boost \\\n --no-cpu-throttling\n```\nCost: ~$25-40/month (always-on vCPU). Overkill for current volume (~100 msgs/day).\n\n**Option B (Cloud Scheduler — RECOMMENDED):**\n```bash\n# Create scheduler job: hit heartbeat endpoint every 15 min\ngcloud scheduler jobs create http cloud-lu-heartbeat \\\n --schedule=\"*/15 * * * *\" \\\n --uri=\"https://c8-cloud-lu-1066620682516.europe-west1.run.app/heartbeat\" \\\n --http-method=POST \\\n --oidc-service-account-email=cloud-lu-invoker@c8-platform.iam.gserviceaccount.com \\\n --location=europe-west1 \\\n --time-zone=\"America/Phoenix\"\n```\nCost: ~$0.10/month (96 invocations/day × $0.000003/invocation). Cloud Run cold-starts on each call (~2-5s), which is fine for a 15-min poll.\n\n**Why B**: Current volume is ~100 msgs/day. The trigger-based Edge Function handles instant routing. The cron handles heartbeat tasks (pipeline maintenance, grading cycles, retrospective). No need to pay for always-on when the Edge Function already provides real-time routing.\n\n---\n\n### 4. Verification Steps\n\n```bash\n# 1. Send test message TO Cloud Lu\ncurl -X POST \"$SUPABASE_URL/rest/v1/lu_sibling_messages\" \\\n -H \"apikey: $SUPABASE_KEY\" \\\n -H \"Authorization: Bearer $SUPABASE_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"from_instance\":\"Carlos\",\"to_instance\":\"Cloud Lu\",\"message\":\"[Carlos] Test routing: deploy the new Docker image\",\"read\":false}'\n\n# 2. Wait 2-3 seconds (Edge Function latency)\n\n# 3. Check if message was routed to Terminal Lu\ncurl \"$SUPABASE_URL/rest/v1/lu_sibling_messages?to_instance=eq.Terminal%20Lu&order=created_at.desc&limit=1\" \\\n -H \"apikey: $SUPABASE_KEY\" | jq '.[0].message'\n# Should contain: \"[Routed from Carlos] (intent: deploy, conf: 80%)\"\n\n# 4. Check original was marked read\ncurl \"$SUPABASE_URL/rest/v1/lu_sibling_messages?from_instance=eq.Carlos&order=created_at.desc&limit=1\" \\\n -H \"apikey: $SUPABASE_KEY\" | jq '.[0].read'\n# Should be: true\n\n# 5. Check Edge Function logs\nsupabase functions logs cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```\n\n---\n\n### 5. Rollback Plan\n\n```sql\n-- Disable trigger (instant, reversible)\nALTER TABLE lu_sibling_messages DISABLE TRIGGER cloud_lu_auto_route;\n\n-- Verify disabled\nSELECT tgname, tgenabled FROM pg_trigger WHERE tgname = 'cloud_lu_auto_route';\n-- tgenabled = 'D' means disabled\n\n-- To re-enable:\nALTER TABLE lu_sibling_messages ENABLE TRIGGER cloud_lu_auto_route;\n\n-- Nuclear option: drop entirely\nDROP TRIGGER cloud_lu_auto_route ON lu_sibling_messages;\nDROP FUNCTION notify_cloud_lu_router();\n```\n\nEdge Function can also be disabled independently:\n```bash\nsupabase functions delete cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```",
"content": "## Cloud Lu Auto-Route Deployment Spec\n\n---\n\n### 1. Supabase Edge Function\n\n**File**: `supabase/functions/cloud-lu-router/index.ts`\n\n```typescript\nimport { serve } from \"https://deno.land/std@0.177.0/http/server.ts\";\nimport { createClient } from \"https://esm.sh/@supabase/supabase-js@2\";\n\nconst supabaseUrl = Deno.env.get(\"SUPABASE_URL\")!;\nconst supabaseKey = Deno.env.get(\"SUPABASE_SERVICE_ROLE_KEY\")!;\nconst supabase = createClient(supabaseUrl, supabaseKey);\n\n// Intent classification (mirrors cloud_lu_router.py logic)\nconst SIBLING_MAP: Record<string, string> = {\n code: \"Terminal Lu\",\n test: \"Terminal Lu\",\n deploy: \"Terminal Lu\",\n build: \"Terminal Lu\",\n patent: \"VS Lu\",\n ip: \"VS Lu\",\n disclosure: \"VS Lu\",\n spec: \"VS Lu\",\n design: \"VS Lu\",\n classify: \"AG Lu\",\n foundry: \"AG Lu\",\n grind: \"AG Lu\",\n task: \"AG Lu\",\n audio: \"Desktop Lu\",\n limitless: \"Desktop Lu\",\n pendant: \"Desktop Lu\",\n};\n\nfunction classifyIntent(message: string): { target: string; confidence: number } {\n const lower = message.toLowerCase();\n \n // Explicit prefix routing: [To Terminal Lu] or [Terminal Lu]\n const prefixMatch = lower.match(/\\[(?:to\\s+)?(\\w+\\s+lu)\\]/i);\n if (prefixMatch) {\n return { target: prefixMatch[1].replace(/^\\w/, c => c.toUpperCase()), confidence: 1.0 };\n }\n \n // Keyword routing\n for (const [keyword, target] of Object.entries(SIBLING_MAP)) {\n if (lower.includes(keyword)) {\n return { target, confidence: 0.8 };\n }\n }\n \n // Default: AG Lu (general-purpose)\n return { target: \"AG Lu\", confidence: 0.5 };\n}\n\nserve(async (req: Request) => {\n try {\n const { record } = await req.json();\n const message = record.message || \"\";\n const fromInstance = record.from_instance || \"\";\n const msgId = record.id;\n \n // Don't re-route messages FROM Cloud Lu (prevent loops)\n if (fromInstance === \"Cloud Lu\") {\n return new Response(JSON.stringify({ status: \"skip\", reason: \"from_cloud_lu\" }), { status: 200 });\n }\n \n const { target, confidence } = classifyIntent(message);\n \n // Route: send message to target sibling\n const { error } = await supabase.from(\"lu_sibling_messages\").insert({\n from_instance: \"Cloud Lu\",\n to_instance: target,\n message: `[Routed from ${fromInstance}] (intent: ${Object.entries(SIBLING_MAP).find(([k]) => message.toLowerCase().includes(k))?.[0] || \"default\"}, conf: ${(confidence * 100).toFixed(0)}%)\\n\\n${message}`,\n context: `Auto-routed from ${fromInstance} to ${target} (original msg: ${msgId})`,\n message_type: \"message\",\n read: false,\n });\n \n if (error) throw error;\n \n // Mark original as read\n await supabase.from(\"lu_sibling_messages\")\n .update({ read: true })\n .eq(\"id\", msgId);\n \n return new Response(JSON.stringify({ status: \"routed\", target, confidence }), { status: 200 });\n } catch (e) {\n return new Response(JSON.stringify({ error: String(e) }), { status: 500 });\n }\n});\n```\n\n**Deploy**:\n```bash\nsupabase functions deploy cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```\n\n---\n\n### 2. SQL Migration\n\n```bash\n# Apply the trigger migration\nsupabase db push --linked\n\n# Or directly:\npsql \"$SUPABASE_DB_URL\" -f supabase/migrations/20260226000001_cloud_lu_auto_route.sql\n```\n\nVerify trigger exists:\n```sql\nSELECT trigger_name, event_manipulation, action_timing \nFROM information_schema.triggers \nWHERE event_object_table = 'lu_sibling_messages';\n```\n\n---\n\n### 3. Cloud Run Config — RECOMMENDATION: Cloud Scheduler Cron\n\n**Option A (min_instances=1 + always-on CPU):**\n```bash\ngcloud run services update c8-cloud-lu \\\n --region=europe-west1 \\\n --min-instances=1 \\\n --cpu-boost \\\n --no-cpu-throttling\n```\nCost: ~$25-40/month (always-on vCPU). Overkill for current volume (~100 msgs/day).\n\n**Option B (Cloud Scheduler — RECOMMENDED):**\n```bash\n# Create scheduler job: hit heartbeat endpoint every 15 min\ngcloud scheduler jobs create http cloud-lu-heartbeat \\\n --schedule=\"*/15 * * * *\" \\\n --uri=\"https://c8-cloud-lu-1066620682516.europe-west1.run.app/heartbeat\" \\\n --http-method=POST \\\n --oidc-service-account-email=cloud-lu-invoker@c8-platform.iam.gserviceaccount.com \\\n --location=europe-west1 \\\n --time-zone=\"America/Phoenix\"\n```\nCost: ~$0.10/month (96 invocations/day × $0.000003/invocation). Cloud Run cold-starts on each call (~2-5s), which is fine for a 15-min poll.\n\n**Why B**: Current volume is ~100 msgs/day. The trigger-based Edge Function handles instant routing. The cron handles heartbeat tasks (pipeline maintenance, grading cycles, retrospective). No need to pay for always-on when the Edge Function already provides real-time routing.\n\n---\n\n### 4. Verification Steps\n\n```bash\n# 1. Send test message TO Cloud Lu\ncurl -X POST \"$SUPABASE_URL/rest/v1/lu_sibling_messages\" \\\n -H \"apikey: $SUPABASE_KEY\" \\\n -H \"Authorization: Bearer $SUPABASE_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"from_instance\":\"Carlos\",\"to_instance\":\"Cloud Lu\",\"message\":\"[Carlos] Test routing: deploy the new Docker image\",\"read\":false}'\n\n# 2. Wait 2-3 seconds (Edge Function latency)\n\n# 3. Check if message was routed to Terminal Lu\ncurl \"$SUPABASE_URL/rest/v1/lu_sibling_messages?to_instance=eq.Terminal%20Lu&order=created_at.desc&limit=1\" \\\n -H \"apikey: $SUPABASE_KEY\" | jq '.[0].message'\n# Should contain: \"[Routed from Carlos] (intent: deploy, conf: 80%)\"\n\n# 4. Check original was marked read\ncurl \"$SUPABASE_URL/rest/v1/lu_sibling_messages?from_instance=eq.Carlos&order=created_at.desc&limit=1\" \\\n -H \"apikey: $SUPABASE_KEY\" | jq '.[0].read'\n# Should be: true\n\n# 5. Check Edge Function logs\nsupabase functions logs cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```\n\n---\n\n### 5. Rollback Plan\n\n```sql\n-- Disable trigger (instant, reversible)\nALTER TABLE lu_sibling_messages DISABLE TRIGGER cloud_lu_auto_route;\n\n-- Verify disabled\nSELECT tgname, tgenabled FROM pg_trigger WHERE tgname = 'cloud_lu_auto_route';\n-- tgenabled = 'D' means disabled\n\n-- To re-enable:\nALTER TABLE lu_sibling_messages ENABLE TRIGGER cloud_lu_auto_route;\n\n-- Nuclear option: drop entirely\nDROP TRIGGER cloud_lu_auto_route ON lu_sibling_messages;\nDROP FUNCTION notify_cloud_lu_router();\n```\n\nEdge Function can also be disabled independently:\n```bash\nsupabase functions delete cloud-lu-router --project-ref llfnvahxgwehcdoohgnf\n```"
}Audit Trail (3)
2d agotask_completedAG Lu (Claude Opus)
2d agotask_claimedAG Lu
2d agotask_createdDesktop Lu
Task ID: 846d85ef-4f17-4fa7-93ab-8bd4e2a8f58e