@steipete/oracle 0.13.0 → 0.14.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 (91) hide show
  1. package/README.md +20 -9
  2. package/dist/bin/oracle-cli.js +63 -63
  3. package/dist/docs-site/.nojekyll +0 -0
  4. package/dist/docs-site/CNAME +1 -0
  5. package/dist/docs-site/RELEASING.html +410 -0
  6. package/dist/docs-site/agents.html +374 -0
  7. package/dist/docs-site/anthropic.html +368 -0
  8. package/dist/docs-site/bridge.html +400 -0
  9. package/dist/docs-site/browser-mode.html +593 -0
  10. package/dist/docs-site/chromium-forks.html +347 -0
  11. package/dist/docs-site/cli-reference.html +346 -0
  12. package/dist/docs-site/configuration.html +452 -0
  13. package/dist/docs-site/favicon.svg +14 -0
  14. package/dist/docs-site/followup.html +375 -0
  15. package/dist/docs-site/gemini.html +383 -0
  16. package/dist/docs-site/grok.html +325 -0
  17. package/dist/docs-site/index.html +360 -0
  18. package/dist/docs-site/install.html +335 -0
  19. package/dist/docs-site/linux.html +321 -0
  20. package/dist/docs-site/llms.txt +43 -0
  21. package/dist/docs-site/manual-tests.html +596 -0
  22. package/dist/docs-site/mcp.html +391 -0
  23. package/dist/docs-site/multimodel.html +364 -0
  24. package/dist/docs-site/mythical-pro-agents.html +360 -0
  25. package/dist/docs-site/notifier.html +338 -0
  26. package/dist/docs-site/openai-endpoints.html +387 -0
  27. package/dist/docs-site/openrouter.html +344 -0
  28. package/dist/docs-site/quickstart.html +369 -0
  29. package/dist/docs-site/refactor/ux.html +532 -0
  30. package/dist/docs-site/sessions.html +388 -0
  31. package/dist/docs-site/social-card.png +0 -0
  32. package/dist/docs-site/social-card.svg +79 -0
  33. package/dist/docs-site/spec.html +363 -0
  34. package/dist/docs-site/testing.html +320 -0
  35. package/dist/docs-site/tui-debug.html +326 -0
  36. package/dist/docs-site/windows-work.html +323 -0
  37. package/dist/docs-site/windows.html +320 -0
  38. package/dist/src/browser/actions/assistantResponse.js +91 -9
  39. package/dist/src/browser/actions/deepResearch.js +180 -52
  40. package/dist/src/browser/actions/modelSelection.js +13 -11
  41. package/dist/src/browser/actions/navigation.js +294 -65
  42. package/dist/src/browser/actions/promptComposer.js +50 -4
  43. package/dist/src/browser/actions/thinkingTime.js +308 -89
  44. package/dist/src/browser/artifacts.js +19 -0
  45. package/dist/src/browser/chatgptFiles.js +797 -0
  46. package/dist/src/browser/chatgptImages.js +130 -3
  47. package/dist/src/browser/chromeLifecycle.js +4 -0
  48. package/dist/src/browser/config.js +2 -0
  49. package/dist/src/browser/index.js +347 -39
  50. package/dist/src/browser/pageActions.js +1 -1
  51. package/dist/src/browser/policies.js +2 -6
  52. package/dist/src/browser/projectSourcesRunner.js +14 -2
  53. package/dist/src/browser/prompt.js +11 -15
  54. package/dist/src/browser/reattach.js +6 -2
  55. package/dist/src/browser/reattachability.js +22 -10
  56. package/dist/src/browser/recoverConversation.js +73 -0
  57. package/dist/src/browser/sessionRunner.js +4 -1
  58. package/dist/src/cli/browserConfig.js +4 -1
  59. package/dist/src/cli/browserTabs.js +129 -54
  60. package/dist/src/cli/followup.js +72 -0
  61. package/dist/src/cli/help.js +1 -1
  62. package/dist/src/cli/options.js +16 -0
  63. package/dist/src/cli/reattachGuidance.js +8 -0
  64. package/dist/src/cli/runOptions.js +2 -12
  65. package/dist/src/cli/sessionCommand.js +4 -0
  66. package/dist/src/cli/sessionDisplay.js +17 -3
  67. package/dist/src/cli/sessionLineage.js +7 -4
  68. package/dist/src/cli/sessionRunner.js +16 -1
  69. package/dist/src/gemini-web/client.js +5 -10
  70. package/dist/src/gemini-web/executor.js +1 -24
  71. package/dist/src/gemini-web/models.js +83 -0
  72. package/dist/src/mcp/server.js +2 -0
  73. package/dist/src/mcp/tools/chatgptImage.js +127 -0
  74. package/dist/src/mcp/tools/consult.js +261 -167
  75. package/dist/src/mcp/types.js +2 -0
  76. package/dist/src/mcp/utils.js +87 -1
  77. package/dist/src/oracle/config.js +27 -1
  78. package/dist/src/oracle/files.js +4 -6
  79. package/dist/src/oracle/geminiModels.js +2 -0
  80. package/dist/src/oracle/markdown.js +36 -3
  81. package/dist/src/oracle/modelResolver.js +21 -13
  82. package/dist/src/oracle/promptAssembly.js +2 -4
  83. package/dist/src/oracle/request.js +3 -5
  84. package/dist/src/oracle/tokenStats.js +5 -1
  85. package/dist/src/oracle.js +1 -1
  86. package/dist/src/sessionManager.js +1 -0
  87. package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
  88. package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
  89. package/package.json +19 -28
  90. package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
  91. package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
@@ -0,0 +1,532 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Oracle UX Refactor Plan — oracle</title>
7
+ <meta name="description" content="Oracle UX Refactor Plan — oracle CLI documentation.">
8
+ <link rel="canonical" href="https://askoracle.sh/refactor/ux.html">
9
+ <meta property="og:type" content="website">
10
+ <meta property="og:site_name" content="oracle">
11
+ <meta property="og:title" content="Oracle UX Refactor Plan — oracle">
12
+ <meta property="og:description" content="Oracle UX Refactor Plan — oracle CLI documentation.">
13
+ <meta property="og:url" content="https://askoracle.sh/refactor/ux.html">
14
+ <meta property="og:image" content="https://askoracle.sh/social-card.png">
15
+ <meta property="og:image:width" content="1200">
16
+ <meta property="og:image:height" content="630">
17
+ <meta name="twitter:card" content="summary_large_image">
18
+ <meta name="twitter:title" content="Oracle UX Refactor Plan — oracle">
19
+ <meta name="twitter:description" content="Oracle UX Refactor Plan — oracle CLI documentation.">
20
+ <meta name="twitter:image" content="https://askoracle.sh/social-card.png">
21
+ <link rel="icon" href="../favicon.svg" type="image/svg+xml">
22
+ <link rel="preconnect" href="https://fonts.googleapis.com">
23
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
24
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
25
+ <script>(function(){var s;try{s=localStorage.getItem('theme')}catch(e){}var d=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.dataset.theme=s||(d?'dark':'light')})();</script>
26
+ <style>
27
+ :root{
28
+ --ink:#0e0a1f;
29
+ --text:#1d1832;
30
+ --muted:#6b6582;
31
+ --subtle:#9c95b5;
32
+ --bg:#fafaff;
33
+ --paper:#ffffff;
34
+ --accent:#7c3aed;
35
+ --accent-soft:rgba(124,58,237,.10);
36
+ --accent-strong:#5b21b6;
37
+ --accent-2:#0ea5e9;
38
+ --accent-glow:#a78bfa;
39
+ --line:#e7e3f0;
40
+ --line-soft:#f2eff8;
41
+ --code-bg:#0c0a1a;
42
+ --code-fg:#e9e6f5;
43
+ --code-inline-fg:#1c1734;
44
+ --pill-border:#dcd5ec;
45
+ --shadow-card:0 4px 14px rgba(14,10,31,.08);
46
+ --scrollbar:#cbc4dc;
47
+ }
48
+ :root[data-theme="dark"]{
49
+ --ink:#f5f2ff;
50
+ --text:#cec7e4;
51
+ --muted:#9189a8;
52
+ --subtle:#6a6383;
53
+ --bg:#0a0815;
54
+ --paper:#15102a;
55
+ --accent:#a78bfa;
56
+ --accent-soft:rgba(167,139,250,.18);
57
+ --accent-strong:#c4b5fd;
58
+ --accent-2:#38bdf8;
59
+ --accent-glow:#c4b5fd;
60
+ --line:#272140;
61
+ --line-soft:#1c1734;
62
+ --code-bg:#06040d;
63
+ --code-fg:#e9e6f5;
64
+ --code-inline-fg:#e9e6f5;
65
+ --pill-border:#2c2549;
66
+ --shadow-card:0 4px 18px rgba(0,0,0,.45);
67
+ --scrollbar:#3a3358;
68
+ }
69
+ :root{color-scheme:light}
70
+ :root[data-theme="dark"]{color-scheme:dark}
71
+ *{box-sizing:border-box}
72
+ html{scroll-behavior:smooth;scroll-padding-top:24px}
73
+ body{margin:0;background:var(--bg);color:var(--text);font-family:"Inter",ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.65;overflow-x:hidden;-webkit-font-smoothing:antialiased;font-feature-settings:"cv02","cv03","cv04","cv11";transition:background-color .18s,color .18s}
74
+ ::selection{background:var(--accent);color:#fff}
75
+ a{color:var(--accent);text-decoration:none;transition:color .12s}
76
+ a:hover{text-decoration:underline;text-underline-offset:.2em}
77
+ .shell{display:grid;grid-template-columns:268px minmax(0,1fr);min-height:100vh}
78
+ .sidebar{position:sticky;top:0;height:100vh;overflow:auto;padding:24px 22px;background:var(--paper);border-right:1px solid var(--line);scrollbar-width:thin;scrollbar-color:var(--line) transparent;transition:background-color .18s,border-color .18s}
79
+ .sidebar::-webkit-scrollbar{width:6px}
80
+ .sidebar::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
81
+ .sidebar-head{display:flex;align-items:center;gap:10px;margin-bottom:24px}
82
+ .brand{display:flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none;flex:1;min-width:0}
83
+ .brand:hover{text-decoration:none}
84
+ .brand .mark{flex:0 0 30px;width:30px;height:30px;border-radius:50%;background:radial-gradient(circle at 32% 32%,#fff 0,#e0d4ff 22%,#7c3aed 60%,#1e1240 100%);box-shadow:0 0 0 1px rgba(124,58,237,.35),0 6px 18px rgba(124,58,237,.35);position:relative}
85
+ .brand .mark::after{content:"";position:absolute;left:50%;top:50%;width:9px;height:9px;border-radius:50%;background:#0c0820;transform:translate(-50%,-50%)}
86
+ .brand strong{display:block;font-size:1.05rem;line-height:1.1;font-weight:600;letter-spacing:0;color:var(--ink)}
87
+ .brand small{display:block;color:var(--muted);font-size:.74rem;margin-top:3px;font-weight:400}
88
+ .theme-toggle{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:34px;height:34px;border-radius:8px;border:1px solid var(--line);background:var(--paper);color:var(--muted);cursor:pointer;padding:0;transition:border-color .15s,color .15s,background-color .15s,transform .12s}
89
+ .theme-toggle:hover{border-color:var(--ink);color:var(--ink)}
90
+ .theme-toggle:active{transform:scale(.94)}
91
+ .theme-toggle svg{width:16px;height:16px;display:block}
92
+ .theme-icon-sun{display:none}
93
+ :root[data-theme="dark"] .theme-icon-sun{display:block}
94
+ :root[data-theme="dark"] .theme-icon-moon{display:none}
95
+ .search{display:block;margin:0 0 22px}
96
+ .search span{display:block;color:var(--muted);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:0;margin-bottom:7px}
97
+ .search input{width:100%;border:1px solid var(--line);background:var(--paper);border-radius:8px;padding:9px 12px;font:inherit;font-size:.9rem;color:var(--text);outline:none;transition:border-color .15s,box-shadow .15s,background-color .18s}
98
+ .search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
99
+ nav section{margin:0 0 18px}
100
+ nav h2{font-size:.68rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 6px;font-weight:600}
101
+ .nav-link{display:block;color:var(--text);text-decoration:none;border-radius:6px;padding:5px 10px;margin:1px 0;font-size:.9rem;line-height:1.4;transition:background .12s,color .12s}
102
+ .nav-link:hover{background:var(--line-soft);color:var(--ink);text-decoration:none}
103
+ .nav-link.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
104
+ main{min-width:0;padding:32px clamp(20px,4.5vw,56px) 80px;max-width:1180px;margin:0 auto;width:100%}
105
+ .hero{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;border-bottom:1px solid var(--line);padding:8px 0 22px;margin-bottom:8px;flex-wrap:wrap}
106
+ .hero-text{min-width:0;flex:1 1 320px}
107
+ .eyebrow{margin:0 0 8px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:0;font-size:.7rem}
108
+ .hero h1{font-size:2.25rem;line-height:1.1;letter-spacing:0;margin:0;font-weight:700;color:var(--ink)}
109
+ .hero-meta{display:flex;gap:8px;flex:0 0 auto;flex-wrap:wrap}
110
+ .repo,.edit,.btn-ghost{border:1px solid var(--line);color:var(--text);text-decoration:none;border-radius:7px;padding:6px 11px;font-weight:500;font-size:.83rem;background:var(--paper);transition:border-color .15s,color .15s,background .15s}
111
+ .repo:hover,.edit:hover,.btn-ghost:hover{border-color:var(--ink);color:var(--ink);text-decoration:none}
112
+ .edit{color:var(--muted)}
113
+ .home-hero{position:relative;padding:24px 0 32px;margin-bottom:8px;border-bottom:1px solid var(--line)}
114
+ .home-hero>*{position:relative;z-index:1}
115
+ .home-hero h1{font-size:3.4rem;line-height:1.04;letter-spacing:0;margin:0 0 .35em;font-weight:700;color:var(--ink);background:linear-gradient(135deg,var(--ink) 0,#7c3aed 60%,#0ea5e9 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
116
+ :root[data-theme="dark"] .home-hero h1{background:linear-gradient(135deg,#f5f2ff 0,#c4b5fd 50%,#7dd3fc 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
117
+ .home-hero .lede{font-size:1.18rem;line-height:1.55;color:var(--text);margin:0 0 1.2em;max-width:62ch}
118
+ .home-cta{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 18px}
119
+ .home-cta .btn{display:inline-flex;align-items:center;gap:7px;border-radius:8px;padding:10px 16px;font-weight:600;font-size:.92rem;text-decoration:none;transition:background .15s,border-color .15s,color .15s,transform .12s}
120
+ .home-cta .btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent-strong));color:#fff;border:1px solid var(--accent);box-shadow:0 4px 14px rgba(124,58,237,.35)}
121
+ .home-cta .btn-primary:hover{background:var(--accent-strong);border-color:var(--accent-strong);text-decoration:none;transform:translateY(-1px)}
122
+ .home-cta .btn-ghost{padding:10px 16px}
123
+ .home-install{display:flex;align-items:center;gap:12px;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:10px 10px 10px 16px;font:500 .9rem/1.2 "JetBrains Mono","SF Mono",ui-monospace,monospace;max-width:34em;border:1px solid #1f1840}
124
+ .home-install .prompt{color:#6f63a3;user-select:none;flex:0 0 auto}
125
+ .home-install code{flex:1;background:transparent;border:0;color:var(--code-fg);font:inherit;padding:0;white-space:pre;overflow:hidden;text-overflow:ellipsis}
126
+ .home-install .copy{flex:0 0 auto;background:rgba(255,255,255,.08);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:5px 11px;font:500 .72rem/1 "Inter",sans-serif;cursor:pointer;transition:background .15s,border-color .15s}
127
+ .home-install .copy:hover{background:rgba(255,255,255,.16)}
128
+ .home-install .copy.copied{background:var(--accent);border-color:var(--accent)}
129
+ .home-services{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 18px}
130
+ .home-services span{display:inline-block;padding:3px 10px;border:1px solid var(--pill-border);border-radius:999px;font-size:.78rem;color:var(--muted);background:var(--paper)}
131
+ .home-services span.pill-pro{background:var(--accent-soft);color:var(--accent);border-color:transparent;font-weight:600}
132
+ .home-visual{display:block;width:min(100%,620px);height:auto;margin:22px 0 0;border-radius:8px;border:1px solid var(--line);box-shadow:var(--shadow-card);background:var(--paper)}
133
+ .doc-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:48px;margin-top:24px}
134
+ .doc-grid-home{margin-top:8px}
135
+ @media(min-width:1180px){.doc-grid{grid-template-columns:minmax(0,72ch) 200px;justify-content:start}.doc-grid-home{grid-template-columns:minmax(0,76ch);justify-content:start}}
136
+ .doc{min-width:0;max-width:72ch;overflow-wrap:break-word}
137
+ .doc-home{max-width:76ch}
138
+ .doc h1{font-size:2.6rem;line-height:1.08;letter-spacing:0;margin:0 0 .4em;font-weight:700;color:var(--ink)}
139
+ body:not(.home) .doc>h1:first-child{display:none}
140
+ .doc h2{font-size:1.45rem;line-height:1.2;margin:2em 0 .5em;font-weight:600;letter-spacing:0;color:var(--ink);position:relative}
141
+ .doc h3{font-size:1.1rem;margin:1.7em 0 .35em;position:relative;font-weight:600;color:var(--ink);letter-spacing:0}
142
+ .doc h4{font-size:.98rem;margin:1.4em 0 .25em;color:var(--ink);position:relative;font-weight:600}
143
+ .doc h2:first-child,.doc h3:first-child,.doc h4:first-child{margin-top:.2em}
144
+ .doc :is(h2,h3,h4) .anchor{position:absolute;left:-1.05em;top:0;color:var(--subtle);opacity:0;text-decoration:none;font-weight:400;padding-right:.3em;transition:opacity .12s,color .12s}
145
+ .doc :is(h2,h3,h4):hover .anchor{opacity:.7}
146
+ .doc :is(h2,h3,h4) .anchor:hover{opacity:1;color:var(--accent);text-decoration:none}
147
+ .doc p{margin:0 0 1.05em}
148
+ .doc ul,.doc ol{padding-left:1.3rem;margin:0 0 1.15em}
149
+ .doc li{margin:.25em 0}
150
+ .doc li>p{margin:0 0 .4em}
151
+ .doc strong{font-weight:600;color:var(--ink)}
152
+ .doc em{font-style:italic}
153
+ .doc code{font-family:"JetBrains Mono","SF Mono",ui-monospace,monospace;font-size:.84em;background:var(--line-soft);border:1px solid var(--line);border-radius:5px;padding:.08em .35em;color:var(--code-inline-fg)}
154
+ .doc pre{position:relative;overflow:auto;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:14px 18px;margin:1.3em 0;font-size:.85em;line-height:1.6;scrollbar-width:thin;scrollbar-color:#3a3358 transparent;border:1px solid #221c40}
155
+ .doc pre.shiki{background:var(--code-bg)!important;color:var(--code-fg)!important}
156
+ .doc pre::-webkit-scrollbar{height:8px;width:8px}
157
+ .doc pre::-webkit-scrollbar-thumb{background:#3a3358;border-radius:8px}
158
+ .doc pre code{display:block;background:transparent;border:0;color:inherit;padding:0;font-size:1em;white-space:pre}
159
+ .doc pre code .line{display:block;min-height:1.6em}
160
+ .doc pre .copy{position:absolute;top:8px;right:8px;background:rgba(255,255,255,.06);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:3px 9px;font:500 .7rem/1 "Inter",sans-serif;cursor:pointer;opacity:0;transition:opacity .15s,background .15s,border-color .15s}
161
+ .doc pre:hover .copy,.doc pre .copy:focus{opacity:1}
162
+ .doc pre .copy:hover{background:rgba(255,255,255,.12)}
163
+ .doc pre .copy.copied{background:var(--accent);border-color:var(--accent);opacity:1}
164
+ .doc blockquote{margin:1.4em 0;padding:10px 16px;border-left:3px solid var(--accent);background:var(--accent-soft);border-radius:0 8px 8px 0;color:var(--text)}
165
+ .doc blockquote p:last-child{margin-bottom:0}
166
+ .doc table{width:100%;border-collapse:collapse;margin:1.2em 0;font-size:.92em}
167
+ .doc th,.doc td{border-bottom:1px solid var(--line);padding:9px 10px;text-align:left;vertical-align:top}
168
+ .doc th{font-weight:600;color:var(--ink);background:var(--line-soft);border-bottom:1px solid var(--line)}
169
+ .doc hr{border:0;border-top:1px solid var(--line);margin:2.2em 0}
170
+ .toc{position:sticky;top:24px;align-self:start;font-size:.84rem;padding-left:14px;border-left:1px solid var(--line);max-height:calc(100vh - 48px);overflow:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
171
+ .toc::-webkit-scrollbar{width:5px}
172
+ .toc::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
173
+ .toc h2{font-size:.66rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 10px;font-weight:600}
174
+ .toc a{display:block;color:var(--muted);text-decoration:none;padding:4px 0 4px 10px;line-height:1.35;border-left:2px solid transparent;margin-left:-12px;transition:color .12s,border-color .12s}
175
+ .toc a:hover{color:var(--ink);text-decoration:none}
176
+ .toc a.active{color:var(--accent);border-left-color:var(--accent);font-weight:500}
177
+ .toc-l3{padding-left:22px!important;font-size:.94em}
178
+ @media(max-width:1179px){.toc{display:none}}
179
+ .page-nav{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:48px;border-top:1px solid var(--line);padding-top:20px}
180
+ .page-nav>a{display:block;border:1px solid var(--line);background:var(--paper);border-radius:9px;padding:13px 16px;text-decoration:none;color:var(--text);transition:border-color .15s,transform .15s,box-shadow .15s,background-color .18s}
181
+ .page-nav>a:hover{border-color:var(--accent);text-decoration:none;color:var(--ink)}
182
+ .page-nav small{display:block;color:var(--muted);font-size:.7rem;text-transform:uppercase;letter-spacing:0;margin-bottom:5px;font-weight:600}
183
+ .page-nav span{display:block;font-weight:600;line-height:1.3;color:var(--ink)}
184
+ .page-nav-prev{text-align:left}
185
+ .page-nav-next{text-align:right;grid-column:2}
186
+ .page-nav-prev:only-child{grid-column:1}
187
+ .nav-toggle{display:none;position:fixed;top:14px;right:14px;top:calc(14px + env(safe-area-inset-top, 0px));right:calc(14px + env(safe-area-inset-right, 0px));z-index:20;width:40px;height:40px;border-radius:9px;background:var(--paper);border:1px solid var(--line);color:var(--ink);cursor:pointer;padding:10px 9px;flex-direction:column;align-items:stretch;justify-content:space-between;box-shadow:var(--shadow-card)}
188
+ .nav-toggle span{display:block;width:100%;height:2px;flex:0 0 2px;background:currentColor;border-radius:2px;transition:transform .2s,opacity .2s}
189
+ .nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(8px) rotate(45deg)}
190
+ .nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
191
+ .nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
192
+ @media(max-width:900px){
193
+ .shell{display:block}
194
+ .sidebar{position:fixed;inset:0 30% 0 0;max-width:320px;height:100vh;z-index:15;transform:translateX(-100%);transition:transform .25s ease,background-color .18s,border-color .18s;box-shadow:0 18px 40px rgba(0,0,0,.18);background:var(--paper);pointer-events:none}
195
+ .sidebar.open{transform:translateX(0);pointer-events:auto}
196
+ .nav-toggle{display:flex}
197
+ main{padding:64px 18px 56px}
198
+ .hero{padding-top:6px}
199
+ .hero h1{font-size:1.8rem}
200
+ .home-hero h1{font-size:2.45rem}
201
+ .doc h1{font-size:2.1rem}
202
+ .hero-meta{width:100%;justify-content:flex-start}
203
+ .home-hero{padding-top:8px}
204
+ .home-visual{margin-top:18px}
205
+ .doc{padding:0}
206
+ .doc-grid{margin-top:18px;gap:24px}
207
+ .doc :is(h2,h3,h4) .anchor{display:none}
208
+ }
209
+ @media(max-width:520px){
210
+ main{padding:60px 14px 48px}
211
+ .doc pre{margin-left:-14px;margin-right:-14px;border-radius:0;border-left:0;border-right:0}
212
+ .home-install{flex-wrap:wrap}
213
+ }
214
+ </style>
215
+ </head>
216
+ <body>
217
+ <button class="nav-toggle" type="button" aria-label="Toggle navigation" aria-expanded="false">
218
+ <span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
219
+ </button>
220
+ <div class="shell">
221
+ <aside class="sidebar">
222
+ <div class="sidebar-head">
223
+ <a class="brand" href="../" aria-label="oracle docs home">
224
+ <span class="mark" aria-hidden="true"></span>
225
+ <span><strong>oracle</strong><small>askoracle.sh</small></span>
226
+ </a>
227
+ <button class="theme-toggle" type="button" aria-label="Toggle dark mode" aria-pressed="false" data-theme-toggle>
228
+ <svg class="theme-icon-moon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.6 12.1A6.5 6.5 0 0 1 7.4 2.7a6.5 6.5 0 1 0 7.2 9.4z" fill="currentColor"/></svg>
229
+ <svg class="theme-icon-sun" viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="3.4" fill="currentColor"/><g stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><line x1="10" y1="2" x2="10" y2="4"/><line x1="10" y1="16" x2="10" y2="18"/><line x1="2" y1="10" x2="4" y2="10"/><line x1="16" y1="10" x2="18" y2="10"/><line x1="4.2" y1="4.2" x2="5.6" y2="5.6"/><line x1="14.4" y1="14.4" x2="15.8" y2="15.8"/><line x1="4.2" y1="15.8" x2="5.6" y2="14.4"/><line x1="14.4" y1="5.6" x2="15.8" y2="4.2"/></g></svg>
230
+ </button>
231
+ </div>
232
+ <label class="search"><span>Search</span><input id="doc-search" type="search" placeholder="browser, mcp, sessions"></label>
233
+ <nav><section><h2>Start</h2><a class="nav-link" href="../">Overview</a><a class="nav-link" href="../install.html">Install</a><a class="nav-link" href="../quickstart.html">Quickstart</a><a class="nav-link" href="../configuration.html">Local configuration (JSON5)</a></section><section><h2>Mythical Pro Agents</h2><a class="nav-link" href="../mythical-pro-agents.html">Mythical Pro Agents</a><a class="nav-link" href="../openai-endpoints.html">OpenAI-Compatible Endpoints</a><a class="nav-link" href="../anthropic.html">Anthropic (Claude) Integration Plan</a><a class="nav-link" href="../gemini.html">Gemini Integration</a><a class="nav-link" href="../openrouter.html">OpenRouter</a><a class="nav-link" href="../grok.html">Grok 4.1 (xAI) Support</a></section><section><h2>Browser Mode</h2><a class="nav-link" href="../browser-mode.html">Browser Mode</a><a class="nav-link" href="../chromium-forks.html">Chromium-based browsers (Chromium, Edge, Brave variants)</a><a class="nav-link" href="../linux.html">Linux Notes</a><a class="nav-link" href="../windows.html">Windows compatibility notes</a><a class="nav-link" href="../windows-work.html">Windows Work</a><a class="nav-link" href="../bridge.html">Bridge (Windows-hosted ChatGPT session → Linux clients)</a></section><section><h2>Agents &amp; MCP</h2><a class="nav-link" href="../agents.html">Coding Agents</a><a class="nav-link" href="../mcp.html">MCP Server</a></section><section><h2>Workflows</h2><a class="nav-link" href="../sessions.html">Sessions</a><a class="nav-link" href="../followup.html">Followups &amp; Lineage</a><a class="nav-link" href="../multimodel.html">Multi-Model Execution</a></section><section><h2>Reference</h2><a class="nav-link" href="../cli-reference.html">CLI Reference</a><a class="nav-link" href="../spec.html">Spec</a><a class="nav-link" href="../notifier.html">Session completion notifications</a><a class="nav-link" href="../tui-debug.html">TUI navigation crash notes (2025-11-19)</a><a class="nav-link" href="../manual-tests.html">Manual Test Suite (Browser Mode + Live API)</a><a class="nav-link" href="../testing.html">Testing quickstart</a><a class="nav-link" href="../RELEASING.html">Release Checklist (npm + Homebrew)</a></section></nav>
234
+ </aside>
235
+ <main>
236
+ <header class="hero">
237
+ <div class="hero-text">
238
+ <p class="eyebrow">Reference</p>
239
+ <h1>Oracle UX Refactor Plan</h1>
240
+ </div>
241
+ <div class="hero-meta">
242
+ <a class="repo" href="https://github.com/steipete/oracle" rel="noopener">GitHub</a>
243
+ <a class="edit" href="https://github.com/steipete/oracle/edit/main/docs/refactor/ux.md" rel="noopener">Edit page</a>
244
+ </div>
245
+ </header>
246
+ <div class="doc-grid">
247
+ <article class="doc"><h1 id="oracle-ux-refactor-plan">Oracle UX Refactor Plan</h1>
248
+ <p>Context: Oracle bundles prompts + files, then sends the bundle to API/browser models for second-model review. Recent multi-model advisory use exposed confusing provider routing, timeout, auth, partial-success, output, and session behaviors.</p>
249
+ <h2 id="diagnosis"><a class="anchor" href="#diagnosis" aria-label="Anchor link">#</a>Diagnosis</h2>
250
+ <ul>
251
+ <li>CLI/docs drift: installed <code>0.11.1</code> rejected <code>--no-azure</code> while local help/docs mention it. Likely stale published artifact, <code>pnpm dlx</code> cache, or docs not verified against packed CLI.</li>
252
+ <li>Azure routing too implicit: exported <code>AZURE_OPENAI_ENDPOINT</code> can steer GPT/OpenAI-family API runs through Azure unless users manually unset env vars or force provider routing.</li>
253
+ <li>Timeout layering unclear: <code>--timeout</code> controls Oracle&#39;s overall deadline; <code>--http-timeout</code> controls SDK transport. A long overall timeout can still fail early at transport.</li>
254
+ <li>Multi-model aggregation saves successful outputs, but any failed model makes the command exit 1. Partial success is real but under-communicated.</li>
255
+ <li>Auth failures are lazy: missing keys fail early; invalid/expired keys fail only after requests start.</li>
256
+ <li>Output summary ordering is weak: saved outputs can be buried under noisy failures.</li>
257
+ <li>Session lifecycle vocabulary is inconsistent across API foreground, API background, browser, and Pro runs.</li>
258
+ <li>Provider/key routing is opaque: users need safe, redacted route/readiness visibility.</li>
259
+ </ul>
260
+ <h2 id="priorities"><a class="anchor" href="#priorities" aria-label="Anchor link">#</a>Priorities</h2>
261
+ <h3 id="1-provider-doctor-preflight"><a class="anchor" href="#1-provider-doctor-preflight" aria-label="Anchor link">#</a>1. Provider Doctor + Preflight</h3>
262
+ <p>Add:</p>
263
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#96D0FF"> doctor</span><span style="color:#6CB6FF"> --providers</span></span>
264
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#96D0FF"> doctor</span><span style="color:#6CB6FF"> --providers</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,claude-4.6-sonnet,gemini-3-pro</span></span>
265
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --preflight</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,claude-4.6-sonnet,gemini-3-pro</span><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "..."</span></span></code></pre>
266
+ <p>Expected output:</p>
267
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Provider readiness</span></span>
268
+ <span class="line"><span></span></span>
269
+ <span class="line"><span>OpenAI: ok</span></span>
270
+ <span class="line"><span> key: OPENAI_API_KEY=sk-...a91</span></span>
271
+ <span class="line"><span> base: api.openai.com</span></span>
272
+ <span class="line"><span> route gpt-5.4: OpenAI Responses API</span></span>
273
+ <span class="line"><span></span></span>
274
+ <span class="line"><span>Azure OpenAI: configured, inactive</span></span>
275
+ <span class="line"><span> endpoint: my-resource.openai.azure.com</span></span>
276
+ <span class="line"><span> key: AZURE_OPENAI_API_KEY=az-...32c</span></span>
277
+ <span class="line"><span> route gpt-5.4: ignored because --provider openai</span></span>
278
+ <span class="line"><span></span></span>
279
+ <span class="line"><span>Anthropic: auth failed</span></span>
280
+ <span class="line"><span> key: ANTHROPIC_API_KEY=sk-...9bc</span></span>
281
+ <span class="line"><span> error: invalid x-api-key</span></span>
282
+ <span class="line"><span></span></span>
283
+ <span class="line"><span>Gemini: auth failed</span></span>
284
+ <span class="line"><span> key: GEMINI_API_KEY=AIza...77e</span></span>
285
+ <span class="line"><span> error: API key expired</span></span></code></pre>
286
+ <p>Implementation:</p>
287
+ <ul>
288
+ <li>Add top-level <code>oracle doctor</code>; keep <code>oracle bridge doctor</code> bridge-specific.</li>
289
+ <li>Extract provider route/auth logic into <code>src/oracle/providerDoctor.ts</code>.</li>
290
+ <li>Support <code>local</code> preflight for env/config/routing and <code>auth</code> preflight for cheap provider network checks.</li>
291
+ <li>Redact all keys. Never print raw env values.</li>
292
+ </ul>
293
+ <h3 id="2-explicit-provider-route-plan"><a class="anchor" href="#2-explicit-provider-route-plan" aria-label="Anchor link">#</a>2. Explicit Provider Route Plan</h3>
294
+ <p>Add:</p>
295
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,gemini-3-pro</span></span>
296
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --provider</span><span style="color:#96D0FF"> openai</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.4</span></span>
297
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --no-azure</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.4</span></span></code></pre>
298
+ <p>Expected output:</p>
299
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Route plan</span></span>
300
+ <span class="line"><span></span></span>
301
+ <span class="line"><span>gpt-5.4</span></span>
302
+ <span class="line"><span> provider: OpenAI</span></span>
303
+ <span class="line"><span> base: api.openai.com</span></span>
304
+ <span class="line"><span> key: OPENAI_API_KEY=sk-...a91</span></span>
305
+ <span class="line"><span> azure: ignored, AZURE_OPENAI_ENDPOINT is set</span></span>
306
+ <span class="line"><span></span></span>
307
+ <span class="line"><span>gemini-3-pro</span></span>
308
+ <span class="line"><span> provider: Google Gemini</span></span>
309
+ <span class="line"><span> base: generativelanguage.googleapis.com</span></span>
310
+ <span class="line"><span> key: GEMINI_API_KEY=AIza...77e</span></span></code></pre>
311
+ <p>Implementation:</p>
312
+ <ul>
313
+ <li>Make provider routing return a structured <code>ProviderRoutePlan</code>.</li>
314
+ <li>Reuse it in run header, doctor, dry-run JSON, and session metadata.</li>
315
+ <li>Add route-plan tests for Azure env present plus <code>--provider openai</code>.</li>
316
+ </ul>
317
+ <h3 id="3-unified-timeout-semantics"><a class="anchor" href="#3-unified-timeout-semantics" aria-label="Anchor link">#</a>3. Unified Timeout Semantics</h3>
318
+ <p>Target behavior:</p>
319
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --timeout</span><span style="color:#96D0FF"> 10m</span><span style="color:#96D0FF"> ...</span></span>
320
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --timeout</span><span style="color:#96D0FF"> 10m</span><span style="color:#6CB6FF"> --http-timeout</span><span style="color:#96D0FF"> 30s</span><span style="color:#96D0FF"> ...</span></span>
321
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --timeout</span><span style="color:#96D0FF"> auto</span><span style="color:#96D0FF"> ...</span></span></code></pre>
322
+ <p>Expected output:</p>
323
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Timeouts</span></span>
324
+ <span class="line"><span> overall: 10m</span></span>
325
+ <span class="line"><span> transport: 10m</span></span>
326
+ <span class="line"><span> session stale cutoff: 10m</span></span></code></pre>
327
+ <p>With explicit shorter transport:</p>
328
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Timeouts</span></span>
329
+ <span class="line"><span> overall: 10m</span></span>
330
+ <span class="line"><span> transport: 30s</span></span>
331
+ <span class="line"><span> note: transport can fail before overall timeout</span></span></code></pre>
332
+ <p>Implementation:</p>
333
+ <ul>
334
+ <li>If user sets <code>--timeout</code> and omits <code>--http-timeout</code>, derive HTTP timeout from overall timeout.</li>
335
+ <li>Keep <code>--http-timeout</code> as explicit override.</li>
336
+ <li>Print timeout plan in verbose and long-running runs.</li>
337
+ <li>Store resolved timeouts in session metadata.</li>
338
+ </ul>
339
+ <p>Migration:</p>
340
+ <ul>
341
+ <li>Keep both flags.</li>
342
+ <li>Warn when <code>--http-timeout &lt; --timeout</code>.</li>
343
+ <li>Update docs so <code>--timeout</code> is the normal user-facing deadline.</li>
344
+ </ul>
345
+ <h3 id="4-partial-success-mode"><a class="anchor" href="#4-partial-success-mode" aria-label="Anchor link">#</a>4. Partial Success Mode</h3>
346
+ <p>Add:</p>
347
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,claude-4.6-sonnet,gemini-3-pro</span><span style="color:#6CB6FF"> --allow-partial</span><span style="color:#96D0FF"> ...</span></span>
348
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> ...</span><span style="color:#6CB6FF"> --partial</span><span style="color:#96D0FF"> fail</span></span>
349
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> ...</span><span style="color:#6CB6FF"> --partial</span><span style="color:#96D0FF"> ok</span></span></code></pre>
350
+ <p>Expected output:</p>
351
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Multi-model result: partial success, 1/3 succeeded</span></span>
352
+ <span class="line"><span></span></span>
353
+ <span class="line"><span>Saved outputs:</span></span>
354
+ <span class="line"><span>- gpt-5.4 -> /tmp/name.gpt-5.4.md</span></span>
355
+ <span class="line"><span></span></span>
356
+ <span class="line"><span>Failures:</span></span>
357
+ <span class="line"><span>- claude-4.6-sonnet: auth failed, invalid x-api-key</span></span>
358
+ <span class="line"><span>- gemini-3-pro: auth failed, API key expired</span></span>
359
+ <span class="line"><span></span></span>
360
+ <span class="line"><span>Session:</span></span>
361
+ <span class="line"><span>- oracle session 20260515-naming-panel</span></span></code></pre>
362
+ <p>Implementation:</p>
363
+ <ul>
364
+ <li>Add <code>allowPartial?: boolean</code> or <code>partialMode: &quot;fail&quot; | &quot;ok&quot;</code> to run options.</li>
365
+ <li>In multi-model runner, if fulfilled &gt; 0 and partial ok, exit 0.</li>
366
+ <li>Add a <code>partial</code> or <code>completed_with_errors</code> session status.</li>
367
+ <li>Keep default exit-1 behavior initially for backcompat, but always print structured partial summary before throwing.</li>
368
+ </ul>
369
+ <h3 id="5-output-manifest-summary-ordering"><a class="anchor" href="#5-output-manifest-summary-ordering" aria-label="Anchor link">#</a>5. Output Manifest + Summary Ordering</h3>
370
+ <p>For multi-model <code>--write-output</code>, always print saved outputs first, then logs, then failures:</p>
371
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Saved outputs:</span></span>
372
+ <span class="line"><span>- gpt-5.4 -> /tmp/name.gpt-5.4.md</span></span>
373
+ <span class="line"><span></span></span>
374
+ <span class="line"><span>Run logs:</span></span>
375
+ <span class="line"><span>- gpt-5.4 -> ~/.oracle/sessions/.../logs/gpt-5.4.log</span></span>
376
+ <span class="line"><span>- claude-4.6-sonnet -> ~/.oracle/sessions/.../logs/claude-4.6-sonnet.log</span></span>
377
+ <span class="line"><span></span></span>
378
+ <span class="line"><span>Failures:</span></span>
379
+ <span class="line"><span>- gemini-3-pro -> auth failed</span></span></code></pre>
380
+ <p>Implementation:</p>
381
+ <ul>
382
+ <li>Add optional output manifest next to the requested path, e.g. <code>/tmp/name.oracle.json</code>.</li>
383
+ <li>Include model, status, output path, log path, error category, elapsed, usage.</li>
384
+ <li>Make manifest useful for agents consuming partial output.</li>
385
+ </ul>
386
+ <h3 id="6-auth-error-classification"><a class="anchor" href="#6-auth-error-classification" aria-label="Anchor link">#</a>6. Auth Error Classification</h3>
387
+ <p>Expected output:</p>
388
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Failures:</span></span>
389
+ <span class="line"><span>- claude-4.6-sonnet: auth failed</span></span>
390
+ <span class="line"><span> key: ANTHROPIC_API_KEY=sk-...9bc</span></span>
391
+ <span class="line"><span> provider said: invalid x-api-key</span></span>
392
+ <span class="line"><span> fix: refresh ANTHROPIC_API_KEY or run `oracle doctor --providers anthropic`</span></span>
393
+ <span class="line"><span></span></span>
394
+ <span class="line"><span>- gemini-3-pro: auth expired</span></span>
395
+ <span class="line"><span> key: GEMINI_API_KEY=AIza...77e</span></span>
396
+ <span class="line"><span> fix: rotate key, then rerun failed model:</span></span>
397
+ <span class="line"><span> oracle session &#x3C;id> --rerun-failed</span></span></code></pre>
398
+ <p>Implementation:</p>
399
+ <ul>
400
+ <li>Normalize provider SDK errors into Oracle user errors.</li>
401
+ <li>Classify auth, expired key, quota, rate limit, model unavailable, and transport separately.</li>
402
+ <li>Store category in per-model metadata.</li>
403
+ </ul>
404
+ <h3 id="7-clear-foreground-detached-lifecycle"><a class="anchor" href="#7-clear-foreground-detached-lifecycle" aria-label="Anchor link">#</a>7. Clear Foreground/Detached Lifecycle</h3>
405
+ <p>Run start should print a compact lifecycle block:</p>
406
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Session: 20260515-name-panel</span></span>
407
+ <span class="line"><span>Mode: api foreground</span></span>
408
+ <span class="line"><span>Models: 3 parallel</span></span>
409
+ <span class="line"><span>Detach: no</span></span>
410
+ <span class="line"><span>Reattach: oracle session 20260515-name-panel</span></span></code></pre>
411
+ <p>For background/Pro:</p>
412
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Session: 20260515-pro-review</span></span>
413
+ <span class="line"><span>Mode: api background</span></span>
414
+ <span class="line"><span>Detach: yes, polling</span></span>
415
+ <span class="line"><span>Reattach: oracle session 20260515-pro-review --live</span></span></code></pre>
416
+ <p>Implementation:</p>
417
+ <ul>
418
+ <li>Add lifecycle fields to session metadata: <code>engine</code>, <code>execution</code>, <code>attached</code>, <code>reattachCommand</code>.</li>
419
+ <li>Use the same fields in <code>status</code>, <code>session</code>, notifications, and run headers.</li>
420
+ <li>Avoid special-case wording for Pro unless the behavior truly differs.</li>
421
+ </ul>
422
+ <h3 id="8-help-docs-single-source-packed-cli-test"><a class="anchor" href="#8-help-docs-single-source-packed-cli-test" aria-label="Anchor link">#</a>8. Help/Docs Single Source + Packed CLI Test</h3>
423
+ <p>Add CI/doc check:</p>
424
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#96D0FF"> docs</span><span style="color:#96D0FF"> check</span></span></code></pre>
425
+ <p>Expected failure:</p>
426
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Docs/help drift:</span></span>
427
+ <span class="line"><span>- skills/oracle/SKILL.md mentions --no-azure</span></span>
428
+ <span class="line"><span>- packed CLI help does not expose --no-azure</span></span></code></pre>
429
+ <p>Implementation:</p>
430
+ <ul>
431
+ <li>Generate docs snippets from Commander metadata or a shared flag registry.</li>
432
+ <li>CI smoke:</li>
433
+ <li><code>pnpm pack</code></li>
434
+ <li>install packed tarball in a temp dir</li>
435
+ <li>run <code>oracle --help --verbose</code></li>
436
+ <li>assert documented flags exist.</li>
437
+ <li>Add skill-doc lint for stale flags.</li>
438
+ </ul>
439
+ <h2 id="azure-backcompat"><a class="anchor" href="#azure-backcompat" aria-label="Anchor link">#</a>Azure Backcompat</h2>
440
+ <ul>
441
+ <li>Keep auto Azure initially.</li>
442
+ <li>Make Azure route reason loud:</li>
443
+ </ul>
444
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-text"><span class="line"><span>Provider: Azure OpenAI</span></span>
445
+ <span class="line"><span>Reason: AZURE_OPENAI_ENDPOINT is set</span></span>
446
+ <span class="line"><span>Opt out: --provider openai or --no-azure</span></span></code></pre>
447
+ <ul>
448
+ <li>Add explicit opt-out options:</li>
449
+ </ul>
450
+ <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --provider</span><span style="color:#96D0FF"> openai</span></span>
451
+ <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --no-azure</span></span>
452
+ <span class="line"><span style="color:#ADBAC7">ORACLE_AZURE</span><span style="color:#F47067">=</span><span style="color:#96D0FF">0</span><span style="color:#F69D50"> oracle</span><span style="color:#96D0FF"> ...</span></span></code></pre>
453
+ <ul>
454
+ <li>Longer term: when both first-party OpenAI and Azure env are present, require <code>--provider azure</code> to use Azure, or gate stricter routing behind a major version.</li>
455
+ </ul>
456
+ <h2 id="tests"><a class="anchor" href="#tests" aria-label="Anchor link">#</a>Tests</h2>
457
+ <ul>
458
+ <li>Packed CLI exposes every documented flag, especially <code>--no-azure</code>.</li>
459
+ <li><code>--timeout 10m</code> passes <code>httpTimeoutMs=600000</code> when <code>--http-timeout</code> is omitted.</li>
460
+ <li><code>--timeout 10m --http-timeout 30s</code> preserves 30s and warns.</li>
461
+ <li>Azure env plus <code>--provider openai</code> routes to OpenAI and omits Azure metadata.</li>
462
+ <li>Azure env plus auto prints route reason and opt-out hint.</li>
463
+ <li><code>doctor --providers</code> redacts keys and classifies missing, valid, invalid, and expired.</li>
464
+ <li>Multi-model partial: one success, two auth failures, <code>--allow-partial</code> exits 0 and prints saved outputs first.</li>
465
+ <li>Multi-model default: same case exits 1 but still prints structured partial summary.</li>
466
+ <li><code>--write-output</code> multi-model writes per-model files and optional manifest.</li>
467
+ <li><code>oracle status</code> displays partial sessions and per-model failures cleanly.</li>
468
+ </ul></article>
469
+ <nav class="toc" aria-label="On this page"><h2>On this page</h2><a class="toc-l2" href="#diagnosis">Diagnosis</a><a class="toc-l2" href="#priorities">Priorities</a><a class="toc-l3" href="#1-provider-doctor-preflight">1. Provider Doctor + Preflight</a><a class="toc-l3" href="#2-explicit-provider-route-plan">2. Explicit Provider Route Plan</a><a class="toc-l3" href="#3-unified-timeout-semantics">3. Unified Timeout Semantics</a><a class="toc-l3" href="#4-partial-success-mode">4. Partial Success Mode</a><a class="toc-l3" href="#5-output-manifest-summary-ordering">5. Output Manifest + Summary Ordering</a><a class="toc-l3" href="#6-auth-error-classification">6. Auth Error Classification</a><a class="toc-l3" href="#7-clear-foreground-detached-lifecycle">7. Clear Foreground/Detached Lifecycle</a><a class="toc-l3" href="#8-help-docs-single-source-packed-cli-test">8. Help/Docs Single Source + Packed CLI Test</a><a class="toc-l2" href="#azure-backcompat">Azure Backcompat</a><a class="toc-l2" href="#tests">Tests</a></nav>
470
+ </div>
471
+ </main>
472
+ </div>
473
+ <script>
474
+ const themeRoot=document.documentElement;
475
+ function applyTheme(mode){themeRoot.dataset.theme=mode;document.querySelectorAll('[data-theme-toggle]').forEach(b=>b.setAttribute('aria-pressed',mode==='dark'?'true':'false'))}
476
+ function storedTheme(){try{return localStorage.getItem('theme')}catch(e){return null}}
477
+ function persistTheme(mode){try{localStorage.setItem('theme',mode)}catch(e){}}
478
+ applyTheme(themeRoot.dataset.theme==='dark'?'dark':'light');
479
+ document.querySelectorAll('[data-theme-toggle]').forEach(btn=>{btn.addEventListener('click',()=>{const next=themeRoot.dataset.theme==='dark'?'light':'dark';applyTheme(next);persistTheme(next)})});
480
+ const systemDark=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)');
481
+ function onSystemChange(e){if(storedTheme())return;applyTheme(e.matches?'dark':'light')}
482
+ if(systemDark){if(systemDark.addEventListener)systemDark.addEventListener('change',onSystemChange);else if(systemDark.addListener)systemDark.addListener(onSystemChange)}
483
+ const sidebar=document.querySelector('.sidebar');
484
+ const toggle=document.querySelector('.nav-toggle');
485
+ const mobileNav=window.matchMedia('(max-width: 900px)');
486
+ const sidebarFocusable='a[href],button,input,select,textarea,[tabindex]';
487
+ function setSidebarFocusable(enabled){
488
+ sidebar?.querySelectorAll(sidebarFocusable).forEach((el)=>{
489
+ if(enabled){
490
+ if(el.dataset.sidebarTabindex!==undefined){
491
+ if(el.dataset.sidebarTabindex)el.setAttribute('tabindex',el.dataset.sidebarTabindex);
492
+ else el.removeAttribute('tabindex');
493
+ delete el.dataset.sidebarTabindex;
494
+ }
495
+ }else if(el.dataset.sidebarTabindex===undefined){
496
+ el.dataset.sidebarTabindex=el.getAttribute('tabindex')??'';
497
+ el.setAttribute('tabindex','-1');
498
+ }
499
+ });
500
+ }
501
+ function setSidebarOpen(open){
502
+ if(!sidebar||!toggle)return;
503
+ sidebar.classList.toggle('open',open);
504
+ toggle.setAttribute('aria-expanded',open?'true':'false');
505
+ if(mobileNav.matches){
506
+ sidebar.inert=!open;
507
+ if(open)sidebar.removeAttribute('aria-hidden');
508
+ else sidebar.setAttribute('aria-hidden','true');
509
+ setSidebarFocusable(open);
510
+ }else{
511
+ sidebar.inert=false;
512
+ sidebar.removeAttribute('aria-hidden');
513
+ setSidebarFocusable(true);
514
+ }
515
+ }
516
+ setSidebarOpen(false);
517
+ toggle?.addEventListener('click',()=>setSidebarOpen(!sidebar?.classList.contains('open')));
518
+ document.addEventListener('click',(e)=>{if(!sidebar?.classList.contains('open'))return;if(sidebar.contains(e.target)||toggle?.contains(e.target))return;setSidebarOpen(false)});
519
+ document.addEventListener('keydown',(e)=>{if(e.key==='Escape')setSidebarOpen(false)});
520
+ const syncSidebarForViewport=()=>setSidebarOpen(sidebar?.classList.contains('open')??false);
521
+ if(mobileNav.addEventListener)mobileNav.addEventListener('change',syncSidebarForViewport);
522
+ else mobileNav.addListener?.(syncSidebarForViewport);
523
+ const input=document.getElementById('doc-search');
524
+ input?.addEventListener('input',()=>{const q=input.value.trim().toLowerCase();document.querySelectorAll('nav section').forEach(sec=>{let any=false;sec.querySelectorAll('.nav-link').forEach(a=>{const m=!q||a.textContent.toLowerCase().includes(q);a.style.display=m?'block':'none';if(m)any=true});sec.style.display=any?'block':'none'})});
525
+ function attachCopy(target,getText){const btn=document.createElement('button');btn.type='button';btn.className='copy';btn.textContent='Copy';btn.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(getText());btn.textContent='Copied';btn.classList.add('copied');setTimeout(()=>{btn.textContent='Copy';btn.classList.remove('copied')},1400)}catch{btn.textContent='Failed';setTimeout(()=>{btn.textContent='Copy'},1400)}});target.appendChild(btn)}
526
+ document.querySelectorAll('.doc pre').forEach(pre=>attachCopy(pre,()=>pre.querySelector('code')?.textContent??''));
527
+ document.querySelectorAll('.home-install').forEach(el=>attachCopy(el,()=>el.querySelector('code')?.textContent??''));
528
+ const tocLinks=document.querySelectorAll('.toc a');
529
+ if(tocLinks.length){const map=new Map();tocLinks.forEach(a=>{const id=a.getAttribute('href').slice(1);const el=document.getElementById(id);if(el)map.set(el,a)});const setActive=l=>{tocLinks.forEach(x=>x.classList.remove('active'));l.classList.add('active')};const obs=new IntersectionObserver(entries=>{const visible=entries.filter(e=>e.isIntersecting).sort((a,b)=>a.boundingClientRect.top-b.boundingClientRect.top);if(visible.length){const link=map.get(visible[0].target);if(link)setActive(link)}},{rootMargin:'-15% 0px -65% 0px',threshold:0});map.forEach((_,el)=>obs.observe(el))}
530
+ </script>
531
+ </body>
532
+ </html>