Skip to content
Back to skills

Cloud Cascade Debug

ASecurity

Investigate why an `ailang publish` cascade didn't fire (or fired and silently failed) on multivac. Inspects gcloud logs across the registry validator, the Pub/Sub `ailang-cascade` topic, and the coordinator's task queue. Use when the user says "auto-cascade didn't work", "why didn't multivac pick this up", "check cloud logs for cascade", or "the dependents didn't get bumped".

  • 34 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 2, 2026
ai-agentsgobashapi

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 2, 2026

npx -y skills add sunholo-data/ailang --skill cloud-cascade-debug --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cloud Cascade Debug?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Cloud Cascade Debug
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sunholo-data-cloud-cascade-debug-ailang/badge)](https://www.skillsdirectory.com/skills/sunholo-data-cloud-cascade-debug-ailang)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cloud-cascade-debug
description: Investigate why an `ailang publish` cascade didn't fire (or fired and silently failed) on multivac. Inspects gcloud logs across the registry validator, the Pub/Sub `ailang-cascade` topic, and the coordinator's task queue. Use when the user says "auto-cascade didn't work", "why didn't multivac pick this up", "check cloud logs for cascade", or "the dependents didn't get bumped".
model: opus
---

# AILANG Cloud Cascade Debugger

After `ailang publish` of a package whose dependents should auto-bump (the
M-PKG-AUTONOMOUS-CASCADE-SAFE pipeline), trace the message through:
**registry validator → ailang-cascade Pub/Sub topic → coordinator subscriber
→ task dispatch → Cloud Run Job execution**. Surfaces the first failing
hop with timestamps + log lines.

## When to use

User says any of:
- "auto-cascade didn't work" / "auto-cascade didn't fire"
- "why didn't multivac pick this up"
- "the dependents didn't get bumped"
- "check the cloud logs for the cascade"
- "I had to manually republish — what happened cloud-side?"

## Quick triage (60-second sanity check)

```bash
# Which project did the publish actually target?
echo "AILANG_CLOUD_PROJECT=$AILANG_CLOUD_PROJECT"
echo "AILANG_TOPIC_PREFIX=$AILANG_TOPIC_PREFIX"
```

If `AILANG_CLOUD_PROJECT=ailang-multivac-dev` (or `*-dev`), cascade messages
went to the **dev** project's topic — production coordinator never sees them.
That alone explains "auto-cascade didn't fire" for prod consumers. Keep
investigating in the dev project then.

## The pipeline (what should happen)

```
1. ailang publish FOO@2.1.0
   ├─→ POST /publish to ailang-registry-validator
   │   (project: ailang-registry; logs in europe-west1)
   │
   └─→ Pub/Sub publish to ailang-cascade topic
       (project: $AILANG_CLOUD_PROJECT; topic: $PREFIX-cascade)
           │
           └─→ Push subscription delivers to:
               https://<coordinator>/pubsub/push
                   │
                   └─→ Coordinator creates task per dependent
                       Looks up agent for inbox "pkg:sunholo/<dep>"
                       Dispatches to Cloud Run Job with env:
                         AILANG_TASK_ID=task-XXX
                         AILANG_AGENT_ID=<resolved agent>
                         (etc., see internal/dispatch/cloudrun/dispatcher.go:117+)
                           │
                           └─→ Job starts, runs the bump, publishes
                               completion to ailang-completions
```

Any hop can fail silently — the publish CLI prints "Cascade-topic
notification published" before any subscriber acks, so success messages
don't mean a dependent actually bumped.

## Workflow

### Step 1 — Identify the publish you're investigating

Get the timestamp + project from the publish output (or from
`ls -lt ~/.ailang/cache/registry/<vendor>/<name>/`):

```
✓ Published sunholo/motoko_ext_abi@2.1.0
→ Cascade-topic notification published for sunholo/motoko_ext_omnigraph
  (root=sunholo/motoko_ext_abi@2.1.0, class=A)
```

The cascade message IDs printed there (e.g. `msg_20260511_211114_88b4f765`)
are the ones to grep for. Convert local time to UTC for log queries.

### Step 2 — Check the validator did receive the publish

```bash
gcloud logging read \
  'resource.type="cloud_run_revision" AND
   resource.labels.service_name="ailang-registry-validator" AND
   httpRequest.requestMethod="POST" AND
   timestamp>="2026-05-11T19:00:00Z" AND
   timestamp<="2026-05-11T19:30:00Z"' \
  --project ailang-registry --limit 20 \
  --format="value(timestamp,httpRequest.requestUrl,httpRequest.status)"
```

Expected: HTTP 200 to `/publish` at the time of your publish. If 4xx/5xx,
the publish failed before cascade messages were emitted — investigate
validator logs directly.

### Step 3 — Confirm cascade messages were emitted

The publish CLI logs each cascade message it emits. Cross-check against
what landed in Pub/Sub. The topic is `<PREFIX>-cascade`:

```bash
PROJECT="${AILANG_CLOUD_PROJECT:-ailang-multivac-dev}"
PREFIX="${AILANG_TOPIC_PREFIX:-ailang-dev}"

gcloud pubsub topics list --project "$PROJECT" \
  --filter="name~cascade" --format="value(name)"
```

If the topic doesn't exist for that project: the cascade publisher silently
no-ops (see `cmd/ailang/pkg_publish.go::newCascadePublisher`). The publish
CLI may still print "Cascade-topic notification published" because it
prints from the legacy-inbox-write path even when the cloud publisher is
nil — confusing but documented.

### Step 4 — Find the coordinator that subscribes

```bash
gcloud pubsub subscriptions list --project "$PROJECT" \
  --filter="topic~cascade" \
  --format="value(name,pushConfig.pushEndpoint)"
```

Push endpoint will be a Cloud Run URL like
`https://ailang-dev-coordinator-XXX-ew.a.run.app/pubsub/push`.

### Step 5 — Check the coordinator received and processed each cascade message

```bash
# Substitute the time window of your publish
gcloud logging read \
  'resource.type="cloud_run_revision" AND
   resource.labels.service_name="ailang-dev-coordinator" AND
   timestamp>="2026-05-11T19:10:00Z" AND
   timestamp<="2026-05-11T19:30:00Z" AND
   (textPayload=~"cascade" OR textPayload=~"task-" OR textPayload=~"failed")' \
  --project "$PROJECT" --limit 50 \
  --format="value(timestamp,textPayload)"
```

Look for log lines:

| Pattern | Meaning |
|---|---|
| `Created task task-XXX (... inbox: pkg:sunholo/...)` | coordinator received the cascade message |
| `Skipping message <id>: no agent registered for inbox "..."` | no route; NOT dispatched, left unread for triage (current behaviour) |
| `Cloud dispatch: task task-XXX → Cloud Run Job (agent: , ...)` | **agent: empty** — pre-2026-08-25 behaviour; dispatched anyway and failed on arrival |
| `task task-XXX → failed (error=...)` | the job ran and exited with an error |
| `task task-XXX already in terminal state "failed", skipping` | repeated retries from Pub/Sub redelivery |
| (no logs at all) | coordinator scaled to zero AND push subscription couldn't wake it (rare) |

### Step 6 — Unrouted inbox: check this FIRST

The coordinator's agent registry is loaded from `~/.ailang/config.yaml` (or the GCS
config on the cloud instance). Since M-COORDINATOR-INBOX-WILDCARDS an inbox with no
match is **refused, not dispatched** — the message is left unread for triage.

Inbox patterns work (a trailing `*` only — this was documented here before it was
implemented, so older notes may mislead):

```yaml
coordinator:
  agents:
    - id: pkg-motoko-ext-family
      label: "Package family: sunholo/motoko_ext_*"
      inbox: "pkg:sunholo/motoko_ext_*"   # trailing * = family pattern
      capabilities: [code, test, docs]
```

Precedence: exact `inbox:` wins, then longest matching prefix
(`pkg:sunholo/motoko_ext_*` beats `pkg:sunholo/*` beats `pkg:*`), then no dispatch.

**Check the registry spelling, not the directory spelling.** Packages are published
with underscores and their directories use hyphens, and `FormatPackageInbox` does no
normalization — `sunholo/motoko_ext_abi` routes to `pkg:sunholo/motoko_ext_abi`, never
`pkg:sunholo/motoko-ext-abi`. Ten ailang-parse tickets were lost to exactly this.

```bash
grep -o 'inbox: "pkg:[^"]*"' config/config.cloud.yaml | sort -u
```

Pre-2026-08-25 the task was dispatched with an empty AgentID and the executor's startup
check ([cmd/ailang/coordinator_cloud.go:171](cmd/ailang/coordinator_cloud.go#L171))
failed them all, posting the failure to inbox `""` where nothing could read it. See
docs/internal/cloud-coordinator-config.md.

### Step 7 — If the job ran and failed for another reason

Pull the failed job's logs by task ID:

```bash
TASK_ID="task-cb56ee02"
gcloud logging read \
  "resource.type=\"cloud_run_job\" AND
   labels.\"run.googleapis.com/execution_name\"=~\"$TASK_ID\"" \
  --project "$PROJECT" --limit 100 \
  --format="value(timestamp,textPayload)"
```

Or by execution name (faster):

```bash
gcloud run jobs executions list --project "$PROJECT" \
  --region europe-west1 --limit 20 \
  --format="value(metadata.name,status.completionTime,status.conditions[0].message)"
```

## Common failure modes (cheat-sheet)

| Symptom | Likely cause | Fix |
|---|---|---|
| Publish prints "Cascade-topic notification published" but no coordinator logs | `AILANG_CLOUD_PROJECT` points to a project with no `*-cascade` topic | Check env vars; the cloud publisher silently no-ops when topic absent |
| Coordinator logs `Created task ... (agent: , inbox: pkg:...)` then `failed (error=AILANG_AGENT_ID required)` | No agent registered for `pkg:*` inboxes in coordinator config | Add `package-cascade-bumper` agent entry |
| Coordinator hasn't logged ANYTHING since hours before the publish | Cloud Run revision crashed; push delivery failing silently | `gcloud run revisions list`; check latest revision health |
| Tasks created but never dispatched (`Cloud dispatch: published task ... to Pub/Sub only (no dispatcher, ...)`) | `cloudDispatcher` not registered (CLI didn't init `cloudrun.NewDispatcher`) | Restart coordinator with proper env (`AILANG_CLOUD_REGION`, etc.) |
| Job dispatched but immediately fails with `AILANG_AGENT_ID required` | Same as the empty-agent case above | Same fix |
| Job dispatched, runs for hours, never publishes completion | Job hung mid-execution; check Cloud Run Job execution logs | `gcloud run jobs executions describe` |

## One-shot triage script

```bash
.claude/skills/cloud-cascade-debug/scripts/triage_cascade.sh \
  <vendor/name>@<version> [time-window-hours]
```

Bundles steps 2-5 into a single output. Defaults to a 1-hour window
ending at NOW. Pass `--project` to override the project (default:
`$AILANG_CLOUD_PROJECT`).

## Notes

- Production project = `ailang-multivac` (no `-dev` suffix); dev project =
  `ailang-multivac-dev`. Check `AILANG_CLOUD_PROJECT` carefully — local
  laptops typically point at dev.
- The validator service lives in `ailang-registry` (separate project)
  but the cascade pipeline lives in whichever project the publisher
  targets via `AILANG_CLOUD_PROJECT`.
- All of this is europe-west1.
- The cloud publisher is best-effort — a failure to write to the cascade
  topic does NOT abort `ailang publish` (the package still publishes).
  Cascade is "fire and forget" by design.

Files in this skill

  • SKILL.md10.1 KB
  • scripts/triage_cascade.sh6.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.