@tea-agent/loop-agent 0.29.2 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +56 -24
  2. package/bin/agent-worker.js +0 -0
  3. package/dist/commands/client-recovery.js +2 -10
  4. package/dist/commands/init.js +1 -1
  5. package/dist/executors/dag-pi-executor.js +15 -4
  6. package/dist/executors/pi-executor.js +5 -3
  7. package/dist/executors/pi-playwright-cli-tool.js +9 -14
  8. package/dist/executors/pi-sdk-executor.js +16 -0
  9. package/dist/shared/operator/capabilities.js +9 -9
  10. package/dist/shared/pi-retry-settings.js +23 -0
  11. package/dist/worker/console/chat/pi-runtime.js +167 -41
  12. package/dist/worker/console/chat/routes.js +21 -2
  13. package/dist/worker/console/chat/runtime-context.js +50 -8
  14. package/dist/worker/console/chat/tool-preview.js +90 -0
  15. package/dist/worker/console/chat/turn-process.js +178 -0
  16. package/dist/worker/console/chat/usage.js +144 -16
  17. package/dist/worker/console/night-aux-ticker.js +141 -0
  18. package/dist/worker/console/operation-runner.js +21 -4
  19. package/dist/worker/console/operator-user-error.js +12 -0
  20. package/dist/worker/console/recovery-cta.js +6 -6
  21. package/dist/worker/console/routes.js +61 -0
  22. package/dist/worker/console/server.js +7 -0
  23. package/dist/worker/console/static/assets/index-D9gnJn_l.js +29 -0
  24. package/dist/worker/console/static/assets/index-rajoXwkM.css +1 -0
  25. package/dist/worker/console/static/index.html +2 -2
  26. package/dist/worker/console/static-src/night-prepare-result.js +118 -0
  27. package/dist/worker/scheduler/clock-install/win32-schtasks.js +70 -15
  28. package/dist/workflows/dag/backend-test-writer-completeness.js +398 -26
  29. package/dist/workflows/dag/dynamic-runtime/map.js +10 -4
  30. package/dist/workflows/dag/frontend-test-case-checklist.js +3 -3
  31. package/dist/workflows/dag/init-hybrid.js +247 -239
  32. package/dist/workflows/dag/node-execution.js +13 -2
  33. package/dist/workflows/dag/types.js +21 -7
  34. package/docs/templates/backend-test-dag.json +664 -460
  35. package/docs/templates/frontend-test-case-checklist.md +1 -1
  36. package/docs/templates/frontend-test-dag.generate-cases.prompt.md +1 -1
  37. package/docs/templates/frontend-test-dag.json +1 -1
  38. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
  39. package/docs/templates/frontend-test-dag.review-cases.prompt.md +1 -1
  40. package/docs/templates/init-managed-agents.md +6 -3
  41. package/harness.json +2 -2
  42. package/package.json +1 -1
  43. package/skills/playwright-cli/SKILL.md +1 -1
  44. package/skills/playwright-cli-case-generator/SKILL.md +1 -1
  45. package/dist/worker/console/static/assets/index-Cwx-ZVEQ.js +0 -29
  46. package/dist/worker/console/static/assets/index-Yyn3ynVv.css +0 -1
@@ -0,0 +1 @@
1
+ :root{--canvas: #f7f7f4;--canvas-soft: #fafaf7;--surface: #ffffff;--surface-muted: #f0efe9;--ink: #26251e;--body: #5a5852;--muted: #807d72;--muted-soft: #a09c92;--hairline: #e6e5e0;--hairline-strong: #cfcdc4;--orange: #f54e00;--orange-active: #d04200;--orange-soft: color-mix(in srgb, var(--orange) 12%, white);--blue: #3f6ea4;--green: #1f8a65;--amber: #a66a00;--red: #c72d53;--peach: #f1d8cb;--mint: #d8ead5;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--radius-sm: 6px;--radius-md: 8px;--radius-lg: 12px;--radius-pill: 999px;--transition-fast: .16s ease;--transition-base: .22s ease;--shadow-panel: 0 1px 2px rgb(38 37 30 / 4%), 0 8px 24px rgb(38 37 30 / 3%);--shadow-soft: 0 10px 30px rgb(38 37 30 / 6%);--shell-max: 1680px;color-scheme:light;font-family:Segoe UI,PingFang SC,Hiragino Sans GB,Noto Sans SC,system-ui,-apple-system,sans-serif;line-height:1.5}*{box-sizing:border-box}html{background:radial-gradient(1200px 480px at 8% -10%,rgb(241 216 203 / 45%),transparent 55%),radial-gradient(900px 420px at 100% 0%,rgb(216 234 213 / 35%),transparent 50%),var(--canvas);min-height:100%}body{margin:0;min-height:100vh;min-width:320px;background:transparent;color:var(--ink);font-size:14px}button,input,select,textarea{font:inherit}a{color:inherit}code,.cmd,.kv dd code{font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace}.embedded-operator-nav{position:sticky;top:0;z-index:40;display:flex;gap:6px;align-items:center;margin:0;padding:8px max(24px,calc((100vw - var(--shell-max)) / 2));border-bottom:1px solid var(--hairline);background:color-mix(in srgb,var(--canvas) 92%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);font-size:13px;font-weight:700;flex-shrink:0}.console-app{display:flex;flex-direction:column;min-height:100dvh}html:has(.console-app.is-chat-focus),body:has(.console-app.is-chat-focus){height:100%;overflow:hidden}.console-app.is-chat-focus{height:100dvh;max-height:100dvh;overflow:hidden}.console-shell{flex:1 1 auto;display:flex;flex-direction:column;min-height:0;width:min(100% - 48px,var(--shell-max));margin:0 auto;padding:var(--space-5) 0 var(--space-12, 48px)}.embedded-operator-nav a,.embedded-operator-nav span{padding:6px 12px;border-radius:var(--radius-pill);text-decoration:none;color:var(--ink)}.embedded-operator-nav a:hover,.embedded-operator-nav a:focus-visible{background:var(--surface);color:var(--orange-active);outline:none}.embedded-operator-nav span[aria-current=page]{background:var(--ink);color:#fff}.top-nav{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);margin:0 0 var(--space-5);padding:6px;border:1px solid var(--hairline);border-radius:var(--radius-pill);background:color-mix(in srgb,var(--surface) 88%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:var(--shadow-panel)}.nav-link{appearance:none;display:inline-flex;align-items:center;min-height:34px;padding:0 14px;border:1px solid transparent;border-radius:var(--radius-pill);background:transparent;color:var(--body);font-size:13px;font-weight:600;cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast),transform var(--transition-fast)}.nav-link:hover:not(:disabled),.nav-link:focus-visible:not(:disabled){background:var(--surface);color:var(--ink);outline:none}.nav-link-active{background:var(--ink);color:#fff}.nav-link-active:hover:not(:disabled),.nav-link-active:focus-visible:not(:disabled){background:var(--ink);color:#fff}.nav-link-external{margin-left:auto;border-color:var(--hairline);background:var(--surface);color:var(--orange-active)}.nav-link-external:hover:not(:disabled){border-color:var(--orange);background:var(--orange-soft);color:var(--orange-active)}.readiness{appearance:none;position:relative;display:inline-flex;align-items:center;gap:6px;margin-left:auto;min-height:34px;padding:0 28px 0 12px;border:1px solid var(--hairline);border-radius:var(--radius-pill);background:var(--surface);color:var(--ink);cursor:pointer;box-shadow:none;transition:background-color var(--transition-fast),border-color var(--transition-fast)}.readiness:hover{border-color:color-mix(in srgb,var(--ink) 18%,var(--hairline));background:color-mix(in srgb,var(--surface) 70%,var(--bg))}.readiness:focus-visible{outline:2px solid color-mix(in srgb,var(--orange) 45%,transparent);outline-offset:2px}.readiness:before{content:"";position:absolute;top:50%;right:10px;width:7px;height:7px;border-radius:50%;transform:translateY(-50%);background:var(--muted-soft)}.readiness[data-state=setup-required]{border-color:var(--hairline);background:var(--surface)}.readiness[data-state=setup-required]:before{background:var(--amber)}.readiness[data-state=ready]{border-color:var(--hairline);background:var(--surface)}.readiness[data-state=ready]:before{background:color-mix(in srgb,var(--green) 72%,white);box-shadow:0 0 0 3px color-mix(in srgb,var(--green) 12%,transparent)}.readiness[data-state=degraded]{border-color:var(--hairline);background:var(--surface)}.readiness[data-state=degraded]:before{background:var(--amber);box-shadow:0 0 0 3px color-mix(in srgb,var(--amber) 12%,transparent)}.readiness-label{margin:0;color:var(--muted);font-size:11px;font-weight:600;line-height:1;letter-spacing:.02em;text-transform:uppercase}.readiness strong{color:var(--ink);font-size:12px;font-weight:700;line-height:1}.readiness[data-state=ready] strong,.readiness[data-state=setup-required] strong,.readiness[data-state=degraded] strong{color:var(--ink)}.flash{display:flex;gap:var(--space-3);align-items:flex-start;margin:0 0 var(--space-4);padding:12px 14px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-panel);animation:flash-in .22s ease}.flash-error{border-color:color-mix(in srgb,var(--red) 35%,var(--hairline));background:color-mix(in srgb,var(--red) 6%,var(--surface));color:var(--red)}.flash-info{border-color:color-mix(in srgb,var(--blue) 30%,var(--hairline));background:color-mix(in srgb,var(--blue) 6%,var(--surface));color:var(--body)}.flash-label{flex:0 0 auto;min-width:3.5rem;font-size:12px;font-weight:700;letter-spacing:.02em}.flash-body{margin:0;overflow-wrap:anywhere}.muted{color:var(--muted)}.console-main{display:grid;gap:var(--space-4)}.console-main--fill{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:var(--space-3)}.console-shell.is-chat-focus{flex:1 1 auto;min-height:0;overflow:hidden;padding-bottom:var(--space-3)}.console-shell.is-chat-focus .top-nav{margin-bottom:var(--space-3);flex-shrink:0}.console-shell.is-chat-focus .console-main--fill{flex:1 1 auto;min-height:0;overflow:hidden}.panel--chat{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;padding:var(--space-3);overflow:hidden}.panel--chat .oc-shell{flex:1 1 auto;min-height:0;height:auto;overflow:hidden}.console-shell.is-chat-focus .panel--chat{padding:var(--space-2)}.console-shell.is-chat-focus .panel--chat .oc-shell{min-height:0;gap:var(--space-2);overflow:hidden}.inspect-split-panel{position:fixed;z-index:50;top:16px;right:16px;bottom:16px;width:min(420px,calc(100vw - 32px));display:grid;align-content:start;gap:var(--space-4);padding:var(--space-5);overflow:auto;border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface);box-shadow:var(--shadow-soft)}.inspect-split-nodes{display:grid;gap:6px;margin:0;padding:0;list-style:none;max-height:220px;overflow:auto}.inspect-split-nodes li{display:grid;grid-template-columns:1fr auto;gap:var(--space-2);align-items:center;padding:6px 8px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--canvas-soft);font-size:12px}.inspect-split-nodes li.is-active{border-color:var(--orange);background:var(--orange-soft)}.inspect-split-nodes code{color:var(--muted);font-size:11px}.inspect-split-header{display:flex;align-items:start;justify-content:space-between;gap:var(--space-3)}.inspect-split-header h2,.inspect-split-panel h3{margin:0}.inspect-split-kicker,.inspect-split-id{margin:0;color:var(--muted);font-size:12px}.inspect-split-facts{display:grid;gap:var(--space-2);margin:0}.inspect-split-facts div{display:grid;grid-template-columns:7rem 1fr;gap:var(--space-2);padding-bottom:var(--space-2);border-bottom:1px solid var(--hairline)}.inspect-split-facts dt{color:var(--muted)}.inspect-split-facts dd{margin:0;overflow-wrap:anywhere}.inspect-split-events{display:grid;gap:8px;margin:0;padding-left:18px;color:var(--body);font-size:12px}.panel{min-width:0;border:1px solid var(--hairline);background:color-mix(in srgb,var(--surface) 96%,transparent);border-radius:var(--radius-lg);padding:var(--space-6);box-shadow:var(--shadow-panel)}.panel h2{margin:0 0 var(--space-2);color:var(--ink);font-size:18px;font-weight:700;letter-spacing:-.01em}.panel-lead{margin:0 0 var(--space-5);color:var(--muted);font-size:13px}.panel h3{margin:0 0 var(--space-3);color:var(--ink);font-size:15px;font-weight:700}.empty-state{border:1px dashed var(--hairline-strong);border-radius:var(--radius-md);padding:var(--space-6);background:var(--canvas-soft);color:var(--body)}.empty-title{margin:0 0 var(--space-2);color:var(--ink);font-size:16px;font-weight:700}.checklist{margin:0 0 var(--space-4);padding:var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--canvas-soft);list-style:none;color:var(--body)}.checklist li{position:relative;padding:6px 0 6px 22px}.checklist li:before{content:"";position:absolute;left:0;top:12px;width:8px;height:8px;border-radius:50%;background:var(--orange);opacity:.75}.kv{display:grid;gap:var(--space-1);margin:0}.kv div{display:grid;grid-template-columns:9rem 1fr;gap:var(--space-3);padding:10px 0;border-bottom:1px solid var(--hairline)}.kv div:last-child{border-bottom:none}.kv dt{color:var(--muted);font-size:12px;font-weight:600}.kv dd{margin:0;color:var(--ink);overflow-wrap:anywhere}code{font-size:.85rem;color:var(--ink)}.cmd{display:block;width:100%;margin:0;padding:var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:#f3efe8;color:var(--ink);font-size:12px;line-height:1.55;overflow-x:auto;white-space:pre-wrap;word-break:break-word;max-height:280px}.external-link{color:var(--orange);text-decoration:none;font-weight:600}.external-link:hover{text-decoration:underline}.error{color:var(--red)}.wizard-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(108px,1fr));gap:var(--space-2);list-style:none;padding:0;margin:0 0 var(--space-5)}.wizard-steps li{position:relative;min-height:52px;display:grid;align-content:center;gap:2px;border:1px solid var(--hairline);border-radius:var(--radius-md);padding:8px 10px;background:var(--canvas-soft);color:var(--muted);font-size:12px;font-weight:650;transition:border-color var(--transition-fast),background-color var(--transition-fast),color var(--transition-fast),box-shadow var(--transition-fast)}.wizard-steps li[data-done=true]{border-color:color-mix(in srgb,var(--green) 35%,var(--hairline));background:color-mix(in srgb,var(--mint) 45%,var(--surface));color:var(--green)}.wizard-steps li[data-active=true]{border-color:var(--orange);background:var(--surface);color:var(--ink);box-shadow:0 0 0 3px var(--orange-soft)}.wizard-steps .step-index{font-size:10px;font-weight:700;letter-spacing:.04em;color:var(--muted-soft)}.wizard-steps li[data-active=true] .step-index,.wizard-steps li[data-done=true] .step-index{color:inherit;opacity:.8}.wizard-steps .step-label{line-height:1.25}.field{display:grid;gap:var(--space-1);margin:0 0 var(--space-4);width:min(100%,520px)}.field span{font-size:12px;font-weight:600;color:var(--muted)}.field input,.field textarea,.field select{width:100%;border:1px solid var(--hairline-strong);border-radius:var(--radius-md);background:var(--surface);color:var(--ink);transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.field input{min-height:40px;padding:0 var(--space-3)}.field select{min-height:40px;padding:0 var(--space-3);cursor:pointer}.field textarea{min-height:120px;padding:var(--space-3);resize:vertical}.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{outline:none;border-color:var(--orange);box-shadow:0 0 0 3px var(--orange-soft)}.field input:disabled,.field textarea:disabled,.field select:disabled{background:var(--surface-muted);color:var(--muted);cursor:not-allowed}.workflow-hint{margin:calc(var(--space-1) * -1) 0 var(--space-3);color:var(--muted);font-size:12px}.prd-drop-zone{position:relative;width:min(100%,720px);margin:0 0 var(--space-3);padding:var(--space-3);border:1px dashed var(--hairline-strong);border-radius:var(--radius-md);background:var(--surface);transition:border-color var(--transition-fast),background-color var(--transition-fast),box-shadow var(--transition-fast)}.prd-drop-zone.is-dragover{border-color:var(--orange);background:var(--orange-soft);box-shadow:0 0 0 3px var(--orange-soft)}.prd-upload-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);margin:0 0 var(--space-3)}.prd-upload-btn{display:inline-flex;align-items:center;cursor:pointer;margin:0}.prd-upload-btn.is-disabled,.prd-upload-btn:has(input:disabled){opacity:.55;cursor:not-allowed;pointer-events:none}.prd-upload-btn:focus-within{outline:none;box-shadow:0 0 0 3px var(--orange-soft)}.prd-upload-hint{font-size:12px}.prd-file-meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);margin:0 0 var(--space-3);padding:var(--space-2) var(--space-3);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface-muted);font-size:12px;color:var(--ink)}.prd-file-list{list-style:none;margin:0 0 var(--space-3);padding:0;display:grid;gap:var(--space-2)}.prd-file-list li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-2) var(--space-3);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface-muted);font-size:12px}.prd-file-list li.is-primary{border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline-strong))}.prd-file-item-name{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--space-1);min-width:0}.prd-file-primary-tag{display:inline-flex;align-items:center;padding:0 6px;border-radius:999px;background:var(--orange-soft);color:var(--orange);font-size:11px;font-weight:700}.prd-file-item-actions{display:inline-flex;flex-wrap:wrap;gap:var(--space-1)}.prd-file-item-actions .btn,.prd-file-clear{min-height:28px;padding:0 var(--space-2);font-size:12px}.prd-drop-hint{margin:0 0 var(--space-3);font-size:13px;font-weight:600;color:var(--orange)}.prd-text-field{width:100%;margin-bottom:0}.prd-file-error{width:min(100%,720px);margin:0 0 var(--space-3);padding:var(--space-2) var(--space-3);border:1px solid color-mix(in srgb,var(--orange) 45%,var(--hairline-strong));border-radius:var(--radius-md);background:var(--orange-soft);color:var(--ink);font-size:13px}.meta-row{display:grid;gap:6px;margin:0 0 var(--space-4);padding:var(--space-3) var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--canvas-soft);font-size:13px}.meta-row code{font-size:12px}.cta-row,.recovery-cta-row{display:flex;flex-wrap:wrap;gap:var(--space-2);align-items:center}.cta-row{margin-top:var(--space-3)}.cta-row .cmd{flex:1 1 100%}.wizard-body{display:grid;gap:var(--space-3);justify-items:stretch;animation:panel-in .24s ease}.wizard-body>div{display:grid;gap:var(--space-3);justify-items:stretch}.wizard-body .field{width:100%;max-width:640px}.wizard-body .cta-row{margin-top:var(--space-1)}.interview-card{width:100%;padding:var(--space-5);border:1px solid var(--hairline);border-radius:var(--radius-lg);background:linear-gradient(180deg,var(--surface),var(--canvas-soft));box-shadow:var(--shadow-panel)}.interview-q{margin:0 0 var(--space-2);color:var(--ink)}.btn,button{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px;padding:0 16px;border:1px solid var(--hairline-strong);border-radius:var(--radius-md);background:var(--surface);color:var(--ink);font-size:13px;font-weight:650;cursor:pointer;transition:border-color var(--transition-fast),background-color var(--transition-fast),color var(--transition-fast),box-shadow var(--transition-fast),transform var(--transition-fast)}.btn:hover:not(:disabled),button:hover:not(:disabled){border-color:color-mix(in srgb,var(--ink) 18%,var(--hairline-strong));background:var(--canvas-soft);outline:none}.btn:focus-visible:not(:disabled),button:focus-visible:not(:disabled){outline:none;box-shadow:0 0 0 3px var(--orange-soft)}.btn:active:not(:disabled),button:active:not(:disabled){transform:translateY(1px)}.btn:disabled,button:disabled{opacity:.48;cursor:not-allowed;transform:none}.btn-primary,button.btn-primary{border-color:var(--orange);background:var(--orange);color:#fff;box-shadow:0 6px 16px #f54e002e}.btn-primary:hover:not(:disabled),button.btn-primary:hover:not(:disabled){border-color:var(--orange-active);background:var(--orange-active);color:#fff}.btn-secondary,button.btn-secondary{border-color:var(--hairline-strong);background:var(--surface);color:var(--ink)}.btn-ghost,button.btn-ghost{border-color:transparent;background:transparent;color:var(--body)}.btn-ghost:hover:not(:disabled),button.btn-ghost:hover:not(:disabled){background:var(--surface-muted);color:var(--ink)}.recovery-cta-row{margin-top:var(--space-3)}.recovery-confirm{margin-top:var(--space-3);padding:var(--space-4);border:1px solid color-mix(in srgb,var(--orange) 40%,var(--hairline));border-radius:var(--radius-md);background:color-mix(in srgb,var(--orange-soft) 55%,var(--surface))}.recovery-confirm h3{margin:0 0 var(--space-2);font-size:15px}.recovery-confirm .cta-row{margin-top:var(--space-3)}.recovery-report{margin-top:var(--space-3);padding:var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface)}.recovery-report-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);margin-bottom:var(--space-3)}.recovery-report-header h3{margin:0;font-size:15px}.recovery-report-facts{display:grid;gap:var(--space-2);margin:0 0 var(--space-3)}.recovery-report-facts div{display:grid;grid-template-columns:5.5rem 1fr;gap:var(--space-2)}.recovery-report-facts dt{color:var(--muted);font-size:12px}.recovery-report-facts dd{margin:0;overflow-wrap:anywhere}.recovery-steps{margin:.5rem 0 .75rem 1.25rem;padding:0;line-height:1.5}.recovery-lane{margin-top:var(--space-4);padding-top:var(--space-3);border-top:1px solid var(--border, #ddd)}.recovery-lane h3{margin:0 0 .35rem;font-size:1rem}.recovery-cta-row button[disabled]{opacity:.4}@keyframes flash-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}@keyframes panel-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}@media(max-width:800px){.console-shell{width:min(100% - 24px,var(--shell-max));padding-top:var(--space-5)}.readiness,.nav-link-external{margin-left:0}.inspect-split-panel{inset:auto 0 0;width:100%;max-height:min(76vh,680px);border-radius:var(--radius-lg) var(--radius-lg) 0 0}.kv div{grid-template-columns:1fr}.wizard-steps{grid-template-columns:repeat(2,minmax(0,1fr))}}.oc-shell{display:flex;flex-direction:column;height:100%;min-height:0;gap:var(--space-3);position:relative;overflow:hidden}.oc-workspace{display:flex;flex:1 1 auto;min-height:0;gap:0;position:relative;overflow:hidden}.oc-main{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.oc-sidebar{flex:0 0 280px;width:280px;min-width:0;display:flex;flex-direction:column;gap:var(--space-2);margin-right:var(--space-3);padding:var(--space-2);overflow:hidden;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface)}.oc-sidebar.is-collapsed{flex:0 0 36px;width:36px;padding:6px;overflow:visible;align-items:center}.oc-sidebar-header-actions{display:inline-flex;align-items:center;gap:2px}.oc-sidebar-toggle{appearance:none;display:inline-grid;place-items:center;width:28px;height:28px;padding:0;border:1px solid transparent;border-radius:var(--radius-sm);background:transparent;color:var(--muted);cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.oc-sidebar-toggle:hover{color:var(--ink);background:color-mix(in srgb,var(--orange) 8%,var(--surface));border-color:var(--hairline)}.oc-sidebar-toggle:focus-visible{outline:2px solid color-mix(in srgb,var(--orange) 45%,transparent);outline-offset:1px}.oc-sidebar-toggle.is-collapsed{width:100%;height:28px}.oc-sidebar-section{display:flex;flex-direction:column;gap:6px;min-height:0}.oc-sidebar-section>header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:13px;flex-shrink:0}.oc-sessions{flex:0 1 auto;max-height:min(34vh,320px)}.oc-session-scroll{min-height:0;max-height:min(28vh,260px);overflow:auto;padding:4px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:linear-gradient(180deg,color-mix(in srgb,var(--canvas-soft) 70%,white),var(--canvas-soft))}.oc-session-group{display:flex;flex-direction:column;gap:2px}.oc-session-group>small{margin:4px 6px 2px;color:var(--muted-soft);font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.oc-session-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px;align-items:center;border-radius:6px;transition:background-color var(--transition-fast)}.oc-session-item:hover,.oc-session-item:focus-within{background:color-mix(in srgb,var(--orange) 8%,var(--surface))}.oc-session-item.is-active{background:var(--orange-soft)}.oc-session-main{min-width:0;padding:5px 6px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.oc-session-main strong,.oc-session-main span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.oc-session-main strong{font-size:12.5px;font-weight:650;line-height:1.25}.oc-session-main span{color:var(--muted-soft);font-size:10px;margin-top:1px;font-variant-numeric:tabular-nums}.oc-session-actions{display:none;align-items:center;gap:0;padding-right:2px}.oc-session-item:hover .oc-session-actions,.oc-session-item:focus-within .oc-session-actions,.oc-session-item.is-active .oc-session-actions{display:inline-flex}.oc-session-menu{padding:3px 4px;border:0;background:transparent;color:var(--muted);cursor:pointer;font:inherit;font-size:10px;white-space:nowrap}.oc-session-menu:hover{color:var(--ink)}.oc-session-delete{color:color-mix(in srgb,var(--red) 75%,var(--muted))}.oc-session-delete:hover{color:var(--red)}.oc-explorer{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:6px;border-top:1px solid var(--hairline);padding-top:var(--space-3);margin-top:2px}.oc-explorer-hint{margin:0 2px;color:var(--muted-soft);font-size:10.5px;letter-spacing:.01em}.oc-tree-scroll{flex:1 1 auto;min-height:120px;max-height:min(52vh,560px);overflow:auto;padding:4px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:linear-gradient(180deg,color-mix(in srgb,var(--canvas-soft) 70%,white),var(--canvas-soft))}.oc-tree,.oc-tree ul{list-style:none;padding:0;margin:0}.oc-tree-node{position:relative}.oc-tree-row{appearance:none;display:grid;grid-template-columns:12px 14px minmax(0,1fr);align-items:center;gap:6px;width:100%;min-height:28px;margin:0;padding:3px 8px;border:0;border-radius:6px;background:transparent;color:var(--ink);text-align:left;cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast)}.oc-tree-row:hover{background:color-mix(in srgb,var(--orange) 8%,var(--surface))}.oc-tree-row:focus-visible{outline:2px solid color-mix(in srgb,var(--orange) 45%,transparent);outline-offset:1px}.oc-tree-chevron{color:var(--muted-soft);transition:transform var(--transition-fast);transform:rotate(0)}.oc-tree-chevron.is-open{transform:rotate(90deg)}.oc-tree-chevron-spacer{width:12px;height:12px}.oc-tree-glyph{flex-shrink:0;color:var(--amber)}.oc-tree-glyph.is-folder-open{color:color-mix(in srgb,var(--orange) 70%,var(--amber))}.oc-tree-glyph.is-file{color:var(--muted)}.oc-tree-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;line-height:1.25;font-variant-numeric:tabular-nums}.oc-tree-dir .oc-tree-label{font-weight:650;color:var(--ink)}.oc-tree-file .oc-tree-label{font-family:JetBrains Mono,SFMono-Regular,Consolas,Segoe UI Mono,monospace;font-size:11.5px;font-weight:500;color:var(--body)}.oc-tree-node.is-dot .oc-tree-label{color:var(--muted-soft);font-weight:500}.oc-tree-node.is-dot .oc-tree-glyph{opacity:.7}.oc-tree-children{position:relative;margin:0}.oc-tree-children:before{content:"";position:absolute;top:0;bottom:2px;left:var(--oc-tree-guide, 14px);width:1px;background:color-mix(in srgb,var(--hairline-strong) 55%,transparent);pointer-events:none}.oc-tree-empty,.oc-sidebar-error{margin:8px 6px;color:var(--muted);font-size:12px;line-height:1.45}.oc-sidebar-error{color:var(--red)}.oc-governance{margin-top:auto;border-top:1px solid var(--hairline);padding-top:8px}.oc-governance-links{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px}.oc-governance-links button{min-height:28px;padding:4px 6px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--surface);color:var(--muted);cursor:pointer;font:inherit;font-size:11px;font-weight:600;text-align:center}.oc-governance-links button:hover{color:var(--ink);border-color:color-mix(in srgb,var(--ink) 18%,var(--hairline))}.oc-governance-panel button{border:0;background:transparent;color:var(--muted);cursor:pointer;font:inherit;font-size:11px}.oc-governance-panel{position:absolute;z-index:10;left:282px;bottom:0;width:min(440px,calc(100vw - 320px));max-height:75%;overflow:auto;padding:12px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-panel)}.oc-governance-panel header,.oc-governance-panel article,.oc-governance-panel label{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 0}.oc-governance-panel small,.oc-governance-panel span{color:var(--muted);font-size:11px}.oc-governance-panel button:disabled{cursor:wait;opacity:.5}.oc-governance-error{color:var(--danger);font-size:12px}.oc-model-provider{display:block!important;border-bottom:1px solid var(--hairline)}.oc-model-provider>div,.oc-model-row,.oc-model-row>div{display:flex;align-items:center;justify-content:space-between;gap:8px}.oc-model-row{padding:4px 0 4px 10px}.oc-model-form{display:grid;gap:6px;margin-top:10px}.oc-model-form input{min-width:0;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);padding:6px 8px;font:inherit;font-size:12px}.oc-model-form button{justify-self:start}.oc-model-test-result{padding:6px 8px;border-radius:var(--radius-sm);background:var(--surface-muted);font-size:12px}.oc-file-preview{position:absolute;z-index:4;inset:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-panel)}.oc-file-preview header{display:flex;align-items:center;gap:var(--space-2);padding:10px 12px;border-bottom:1px solid var(--hairline)}.oc-file-tabs{display:flex;min-width:0;gap:2px;overflow-x:auto}.oc-file-tabs button{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--muted);padding:4px 7px;cursor:pointer}.oc-file-tabs button.is-active{background:var(--surface-muted);color:var(--ink);font-weight:650}.oc-file-preview header span{flex:1;color:var(--muted);font-size:11px}.oc-file-preview pre{flex:1;min-height:0;margin:0;padding:var(--space-3);overflow:auto;font-size:12px;line-height:1.5;white-space:pre-wrap}.oc-file-preview-loading{position:absolute;z-index:5;right:12px;top:12px;padding:6px 8px;border-radius:var(--radius-sm);background:var(--surface-muted);color:var(--muted);font-size:12px}.oc-process{display:flex;flex-direction:column;flex:0 0 min(360px,42%);width:min(360px,42%);min-width:280px;min-height:0;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-panel);margin-left:var(--space-3);overflow:hidden;animation:panel-in .18s ease}.oc-turn-group{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}.oc-process-inline{margin:0 0 4px 44px;max-width:min(720px,100%)}.oc-process-inline-summary{display:inline-flex;align-items:center;gap:6px;min-height:24px;padding:2px 0;border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:12px;text-align:left}.oc-process-inline-summary:hover,.oc-process-inline-summary.is-open{color:var(--ink)}.oc-process-inline-summary.is-running{color:var(--accent, #2563eb)}.oc-process-inline-summary.is-error{color:var(--danger, #dc2626)}.oc-process-inline-summary .oc-tool-chevron{width:12px;height:12px;flex-shrink:0;transition:transform .15s ease}.oc-process-inline-summary.is-open .oc-tool-chevron{transform:rotate(90deg)}.oc-process-inline-body{display:flex;flex-direction:column;gap:8px;margin-top:8px}.oc-tool-duration{flex-shrink:0;font-size:11px;font-variant-numeric:tabular-nums;color:var(--muted)}.oc-tool-expand-result{margin-top:4px;font-size:12px}.oc-process-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:10px 12px;border-bottom:1px solid var(--hairline);flex-shrink:0}.oc-process-title{display:inline-flex;align-items:center;gap:8px;font-weight:700;font-size:13px;color:var(--ink)}.oc-process-title-mark{width:8px;height:8px;border-radius:50%;background:var(--orange)}.oc-process-count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 6px;border-radius:var(--radius-pill);background:var(--surface-muted);color:var(--muted);font-size:11px;font-weight:650}.oc-process-close{font-size:12px}.oc-process-timeline{flex:1 1 auto;min-height:0;overflow-y:auto;padding:var(--space-3);display:flex;flex-direction:column;gap:0}.oc-process-empty{padding:var(--space-4);color:var(--muted);font-size:12.5px;line-height:1.5;text-align:center}.oc-process-item{display:grid;grid-template-columns:20px 52px minmax(0,1fr);gap:8px;align-items:start;padding:4px 0}.oc-process-rail{position:relative;display:grid;place-items:center;min-height:34px}.oc-process-rail:before{position:absolute;top:0;bottom:0;width:1px;background:var(--hairline);content:""}.oc-process-item.is-first .oc-process-rail:before{top:50%}.oc-process-item.is-last .oc-process-rail:before{bottom:50%}.oc-process-dot{position:relative;z-index:1;width:8px;height:8px;border-radius:50%;background:var(--surface);border:2px solid color-mix(in srgb,var(--orange) 55%,var(--hairline))}.oc-process-item.is-running .oc-process-dot{border-color:var(--orange-active);background:var(--orange-soft)}.oc-process-item.is-error .oc-process-dot{border-color:var(--red);background:color-mix(in srgb,var(--red) 18%,var(--surface))}.oc-process-time{padding-top:10px;font-size:11px;color:var(--muted-soft);font-variant-numeric:tabular-nums;white-space:nowrap}.oc-process-body{min-width:0}.oc-process-toggle{cursor:pointer;font:inherit}.oc-process-toggle.is-active{border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline));background:color-mix(in srgb,var(--orange) 10%,var(--surface));color:var(--orange-active)}.oc-process-toggle.is-running{border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline));color:var(--orange-active)}.oc-process-toggle.is-error{border-color:color-mix(in srgb,var(--red) 35%,var(--hairline));background:color-mix(in srgb,var(--red) 8%,var(--surface));color:var(--red)}.oc-process-summary{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border:1px solid var(--hairline);border-radius:var(--radius-pill);background:var(--surface);color:var(--muted);font-size:11.5px;font-weight:650;cursor:pointer;font:inherit;max-width:min(420px,100%);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.oc-process-summary:hover,.oc-process-summary.is-open{border-color:color-mix(in srgb,var(--orange) 35%,var(--hairline));color:var(--orange-active)}.oc-process-summary.is-running{color:var(--orange-active);border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline));background:var(--orange-soft)}.oc-process-summary.is-error{color:var(--red);border-color:color-mix(in srgb,var(--red) 35%,var(--hairline));background:color-mix(in srgb,var(--red) 8%,var(--surface))}.oc-process-summary.is-ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 30%,var(--hairline))}@media(max-width:900px){.oc-sidebar{position:absolute;inset:0 auto 0 0;z-index:7;width:min(300px,calc(100% - 24px));margin-right:0;box-shadow:var(--shadow-soft)}.oc-sidebar.is-collapsed{position:static;width:auto}.oc-workspace.has-process .oc-process{position:absolute;top:0;right:0;bottom:0;z-index:8;width:min(360px,calc(100% - 24px));min-width:0;flex:none;margin-left:0;border-radius:var(--radius-md) 0 0 var(--radius-md);box-shadow:var(--shadow-soft)}}.oc-banner{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);padding:10px 14px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 94%,transparent);box-shadow:var(--shadow-panel)}.oc-shell>.oc-alert:first-child{margin-top:0}.oc-banner-title{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--ink)}.oc-banner-dot{width:8px;height:8px;border-radius:50%;background:var(--orange)}.oc-banner-body{color:var(--body);font-size:12.5px;line-height:1.45}.oc-banner-body strong{color:var(--ink)}.oc-cap-chips{display:inline-flex;flex-wrap:wrap;gap:6px;margin-left:auto;align-items:center}.oc-cap-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border:1px solid color-mix(in srgb,var(--green) 30%,var(--hairline));border-radius:var(--radius-pill);background:color-mix(in srgb,var(--mint) 50%,var(--surface));color:var(--green);font-size:11.5px;font-weight:650}button.oc-cap-chip{font:inherit;cursor:pointer}.oc-tools-menu{position:relative}.oc-tools-menu--composer .oc-tools-catalog{top:auto;bottom:calc(100% + 8px)}.oc-tools-toggle.is-active{border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline));background:color-mix(in srgb,var(--orange) 10%,var(--surface));color:var(--orange-active)}.oc-tools-catalog{position:absolute;top:calc(100% + 8px);right:0;z-index:20;width:min(420px,calc(100vw - 48px));max-height:min(480px,60vh);display:flex;flex-direction:column;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-soft);animation:panel-in .16s ease;overflow:hidden}.oc-tools-catalog-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--hairline);flex-shrink:0}.oc-tools-catalog-head strong{font-size:13px;color:var(--ink)}.oc-tools-catalog-meta{font-size:11.5px;color:var(--muted-soft)}.oc-tools-catalog-close{margin-left:auto;font-size:12px}.oc-tools-catalog-body{overflow-y:auto;padding:var(--space-3);display:flex;flex-direction:column;gap:var(--space-3)}.oc-tools-group-title{margin:0 0 8px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted-soft)}.oc-tools-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.oc-tools-item{padding:8px 10px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--surface-muted) 55%,var(--surface))}.oc-tools-item-head{display:flex;align-items:center;gap:8px;margin-bottom:4px}.oc-tools-name{font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:12.5px;font-weight:650;color:var(--ink)}.oc-tools-kind{margin-left:auto;font-size:10.5px;font-weight:650;padding:1px 7px;border-radius:var(--radius-pill);color:var(--muted);background:var(--surface);border:1px solid var(--hairline)}.oc-tools-kind.is-explore,.oc-tools-kind.is-read{color:var(--green);border-color:color-mix(in srgb,var(--green) 28%,var(--hairline));background:color-mix(in srgb,var(--mint) 45%,transparent)}.oc-tools-kind.is-mutation{color:var(--orange-active);border-color:color-mix(in srgb,var(--orange) 35%,var(--hairline));background:var(--orange-soft)}.oc-tools-kind.is-long-running{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 35%,var(--hairline));background:color-mix(in srgb,var(--amber) 10%,var(--surface))}.oc-tools-desc{margin:0;font-size:12px;line-height:1.45;color:var(--body)}.oc-tools-cli{margin:4px 0 0;font-size:11px;color:var(--muted-soft)}.oc-tools-cli code{font-size:11px;color:var(--muted)}.oc-alert{padding:8px 12px;border-radius:var(--radius-md);font-size:12.5px;line-height:1.45;animation:panel-in .18s ease}.oc-alert-warning{border:1px solid color-mix(in srgb,var(--amber) 35%,var(--hairline));background:color-mix(in srgb,var(--amber) 8%,var(--surface));color:var(--amber)}.oc-alert-error{border:1px solid color-mix(in srgb,var(--red) 35%,var(--hairline));background:color-mix(in srgb,var(--red) 7%,var(--surface));color:var(--red)}.oc-messages{flex:1 1 auto;min-height:0;overflow-y:auto;padding:var(--space-3) var(--space-3) var(--space-2);display:flex;flex-direction:column;gap:var(--space-3)}.oc-messages.has-thread:before{content:"";flex:1 1 auto;min-height:0}.oc-messages.is-empty{justify-content:center;align-items:center;padding:var(--space-5) var(--space-4) var(--space-4);background:radial-gradient(640px 300px at 50% 28%,rgb(241 216 203 / 34%),transparent 68%),radial-gradient(520px 240px at 78% 78%,rgb(216 234 213 / 26%),transparent 62%)}.oc-main.is-landing{position:relative}.oc-day-sep{display:flex;align-items:center;gap:var(--space-3);color:var(--muted-soft);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;margin:var(--space-2) 0}.oc-day-sep:before,.oc-day-sep:after{content:"";flex:1;height:1px;background:var(--hairline)}.oc-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:0 1 auto;gap:var(--space-5);text-align:center;width:min(100%,680px);padding:var(--space-2) var(--space-2) var(--space-4);animation:oc-empty-in .28s ease both}@keyframes oc-empty-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.oc-empty{animation:none}}.oc-empty-hero{display:flex;flex-direction:column;align-items:center;gap:var(--space-3)}.oc-empty-icon{display:grid;place-items:center;width:56px;height:56px;border-radius:50%;background:linear-gradient(145deg,color-mix(in srgb,var(--orange) 18%,white),color-mix(in srgb,var(--mint) 35%,white));color:var(--orange-active);font-size:26px;font-weight:800;font-family:var(--font-mono, "JetBrains Mono", monospace);box-shadow:0 0 0 1px color-mix(in srgb,var(--orange) 18%,transparent)}.oc-empty-copy{display:flex;flex-direction:column;align-items:center;gap:var(--space-2)}.oc-empty h3{margin:0;font-size:20px;font-weight:700;letter-spacing:-.02em;color:var(--ink)}.oc-empty p{margin:0;max-width:48ch;color:var(--muted);font-size:13px;line-height:1.55}.oc-suggestions{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2);width:100%}@media(max-width:560px){.oc-suggestions{grid-template-columns:1fr}}.oc-suggestion{appearance:none;display:flex;flex-direction:column;gap:4px;text-align:left;padding:12px 14px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 88%,transparent);color:var(--ink);cursor:pointer;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);transition:border-color var(--transition-fast),background var(--transition-fast),transform var(--transition-fast),box-shadow var(--transition-fast)}.oc-suggestion:hover:not(:disabled){border-color:var(--orange);background:var(--surface);box-shadow:0 0 0 3px var(--orange-soft);transform:translateY(-1px)}.oc-suggestion:disabled{opacity:.55;cursor:not-allowed}.oc-suggestion strong{font-size:13px;font-weight:700}.oc-suggestion span{color:var(--muted);font-size:12px;line-height:1.4}.oc-empty-tips{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-2) var(--space-3);margin:0;padding:0;list-style:none;color:var(--muted-soft);font-size:12px}.oc-empty-tips li{display:inline-flex;align-items:center;gap:6px}.oc-empty-tips kbd{display:inline-grid;place-items:center;min-width:1.4em;padding:1px 6px;border:1px solid var(--hairline);border-radius:5px;background:var(--surface);color:var(--body);font-family:var(--font-mono, "JetBrains Mono", monospace);font-size:11px;font-weight:600;line-height:1.4}.oc-empty-cta{margin-top:calc(var(--space-1) * -1)}.oc-row{display:flex;flex-direction:column;gap:4px;max-width:100%}.oc-row.is-user{align-self:flex-end;align-items:flex-end;width:auto;max-width:min(100%,720px)}.oc-row.is-assistant,.oc-row.is-tool{align-self:stretch;align-items:stretch;width:100%;max-width:100%}.oc-meta{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--muted-soft)}.oc-row.is-assistant .oc-meta,.oc-row.is-user .oc-meta{width:100%;max-width:100%}.oc-message-copy{appearance:none;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:26px;height:26px;margin-left:auto;padding:0;border:1px solid transparent;border-radius:var(--radius-sm);background:transparent;color:var(--muted-soft);cursor:pointer;opacity:0;transition:opacity var(--transition-fast),background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.oc-row:hover .oc-message-copy,.oc-row:focus-within .oc-message-copy,.oc-message-copy:focus-visible{opacity:1}.oc-message-copy:hover{color:var(--body);background:color-mix(in srgb,var(--ink) 6%,transparent);border-color:var(--hairline)}.oc-message-copy.is-copied{opacity:1;color:var(--green, #1a7f37);border-color:color-mix(in srgb,var(--green, #1a7f37) 35%,transparent)}@media(hover:none){.oc-message-copy{opacity:.5}}.oc-avatar{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;font-size:11px;font-weight:700;flex-shrink:0}.oc-avatar-user{background:var(--ink);color:#fff}.oc-avatar-assistant{background:var(--orange);color:#fff}.oc-role{font-weight:700;color:var(--body)}.oc-time{font-variant-numeric:tabular-nums}.oc-bubble{padding:10px 14px;border-radius:var(--radius-lg);font-size:14px;line-height:1.6;overflow-wrap:anywhere;word-break:break-word;animation:bubble-in .16s ease}@keyframes bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.oc-bubble-user{background:var(--ink);color:#fff;border-bottom-right-radius:4px}.oc-bubble-assistant{background:var(--surface);color:var(--ink);border:1px solid var(--hairline);border-bottom-left-radius:4px;box-shadow:var(--shadow-panel)}.oc-bubble-tool{background:var(--canvas-soft);color:var(--body);border:1px solid var(--hairline)}.oc-bubble-error{border-color:color-mix(in srgb,var(--red) 40%,var(--hairline));background:color-mix(in srgb,var(--red) 7%,var(--surface));color:var(--red)}.oc-md{display:flex;flex-direction:column;gap:var(--space-2)}.oc-md>*:first-child{margin-top:0}.oc-md>*:last-child{margin-bottom:0}.oc-md p{margin:0}.oc-md h1,.oc-md h2,.oc-md h3,.oc-md h4{margin:var(--space-3) 0 var(--space-2);color:inherit;font-weight:700;line-height:1.3}.oc-md h1{font-size:1.3em}.oc-md h2{font-size:1.18em}.oc-md h3{font-size:1.06em}.oc-md h4{font-size:1em}.oc-md ul,.oc-md ol{margin:0;padding-left:1.4em;display:flex;flex-direction:column;gap:2px}.oc-md li{margin:0}.oc-md blockquote{margin:0;padding:2px 0 2px 12px;border-left:3px solid var(--hairline-strong);color:var(--body)}.oc-bubble-user .oc-md blockquote{border-left-color:#ffffff59;color:#ffffffd1}.oc-md code{font-size:.86em;padding:1px 5px;border-radius:4px;background:color-mix(in srgb,var(--ink) 8%,transparent)}.oc-bubble-user .oc-md code{background:#ffffff29}.oc-md pre{margin:0;padding:0;background:transparent}.oc-codeblock{margin:0;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface-muted);overflow:hidden}.oc-bubble-assistant .oc-codeblock{background:#f3efe8}.oc-codeblock-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:5px 6px 5px 10px;border-bottom:1px solid var(--hairline);font-size:11px;color:var(--muted);background:color-mix(in srgb,var(--ink) 4%,transparent)}.oc-codeblock-lang{font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-weight:600;text-transform:lowercase}.oc-codeblock-copy{appearance:none;display:inline-flex;align-items:center;gap:5px;min-height:26px;padding:0 9px;border:1px solid transparent;border-radius:var(--radius-sm);background:transparent;color:var(--muted);font-size:11px;font-weight:600;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.oc-codeblock-copy:hover{background:var(--surface);color:var(--ink);border-color:var(--hairline-strong)}.oc-codeblock pre{margin:0;padding:var(--space-3) var(--space-4);overflow-x:auto;font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:12.5px;line-height:1.55;white-space:pre;color:var(--ink)}.oc-md a{color:var(--orange);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--orange) 40%,transparent)}.oc-md a:hover{border-bottom-color:var(--orange)}.oc-md hr{margin:var(--space-2) 0;border:none;border-top:1px solid var(--hairline-strong)}.oc-stream{white-space:pre-wrap;font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:13px;line-height:1.55}.oc-cursor{display:inline-block;width:7px;height:1.05em;margin-left:2px;vertical-align:text-bottom;background:var(--orange);animation:oc-blink 1s steps(2,start) infinite;border-radius:1px}@keyframes oc-blink{to{opacity:0}}.oc-tool{border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);overflow:hidden;box-shadow:var(--shadow-panel);animation:panel-in .16s ease}.oc-tool.is-error{border-color:color-mix(in srgb,var(--red) 38%,var(--hairline))}.oc-tool.is-running{border-color:color-mix(in srgb,var(--orange) 40%,var(--hairline))}.oc-tool-head{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:9px 12px;border:none;background:transparent;text-align:left;cursor:pointer;font:inherit;color:var(--ink)}.oc-tool-head:hover{background:var(--surface-muted)}.oc-tool-chevron{flex-shrink:0;width:12px;height:12px;transition:transform var(--transition-fast)}.oc-tool-head[aria-expanded=true] .oc-tool-chevron{transform:rotate(90deg)}.oc-tool-icon{display:grid;place-items:center;width:22px;height:22px;border-radius:6px;background:var(--surface-muted);color:var(--orange-active);flex-shrink:0}.oc-tool-name{font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:12.5px;font-weight:650;flex-shrink:0}.oc-tool-args{color:var(--muted);font-size:11.5px;font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-right:8px;min-width:0}.oc-tool-status{margin-left:auto;flex-shrink:0;font-size:11px;font-weight:650;padding:2px 8px;border-radius:var(--radius-pill)}.oc-tool-waiting{color:var(--muted);font-size:12px;animation:pulse 1.5s infinite}.oc-tool-status.is-running{color:var(--orange-active);background:var(--orange-soft)}.oc-tool-status.is-ok{color:var(--green);background:color-mix(in srgb,var(--mint) 60%,transparent)}.oc-tool-status.is-error{color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}.oc-tool-body{padding:0 var(--space-4) var(--space-3);border-top:1px solid var(--hairline)}.oc-tool-section{display:flex;flex-direction:column;gap:4px;padding-top:var(--space-3)}.oc-tool-label{font-size:11px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--muted-soft)}.oc-tool-code{margin:0;padding:var(--space-3);border-radius:var(--radius-sm);background:var(--surface-muted);font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:260px;overflow-y:auto;color:var(--body)}.oc-composer{flex:0 0 auto;flex-shrink:0;border-top:1px solid var(--hairline);padding:var(--space-2) var(--space-3) var(--space-3);background:color-mix(in srgb,var(--canvas) 92%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:2}.oc-composer-inner{display:flex;flex-direction:column;gap:var(--space-2);max-width:1080px;margin:0 auto;position:relative}.console-shell.is-chat-focus .oc-composer-inner{max-width:none}.oc-composer-shell{position:relative;display:flex;align-items:flex-end;gap:var(--space-2);padding:8px 8px 8px 14px;border:1px solid var(--hairline-strong);border-radius:var(--radius-lg);background:var(--surface);box-shadow:var(--shadow-panel);transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.oc-composer-shell:focus-within{border-color:var(--orange);box-shadow:0 0 0 3px var(--orange-soft)}.oc-composer-shell.is-busy{opacity:.78}.oc-textarea{flex:1 1 auto;min-width:0;min-height:52px;max-height:280px;padding:8px 0;border:none;background:transparent;color:var(--ink);font:inherit;font-size:14px;line-height:1.5;resize:none;outline:none}.oc-textarea::placeholder{color:var(--muted-soft)}.oc-send{appearance:none;display:grid;place-items:center;width:38px;height:38px;flex-shrink:0;padding:0;border:1px solid var(--orange);border-radius:50%;background:var(--orange);color:#fff;cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast),transform var(--transition-fast)}.oc-send:hover:not(:disabled){background:var(--orange-active);border-color:var(--orange-active)}.oc-send:active:not(:disabled){transform:scale(.94)}.oc-send:disabled{opacity:.4;cursor:not-allowed}.oc-stop{appearance:none;display:grid;place-items:center;width:38px;height:38px;flex-shrink:0;padding:0;border:1px solid var(--hairline-strong);border-radius:50%;background:var(--surface);color:var(--red);cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast)}.oc-stop:hover{background:color-mix(in srgb,var(--red) 8%,var(--surface));border-color:var(--red)}.oc-composer-foot{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;font-size:11.5px;color:var(--muted)}.oc-composer-hint{display:inline-flex;align-items:center;gap:5px}.oc-kbd{display:inline-block;padding:1px 6px;border:1px solid var(--hairline-strong);border-bottom-width:2px;border-radius:4px;background:var(--surface);color:var(--body);font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:10.5px;line-height:1.4}.oc-operation-card{width:min(720px,calc(100% - 42px));margin:var(--space-3) auto;padding:var(--space-4);border:1px solid var(--hairline-strong);border-left:4px solid var(--blue);border-radius:var(--radius-lg);background:color-mix(in srgb,var(--surface) 96%,var(--blue) 4%);box-shadow:var(--shadow-sm)}.oc-operation-card.is-succeeded{border-left-color:var(--green)}.oc-operation-card.is-failed,.oc-operation-card.is-timed-out{border-left-color:var(--red)}.oc-operation-card.is-needs-reconcile{border-left-color:var(--orange)}.oc-operation-head,.oc-operation-actions{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}.oc-operation-kicker{margin-bottom:2px;color:var(--muted);font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.oc-operation-state{padding:3px 9px;border-radius:999px;background:color-mix(in srgb,var(--blue) 12%,transparent);color:var(--blue);font-size:11px;font-weight:700}.oc-operation-state.is-succeeded{background:color-mix(in srgb,var(--green) 12%,transparent);color:var(--green)}.oc-operation-state.is-failed,.oc-operation-state.is-timed-out{background:color-mix(in srgb,var(--red) 12%,transparent);color:var(--red)}.oc-operation-state.is-needs-reconcile{background:color-mix(in srgb,var(--orange) 14%,transparent);color:var(--orange-active)}.oc-operation-id,.oc-operation-controller{margin-top:var(--space-2);color:var(--muted);font-size:12px;overflow-wrap:anywhere}.oc-operation-identities{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--space-3)}.oc-operation-identities span{padding:3px 7px;border:1px solid var(--hairline);border-radius:999px;background:var(--surface-raised);color:var(--muted);font-size:11px}.oc-operation-preview{max-height:150px;margin:var(--space-3) 0 0;padding:var(--space-2) var(--space-3);overflow:auto;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface-sunken);color:var(--body);font-size:11px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.oc-operation-preview.is-error{border-color:color-mix(in srgb,var(--red) 30%,var(--hairline));color:var(--red)}.oc-operation-actions{justify-content:flex-start;margin-top:var(--space-3)}.oc-operation-actions time{margin-left:auto;color:var(--muted-soft);font-size:11px}.oc-interview-start{margin:var(--space-3) auto}.oc-draft-card{margin:var(--space-3);padding:var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface-raised)}.oc-draft-card>header,.oc-task-kind-card{display:flex;align-items:center;gap:var(--space-3);justify-content:space-between}.oc-interview-bubble{margin:var(--space-3) 0;padding:var(--space-3);border-left:3px solid var(--accent);background:var(--surface-sunken)}.oc-interview-bubble textarea{width:100%;min-height:72px;margin:var(--space-2) 0;resize:vertical}.oc-interview-bubble .btn+.btn{margin-left:var(--space-2)}.oc-draft-card pre{max-height:300px;overflow:auto;white-space:pre-wrap;font-size:11px}.oc-assessment{margin:var(--space-3) 0;color:var(--orange)}.oc-assessment.is-fresh,.oc-task-kind-card.is-confirmed{color:var(--green)}.oc-task-kind-card{margin-top:var(--space-3);padding:var(--space-3);border:1px solid var(--hairline);border-radius:var(--radius-md)}.oc-task-kind-card small{color:var(--muted)}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}.oc-human-gate-card{margin:12px 0;padding:14px;border:1px solid var(--border);border-left:4px solid var(--accent);border-radius:10px;background:var(--surface-raised)}.oc-human-gate-card header,.oc-human-gate-card footer{display:flex;justify-content:space-between;align-items:center;gap:12px}.oc-human-gate-card header div{display:grid;gap:3px}.oc-human-gate-card header span{font-size:12px;text-transform:uppercase}.oc-human-gate-challenges,.oc-human-gate-card ol{max-height:160px;overflow:auto}.oc-human-gate-card footer{margin-top:12px}.oc-human-gate-error{margin-top:8px;color:var(--danger)}.oc-human-gate-card.is-confirmed{border-left-color:var(--success)}.oc-task-context{margin:var(--space-3);padding:var(--space-3);border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface-raised)}.oc-task-context>header{display:flex;justify-content:space-between;gap:var(--space-2);align-items:center}.oc-task-context>header div{display:grid;gap:2px}.oc-task-context>header small,.oc-task-context>header span,.oc-task-context-empty{color:var(--text-muted)}.oc-task-context-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-2);margin-top:var(--space-3)}.oc-task-context-grid>div{display:grid;gap:4px;min-width:0;padding:var(--space-2);border:1px solid var(--hairline);border-radius:var(--radius-md)}.oc-task-context-grid span,.oc-task-context-grid small{overflow-wrap:anywhere}.oc-shortcut-palette{position:absolute;z-index:12;left:0;right:0;bottom:calc(100% + 8px);display:grid;padding:6px;border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface-raised);box-shadow:var(--shadow-lg)}.oc-shortcut-palette button{display:flex;gap:var(--space-3);align-items:center;border:0;border-radius:var(--radius-md);padding:9px 10px;color:inherit;background:transparent;text-align:left}.oc-shortcut-palette button:hover,.oc-shortcut-palette button.is-active{background:var(--surface-hover)}.oc-shortcut-palette button span{display:grid;gap:2px}.oc-shortcut-palette button small{color:var(--text-muted)}.oc-composer-inner{position:relative}@media(max-width:800px){.oc-task-context-grid{grid-template-columns:1fr}}.oc-file-palette{position:absolute;z-index:13;left:0;right:0;bottom:calc(100% + 8px);display:grid;max-height:240px;overflow:auto;padding:6px;border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface-raised);box-shadow:var(--shadow-lg)}.oc-file-palette button{border:0;padding:8px 10px;color:inherit;background:transparent;text-align:left;border-radius:var(--radius-md)}.oc-file-palette button:hover{background:var(--surface-hover)}.oc-runtime-controls{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px}.oc-runtime-controls select{max-width:220px;border:1px solid var(--hairline);border-radius:var(--radius-md);padding:5px 8px;color:inherit;background:var(--surface-raised)}.oc-runtime-controls select.oc-model-select{max-width:min(100%,360px);font-family:JetBrains Mono,SFMono-Regular,Consolas,monospace;font-size:12px}.oc-runtime-controls .oc-process-summary{margin-left:0}.oc-usage{color:var(--text-muted);font-size:12px;font-variant-numeric:tabular-nums}.oc-runtime-context-menu{position:relative;margin-left:auto;flex-shrink:0}.oc-runtime-context-toggle.is-active{color:var(--orange-active);background:color-mix(in srgb,var(--orange) 10%,var(--surface))}.oc-runtime-context-panel{position:absolute;right:0;bottom:calc(100% + 8px);z-index:16;width:min(760px,calc(100vw - 24px));max-height:min(72vh,720px);display:flex;flex-direction:column;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface);box-shadow:var(--shadow-soft);animation:panel-in .16s ease;overflow:hidden}.oc-runtime-context-head{display:flex;align-items:flex-start;gap:12px;flex-shrink:0;padding:12px 14px;border-bottom:1px solid var(--hairline);background:var(--surface-raised)}.oc-runtime-context-head-copy{flex:1;min-width:0;display:grid;gap:2px}.oc-runtime-context-head strong{font-size:14px}.oc-runtime-context-meta{font-size:11px;color:var(--muted)}.oc-runtime-context-close{flex-shrink:0;min-height:28px;padding:0 8px;font-size:12px}.oc-runtime-context-body{flex:1;min-height:0;overflow:auto;padding:12px 14px 14px;display:grid;gap:14px}.oc-runtime-context-chips{display:flex;flex-wrap:wrap;gap:6px}.oc-runtime-context-chip{display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:4px 8px;border:1px solid var(--hairline);border-radius:999px;background:var(--canvas-soft);color:var(--body);font-size:11px;line-height:1.3}.oc-runtime-context-chip code{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.oc-runtime-context-section{display:grid;gap:8px;min-width:0}.oc-runtime-context-section-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.oc-runtime-context-section-head strong{font-size:12px}.oc-runtime-context-hash{display:inline-block;margin-left:6px;font-size:11px;color:var(--muted)}.oc-runtime-context-text{margin:0;max-height:min(36vh,360px);overflow:auto;padding:10px 12px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--canvas-soft);color:var(--body);font-size:12px;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere}.oc-runtime-context-empty{margin:0;color:var(--muted);font-size:12px}.oc-runtime-context-skill-cards{margin:0;padding:0;list-style:none;display:grid;gap:8px}.oc-runtime-context-skill-cards details{border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--surface-raised);overflow:hidden}.oc-runtime-context-skill-cards summary{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:12px}.oc-runtime-context-skill-cards summary span{color:var(--muted);font-variant-numeric:tabular-nums}.oc-runtime-context-skill-desc{margin:0;padding:0 10px 8px;color:var(--muted);font-size:12px;line-height:1.45}.oc-runtime-context-skill-cards .oc-runtime-context-text{max-height:min(28vh,280px);border-left:none;border-right:none;border-bottom:none;border-radius:0}.oc-runtime-context-tools{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:6px}.oc-runtime-context-tools li code{display:inline-block;padding:3px 7px;border:1px solid var(--hairline);border-radius:6px;background:var(--canvas-soft);font-size:11px}.oc-runtime-context-raw{padding-top:10px;border-top:1px solid var(--hairline);font-size:12px;color:var(--muted)}.oc-runtime-context-raw summary{cursor:pointer;-webkit-user-select:none;user-select:none}.oc-runtime-context-raw pre{margin:8px 0 0;max-height:180px;overflow:auto;padding:8px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--canvas-soft);font-size:11px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}@media(max-width:800px){.oc-runtime-context-menu{margin-left:0;width:100%}.oc-runtime-context-panel{left:0;right:0;width:auto;max-height:min(78vh,680px)}}.oc-artifact-card{max-width:100%;margin:12px 0;padding:14px;overflow:hidden;border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--surface-raised)}.oc-artifact-card header{display:flex;justify-content:space-between;gap:12px}.oc-artifact-card pre{max-height:320px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere}.oc-artifact-card iframe{width:100%;min-height:280px;border:1px solid var(--hairline);background:#fff}.oc-load-history{display:block;margin:8px auto}.oc-attach-button{display:inline-flex;min-height:24px;align-items:center;color:var(--muted);cursor:pointer;font-size:12px}.oc-composer-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:10px 14px;margin-bottom:6px;font-size:11.5px;color:var(--muted)}.oc-composer-toolbar .oc-attach-button{margin-bottom:0}.oc-attachment-list{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}.oc-attachment-list span{display:inline-flex;align-items:center;gap:5px;max-width:100%;padding:4px 8px;border:1px solid var(--hairline);border-radius:999px;overflow-wrap:anywhere}.oc-attachment-list button{border:0;color:inherit;background:transparent;cursor:pointer}@media(max-width:640px){.oc-runtime-controls,.oc-composer-foot{align-items:stretch;flex-direction:column}.oc-runtime-controls select,.oc-runtime-controls button{width:100%;max-width:100%;min-height:44px}.oc-artifact-card{width:100%}.oc-composer{padding-inline:8px}}.oc-branch-actions{display:inline-flex;gap:.4rem;align-items:center;flex-wrap:wrap}.oc-branch-badge{padding:.15rem .45rem;border-radius:999px;border:1px solid currentColor;font-size:.72rem}.oc-branch-badge.is-branch{color:#f6ad55}.oc-branch-badge.is-mainline{color:#68d391}.night-workbench .night-health{margin:var(--space-4) 0;padding:var(--space-3) var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface-muted)}.night-health-main{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3)}.night-health-pill{display:inline-flex;align-items:center;padding:2px 10px;border-radius:var(--radius-pill);background:color-mix(in srgb,var(--green) 14%,white);color:var(--green);font-size:12px;font-weight:600}.night-health-pill.is-bad{background:color-mix(in srgb,var(--red) 14%,white);color:var(--red)}.night-health-hint{margin:var(--space-2) 0 0}.night-aux-ticker{margin-top:var(--space-3);padding-top:var(--space-3);border-top:1px solid var(--hairline)}.night-doctor-list{margin:var(--space-2) 0 0;padding-left:1.2em;color:var(--body);font-size:12.5px}.night-kpi{display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-4);margin:var(--space-3) 0;color:var(--body);font-size:13px}.night-board,.night-wizard,.night-discard-card,.night-advanced{margin-top:var(--space-5)}.night-schedule-list{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-3)}.night-schedule-row{padding:var(--space-3) var(--space-4);border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--surface)}.night-schedule-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-2)}.night-status-chip{font-size:12px;color:var(--blue);font-weight:600}.night-next-action{font-size:12px;overflow-wrap:anywhere}.night-review-card,.night-discard-card{padding:var(--space-4);border:1px solid var(--hairline-strong);border-radius:var(--radius-md);background:var(--canvas-soft)}.night-writeset{margin:0;padding-left:1.1em}.night-advanced{border-top:1px solid var(--hairline);padding-top:var(--space-3)}.night-advanced summary{cursor:pointer;color:var(--body);font-weight:600}.checkbox-field{display:flex;align-items:center;gap:var(--space-2)}
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
7
  <title>Loop 操作台 · Operator Console</title>
8
- <script type="module" crossorigin src="/assets/index-Cwx-ZVEQ.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-Yyn3ynVv.css">
8
+ <script type="module" crossorigin src="/assets/index-D9gnJn_l.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-rajoXwkM.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -0,0 +1,118 @@
1
+ function asRecord(value) {
2
+ if (!value || typeof value !== "object" || Array.isArray(value))
3
+ return null;
4
+ return value;
5
+ }
6
+ function readString(rec, key) {
7
+ const value = rec[key];
8
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
9
+ }
10
+ function readStringList(rec, key) {
11
+ const value = rec[key];
12
+ if (!Array.isArray(value))
13
+ return undefined;
14
+ const items = value.filter((entry) => typeof entry === "string");
15
+ return items.length > 0 ? items : undefined;
16
+ }
17
+ /** Pull reviewPacket from accept envelope, operation.result, or raw CLI JSON. */
18
+ export function extractNightPrepareReview(payload) {
19
+ const root = asRecord(payload);
20
+ if (!root)
21
+ return null;
22
+ const nestedResult = asRecord(root.result);
23
+ const candidates = [
24
+ asRecord(root.reviewPacket),
25
+ nestedResult ? asRecord(nestedResult.reviewPacket) : null,
26
+ nestedResult,
27
+ root,
28
+ ].filter(Boolean);
29
+ for (const candidate of candidates) {
30
+ const scheduleId = readString(candidate, "scheduleId") ?? readString(candidate, "id");
31
+ const gateToken = readString(candidate, "gateToken") ??
32
+ readString(candidate, "approveGate") ??
33
+ readString(candidate, "writeSetGateToken");
34
+ if (!scheduleId || !gateToken)
35
+ continue;
36
+ return {
37
+ scheduleId,
38
+ gateToken,
39
+ ...(readString(candidate, "featureId")
40
+ ? { featureId: readString(candidate, "featureId") }
41
+ : {}),
42
+ ...(readString(candidate, "taskId")
43
+ ? { taskId: readString(candidate, "taskId") }
44
+ : {}),
45
+ ...(readStringList(candidate, "writeSet")
46
+ ? { writeSet: readStringList(candidate, "writeSet") }
47
+ : {}),
48
+ ...(readString(candidate, "worktreePath")
49
+ ? { worktreePath: readString(candidate, "worktreePath") }
50
+ : {}),
51
+ ...(readString(candidate, "branch")
52
+ ? { branch: readString(candidate, "branch") }
53
+ : {}),
54
+ ...(readString(candidate, "baseBranch")
55
+ ? { baseBranch: readString(candidate, "baseBranch") }
56
+ : {}),
57
+ ...(readString(candidate, "baseCommit")
58
+ ? { baseCommit: readString(candidate, "baseCommit") }
59
+ : {}),
60
+ ...(readString(candidate, "executeAtUtc")
61
+ ? { executeAtUtc: readString(candidate, "executeAtUtc") }
62
+ : {}),
63
+ ...(readString(candidate, "taskCard")
64
+ ? { taskCard: readString(candidate, "taskCard") }
65
+ : {}),
66
+ };
67
+ }
68
+ return null;
69
+ }
70
+ /** Map featureId → conventional Feature Packet directory (repo-relative). */
71
+ export function featureDirFromFeatureId(featureId) {
72
+ const id = featureId.trim().replace(/^\/+|\/+$/g, "");
73
+ return `docs/features/${id}`;
74
+ }
75
+ /** datetime-local value → admission `--at` (`YYYY-MM-DD HH:mm`). */
76
+ export function datetimeLocalToAdmissionAt(value) {
77
+ const trimmed = value.trim();
78
+ const match = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/.exec(trimmed);
79
+ if (!match)
80
+ return null;
81
+ return `${match[1]} ${match[2]}`;
82
+ }
83
+ export function defaultNightAtLocal() {
84
+ const d = new Date();
85
+ d.setHours(20, 0, 0, 0);
86
+ const pad = (n) => String(n).padStart(2, "0");
87
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
88
+ }
89
+ export function formatUtcLocal(iso) {
90
+ if (!iso)
91
+ return "—";
92
+ const ms = Date.parse(iso);
93
+ if (Number.isNaN(ms))
94
+ return iso;
95
+ try {
96
+ return new Intl.DateTimeFormat("zh-CN", {
97
+ dateStyle: "short",
98
+ timeStyle: "short",
99
+ timeZone: "Asia/Shanghai",
100
+ }).format(new Date(ms));
101
+ }
102
+ catch {
103
+ return iso;
104
+ }
105
+ }
106
+ export function nightRowCanHarvest(row) {
107
+ return (row.mergeState === "pending-harvest" ||
108
+ /\bscheduler harvest\b/i.test(row.nextAction));
109
+ }
110
+ export function nightRowCanDiscard(row) {
111
+ return (row.status === "failed" ||
112
+ row.status === "human_required" ||
113
+ row.status === "cancelled" ||
114
+ /\bscheduler discard\b/i.test(row.nextAction));
115
+ }
116
+ export function nightRowNeedsForceDiscard(status) {
117
+ return status === "failed" || status === "human_required";
118
+ }
@@ -1,13 +1,23 @@
1
1
  import { spawn } from "node:child_process";
2
+ import { mkdir, unlink, writeFile } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
2
5
  import { deriveClockUnitName } from "../clock.js";
3
6
  import { MANAGED_MARKER } from "./types.js";
7
+ /** schtasks /TR hard limit (Windows). Long node+bin+args lines must use a .cmd wrapper. */
8
+ export const SCHTASKS_TR_MAX_CHARS = 261;
4
9
  function taskName(unitName) {
5
10
  // schtasks task path; keep under user-visible folder.
6
11
  return `\\${unitName}`;
7
12
  }
8
- export function renderSchtasksCreateArgs(input) {
9
- // Build a single command line with quoted paths. No PowerShell wrapper.
10
- const command = [
13
+ /** Short, user-writable wrapper path (avoids long repo paths in /TR). */
14
+ export function schtasksTickWrapperPath(unitName) {
15
+ const localAppData = process.env.LOCALAPPDATA?.trim() ||
16
+ path.join(os.homedir(), "AppData", "Local");
17
+ return path.join(localAppData, "tea-agent", "loop-agent-night", `${unitName}.cmd`);
18
+ }
19
+ export function renderSchtasksTickCmd(input) {
20
+ const line = [
11
21
  quoteWin(input.nodeBin),
12
22
  quoteWin(input.agentWorkerEntry),
13
23
  "scheduler",
@@ -20,15 +30,24 @@ export function renderSchtasksCreateArgs(input) {
20
30
  "schtasks",
21
31
  "--json",
22
32
  ].join(" ");
33
+ return [
34
+ "@echo off",
35
+ `cd /d ${quoteWin(input.controlRepoRoot)}`,
36
+ line,
37
+ "",
38
+ ].join("\r\n");
39
+ }
40
+ export function renderSchtasksCreateArgs(input) {
23
41
  // /SC MINUTE /MO N → every N minutes (minimum 1). Sub-minute not supported by schtasks.
24
42
  const minutes = Math.max(1, Math.round(input.intervalSec / 60));
43
+ const tr = quoteWin(input.trPath);
25
44
  return [
26
45
  "/Create",
27
46
  "/F",
28
47
  "/TN",
29
48
  taskName(input.unitName),
30
49
  "/TR",
31
- command,
50
+ tr,
32
51
  "/SC",
33
52
  "MINUTE",
34
53
  "/MO",
@@ -37,11 +56,31 @@ export function renderSchtasksCreateArgs(input) {
37
56
  "LIMITED",
38
57
  ];
39
58
  }
59
+ export function assertSchtasksTrLength(trPath) {
60
+ const tr = quoteWin(trPath);
61
+ if (tr.length > SCHTASKS_TR_MAX_CHARS) {
62
+ throw new Error(`schtasks /TR exceeds ${SCHTASKS_TR_MAX_CHARS} characters (${tr.length}). ` +
63
+ `Use a shorter LOCALAPPDATA path or shorten the wrapper location. Got: ${tr}`);
64
+ }
65
+ }
40
66
  function quoteWin(value) {
41
67
  if (!/[ \t"]/.test(value))
42
68
  return value;
43
69
  return `"${value.replace(/"/g, '\\"')}"`;
44
70
  }
71
+ function formatSchtasksFailure(detail) {
72
+ const raw = detail.trim() || "unknown schtasks error";
73
+ if (/261/.test(raw) || /\/TR/i.test(raw)) {
74
+ return (`${raw} — Windows schtasks /TR 不能超过 ${SCHTASKS_TR_MAX_CHARS} 个字符。` +
75
+ `已应改用短路径 .cmd 包装;若仍失败请升级到含此修复的版本,或改用 Console 前台辅助 ticker / 手动 scheduler tick。`);
76
+ }
77
+ if (/access is denied|拒绝访问|0x80070005/i.test(raw)) {
78
+ return (`${raw} — 当前用户无权限创建计划任务。` +
79
+ `本适配器使用 /RL LIMITED,通常不需要管理员;请检查公司策略是否禁止普通用户创建任务。` +
80
+ `可改用 Console「开着时辅助 tick」或手动:agent-worker scheduler tick --repo .`);
81
+ }
82
+ return raw;
83
+ }
45
84
  async function runSchtasks(args) {
46
85
  return new Promise((resolve) => {
47
86
  const child = spawn("schtasks", args, {
@@ -68,6 +107,14 @@ async function runSchtasks(args) {
68
107
  });
69
108
  });
70
109
  }
110
+ async function writeTickWrapper(input) {
111
+ const wrapper = schtasksTickWrapperPath(input.unitName);
112
+ await mkdir(path.dirname(wrapper), { recursive: true });
113
+ const body = renderSchtasksTickCmd(input);
114
+ await writeFile(wrapper, body, "utf8");
115
+ assertSchtasksTrLength(wrapper);
116
+ return wrapper;
117
+ }
71
118
  export const win32SchtasksAdapter = {
72
119
  provider: "schtasks",
73
120
  async isAvailable() {
@@ -84,13 +131,11 @@ export const win32SchtasksAdapter = {
84
131
  return deriveClockUnitName(controlRepoRoot);
85
132
  },
86
133
  renderConfig(input) {
134
+ const wrapper = schtasksTickWrapperPath(input.receipt.unitName);
87
135
  return renderSchtasksCreateArgs({
88
136
  unitName: input.receipt.unitName,
89
137
  intervalSec: input.receipt.intervalSec,
90
- nodeBin: input.entrypoints.nodeBin,
91
- agentWorkerEntry: input.entrypoints.agentWorkerEntry,
92
- controlRepoRoot: input.entrypoints.controlRepoRoot,
93
- loopAgentBin: input.entrypoints.loopAgentBin,
138
+ trPath: wrapper,
94
139
  }).join(" ");
95
140
  },
96
141
  async install(input) {
@@ -101,17 +146,21 @@ export const win32SchtasksAdapter = {
101
146
  "/TN",
102
147
  taskName(input.receipt.unitName),
103
148
  ]);
104
- const args = renderSchtasksCreateArgs({
149
+ const trPath = await writeTickWrapper({
105
150
  unitName: input.receipt.unitName,
106
- intervalSec: input.receipt.intervalSec,
107
151
  nodeBin: input.entrypoints.nodeBin,
108
152
  agentWorkerEntry: input.entrypoints.agentWorkerEntry,
109
153
  controlRepoRoot: input.entrypoints.controlRepoRoot,
110
154
  loopAgentBin: input.entrypoints.loopAgentBin,
111
155
  });
156
+ const args = renderSchtasksCreateArgs({
157
+ unitName: input.receipt.unitName,
158
+ intervalSec: input.receipt.intervalSec,
159
+ trPath,
160
+ });
112
161
  const created = await runSchtasks(args);
113
162
  if (created.code !== 0) {
114
- throw new Error(`schtasks create failed: ${created.stderr || created.stdout || `exit ${created.code}`}`);
163
+ throw new Error(`schtasks create failed: ${formatSchtasksFailure(created.stderr || created.stdout || `exit ${created.code}`)}`);
115
164
  }
116
165
  // Marker is stored only in install receipt; schtasks has limited annotation.
117
166
  // Ownership is enforced via receipt unitName hash + TR path match on probe.
@@ -127,11 +176,14 @@ export const win32SchtasksAdapter = {
127
176
  "LIST",
128
177
  ]);
129
178
  if (query.code !== 0) {
179
+ await unlink(schtasksTickWrapperPath(input.receipt.unitName)).catch(() => undefined);
130
180
  return; // already gone
131
181
  }
132
182
  const body = `${query.stdout}\n${query.stderr}`;
183
+ const wrapper = schtasksTickWrapperPath(input.receipt.unitName);
133
184
  if (!body.includes(input.receipt.controlRepoRoot) &&
134
- !body.includes(input.receipt.agentWorkerEntry)) {
185
+ !body.includes(input.receipt.agentWorkerEntry) &&
186
+ !body.includes(wrapper)) {
135
187
  throw new Error(`Refusing to uninstall schtasks unit that does not match install receipt: ${input.receipt.unitName}`);
136
188
  }
137
189
  const del = await runSchtasks([
@@ -141,8 +193,9 @@ export const win32SchtasksAdapter = {
141
193
  taskName(input.receipt.unitName),
142
194
  ]);
143
195
  if (del.code !== 0) {
144
- throw new Error(`schtasks delete failed: ${del.stderr || del.stdout || `exit ${del.code}`}`);
196
+ throw new Error(`schtasks delete failed: ${formatSchtasksFailure(del.stderr || del.stdout || `exit ${del.code}`)}`);
145
197
  }
198
+ await unlink(wrapper).catch(() => undefined);
146
199
  },
147
200
  async probe(input) {
148
201
  const unitName = input.receipt?.unitName ?? input.unitName;
@@ -158,9 +211,11 @@ export const win32SchtasksAdapter = {
158
211
  const body = `${query.stdout}\n${query.stderr}`;
159
212
  let configMatches = null;
160
213
  if (present && input.receipt) {
214
+ const wrapper = schtasksTickWrapperPath(input.receipt.unitName);
161
215
  configMatches =
162
- body.includes(input.receipt.controlRepoRoot) &&
163
- body.includes(input.receipt.agentWorkerEntry);
216
+ body.includes(wrapper) ||
217
+ (body.includes(input.receipt.controlRepoRoot) &&
218
+ body.includes(input.receipt.agentWorkerEntry));
164
219
  }
165
220
  return {
166
221
  present,