[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GYEC4Y1PYY0FDZV9PVFVBT":3,"skill-same:01M6GYEC4Y1PYY0FDZV9PVFVBT":72},{"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":30,"linkOnly":31,"markdownContent":32,"markdownBody":33,"frontMatter":34,"refName":35,"commitSha":36,"skillDirectory":37,"forksCount":38,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":41,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6GYEC4Y1PYY0FDZV9PVFVBT","distinguish-duration-from-deadline",null,"Use when a spec says \"within 30 minutes\" or \"by end of day\" — separate a measured elapsed duration from a fixed wall-clock deadline so the two are never conflated.","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-distinguish-duration-from-deadline\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-distinguish-duration-from-deadline\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29],"distinguish duration from deadline","spec","use","never","end","end of day","clock","minutes","wall","when","2026-11-10 10:12:30",false,"---\nname: distinguish-duration-from-deadline\ndescription: Use when a spec says \"within 30 minutes\" or \"by end of day\" — separate a measured elapsed duration from a fixed wall-clock deadline so the two are never conflated.\n---\n\n# Distinguish duration from deadline\n\n\"Retry within 30 minutes\" and \"finish by 17:00\" are different guarantees. A duration is an elapsed interval measured from an event; a deadline is a fixed instant that may already have passed. Mixing them produces jobs that run past their cut-off or measure time with a clock that jumps.\n\n## Procedure\n\n1. Classify each time bound in the task: elapsed (`timeout=30s`, `retry_window`) or absolute (`due_at`, `expires_at`, `SLA breach at`).\n2. Measure elapsed time with a monotonic clock, never wall time:\n```python\nimport time\nstart = time.monotonic()\n...\nif time.monotonic() - start > 30: raise TimeoutError\n```\n3. Carry a deadline as an absolute UTC instant through the call chain and recompute remaining budget at each hop:\n```python\ndeadline = start_wall + timedelta(seconds=90)\nremaining = (deadline - datetime.now(timezone.utc)).total_seconds()\nif remaining \u003C= 0: abort(\"budget exhausted\")\n```\n4. Do not recompute a duration at each retry — that turns a 90s budget into 90s per attempt. Pass the original deadline down and let it shrink.\n5. When an NTP step or DST change can occur mid-run, prefer monotonic for the interval and wall time only to *report* the deadline in the user's zone.\n6. If the deadline is expressed in business hours (\"by 17:00 next working day\"), resolve it to an instant using the user's zone and a holiday calendar, then hand only the instant to the worker.\n7. State the guarantee explicitly in logs: `attempt=3 elapsed=41.2s remaining=48.8s`.\n\n## Pitfalls\n\n- `time.time()` is wall time and can jump backwards on NTP correction or DST; a 30s timeout computed from it can be huge or negative.\n- Sleeping `interval` between 5 retries under a 90s deadline overshoots: 5×20s + work > 90s. Budget the total, not the interval.\n- `asyncio.wait_for` and HTTP `timeout=` measure elapsed, but a connection pool queue wait may not count — the user sees a much later finish than the timeout promises.\n- A cron job \"every 30 minutes\" plus a run that takes 25 minutes drifts into overlap; elapsed work and fixed-schedule are separate concerns.\n- Reporting a deadline as a duration (\"in ~2 hours\") is wrong across a DST shift; give the absolute local time.\n- A per-attempt timeout larger than the remaining deadline guarantees an overrun; always clamp each attempt to what the deadline still allows.\n\n## Verification\n\n```\npython3 -c \"import time; s=time.monotonic(); [time.sleep(0.01) for _ in range(200)]; print('elapsed', round(time.monotonic()-s,3))\"\n```\nElapsed time computed from `monotonic()` unaffected by a wall-clock step = correct basis. Report: \"retry budget is a 90s absolute deadline passed down; elapsed measured with `monotonic`; observed overshoot 0s.\"\n","# Distinguish duration from deadline\n\n\"Retry within 30 minutes\" and \"finish by 17:00\" are different guarantees. A duration is an elapsed interval measured from an event; a deadline is a fixed instant that may already have passed. Mixing them produces jobs that run past their cut-off or measure time with a clock that jumps.\n\n## Procedure\n\n1. Classify each time bound in the task: elapsed (`timeout=30s`, `retry_window`) or absolute (`due_at`, `expires_at`, `SLA breach at`).\n2. Measure elapsed time with a monotonic clock, never wall time:\n```python\nimport time\nstart = time.monotonic()\n...\nif time.monotonic() - start > 30: raise TimeoutError\n```\n3. Carry a deadline as an absolute UTC instant through the call chain and recompute remaining budget at each hop:\n```python\ndeadline = start_wall + timedelta(seconds=90)\nremaining = (deadline - datetime.now(timezone.utc)).total_seconds()\nif remaining \u003C= 0: abort(\"budget exhausted\")\n```\n4. Do not recompute a duration at each retry — that turns a 90s budget into 90s per attempt. Pass the original deadline down and let it shrink.\n5. When an NTP step or DST change can occur mid-run, prefer monotonic for the interval and wall time only to *report* the deadline in the user's zone.\n6. If the deadline is expressed in business hours (\"by 17:00 next working day\"), resolve it to an instant using the user's zone and a holiday calendar, then hand only the instant to the worker.\n7. State the guarantee explicitly in logs: `attempt=3 elapsed=41.2s remaining=48.8s`.\n\n## Pitfalls\n\n- `time.time()` is wall time and can jump backwards on NTP correction or DST; a 30s timeout computed from it can be huge or negative.\n- Sleeping `interval` between 5 retries under a 90s deadline overshoots: 5×20s + work > 90s. Budget the total, not the interval.\n- `asyncio.wait_for` and HTTP `timeout=` measure elapsed, but a connection pool queue wait may not count — the user sees a much later finish than the timeout promises.\n- A cron job \"every 30 minutes\" plus a run that takes 25 minutes drifts into overlap; elapsed work and fixed-schedule are separate concerns.\n- Reporting a deadline as a duration (\"in ~2 hours\") is wrong across a DST shift; give the absolute local time.\n- A per-attempt timeout larger than the remaining deadline guarantees an overrun; always clamp each attempt to what the deadline still allows.\n\n## Verification\n\n```\npython3 -c \"import time; s=time.monotonic(); [time.sleep(0.01) for _ in range(200)]; print('elapsed', round(time.monotonic()-s,3))\"\n```\nElapsed time computed from `monotonic()` unaffected by a wall-clock step = correct basis. Report: \"retry budget is a 90s absolute deadline passed down; elapsed measured with `monotonic`; observed overshoot 0s.\"\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-distinguish-duration-from-deadline",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-15 02:28:10",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill distinguish-duration-from-deadline",{"tool":50,"command":51},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill distinguish-duration-from-deadline",{"tool":53,"command":54},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill distinguish-duration-from-deadline","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-distinguish-duration-from-deadline\u002FSKILL.md",true,[58,62,68],{"path":59,"resourceType":59,"resourceTypeDesc":60,"sizeBytes":61,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":63,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":66,"sourceHtmlUrl":67},"SOURCE.md","REFERENCE","参考文档",360,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-distinguish-duration-from-deadline\u002FSOURCE.md",{"path":69,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":70,"sourceHtmlUrl":71},"TRUST.auto.yaml",2217,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-distinguish-duration-from-deadline\u002FTRUST.auto.yaml",[73,101,124,142,155,165],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":77,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":30},"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",[],[81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":105,"licenseFileUrl":106,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":30},"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",[],[110,111,112,113,114,115,116,117,118,119,120,121,122,123],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":105,"licenseFileUrl":128,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":30},"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",[],[132,111,133,134,135,136,137,121,120,119,138,139,140,115,141,114,113],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":105,"licenseFileUrl":146,"sourceHtmlUrl":147,"categories":148,"keywords":149,"publishedAt":30},"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",[],[150,151,112,152,153,122,120,154,118,117,115,114],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":156,"name":157,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":158,"sourceHtmlUrl":159,"categories":160,"keywords":161,"publishedAt":30},"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",[],[162,163,164],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":169,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":30},"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",[],[173,174,175,176,177,178,179,22,180,181,182],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]