{"allowContribute":false,"item":{"artifactHtml":"\u003cstyle\u003e*{box-sizing:border-box}\n\n  :root{--paper:#FCFCFA;--ink:#141A18;--ink2:#4D5A57;--accent:#C0392B;--accent2:#0D5A63;--soft:#FBE9E7;--soft2:#E8F2F1;--hair:#E6E0DE;--warn:#B7791F;--good:#2E7D32}\n  :root[data-theme=\"dark\"]{--paper:#131616;--ink:#E8EDEC;--ink2:#AEB8B5;--accent:#E57373;--accent2:#6FC5D2;--soft:#2A1D1C;--soft2:#12333A;--hair:#2B3233;--warn:#E0A85C;--good:#7FC99A}\n  .doc{background:var(--paper);color:var(--ink);padding:28px 30px;font:15.5px/1.75 -apple-system,\"PingFang TC\",sans-serif}\n  .eyebrow{font:700 11px ui-monospace;letter-spacing:.14em;color:var(--accent)}\n  h1{font-size:26px;line-height:1.28;letter-spacing:-.015em;margin:10px 0 0}\n  .lede{color:var(--ink2);margin-top:8px;font-size:14px}\n  h2{font-size:18px;margin:28px 0 10px;padding-top:16px;border-top:1px solid var(--hair)}\n  h3{font-size:15px;margin:18px 0 6px;color:var(--ink)}\n  p{color:var(--ink2);max-width:68ch;margin:8px 0}\n  .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin:16px 0}\n  .stat{background:var(--soft);border-radius:8px;padding:12px 14px}\n  .stat.soft2{background:var(--soft2)}\n  .stat .k{font:600 11px ui-monospace;letter-spacing:.06em;color:var(--accent)}\n  .stat .k.c2{color:var(--accent2)}\n  .stat .v{font-size:20px;font-weight:800;margin-top:4px;color:var(--ink)}\n  .stat .n{font-size:11.5px;color:var(--ink2);margin-top:2px}\n  table{border-collapse:collapse;width:100%;font-size:13px;margin:10px 0}\n  th,td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--hair);vertical-align:top}\n  th{font:600 10.5px ui-monospace;letter-spacing:.05em;color:var(--ink2);background:var(--soft2)}\n  .pill{display:inline-block;padding:2px 8px;border-radius:999px;font:700 11px ui-monospace}\n  .pill.r{background:rgba(192,57,43,.13);color:var(--accent)}\n  .pill.y{background:rgba(183,121,31,.15);color:var(--warn)}\n  .pill.g{background:rgba(46,125,50,.13);color:var(--good)}\n  .callout{display:flex;gap:12px;padding:13px 15px;background:var(--soft);border-radius:8px;margin:14px 0;border-left:3px solid var(--accent)}\n  .callout.blue{background:var(--soft2);border-left-color:var(--accent2)}\n  .callout .tag{flex:none;font:700 11px ui-monospace;letter-spacing:.07em;color:var(--accent);padding-top:2px}\n  .callout.blue .tag{color:var(--accent2)}\n  code{font:12.5px ui-monospace;background:var(--soft2);padding:1px 6px;border-radius:4px}\n  pre{background:var(--soft2);padding:12px 14px;border-radius:8px;overflow-x:auto;font:12.5px/1.6 ui-monospace;margin:10px 0}\n  .src{font:11px ui-monospace;color:var(--ink2);margin-top:4px}\n  @media(max-width:640px){.doc{padding:20px 16px}h1{font-size:22px}}\n\n.wrap{display:block;width:100%;max-width:100%;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;overscroll-behavior-inline:contain;scrollbar-width:thin;scrollbar-color:var(--hair) transparent;touch-action:pan-x;margin:10px 0;border-radius:6px;isolation:isolate}\n.wrap::-webkit-scrollbar{height:6px}\n.wrap::-webkit-scrollbar-thumb{background:var(--hair);border-radius:3px}\n.wrap::-webkit-scrollbar-track{background:transparent}\n.wrap table{margin:0}\n.scroll-hint{font:11px ui-monospace;color:var(--ink2);opacity:.7;margin:10px 0 -4px;display:none}\n@media(max-width:640px){.doc{padding:20px 14px;overflow-x:hidden}h1{font-size:22px}.wrap{margin-left:-14px;margin-right:-14px;padding:0 14px;width:auto;max-width:none;border-radius:0}.scroll-hint{display:block}table{min-width:600px}}\n\n\u003c/style\u003e\u003cdiv class=\"doc\"\u003e\n\u003cheader\u003e\n  \u003cdiv class=\"eyebrow\"\u003eBUG REPORT · AGENT 排程可靠性\u003c/div\u003e\n  \u003ch1\u003eCubeLV 平台 Bug 回報：單指令併發指派導致任務錯位重跑與餓死（美股研究員）\u003c/h1\u003e\n  \u003cp class=\"lede\"\u003e回報日期：2026-08-19 ｜ 觸發員工：美股價值研究員（dee994a67775002d5796d277 / maxConcurrentRuns=1）｜ 嚴重程度：🔴 高 ｜ 來源：一次指派 4 筆 TODO 併發案例\u003c/p\u003e\n\u003c/header\u003e\n\n\u003csection data-cube=\"stats\" class=\"stats\"\u003e\n  \u003cdiv class=\"stat\"\u003e\u003cdiv class=\"k\"\u003e重複次數\u003c/div\u003e\u003cdiv class=\"v\"\u003eRDDT ×2\u003c/div\u003e\u003cdiv class=\"n\"\u003e同一標的產出兩份完整+兩份摘要\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat\"\u003e\u003cdiv class=\"k\"\u003e餓死任務\u003c/div\u003e\u003cdiv class=\"v\"\u003eBSX ×1\u003c/div\u003e\u003cdiv class=\"n\"\u003e無任何筆記產出、卡中間態\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat soft2\"\u003e\u003cdiv class=\"k c2\"\u003e併發數\u003c/div\u003e\u003cdiv class=\"v\"\u003e4 併 1 線程\u003c/div\u003e\u003cdiv class=\"n\"\u003e單員工同時收 4 筆任務\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat soft2\"\u003e\u003cdiv class=\"k c2\"\u003e污染筆記\u003c/div\u003e\u003cdiv class=\"v\"\u003e2 筆重複\u003c/div\u003e\u003cdiv class=\"n\"\u003e已進垃圾桶可還原\u003c/div\u003e\u003c/div\u003e\n\u003c/section\u003e\n\n\u003cdiv class=\"callout\"\u003e\u003cspan class=\"tag\"\u003e一句話\u003c/span\u003e\u003cdiv\u003e對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 的單線程員工一次併發指派多筆 TODO，排程器沒有原子鎖定 \u003ccode\u003etodoId\u003c/code\u003e，導致「搶錯槽位重跑 + 被搶走的任務餓死」——不是偶發，是結構性併發缺陷。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e一、現象\u003c/h2\u003e\n\u003cp\u003e使用者一次建立 4 筆「美股研究」TODO 並指派給同一位美股價值研究員，預期是 4 筆依序排隊（RDDT → PFE → BSX → DUOL 各跑一次）。實際結果：\u003c/p\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e#\u003c/th\u003e\u003cth\u003eTODO\u003c/th\u003e\u003cth\u003eID 尾碼\u003c/th\u003e\u003cth\u003e預期\u003c/th\u003e\u003cth\u003e實際\u003c/th\u003e\u003cth\u003e產出\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003eRDDT Reddit\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e8ce01016\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003e7f23f11e\u003c/code\u003e + 快覽 \u003ccode\u003eab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003ePFE 輝瑞\u003c/td\u003e\u003ctd\u003e\u003ccode\u003edde0319d\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 PFE\u003c/td\u003e\u003ctd\u003e跑 PFE ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e3\u003c/td\u003e\u003ctd\u003e\u003cstrong\u003eBSX 波士頓科學\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e9d160673\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 BSX\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e錯位重跑 RDDT ❌\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e無 BSX、卻多一份 RDDT\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003eDUOL 多鄰國\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eb3fa4adb\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅（去重生效）\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cp\u003e結果：\u003cstrong\u003eRDDT 被執行兩次\u003c/strong\u003e（完整報告 \u003ccode\u003e7f23f11e\u003c/code\u003e 與 \u003ccode\u003effa945c8\u003c/code\u003e、摘要 \u003ccode\u003eab73c2b5\u003c/code\u003e 與 \u003ccode\u003ec57d3a2c\u003c/code\u003e 重複）；\u003cstrong\u003eBSX 完全沒被執行\u003c/strong\u003e，呈現「有 sessionID 但 completed=null」的餓死狀態，不會自動重試也不會被重新派發。\u003c/p\u003e\n\n\u003ch2\u003e二、重現步驟\u003c/h2\u003e\n\u003col style=\"color:var(--ink2)\"\u003e\n  \u003cli\u003e員工 \u003ccode\u003e美股價值研究員 dee994a6\u003c/code\u003e 設為 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e單次 \u003ccode\u003evault_create_items\u003c/code\u003e 批次建立 4 筆 TODO，\u003ccode\u003eassignee\u003c/code\u003e 皆指向該員工（同一個 API call 內 4 筆同時可執行）。\u003c/li\u003e\n  \u003cli\u003e平台「指派即自動執行」同時觸發 4 筆可執行 → 排程器依序取下一棒，但取棒邏輯為「掃描下一個未完成」而非原子鎖定指定 \u003ccode\u003etodoId\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e第 2 棒取到 BSX 的執行槽（session \u003ccode\u003ec367f5b1\u003c/code\u003e），實際執行的卻是 RDDT 的內容。\u003c/li\u003e\n  \u003cli\u003eBSX 的 TODO 留在 \u003ccode\u003esessionID=c367f5b1 / completed=null\u003c/code\u003e 中間態，session 已結束不會重試，TODO 也不會再被派。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp class=\"src\"\u003e註：後續以 \u003ccode\u003etodoId\u003c/code\u003e 定點重跑 BSX（runId 6a854033）可正常完成，證明任務內容本身無誤，問題在排程分派。\u003c/p\u003e\n\n\u003ch2\u003e三、證據\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e證據項\u003c/th\u003e\u003cth\u003e內容\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eBSX TODO\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eTODO__美股研究 - BSX_9d160673.json\u003c/code\u003e — \u003ccode\u003eassignee=dee994a6 / sessionID=c367f5b1 / completed=null\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT__session_c367f5b1-0fee-ad8e-511c-9c0d8f78b1cc.json\u003c/code\u003e 開頭即為 \u003ccode\u003e「RDDT（Reddit）美股價值研究已完成…」\u003c/code\u003e，與 BSX 無關\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重複筆記\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003eRDDT ffa945c87a74...\u003c/code\u003e 與 \u003ccode\u003e7f23f11e...\u003c/code\u003e 內容高度重複；每日研究 \u003ccode\u003ec57d3a2c\u003c/code\u003e 與 \u003ccode\u003eab73c2b5\u003c/code\u003e 重複，已移至垃圾桶\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e對照組\u003c/td\u003e\u003ctd\u003eDUOL 的 session \u003ccode\u003e686aa600\u003c/code\u003e 正確觸發去重邏輯「TODO 早已完成，不會重複建立報告」而安全跳過，證明「已完成的去重有、排隊中的防錯位沒有」\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cpre\u003eTODO 9d160673 — sessionID: c367f5b1 / completed: null\nCOMMENT c367f5b1 — content preview: \"RDDT（Reddit）美股價值研究已完成，任務全數交付。\"\n→ 槽位與內容不一致 = 錯位重跑的直接證據\u003c/pre\u003e\n\n\u003ch2\u003e四、根因分析\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e層\u003c/th\u003e\u003cth\u003e問題\u003c/th\u003e\u003cth\u003e說明\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eClaim 非原子\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e搶 TODO 未做 CAS\u003c/td\u003e\u003ctd\u003e先查「下一個未完成」再寫 \u003ccode\u003esessionID\u003c/code\u003e，中間無 \u003ccode\u003ecompare-and-swap（sessionID == null 才寫入）\u003c/code\u003e，併發下可同時搶到同一槽\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e掃描式取棒\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e未鎖定 todoId\u003c/td\u003e\u003ctd\u003e執行器以掃描方式取棒，而非 \u003ccode\u003etodoId\u003c/code\u003e 定點 Claim，導致 BSX 的額度被 RDDT 內容佔用\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e狀態機缺口\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態無自癒\u003c/td\u003e\u003ctd\u003e\u003ccode\u003esessionID 已佔用 + completed=null + session 已結束\u003c/code\u003e 不會自動重試也不會回隊列，形成餓死\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e去重不完整\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e僅防「已完成」重建\u003c/td\u003e\u003ctd\u003eDUOL 的「已完成去重」有效，但「執行中/排隊中」的 \u003ccode\u003e(agentId + 標的)\u003c/code\u003e 冪等鍵缺失\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cdiv class=\"callout blue\"\u003e\u003cspan class=\"tag\"\u003e同類\u003c/span\u003e\u003cdiv\u003e與已回報的 \u003ccode\u003eONCE 排程連發 7 次（bfb9b447）\u003c/code\u003e、\u003ccode\u003eDAILY 連兩天漏觸發（85b2d8d）\u003c/code\u003e 屬同一類「排程可靠性」缺陷：高併發或定時觸發下的冪等與原子性不足。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e五、影響\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e資料污染\u003c/strong\u003e：重複筆記進入「美股研究 / 每日研究」，需人工進垃圾桶清理。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e任務丢失\u003c/strong\u003e：被餓死的 BSX 無聲失敗，使用者以為已排程實則未執行。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e成本放大\u003c/strong\u003e：每重跑一次消耗 ~30 credits 與 tokens，大量併發時線性放大（與 ONCE 連發燒掉 246 credits 同機制）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e可重現性高\u003c/strong\u003e：只要對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 員工一次併發 \u0026gt;1 筆，即高機率復現。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e六、建議修復（依優先級）\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003eP0/P1\u003c/th\u003e\u003cth\u003e修復項\u003c/th\u003e\u003cth\u003e做法\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003eClaim 原子化（CAS）\u003c/td\u003e\u003ctd\u003e搶 TODO 改為 \u003ccode\u003eupdate where sessionID is null\u003c/code\u003e 的原子寫入，失敗則放棄不重試，避免先查後寫的競態\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003etodoId 定點執行\u003c/td\u003e\u003ctd\u003e觸發時綁定指定 \u003ccode\u003etodoId\u003c/code\u003e（如本次補跑用 \u003ccode\u003erun_agent_task({todoId})\u003c/code\u003e），不再掃描「下一個未完成」\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e冪等鍵\u003c/td\u003e\u003ctd\u003e以 \u003ccode\u003e(agentId + 標的代號/任務指紋)\u003c/code\u003e 去重：執行中或已完成的不重派，排隊中的合併\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態自癒\u003c/td\u003e\u003ctd\u003esession 已結束但 TODO 仍為 \u003ccode\u003ecompleted=null\u003c/code\u003e 時，自動清空 \u003ccode\u003esessionID\u003c/code\u003e 回隊列或標失敗可重試\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e P2 \u003c/td\u003e\u003ctd\u003e背壓與可觀測性\u003c/td\u003e\u003ctd\u003e佇列長度 \u0026gt; \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 時回 \u003ccode\u003equeued\u003c/code\u003e 而非硬搶；任務面板顯示「排隊中 / 執行中 / 餓死待重試」三態與 session 對應\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\n\u003ch2\u003e七、使用者暫時繞過（修復前）\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e逐一派單\u003c/strong\u003e：派一筆 → 等 \u003ccode\u003ecompleted=true\u003c/code\u003e → 再派下一筆（本次 BSX 補跑即用此方式成功）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e或提高併發\u003c/strong\u003e：將員工 \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 調大，或拆給不同員工，才能真正併行多標的。\u003c/li\u003e\n  \u003cli\u003e避免對同一單線程員工「一次批次指派多筆」。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e八、本次處置\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e動作\u003c/th\u003e\u003cth\u003e結果\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e刪除重複 RDDT\u003c/td\u003e\u003ctd\u003e完整 \u003ccode\u003effa945c87a74...\u003c/code\u003e + 摘要 \u003ccode\u003ec57d3a2c...\u003c/code\u003e 已移至垃圾桶（可還原），保留正本 \u003ccode\u003e7f23f11e / ab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e刪除錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT c367f5b1\u003c/code\u003e 已刪（內容實為 RDDT）\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重置並定點重跑 BSX\u003c/td\u003e\u003ctd\u003e清空 \u003ccode\u003e9d160673\u003c/code\u003e 的 \u003ccode\u003esessionID\u003c/code\u003e 後以 \u003ccode\u003etodoId\u003c/code\u003e 定點重派（runId \u003ccode\u003e6a854033\u003c/code\u003e），完成後 \u003ccode\u003ecompleted:true / session 68432d5a\u003c/code\u003e，四檔齊套\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cp class=\"src\"\u003e相關 Bug：排程重複觸發 + 預算未攔截 a98abad428a49fb8a19f68fa ｜ DAILY 漏觸發 85b2d8d02e25dddf4e8856da ｜ 深層連結 966c0bcf177e812a96fa10a2 ｜ 組織層級缺失 d92063167716640828a93968\u003c/p\u003e\n\u003c/div\u003e","content":"\u003cdiv class=\"doc\"\u003e\n\n\n\u003ctable\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e重複次數\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003eRDDT ×2\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e同一標的產出兩份完整+兩份摘要\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e餓死任務\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003eBSX ×1\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e無任何筆記產出、卡中間態\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e併發數\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e4 併 1 線程\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e單員工同時收 4 筆任務\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e污染筆記\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e2 筆重複\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e已進垃圾桶可還原\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\n\n\u003cdiv class=\"callout\"\u003e\u003cspan class=\"tag\"\u003e一句話\u003c/span\u003e\u003cdiv\u003e對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 的單線程員工一次併發指派多筆 TODO，排程器沒有原子鎖定 \u003ccode\u003etodoId\u003c/code\u003e，導致「搶錯槽位重跑 + 被搶走的任務餓死」——不是偶發，是結構性併發缺陷。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e一、現象\u003c/h2\u003e\n\u003cp\u003e使用者一次建立 4 筆「美股研究」TODO 並指派給同一位美股價值研究員，預期是 4 筆依序排隊（RDDT → PFE → BSX → DUOL 各跑一次）。實際結果：\u003c/p\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e#\u003c/th\u003e\u003cth\u003eTODO\u003c/th\u003e\u003cth\u003eID 尾碼\u003c/th\u003e\u003cth\u003e預期\u003c/th\u003e\u003cth\u003e實際\u003c/th\u003e\u003cth\u003e產出\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003eRDDT Reddit\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e8ce01016\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003e7f23f11e\u003c/code\u003e + 快覽 \u003ccode\u003eab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003ePFE 輝瑞\u003c/td\u003e\u003ctd\u003e\u003ccode\u003edde0319d\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 PFE\u003c/td\u003e\u003ctd\u003e跑 PFE ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e3\u003c/td\u003e\u003ctd\u003e\u003cstrong\u003eBSX 波士頓科學\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e9d160673\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 BSX\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e錯位重跑 RDDT ❌\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e無 BSX、卻多一份 RDDT\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003eDUOL 多鄰國\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eb3fa4adb\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅（去重生效）\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e結果：\u003cstrong\u003eRDDT 被執行兩次\u003c/strong\u003e（完整報告 \u003ccode\u003e7f23f11e\u003c/code\u003e 與 \u003ccode\u003effa945c8\u003c/code\u003e、摘要 \u003ccode\u003eab73c2b5\u003c/code\u003e 與 \u003ccode\u003ec57d3a2c\u003c/code\u003e 重複）；\u003cstrong\u003eBSX 完全沒被執行\u003c/strong\u003e，呈現「有 sessionID 但 completed=null」的餓死狀態，不會自動重試也不會被重新派發。\u003c/p\u003e\n\n\u003ch2\u003e二、重現步驟\u003c/h2\u003e\n\u003col style=\"color:var(--ink2)\"\u003e\n  \u003cli\u003e員工 \u003ccode\u003e美股價值研究員 dee994a6\u003c/code\u003e 設為 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e單次 \u003ccode\u003evault_create_items\u003c/code\u003e 批次建立 4 筆 TODO，\u003ccode\u003eassignee\u003c/code\u003e 皆指向該員工（同一個 API call 內 4 筆同時可執行）。\u003c/li\u003e\n  \u003cli\u003e平台「指派即自動執行」同時觸發 4 筆可執行 → 排程器依序取下一棒，但取棒邏輯為「掃描下一個未完成」而非原子鎖定指定 \u003ccode\u003etodoId\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e第 2 棒取到 BSX 的執行槽（session \u003ccode\u003ec367f5b1\u003c/code\u003e），實際執行的卻是 RDDT 的內容。\u003c/li\u003e\n  \u003cli\u003eBSX 的 TODO 留在 \u003ccode\u003esessionID=c367f5b1 / completed=null\u003c/code\u003e 中間態，session 已結束不會重試，TODO 也不會再被派。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp class=\"src\"\u003e註：後續以 \u003ccode\u003etodoId\u003c/code\u003e 定點重跑 BSX（runId 6a854033）可正常完成，證明任務內容本身無誤，問題在排程分派。\u003c/p\u003e\n\n\u003ch2\u003e三、證據\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e證據項\u003c/th\u003e\u003cth\u003e內容\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eBSX TODO\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eTODO__美股研究 - BSX_9d160673.json\u003c/code\u003e — \u003ccode\u003eassignee=dee994a6 / sessionID=c367f5b1 / completed=null\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT__session_c367f5b1-0fee-ad8e-511c-9c0d8f78b1cc.json\u003c/code\u003e 開頭即為 \u003ccode\u003e「RDDT（Reddit）美股價值研究已完成…」\u003c/code\u003e，與 BSX 無關\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重複筆記\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003eRDDT ffa945c87a74...\u003c/code\u003e 與 \u003ccode\u003e7f23f11e...\u003c/code\u003e 內容高度重複；每日研究 \u003ccode\u003ec57d3a2c\u003c/code\u003e 與 \u003ccode\u003eab73c2b5\u003c/code\u003e 重複，已移至垃圾桶\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e對照組\u003c/td\u003e\u003ctd\u003eDUOL 的 session \u003ccode\u003e686aa600\u003c/code\u003e 正確觸發去重邏輯「TODO 早已完成，不會重複建立報告」而安全跳過，證明「已完成的去重有、排隊中的防錯位沒有」\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cpre\u003eTODO 9d160673 — sessionID: c367f5b1 / completed: null\nCOMMENT c367f5b1 — content preview: \"RDDT（Reddit）美股價值研究已完成，任務全數交付。\"\n→ 槽位與內容不一致 = 錯位重跑的直接證據\u003c/pre\u003e\n\n\u003ch2\u003e四、根因分析\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e層\u003c/th\u003e\u003cth\u003e問題\u003c/th\u003e\u003cth\u003e說明\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eClaim 非原子\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e搶 TODO 未做 CAS\u003c/td\u003e\u003ctd\u003e先查「下一個未完成」再寫 \u003ccode\u003esessionID\u003c/code\u003e，中間無 \u003ccode\u003ecompare-and-swap（sessionID == null 才寫入）\u003c/code\u003e，併發下可同時搶到同一槽\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e掃描式取棒\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e未鎖定 todoId\u003c/td\u003e\u003ctd\u003e執行器以掃描方式取棒，而非 \u003ccode\u003etodoId\u003c/code\u003e 定點 Claim，導致 BSX 的額度被 RDDT 內容佔用\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e狀態機缺口\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態無自癒\u003c/td\u003e\u003ctd\u003e\u003ccode\u003esessionID 已佔用 + completed=null + session 已結束\u003c/code\u003e 不會自動重試也不會回隊列，形成餓死\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e去重不完整\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e僅防「已完成」重建\u003c/td\u003e\u003ctd\u003eDUOL 的「已完成去重」有效，但「執行中/排隊中」的 \u003ccode\u003e(agentId + 標的)\u003c/code\u003e 冪等鍵缺失\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"callout blue\"\u003e\u003cspan class=\"tag\"\u003e同類\u003c/span\u003e\u003cdiv\u003e與已回報的 \u003ccode\u003eONCE 排程連發 7 次（bfb9b447）\u003c/code\u003e、\u003ccode\u003eDAILY 連兩天漏觸發（85b2d8d）\u003c/code\u003e 屬同一類「排程可靠性」缺陷：高併發或定時觸發下的冪等與原子性不足。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e五、影響\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e資料污染\u003c/strong\u003e：重複筆記進入「美股研究 / 每日研究」，需人工進垃圾桶清理。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e任務丢失\u003c/strong\u003e：被餓死的 BSX 無聲失敗，使用者以為已排程實則未執行。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e成本放大\u003c/strong\u003e：每重跑一次消耗 ~30 credits 與 tokens，大量併發時線性放大（與 ONCE 連發燒掉 246 credits 同機制）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e可重現性高\u003c/strong\u003e：只要對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 員工一次併發 \u0026gt;1 筆，即高機率復現。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e六、建議修復（依優先級）\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003eP0/P1\u003c/th\u003e\u003cth\u003e修復項\u003c/th\u003e\u003cth\u003e做法\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003eClaim 原子化（CAS）\u003c/td\u003e\u003ctd\u003e搶 TODO 改為 \u003ccode\u003eupdate where sessionID is null\u003c/code\u003e 的原子寫入，失敗則放棄不重試，避免先查後寫的競態\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003etodoId 定點執行\u003c/td\u003e\u003ctd\u003e觸發時綁定指定 \u003ccode\u003etodoId\u003c/code\u003e（如本次補跑用 \u003ccode\u003erun_agent_task({todoId})\u003c/code\u003e），不再掃描「下一個未完成」\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e冪等鍵\u003c/td\u003e\u003ctd\u003e以 \u003ccode\u003e(agentId + 標的代號/任務指紋)\u003c/code\u003e 去重：執行中或已完成的不重派，排隊中的合併\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態自癒\u003c/td\u003e\u003ctd\u003esession 已結束但 TODO 仍為 \u003ccode\u003ecompleted=null\u003c/code\u003e 時，自動清空 \u003ccode\u003esessionID\u003c/code\u003e 回隊列或標失敗可重試\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e P2 \u003c/td\u003e\u003ctd\u003e背壓與可觀測性\u003c/td\u003e\u003ctd\u003e佇列長度 \u0026gt; \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 時回 \u003ccode\u003equeued\u003c/code\u003e 而非硬搶；任務面板顯示「排隊中 / 執行中 / 餓死待重試」三態與 session 對應\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\n\u003ch2\u003e七、使用者暫時繞過（修復前）\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e逐一派單\u003c/strong\u003e：派一筆 → 等 \u003ccode\u003ecompleted=true\u003c/code\u003e → 再派下一筆（本次 BSX 補跑即用此方式成功）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e或提高併發\u003c/strong\u003e：將員工 \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 調大，或拆給不同員工，才能真正併行多標的。\u003c/li\u003e\n  \u003cli\u003e避免對同一單線程員工「一次批次指派多筆」。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e八、本次處置\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e動作\u003c/th\u003e\u003cth\u003e結果\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e刪除重複 RDDT\u003c/td\u003e\u003ctd\u003e完整 \u003ccode\u003effa945c87a74...\u003c/code\u003e + 摘要 \u003ccode\u003ec57d3a2c...\u003c/code\u003e 已移至垃圾桶（可還原），保留正本 \u003ccode\u003e7f23f11e / ab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e刪除錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT c367f5b1\u003c/code\u003e 已刪（內容實為 RDDT）\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重置並定點重跑 BSX\u003c/td\u003e\u003ctd\u003e清空 \u003ccode\u003e9d160673\u003c/code\u003e 的 \u003ccode\u003esessionID\u003c/code\u003e 後以 \u003ccode\u003etodoId\u003c/code\u003e 定點重派（runId \u003ccode\u003e6a854033\u003c/code\u003e），完成後 \u003ccode\u003ecompleted:true / session 68432d5a\u003c/code\u003e，四檔齊套\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp class=\"src\"\u003e相關 Bug：排程重複觸發 + 預算未攔截 a98abad428a49fb8a19f68fa ｜ DAILY 漏觸發 85b2d8d02e25dddf4e8856da ｜ 深層連結 966c0bcf177e812a96fa10a2 ｜ 組織層級缺失 d92063167716640828a93968\u003c/p\u003e\n\u003c/div\u003e","createdAt":1787138655096,"deletedAt":null,"displayMode":"artifact","id":"63c8adad1381c2538f0dad7d","isNew":false,"isPublic":true,"itemType":"NOTE","name":"CubeLV 平台 Bug 回報：單指令併發指派導致任務錯位重跑與餓死（美股研究員）","parents":{"4465d0a863da5d1b345d888c":1787138655096},"preParentID":null,"updatedAt":1788024625209,"updatedBy":{"userId":"6a3dcfc700e9b9fd06d5ef","userName":"蔡其樺"},"version":33},"ownerName":"蔡其樺","subtree":[{"artifactHtml":"\u003cstyle\u003e*{box-sizing:border-box}\n\n  :root{--paper:#FCFCFA;--ink:#141A18;--ink2:#4D5A57;--accent:#C0392B;--accent2:#0D5A63;--soft:#FBE9E7;--soft2:#E8F2F1;--hair:#E6E0DE;--warn:#B7791F;--good:#2E7D32}\n  :root[data-theme=\"dark\"]{--paper:#131616;--ink:#E8EDEC;--ink2:#AEB8B5;--accent:#E57373;--accent2:#6FC5D2;--soft:#2A1D1C;--soft2:#12333A;--hair:#2B3233;--warn:#E0A85C;--good:#7FC99A}\n  .doc{background:var(--paper);color:var(--ink);padding:28px 30px;font:15.5px/1.75 -apple-system,\"PingFang TC\",sans-serif}\n  .eyebrow{font:700 11px ui-monospace;letter-spacing:.14em;color:var(--accent)}\n  h1{font-size:26px;line-height:1.28;letter-spacing:-.015em;margin:10px 0 0}\n  .lede{color:var(--ink2);margin-top:8px;font-size:14px}\n  h2{font-size:18px;margin:28px 0 10px;padding-top:16px;border-top:1px solid var(--hair)}\n  h3{font-size:15px;margin:18px 0 6px;color:var(--ink)}\n  p{color:var(--ink2);max-width:68ch;margin:8px 0}\n  .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin:16px 0}\n  .stat{background:var(--soft);border-radius:8px;padding:12px 14px}\n  .stat.soft2{background:var(--soft2)}\n  .stat .k{font:600 11px ui-monospace;letter-spacing:.06em;color:var(--accent)}\n  .stat .k.c2{color:var(--accent2)}\n  .stat .v{font-size:20px;font-weight:800;margin-top:4px;color:var(--ink)}\n  .stat .n{font-size:11.5px;color:var(--ink2);margin-top:2px}\n  table{border-collapse:collapse;width:100%;font-size:13px;margin:10px 0}\n  th,td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--hair);vertical-align:top}\n  th{font:600 10.5px ui-monospace;letter-spacing:.05em;color:var(--ink2);background:var(--soft2)}\n  .pill{display:inline-block;padding:2px 8px;border-radius:999px;font:700 11px ui-monospace}\n  .pill.r{background:rgba(192,57,43,.13);color:var(--accent)}\n  .pill.y{background:rgba(183,121,31,.15);color:var(--warn)}\n  .pill.g{background:rgba(46,125,50,.13);color:var(--good)}\n  .callout{display:flex;gap:12px;padding:13px 15px;background:var(--soft);border-radius:8px;margin:14px 0;border-left:3px solid var(--accent)}\n  .callout.blue{background:var(--soft2);border-left-color:var(--accent2)}\n  .callout .tag{flex:none;font:700 11px ui-monospace;letter-spacing:.07em;color:var(--accent);padding-top:2px}\n  .callout.blue .tag{color:var(--accent2)}\n  code{font:12.5px ui-monospace;background:var(--soft2);padding:1px 6px;border-radius:4px}\n  pre{background:var(--soft2);padding:12px 14px;border-radius:8px;overflow-x:auto;font:12.5px/1.6 ui-monospace;margin:10px 0}\n  .src{font:11px ui-monospace;color:var(--ink2);margin-top:4px}\n  @media(max-width:640px){.doc{padding:20px 16px}h1{font-size:22px}}\n\n.wrap{display:block;width:100%;max-width:100%;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;overscroll-behavior-inline:contain;scrollbar-width:thin;scrollbar-color:var(--hair) transparent;touch-action:pan-x;margin:10px 0;border-radius:6px;isolation:isolate}\n.wrap::-webkit-scrollbar{height:6px}\n.wrap::-webkit-scrollbar-thumb{background:var(--hair);border-radius:3px}\n.wrap::-webkit-scrollbar-track{background:transparent}\n.wrap table{margin:0}\n.scroll-hint{font:11px ui-monospace;color:var(--ink2);opacity:.7;margin:10px 0 -4px;display:none}\n@media(max-width:640px){.doc{padding:20px 14px;overflow-x:hidden}h1{font-size:22px}.wrap{margin-left:-14px;margin-right:-14px;padding:0 14px;width:auto;max-width:none;border-radius:0}.scroll-hint{display:block}table{min-width:600px}}\n\n\u003c/style\u003e\u003cdiv class=\"doc\"\u003e\n\u003cheader\u003e\n  \u003cdiv class=\"eyebrow\"\u003eBUG REPORT · AGENT 排程可靠性\u003c/div\u003e\n  \u003ch1\u003eCubeLV 平台 Bug 回報：單指令併發指派導致任務錯位重跑與餓死（美股研究員）\u003c/h1\u003e\n  \u003cp class=\"lede\"\u003e回報日期：2026-08-19 ｜ 觸發員工：美股價值研究員（dee994a67775002d5796d277 / maxConcurrentRuns=1）｜ 嚴重程度：🔴 高 ｜ 來源：一次指派 4 筆 TODO 併發案例\u003c/p\u003e\n\u003c/header\u003e\n\n\u003csection data-cube=\"stats\" class=\"stats\"\u003e\n  \u003cdiv class=\"stat\"\u003e\u003cdiv class=\"k\"\u003e重複次數\u003c/div\u003e\u003cdiv class=\"v\"\u003eRDDT ×2\u003c/div\u003e\u003cdiv class=\"n\"\u003e同一標的產出兩份完整+兩份摘要\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat\"\u003e\u003cdiv class=\"k\"\u003e餓死任務\u003c/div\u003e\u003cdiv class=\"v\"\u003eBSX ×1\u003c/div\u003e\u003cdiv class=\"n\"\u003e無任何筆記產出、卡中間態\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat soft2\"\u003e\u003cdiv class=\"k c2\"\u003e併發數\u003c/div\u003e\u003cdiv class=\"v\"\u003e4 併 1 線程\u003c/div\u003e\u003cdiv class=\"n\"\u003e單員工同時收 4 筆任務\u003c/div\u003e\u003c/div\u003e\n  \u003cdiv class=\"stat soft2\"\u003e\u003cdiv class=\"k c2\"\u003e污染筆記\u003c/div\u003e\u003cdiv class=\"v\"\u003e2 筆重複\u003c/div\u003e\u003cdiv class=\"n\"\u003e已進垃圾桶可還原\u003c/div\u003e\u003c/div\u003e\n\u003c/section\u003e\n\n\u003cdiv class=\"callout\"\u003e\u003cspan class=\"tag\"\u003e一句話\u003c/span\u003e\u003cdiv\u003e對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 的單線程員工一次併發指派多筆 TODO，排程器沒有原子鎖定 \u003ccode\u003etodoId\u003c/code\u003e，導致「搶錯槽位重跑 + 被搶走的任務餓死」——不是偶發，是結構性併發缺陷。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e一、現象\u003c/h2\u003e\n\u003cp\u003e使用者一次建立 4 筆「美股研究」TODO 並指派給同一位美股價值研究員，預期是 4 筆依序排隊（RDDT → PFE → BSX → DUOL 各跑一次）。實際結果：\u003c/p\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e#\u003c/th\u003e\u003cth\u003eTODO\u003c/th\u003e\u003cth\u003eID 尾碼\u003c/th\u003e\u003cth\u003e預期\u003c/th\u003e\u003cth\u003e實際\u003c/th\u003e\u003cth\u003e產出\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003eRDDT Reddit\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e8ce01016\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003e7f23f11e\u003c/code\u003e + 快覽 \u003ccode\u003eab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003ePFE 輝瑞\u003c/td\u003e\u003ctd\u003e\u003ccode\u003edde0319d\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 PFE\u003c/td\u003e\u003ctd\u003e跑 PFE ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e3\u003c/td\u003e\u003ctd\u003e\u003cstrong\u003eBSX 波士頓科學\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e9d160673\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 BSX\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e錯位重跑 RDDT ❌\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e無 BSX、卻多一份 RDDT\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003eDUOL 多鄰國\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eb3fa4adb\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅（去重生效）\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cp\u003e結果：\u003cstrong\u003eRDDT 被執行兩次\u003c/strong\u003e（完整報告 \u003ccode\u003e7f23f11e\u003c/code\u003e 與 \u003ccode\u003effa945c8\u003c/code\u003e、摘要 \u003ccode\u003eab73c2b5\u003c/code\u003e 與 \u003ccode\u003ec57d3a2c\u003c/code\u003e 重複）；\u003cstrong\u003eBSX 完全沒被執行\u003c/strong\u003e，呈現「有 sessionID 但 completed=null」的餓死狀態，不會自動重試也不會被重新派發。\u003c/p\u003e\n\n\u003ch2\u003e二、重現步驟\u003c/h2\u003e\n\u003col style=\"color:var(--ink2)\"\u003e\n  \u003cli\u003e員工 \u003ccode\u003e美股價值研究員 dee994a6\u003c/code\u003e 設為 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e單次 \u003ccode\u003evault_create_items\u003c/code\u003e 批次建立 4 筆 TODO，\u003ccode\u003eassignee\u003c/code\u003e 皆指向該員工（同一個 API call 內 4 筆同時可執行）。\u003c/li\u003e\n  \u003cli\u003e平台「指派即自動執行」同時觸發 4 筆可執行 → 排程器依序取下一棒，但取棒邏輯為「掃描下一個未完成」而非原子鎖定指定 \u003ccode\u003etodoId\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e第 2 棒取到 BSX 的執行槽（session \u003ccode\u003ec367f5b1\u003c/code\u003e），實際執行的卻是 RDDT 的內容。\u003c/li\u003e\n  \u003cli\u003eBSX 的 TODO 留在 \u003ccode\u003esessionID=c367f5b1 / completed=null\u003c/code\u003e 中間態，session 已結束不會重試，TODO 也不會再被派。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp class=\"src\"\u003e註：後續以 \u003ccode\u003etodoId\u003c/code\u003e 定點重跑 BSX（runId 6a854033）可正常完成，證明任務內容本身無誤，問題在排程分派。\u003c/p\u003e\n\n\u003ch2\u003e三、證據\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e證據項\u003c/th\u003e\u003cth\u003e內容\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eBSX TODO\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eTODO__美股研究 - BSX_9d160673.json\u003c/code\u003e — \u003ccode\u003eassignee=dee994a6 / sessionID=c367f5b1 / completed=null\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT__session_c367f5b1-0fee-ad8e-511c-9c0d8f78b1cc.json\u003c/code\u003e 開頭即為 \u003ccode\u003e「RDDT（Reddit）美股價值研究已完成…」\u003c/code\u003e，與 BSX 無關\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重複筆記\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003eRDDT ffa945c87a74...\u003c/code\u003e 與 \u003ccode\u003e7f23f11e...\u003c/code\u003e 內容高度重複；每日研究 \u003ccode\u003ec57d3a2c\u003c/code\u003e 與 \u003ccode\u003eab73c2b5\u003c/code\u003e 重複，已移至垃圾桶\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e對照組\u003c/td\u003e\u003ctd\u003eDUOL 的 session \u003ccode\u003e686aa600\u003c/code\u003e 正確觸發去重邏輯「TODO 早已完成，不會重複建立報告」而安全跳過，證明「已完成的去重有、排隊中的防錯位沒有」\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cpre\u003eTODO 9d160673 — sessionID: c367f5b1 / completed: null\nCOMMENT c367f5b1 — content preview: \"RDDT（Reddit）美股價值研究已完成，任務全數交付。\"\n→ 槽位與內容不一致 = 錯位重跑的直接證據\u003c/pre\u003e\n\n\u003ch2\u003e四、根因分析\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e層\u003c/th\u003e\u003cth\u003e問題\u003c/th\u003e\u003cth\u003e說明\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eClaim 非原子\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e搶 TODO 未做 CAS\u003c/td\u003e\u003ctd\u003e先查「下一個未完成」再寫 \u003ccode\u003esessionID\u003c/code\u003e，中間無 \u003ccode\u003ecompare-and-swap（sessionID == null 才寫入）\u003c/code\u003e，併發下可同時搶到同一槽\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e掃描式取棒\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e未鎖定 todoId\u003c/td\u003e\u003ctd\u003e執行器以掃描方式取棒，而非 \u003ccode\u003etodoId\u003c/code\u003e 定點 Claim，導致 BSX 的額度被 RDDT 內容佔用\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e狀態機缺口\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態無自癒\u003c/td\u003e\u003ctd\u003e\u003ccode\u003esessionID 已佔用 + completed=null + session 已結束\u003c/code\u003e 不會自動重試也不會回隊列，形成餓死\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e去重不完整\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e僅防「已完成」重建\u003c/td\u003e\u003ctd\u003eDUOL 的「已完成去重」有效，但「執行中/排隊中」的 \u003ccode\u003e(agentId + 標的)\u003c/code\u003e 冪等鍵缺失\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cdiv class=\"callout blue\"\u003e\u003cspan class=\"tag\"\u003e同類\u003c/span\u003e\u003cdiv\u003e與已回報的 \u003ccode\u003eONCE 排程連發 7 次（bfb9b447）\u003c/code\u003e、\u003ccode\u003eDAILY 連兩天漏觸發（85b2d8d）\u003c/code\u003e 屬同一類「排程可靠性」缺陷：高併發或定時觸發下的冪等與原子性不足。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e五、影響\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e資料污染\u003c/strong\u003e：重複筆記進入「美股研究 / 每日研究」，需人工進垃圾桶清理。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e任務丢失\u003c/strong\u003e：被餓死的 BSX 無聲失敗，使用者以為已排程實則未執行。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e成本放大\u003c/strong\u003e：每重跑一次消耗 ~30 credits 與 tokens，大量併發時線性放大（與 ONCE 連發燒掉 246 credits 同機制）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e可重現性高\u003c/strong\u003e：只要對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 員工一次併發 \u0026gt;1 筆，即高機率復現。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e六、建議修復（依優先級）\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003eP0/P1\u003c/th\u003e\u003cth\u003e修復項\u003c/th\u003e\u003cth\u003e做法\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003eClaim 原子化（CAS）\u003c/td\u003e\u003ctd\u003e搶 TODO 改為 \u003ccode\u003eupdate where sessionID is null\u003c/code\u003e 的原子寫入，失敗則放棄不重試，避免先查後寫的競態\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003etodoId 定點執行\u003c/td\u003e\u003ctd\u003e觸發時綁定指定 \u003ccode\u003etodoId\u003c/code\u003e（如本次補跑用 \u003ccode\u003erun_agent_task({todoId})\u003c/code\u003e），不再掃描「下一個未完成」\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e冪等鍵\u003c/td\u003e\u003ctd\u003e以 \u003ccode\u003e(agentId + 標的代號/任務指紋)\u003c/code\u003e 去重：執行中或已完成的不重派，排隊中的合併\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態自癒\u003c/td\u003e\u003ctd\u003esession 已結束但 TODO 仍為 \u003ccode\u003ecompleted=null\u003c/code\u003e 時，自動清空 \u003ccode\u003esessionID\u003c/code\u003e 回隊列或標失敗可重試\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e P2 \u003c/td\u003e\u003ctd\u003e背壓與可觀測性\u003c/td\u003e\u003ctd\u003e佇列長度 \u0026gt; \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 時回 \u003ccode\u003equeued\u003c/code\u003e 而非硬搶；任務面板顯示「排隊中 / 執行中 / 餓死待重試」三態與 session 對應\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\n\u003ch2\u003e七、使用者暫時繞過（修復前）\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e逐一派單\u003c/strong\u003e：派一筆 → 等 \u003ccode\u003ecompleted=true\u003c/code\u003e → 再派下一筆（本次 BSX 補跑即用此方式成功）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e或提高併發\u003c/strong\u003e：將員工 \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 調大，或拆給不同員工，才能真正併行多標的。\u003c/li\u003e\n  \u003cli\u003e避免對同一單線程員工「一次批次指派多筆」。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e八、本次處置\u003c/h2\u003e\n\u003cdiv class=\"scroll-hint\"\u003e← 左右滑動查看完整表格 →\u003c/div\u003e\u003cdiv class=\"wrap\"\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e動作\u003c/th\u003e\u003cth\u003e結果\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e刪除重複 RDDT\u003c/td\u003e\u003ctd\u003e完整 \u003ccode\u003effa945c87a74...\u003c/code\u003e + 摘要 \u003ccode\u003ec57d3a2c...\u003c/code\u003e 已移至垃圾桶（可還原），保留正本 \u003ccode\u003e7f23f11e / ab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e刪除錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT c367f5b1\u003c/code\u003e 已刪（內容實為 RDDT）\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重置並定點重跑 BSX\u003c/td\u003e\u003ctd\u003e清空 \u003ccode\u003e9d160673\u003c/code\u003e 的 \u003ccode\u003esessionID\u003c/code\u003e 後以 \u003ccode\u003etodoId\u003c/code\u003e 定點重派（runId \u003ccode\u003e6a854033\u003c/code\u003e），完成後 \u003ccode\u003ecompleted:true / session 68432d5a\u003c/code\u003e，四檔齊套\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\n\u003cp class=\"src\"\u003e相關 Bug：排程重複觸發 + 預算未攔截 a98abad428a49fb8a19f68fa ｜ DAILY 漏觸發 85b2d8d02e25dddf4e8856da ｜ 深層連結 966c0bcf177e812a96fa10a2 ｜ 組織層級缺失 d92063167716640828a93968\u003c/p\u003e\n\u003c/div\u003e","content":"\u003cdiv class=\"doc\"\u003e\n\n\n\u003ctable\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e重複次數\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003eRDDT ×2\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e同一標的產出兩份完整+兩份摘要\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e餓死任務\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003eBSX ×1\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e無任何筆記產出、卡中間態\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e併發數\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e4 併 1 線程\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e單員工同時收 4 筆任務\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cp\u003e污染筆記\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e2 筆重複\u003c/p\u003e\u003c/td\u003e\u003ctd\u003e\u003cp\u003e已進垃圾桶可還原\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\n\n\u003cdiv class=\"callout\"\u003e\u003cspan class=\"tag\"\u003e一句話\u003c/span\u003e\u003cdiv\u003e對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 的單線程員工一次併發指派多筆 TODO，排程器沒有原子鎖定 \u003ccode\u003etodoId\u003c/code\u003e，導致「搶錯槽位重跑 + 被搶走的任務餓死」——不是偶發，是結構性併發缺陷。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e一、現象\u003c/h2\u003e\n\u003cp\u003e使用者一次建立 4 筆「美股研究」TODO 並指派給同一位美股價值研究員，預期是 4 筆依序排隊（RDDT → PFE → BSX → DUOL 各跑一次）。實際結果：\u003c/p\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e#\u003c/th\u003e\u003cth\u003eTODO\u003c/th\u003e\u003cth\u003eID 尾碼\u003c/th\u003e\u003cth\u003e預期\u003c/th\u003e\u003cth\u003e實際\u003c/th\u003e\u003cth\u003e產出\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003eRDDT Reddit\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e8ce01016\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e跑 RDDT ✅\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003e7f23f11e\u003c/code\u003e + 快覽 \u003ccode\u003eab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003ePFE 輝瑞\u003c/td\u003e\u003ctd\u003e\u003ccode\u003edde0319d\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 PFE\u003c/td\u003e\u003ctd\u003e跑 PFE ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e3\u003c/td\u003e\u003ctd\u003e\u003cstrong\u003eBSX 波士頓科學\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e9d160673\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 BSX\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e錯位重跑 RDDT ❌\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e無 BSX、卻多一份 RDDT\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003eDUOL 多鄰國\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eb3fa4adb\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅（去重生效）\u003c/td\u003e\u003ctd\u003e跑 DUOL ✅\u003c/td\u003e\u003ctd\u003e正常\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e結果：\u003cstrong\u003eRDDT 被執行兩次\u003c/strong\u003e（完整報告 \u003ccode\u003e7f23f11e\u003c/code\u003e 與 \u003ccode\u003effa945c8\u003c/code\u003e、摘要 \u003ccode\u003eab73c2b5\u003c/code\u003e 與 \u003ccode\u003ec57d3a2c\u003c/code\u003e 重複）；\u003cstrong\u003eBSX 完全沒被執行\u003c/strong\u003e，呈現「有 sessionID 但 completed=null」的餓死狀態，不會自動重試也不會被重新派發。\u003c/p\u003e\n\n\u003ch2\u003e二、重現步驟\u003c/h2\u003e\n\u003col style=\"color:var(--ink2)\"\u003e\n  \u003cli\u003e員工 \u003ccode\u003e美股價值研究員 dee994a6\u003c/code\u003e 設為 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e單次 \u003ccode\u003evault_create_items\u003c/code\u003e 批次建立 4 筆 TODO，\u003ccode\u003eassignee\u003c/code\u003e 皆指向該員工（同一個 API call 內 4 筆同時可執行）。\u003c/li\u003e\n  \u003cli\u003e平台「指派即自動執行」同時觸發 4 筆可執行 → 排程器依序取下一棒，但取棒邏輯為「掃描下一個未完成」而非原子鎖定指定 \u003ccode\u003etodoId\u003c/code\u003e。\u003c/li\u003e\n  \u003cli\u003e第 2 棒取到 BSX 的執行槽（session \u003ccode\u003ec367f5b1\u003c/code\u003e），實際執行的卻是 RDDT 的內容。\u003c/li\u003e\n  \u003cli\u003eBSX 的 TODO 留在 \u003ccode\u003esessionID=c367f5b1 / completed=null\u003c/code\u003e 中間態，session 已結束不會重試，TODO 也不會再被派。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp class=\"src\"\u003e註：後續以 \u003ccode\u003etodoId\u003c/code\u003e 定點重跑 BSX（runId 6a854033）可正常完成，證明任務內容本身無誤，問題在排程分派。\u003c/p\u003e\n\n\u003ch2\u003e三、證據\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e證據項\u003c/th\u003e\u003cth\u003e內容\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003eBSX TODO\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eTODO__美股研究 - BSX_9d160673.json\u003c/code\u003e — \u003ccode\u003eassignee=dee994a6 / sessionID=c367f5b1 / completed=null\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT__session_c367f5b1-0fee-ad8e-511c-9c0d8f78b1cc.json\u003c/code\u003e 開頭即為 \u003ccode\u003e「RDDT（Reddit）美股價值研究已完成…」\u003c/code\u003e，與 BSX 無關\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重複筆記\u003c/td\u003e\u003ctd\u003e美股研究 \u003ccode\u003eRDDT ffa945c87a74...\u003c/code\u003e 與 \u003ccode\u003e7f23f11e...\u003c/code\u003e 內容高度重複；每日研究 \u003ccode\u003ec57d3a2c\u003c/code\u003e 與 \u003ccode\u003eab73c2b5\u003c/code\u003e 重複，已移至垃圾桶\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e對照組\u003c/td\u003e\u003ctd\u003eDUOL 的 session \u003ccode\u003e686aa600\u003c/code\u003e 正確觸發去重邏輯「TODO 早已完成，不會重複建立報告」而安全跳過，證明「已完成的去重有、排隊中的防錯位沒有」\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cpre\u003eTODO 9d160673 — sessionID: c367f5b1 / completed: null\nCOMMENT c367f5b1 — content preview: \"RDDT（Reddit）美股價值研究已完成，任務全數交付。\"\n→ 槽位與內容不一致 = 錯位重跑的直接證據\u003c/pre\u003e\n\n\u003ch2\u003e四、根因分析\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e層\u003c/th\u003e\u003cth\u003e問題\u003c/th\u003e\u003cth\u003e說明\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eClaim 非原子\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e搶 TODO 未做 CAS\u003c/td\u003e\u003ctd\u003e先查「下一個未完成」再寫 \u003ccode\u003esessionID\u003c/code\u003e，中間無 \u003ccode\u003ecompare-and-swap（sessionID == null 才寫入）\u003c/code\u003e，併發下可同時搶到同一槽\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003e掃描式取棒\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e未鎖定 todoId\u003c/td\u003e\u003ctd\u003e執行器以掃描方式取棒，而非 \u003ccode\u003etodoId\u003c/code\u003e 定點 Claim，導致 BSX 的額度被 RDDT 內容佔用\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e狀態機缺口\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態無自癒\u003c/td\u003e\u003ctd\u003e\u003ccode\u003esessionID 已佔用 + completed=null + session 已結束\u003c/code\u003e 不會自動重試也不會回隊列，形成餓死\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003e去重不完整\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e僅防「已完成」重建\u003c/td\u003e\u003ctd\u003eDUOL 的「已完成去重」有效，但「執行中/排隊中」的 \u003ccode\u003e(agentId + 標的)\u003c/code\u003e 冪等鍵缺失\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"callout blue\"\u003e\u003cspan class=\"tag\"\u003e同類\u003c/span\u003e\u003cdiv\u003e與已回報的 \u003ccode\u003eONCE 排程連發 7 次（bfb9b447）\u003c/code\u003e、\u003ccode\u003eDAILY 連兩天漏觸發（85b2d8d）\u003c/code\u003e 屬同一類「排程可靠性」缺陷：高併發或定時觸發下的冪等與原子性不足。\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2\u003e五、影響\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e資料污染\u003c/strong\u003e：重複筆記進入「美股研究 / 每日研究」，需人工進垃圾桶清理。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e任務丢失\u003c/strong\u003e：被餓死的 BSX 無聲失敗，使用者以為已排程實則未執行。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e成本放大\u003c/strong\u003e：每重跑一次消耗 ~30 credits 與 tokens，大量併發時線性放大（與 ONCE 連發燒掉 246 credits 同機制）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e可重現性高\u003c/strong\u003e：只要對 \u003ccode\u003emaxConcurrentRuns=1\u003c/code\u003e 員工一次併發 \u0026gt;1 筆，即高機率復現。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e六、建議修復（依優先級）\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003eP0/P1\u003c/th\u003e\u003cth\u003e修復項\u003c/th\u003e\u003cth\u003e做法\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003eClaim 原子化（CAS）\u003c/td\u003e\u003ctd\u003e搶 TODO 改為 \u003ccode\u003eupdate where sessionID is null\u003c/code\u003e 的原子寫入，失敗則放棄不重試，避免先查後寫的競態\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill r\"\u003eP0\u003c/span\u003e\u003c/td\u003e\u003ctd\u003etodoId 定點執行\u003c/td\u003e\u003ctd\u003e觸發時綁定指定 \u003ccode\u003etodoId\u003c/code\u003e（如本次補跑用 \u003ccode\u003erun_agent_task({todoId})\u003c/code\u003e），不再掃描「下一個未完成」\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e冪等鍵\u003c/td\u003e\u003ctd\u003e以 \u003ccode\u003e(agentId + 標的代號/任務指紋)\u003c/code\u003e 去重：執行中或已完成的不重派，排隊中的合併\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cspan class=\"pill y\"\u003eP1\u003c/span\u003e\u003c/td\u003e\u003ctd\u003e中間態自癒\u003c/td\u003e\u003ctd\u003esession 已結束但 TODO 仍為 \u003ccode\u003ecompleted=null\u003c/code\u003e 時，自動清空 \u003ccode\u003esessionID\u003c/code\u003e 回隊列或標失敗可重試\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e P2 \u003c/td\u003e\u003ctd\u003e背壓與可觀測性\u003c/td\u003e\u003ctd\u003e佇列長度 \u0026gt; \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 時回 \u003ccode\u003equeued\u003c/code\u003e 而非硬搶；任務面板顯示「排隊中 / 執行中 / 餓死待重試」三態與 session 對應\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\n\u003ch2\u003e七、使用者暫時繞過（修復前）\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003e逐一派單\u003c/strong\u003e：派一筆 → 等 \u003ccode\u003ecompleted=true\u003c/code\u003e → 再派下一筆（本次 BSX 補跑即用此方式成功）。\u003c/li\u003e\n  \u003cli\u003e\u003cstrong\u003e或提高併發\u003c/strong\u003e：將員工 \u003ccode\u003emaxConcurrentRuns\u003c/code\u003e 調大，或拆給不同員工，才能真正併行多標的。\u003c/li\u003e\n  \u003cli\u003e避免對同一單線程員工「一次批次指派多筆」。\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003e八、本次處置\u003c/h2\u003e\n\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth\u003e動作\u003c/th\u003e\u003cth\u003e結果\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003ctd\u003e刪除重複 RDDT\u003c/td\u003e\u003ctd\u003e完整 \u003ccode\u003effa945c87a74...\u003c/code\u003e + 摘要 \u003ccode\u003ec57d3a2c...\u003c/code\u003e 已移至垃圾桶（可還原），保留正本 \u003ccode\u003e7f23f11e / ab73c2b5\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e刪除錯位 COMMENT\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eCOMMENT c367f5b1\u003c/code\u003e 已刪（內容實為 RDDT）\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e重置並定點重跑 BSX\u003c/td\u003e\u003ctd\u003e清空 \u003ccode\u003e9d160673\u003c/code\u003e 的 \u003ccode\u003esessionID\u003c/code\u003e 後以 \u003ccode\u003etodoId\u003c/code\u003e 定點重派（runId \u003ccode\u003e6a854033\u003c/code\u003e），完成後 \u003ccode\u003ecompleted:true / session 68432d5a\u003c/code\u003e，四檔齊套\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp class=\"src\"\u003e相關 Bug：排程重複觸發 + 預算未攔截 a98abad428a49fb8a19f68fa ｜ DAILY 漏觸發 85b2d8d02e25dddf4e8856da ｜ 深層連結 966c0bcf177e812a96fa10a2 ｜ 組織層級缺失 d92063167716640828a93968\u003c/p\u003e\n\u003c/div\u003e","createdAt":1787138655096,"deletedAt":null,"displayMode":"artifact","id":"63c8adad1381c2538f0dad7d","isNew":false,"isPublic":true,"itemType":"NOTE","name":"CubeLV 平台 Bug 回報：單指令併發指派導致任務錯位重跑與餓死（美股研究員）","parents":{"4465d0a863da5d1b345d888c":1787138655096},"preParentID":null,"updatedAt":1788024625209,"updatedBy":{"userId":"6a3dcfc700e9b9fd06d5ef","userName":"蔡其樺"},"version":33}]}