[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H0GDNP29XQB615HTVJK6ZF":3,"skill-same:01M6H0GDNP29XQB615HTVJK6ZF":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":44,"ownerDescription":45,"updatedAt":46,"install":47,"resources":60},"01M6H0GDNP29XQB615HTVJK6ZF","stop-a-runaway-loop-amplifier",null,"Use when two or more services or agents call each other and a failure multiplies instead of settling — adds a hop budget, correlation dedupe and a loop breaker so one request cannot fan out into thousands.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",81,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32],"loop","stop","stop a runaway loop amplifier","services","correlation","Budget","hop","use","call","more","request","fan out","when","2026-11-10 10:12:30",false,"---\nname: stop-a-runaway-loop-amplifier\ndescription: Use when two or more services or agents call each other and a failure multiplies instead of settling — adds a hop budget, correlation dedupe and a loop breaker so one request cannot fan out into thousands.\n---\n\n# Stop a runaway loop amplifier\n\nA retry that spawns a retry, a webhook that triggers a callback that triggers the webhook, an agent that re-plans itself: these are loops where volume multiplies at each hop. They fill queues, wallets and rate limits in seconds. Break the cycle with a hop budget and a dedupe on the causal chain, not just a timeout.\n\n## Procedure\n\n1. Trace *one* failing request end to end and count the calls it spawns. If a single request can generate more than a bounded number of downstream calls, you have an amplifier regardless of what the trace looks like on a happy path.\n\n2. Propagate a hop count on every cross-service call and refuse beyond a small limit. Stick it in the same header as correlation so it travels automatically:\n       x-hop-count: 0 → 1 → 2 → 3 (drop)\n       if int(r.Header.Get(\"x-hop-count\")) >= 3 { return 429, \"hop budget exceeded\" }\n\n3. Dedupe on the causal chain: carry the originating event id and drop any work whose `(origin_id, step)` has already been processed. A webhook that fires in response to an event its own handler emitted is caught here:\n       if redis.set(f\"seen:{origin}:{step}\", 1, nx=True, ex=300) is None { return }   \u002F\u002F already handled\n\n4. Make triggers *edge-triggered on change*, not level-triggered on state. A poller that enqueues work every time it sees a non-empty queue re-enqueues its own output forever; enqueue only when the value *transitions*.\n\n5. Bound each queue's max depth and each consumer's in-flight, and shed when full rather than buffering without limit. An unbounded buffer hides the loop until memory runs out, which is a worse failure than a shed.\n\n6. Put a global rate fuse on outbound calls per origin id: if one causal chain exceeds N calls\u002Fsecond, trip a breaker for that origin and alert. This catches loops you did not foresee.\n\n7. Break the cycle at the design level where you can: make one direction of the loop asynchronous-only, or have the handler ignore events it caused (by `emitter == self`). Cheaper than any runtime guard.\n\n## Pitfalls\n\n- A timeout that stops *waiting* but not the loop: the caller gives up while the callee keeps spawning.\n- Correlation id forwarded but not the hop count, so the trace is observable but the loop is not bounded.\n- Idempotency keyed on `(message_id)` where the loop generates a fresh id at each hop, making every iteration look new.\n- A retry with backoff but no cap on *attempts*, so a slow loop still multiplies, just over a longer window.\n\n## Verification\n\n    # emit one event and count the resulting calls; it must stay bounded\n    curl -s -X POST localhost:8080\u002Fevents -d '{\"type\":\"order.created\",\"id\":\"e1\"}'\n    curl -s 'localhost:9090\u002Fapi\u002Fv1\u002Fquery?query=sum(increase(calls_total[1m]))' | jq '.data.result[].value'\n    # expect a small bounded number, not growth; x-hop-count capped in logs\n    grep 'hop budget exceeded' \u002Fvar\u002Flog\u002F*.log | wc -l\n    redis-cli keys 'seen:e1:*'   # dedupe keys present for each step\n\nReport: the hop limit, the dedupe key scheme, the per-origin rate fuse, and an injected loop where volume stayed bounded and the breaker tripped instead of multiplying.\n","# Stop a runaway loop amplifier\n\nA retry that spawns a retry, a webhook that triggers a callback that triggers the webhook, an agent that re-plans itself: these are loops where volume multiplies at each hop. They fill queues, wallets and rate limits in seconds. Break the cycle with a hop budget and a dedupe on the causal chain, not just a timeout.\n\n## Procedure\n\n1. Trace *one* failing request end to end and count the calls it spawns. If a single request can generate more than a bounded number of downstream calls, you have an amplifier regardless of what the trace looks like on a happy path.\n\n2. Propagate a hop count on every cross-service call and refuse beyond a small limit. Stick it in the same header as correlation so it travels automatically:\n       x-hop-count: 0 → 1 → 2 → 3 (drop)\n       if int(r.Header.Get(\"x-hop-count\")) >= 3 { return 429, \"hop budget exceeded\" }\n\n3. Dedupe on the causal chain: carry the originating event id and drop any work whose `(origin_id, step)` has already been processed. A webhook that fires in response to an event its own handler emitted is caught here:\n       if redis.set(f\"seen:{origin}:{step}\", 1, nx=True, ex=300) is None { return }   \u002F\u002F already handled\n\n4. Make triggers *edge-triggered on change*, not level-triggered on state. A poller that enqueues work every time it sees a non-empty queue re-enqueues its own output forever; enqueue only when the value *transitions*.\n\n5. Bound each queue's max depth and each consumer's in-flight, and shed when full rather than buffering without limit. An unbounded buffer hides the loop until memory runs out, which is a worse failure than a shed.\n\n6. Put a global rate fuse on outbound calls per origin id: if one causal chain exceeds N calls\u002Fsecond, trip a breaker for that origin and alert. This catches loops you did not foresee.\n\n7. Break the cycle at the design level where you can: make one direction of the loop asynchronous-only, or have the handler ignore events it caused (by `emitter == self`). Cheaper than any runtime guard.\n\n## Pitfalls\n\n- A timeout that stops *waiting* but not the loop: the caller gives up while the callee keeps spawning.\n- Correlation id forwarded but not the hop count, so the trace is observable but the loop is not bounded.\n- Idempotency keyed on `(message_id)` where the loop generates a fresh id at each hop, making every iteration look new.\n- A retry with backoff but no cap on *attempts*, so a slow loop still multiplies, just over a longer window.\n\n## Verification\n\n    # emit one event and count the resulting calls; it must stay bounded\n    curl -s -X POST localhost:8080\u002Fevents -d '{\"type\":\"order.created\",\"id\":\"e1\"}'\n    curl -s 'localhost:9090\u002Fapi\u002Fv1\u002Fquery?query=sum(increase(calls_total[1m]))' | jq '.data.result[].value'\n    # expect a small bounded number, not growth; x-hop-count capped in logs\n    grep 'hop budget exceeded' \u002Fvar\u002Flog\u002F*.log | wc -l\n    redis-cli keys 'seen:e1:*'   # dedupe keys present for each step\n\nReport: the hop limit, the dedupe key scheme, the per-origin rate fuse, and an injected loop where volume stayed bounded and the breaker tripped instead of multiplying.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-12 02:28:42",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill stop-a-runaway-loop-amplifier",{"tool":53,"command":54},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill stop-a-runaway-loop-amplifier",{"tool":56,"command":57},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill stop-a-runaway-loop-amplifier","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier\u002FSKILL.md",true,[61,65,71],{"path":62,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":64,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":66,"resourceType":67,"resourceTypeDesc":68,"sizeBytes":69,"sourceHtmlUrl":70},"SOURCE.md","REFERENCE","参考文档",355,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier\u002FSOURCE.md",{"path":72,"resourceType":67,"resourceTypeDesc":68,"sizeBytes":73,"sourceHtmlUrl":74},"TRUST.auto.yaml",2217,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-stop-a-runaway-loop-amplifier\u002FTRUST.auto.yaml",[76,104,127,145,158,168],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":80,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":33},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":108,"licenseFileUrl":109,"sourceHtmlUrl":110,"categories":111,"keywords":112,"publishedAt":33},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[113,114,115,116,117,118,119,120,121,122,123,124,125,126],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":108,"licenseFileUrl":131,"sourceHtmlUrl":132,"categories":133,"keywords":134,"publishedAt":33},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[135,114,136,137,138,139,140,124,123,122,141,142,143,118,144,117,116],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":108,"licenseFileUrl":149,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":33},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[153,154,115,155,156,125,123,157,121,120,118,117],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":159,"name":160,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":161,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":33},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[165,166,167],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":172,"sourceHtmlUrl":173,"categories":174,"keywords":175,"publishedAt":33},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[176,177,178,179,180,181,182,27,183,184,185],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]