agentleFS
sunholo-datasunholo-data/ailang/.agents/skills/cloud-cascade-debug/SKILL.md

cloud-cascade-debug

Skill38 starsChanged 6 days agoApache-2.0View on GitHub

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".

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    After ailang publish of a package whose dependents should auto-bump (the M-PKG-AUTONOMOUS-CASCADE-SAFE pipeline), trace the message through:

    line 9
  2. Very specific:

    If AILANG_CLOUD_PROJECT=ailang-multivac-dev (or *-dev), cascade messages went to the dev project's topic — production coordinator never …

    line 32
  3. Very specific:

    If the topic doesn't exist for that project: the cascade publisher silently no-ops (see cmd/ailang/pkg_publish.go::newCascadePublisher).

    line 111
  4. Distinctive:

    Look for log lines:

    line 142
  5. Distinctive:

    All of this is europe-west1.

    line 239

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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)

# 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

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:

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

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

# 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:

PatternMeaning
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", skippingrepeated 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):

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.

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) 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:

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):

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)

SymptomLikely causeFix
Publish prints "Cascade-topic notification published" but no coordinator logsAILANG_CLOUD_PROJECT points to a project with no *-cascade topicCheck 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 configAdd package-cascade-bumper agent entry
Coordinator hasn't logged ANYTHING since hours before the publishCloud Run revision crashed; push delivery failing silentlygcloud 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 requiredSame as the empty-agent case aboveSame fix
Job dispatched, runs for hours, never publishes completionJob hung mid-execution; check Cloud Run Job execution logsgcloud run jobs executions describe

One-shot triage script

.Codex/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.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.