test(baseline): align UI and model profile expectations

This commit is contained in:
Alexandre Teixeira
2026-09-22 23:27:17 +01:00
parent 9bc1cdcab0
commit c0a1cecc00
26 changed files with 108 additions and 77 deletions
+2 -2
View File
@@ -161,13 +161,13 @@ def test_email_settings_show_away_account_and_compact_display_controls() -> None
assert "enabled ? 'Show' : 'Hide'" in source assert "enabled ? 'Show' : 'Hide'" in source
assert "email-settings-inline-link" in source assert "email-settings-inline-link" in source
assert "email-auto-reply-exclude" not in source assert "email-auto-reply-exclude" not in source
assert "_emailWritingStyleHtml(writingStyle) + _emailDisplaySettingsHtml()" in source assert "_emailWritingStyleHtml(writingStyle) + _emailDisplaySettingsHtml(cfg)" in source
assert ".email-settings-status.is-success" in style assert ".email-settings-status.is-success" in style
assert "var(--color-success, #4caf50)" in style assert "var(--color-success, #4caf50)" in style
assert ".email-style-settings-extract svg" in style assert ".email-style-settings-extract svg" in style
assert "export async function mountEmailSettings(host)" in source assert "export async function mountEmailSettings(host)" in source
assert "_openGlobalEmailSettings('show-tags')" in source assert "_openGlobalEmailSettings('show-tags')" in source
assert source.count('class="admin-card email-settings-section') == 4 assert source.count('class="admin-card email-settings-section') == 5
assert 'id="settings-email-default-card"' in (ROOT / "static/index.html").read_text(encoding="utf-8") assert 'id="settings-email-default-card"' in (ROOT / "static/index.html").read_text(encoding="utf-8")
assert "multipleAccounts" in source assert "multipleAccounts" in source
+1 -1
View File
@@ -8,7 +8,7 @@ THEME_JS = (ROOT / "static/js/theme.js").read_text(encoding="utf-8")
def test_five_distinct_builtin_themes_are_available() -> None: def test_five_distinct_builtin_themes_are_available() -> None:
expected = { expected = {
"eclipse": "constellations", "eclipse": "starfield-depth",
"porcelain": "dots", "porcelain": "dots",
"arcade": "synapse", "arcade": "synapse",
"blueprint": "dots", "blueprint": "dots",
+3 -2
View File
@@ -25,8 +25,9 @@ def test_measured_ttft_is_shown_in_message_stats():
def test_compact_footer_and_details_show_real_performance_counters(): def test_compact_footer_and_details_show_real_performance_counters():
assert "`${Number(tps).toFixed(2)} tok/s`" in RENDERER assert "`${Number(tps).toFixed(2)} tok/s`" in RENDERER
assert "`${Number(ttft).toFixed(3)}s TTFT`" in RENDERER assert "const visibleTtft = metrics.client_ttft ?? metrics.time_to_first_token" in RENDERER
assert "`${Number(injectedTokens).toLocaleString()} in`" in RENDERER assert "${Number(visibleTtft).toFixed(3)}s" in RENDERER
assert "${Number(injectedTokens).toLocaleString()}" in RENDERER
assert '<span class="ctx-label">Input</span>' in RENDERER assert '<span class="ctx-label">Input</span>' in RENDERER
assert '<span class="ctx-label">Injected</span>' in RENDERER assert '<span class="ctx-label">Injected</span>' in RENDERER
assert 'all rounds' not in RENDERER assert 'all rounds' not in RENDERER
@@ -87,7 +87,7 @@ async def test_malformed_text_artifact_write_uses_one_bounded_raw_body_handoff(m
events = [json.loads(chunk[6:]) for chunk in raw if '[DONE]' not in chunk] events = [json.loads(chunk[6:]) for chunk in raw if '[DONE]' not in chunk]
assert len(requests) == 2 assert len(requests) == 2
assert 'tools' not in requests[1] assert 'tools' not in requests[1]
assert requests[1]['max_tokens'] == 4096 assert requests[1]['max_tokens'] == 8192
assert len(executed) == 1 assert len(executed) == 1
assert executed[0].tool_type == 'write_file' assert executed[0].tool_type == 'write_file'
assert executed[0].content == ( assert executed[0].content == (
+1 -1
View File
@@ -12,7 +12,7 @@ def test_mobile_compare_mounts_accessible_tabs_without_removing_panes():
index = _read("static/js/compare/index.js") index = _read("static/js/compare/index.js")
panes = _read("static/js/compare/panes.js") panes = _read("static/js/compare/panes.js")
assert "mountMobilePaneTabs(container, grid)" in index assert "mountMobilePaneTabs(container, grid, (anchor) => _addPane(anchor))" in index
assert "role', 'tablist'" in panes assert "role', 'tablist'" in panes
assert "role', 'tab'" in panes assert "role', 'tab'" in panes
assert "role', 'tabpanel'" in panes assert "role', 'tabpanel'" in panes
+2 -1
View File
@@ -83,7 +83,8 @@ def test_pages_site_owns_its_entrypoint_and_media():
assert REPO / "website/index.html" in website_files assert REPO / "website/index.html" in website_files
assert REPO / "docs/index.html" not in docs_files assert REPO / "docs/index.html" not in docs_files
assert not [p for p in docs_files if p.suffix.lower() in VIDEO_EXTS | {".md"}] assert not [p for p in docs_files if p.suffix.lower() in VIDEO_EXTS]
assert not [p for p in docs_files if p.name in PUBLIC_GUIDES]
website_paths = {p.relative_to(REPO / "website").as_posix() for p in website_files} website_paths = {p.relative_to(REPO / "website").as_posix() for p in website_files}
assert PUBLIC_GUIDES <= website_paths assert PUBLIC_GUIDES <= website_paths
@@ -18,7 +18,7 @@ def test_expanded_document_card_has_export_beside_clone():
def test_expanded_export_reuses_download_function_without_proxy_click(): def test_expanded_export_reuses_download_function_without_proxy_click():
assert "const exportDocumentFile = async () =>" in DOC_LIBRARY_JS assert "const exportDocumentFile = async (format = 'original') =>" in DOC_LIBRARY_JS
assert "await exportDocumentFile();" in DOC_LIBRARY_JS assert "await exportDocumentFile();" in DOC_LIBRARY_JS
assert "exportItem.click();" not in DOC_LIBRARY_JS assert "exportItem.click();" not in DOC_LIBRARY_JS
assert "exportItem.type = 'button';" in DOC_LIBRARY_JS assert "exportItem.type = 'button';" in DOC_LIBRARY_JS
+6 -4
View File
@@ -10,24 +10,26 @@ SOURCE = (ROOT / "static/js/documentLibrary.js").read_text(encoding="utf-8")
STYLE = (ROOT / "static/style.css").read_text(encoding="utf-8") STYLE = (ROOT / "static/style.css").read_text(encoding="utf-8")
def test_mobile_footer_exposes_open_and_more_only(): def test_mobile_footer_exposes_delete_open_and_more():
assert "doclib-expanded-open-btn" in SOURCE assert "doclib-expanded-open-btn" in SOURCE
assert "doclib-expanded-mobile-more" in SOURCE assert "doclib-expanded-mobile-more" in SOURCE
assert "label: 'Open in new chat'" in SOURCE assert "label: 'Open in new chat'" in SOURCE
assert "'Open in original' : 'Open document'" in SOURCE assert "'Open in original' : 'Open document'" in SOURCE
assert "label: 'Export file'" in SOURCE assert "label: 'Export file ›'" in SOURCE
assert "label: 'Original format'" in SOURCE
assert "label: 'Markdown (.md)'" in SOURCE
assert "'Restore document' : 'Archive document'" in SOURCE assert "'Restore document' : 'Archive document'" in SOURCE
assert "label: 'Delete document'" in SOURCE assert "label: 'Delete document'" in SOURCE
mobile_css = STYLE.split("The Documents preview footer only exposes Open and More", 1)[1] mobile_css = STYLE.split("On phones, keep Delete explicit", 1)[1]
mobile_css = mobile_css.split("/* Chat top bar", 1)[0] mobile_css = mobile_css.split("/* Chat top bar", 1)[0]
for hidden_action in ( for hidden_action in (
".doclib-expanded-delete-btn",
".doclib-expanded-archive-btn", ".doclib-expanded-archive-btn",
".doclib-expanded-clone-btn", ".doclib-expanded-clone-btn",
".doclib-expanded-export-btn", ".doclib-expanded-export-btn",
): ):
assert hidden_action in mobile_css assert hidden_action in mobile_css
assert ".doclib-expanded-delete-btn {\n display: inline-flex !important" in mobile_css
assert ".doclib-expanded-mobile-more" in mobile_css assert ".doclib-expanded-mobile-more" in mobile_css
assert "display: inline-flex" in mobile_css assert "display: inline-flex" in mobile_css
assert "box-sizing: border-box" in mobile_css assert "box-sizing: border-box" in mobile_css
+3 -1
View File
@@ -91,13 +91,15 @@ def test_apply_pan_updates_state_canvas_overlay_and_cursor_classes():
def test_hand_navigation_is_wired_to_toolbar_keyboard_and_offline_graph(): def test_hand_navigation_is_wired_to_toolbar_keyboard_and_offline_graph():
toolbar = (ROOT / "static/js/editor/build/toolbar.js").read_text(encoding="utf-8") toolbar = (ROOT / "static/js/editor/build/toolbar.js").read_text(encoding="utf-8")
shortcuts = (ROOT / "static/js/editor/tool-shortcuts.js").read_text(encoding="utf-8")
keyboard = (ROOT / "static/js/editor/keyboard-shortcuts.js").read_text(encoding="utf-8") keyboard = (ROOT / "static/js/editor/keyboard-shortcuts.js").read_text(encoding="utf-8")
events = (ROOT / "static/js/editor/canvas-events.js").read_text(encoding="utf-8") events = (ROOT / "static/js/editor/canvas-events.js").read_text(encoding="utf-8")
editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8") editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8")
service_worker = (ROOT / "static/sw.js").read_text(encoding="utf-8") service_worker = (ROOT / "static/sw.js").read_text(encoding="utf-8")
assert "{ id: 'hand', label: 'Hand'" in toolbar assert "{ id: 'hand', label: 'Hand'" in toolbar
assert "key: 'H'" in toolbar assert "t.key = TOOL_SHORTCUTS[t.id]" in toolbar
assert "hand: 'H'" in shortcuts
assert "e.code === 'Space'" in keyboard assert "e.code === 'Space'" in keyboard
assert "setTemporaryPan?.(true)" in keyboard assert "setTemporaryPan?.(true)" in keyboard
assert "isDirectPanIntent(state.tool, state.spacePanActive" in events assert "isDirectPanIntent(state.tool, state.spacePanActive" in events
+2 -2
View File
@@ -20,8 +20,8 @@ def test_hover_thumbnail_uses_rendered_layer_output():
def test_inline_layer_rows_share_the_common_thumbnail_renderer(): def test_inline_layer_rows_share_the_common_thumbnail_renderer():
panel = (ROOT / "static/js/editor/layer-panel.js").read_text() panel = (ROOT / "static/js/editor/layer-panel.js").read_text()
assert "const previewCanvas = renderLayer?.(layer) || layer.canvas;" in panel assert "const thumb = createInlineThumbnail(() => renderLayer?.(layer) || layer.canvas, `${layer.name} preview`);" in panel
assert "const thumb = createInlineThumbnail(previewCanvas, `${layer.name} preview`);" in panel assert "thumb._refreshPreview = draw;" in panel
assert "thumbCtx.fillStyle = ((x / tile + y / tile) & 1)" not in panel assert "thumbCtx.fillStyle = ((x / tile + y / tile) & 1)" not in panel
+3 -1
View File
@@ -119,6 +119,7 @@ def test_rasterize_text_layer_clears_retained_metadata_only_for_text():
def test_text_tool_is_retained_across_editor_subsystems(): def test_text_tool_is_retained_across_editor_subsystems():
editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8") editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8")
toolbar = (ROOT / "static/js/editor/build/toolbar.js").read_text(encoding="utf-8") toolbar = (ROOT / "static/js/editor/build/toolbar.js").read_text(encoding="utf-8")
shortcuts = (ROOT / "static/js/editor/tool-shortcuts.js").read_text(encoding="utf-8")
controls = (ROOT / "static/js/editor/build/controls.js").read_text(encoding="utf-8") controls = (ROOT / "static/js/editor/build/controls.js").read_text(encoding="utf-8")
codec = (ROOT / "static/js/editor/document-codec.js").read_text(encoding="utf-8") codec = (ROOT / "static/js/editor/document-codec.js").read_text(encoding="utf-8")
geometry = (ROOT / "static/js/editor/document-geometry.js").read_text(encoding="utf-8") geometry = (ROOT / "static/js/editor/document-geometry.js").read_text(encoding="utf-8")
@@ -127,7 +128,8 @@ def test_text_tool_is_retained_across_editor_subsystems():
merge = (ROOT / "static/js/editor/wire-merge-buttons.js").read_text(encoding="utf-8") merge = (ROOT / "static/js/editor/wire-merge-buttons.js").read_text(encoding="utf-8")
assert "{ id: 'text', label: 'Text'" in toolbar assert "{ id: 'text', label: 'Text'" in toolbar
assert "key: 'T'" in toolbar assert "t.key = TOOL_SHORTCUTS[t.id]" in toolbar
assert "text: 'T'" in shortcuts
assert 'id="ge-text-section"' in controls assert 'id="ge-text-section"' in controls
assert "if (state.tool === 'text') return _placeText(e);" in editor assert "if (state.tool === 'text') return _placeText(e);" in editor
assert "kind: l.kind || 'raster'" in editor assert "kind: l.kind || 'raster'" in editor
+9 -9
View File
@@ -32,15 +32,15 @@ def test_stacked_labels_share_one_size_and_position_rule():
assert "top: 2px;" in STYLE assert "top: 2px;" in STYLE
def test_narrow_topbar_reflows_essential_actions_instead_of_clipping_them(): def test_narrow_topbar_scrolls_essential_actions_and_hides_ai_group_first():
assert "ge-topbar-overflow" in OVERFLOW assert "if (topbar.scrollWidth > topbar.clientWidth)" in OVERFLOW
assert "topbar.classList.add('ge-topbar-overflow')" in OVERFLOW assert "aiGroup.forEach(el => { el.style.display = 'none'; });" in OVERFLOW
assert "(max-width: 700px)" in OVERFLOW assert "new ResizeObserver(() => syncOverflow())" in OVERFLOW
assert ".ge-topbar.ge-topbar-overflow" in STYLE mobile = STYLE[STYLE.index("/* Editor topbar — scrolls horizontally") :]
assert "flex: 1 0 100%;" in STYLE topbar = mobile[mobile.index(".ge-topbar {") : mobile.index("}", mobile.index(".ge-topbar {"))]
right_start = STYLE.index(".ge-topbar-overflow .ge-topbar-right") assert "overflow-x: auto;" in topbar
overflow_right = STYLE[right_start:STYLE.index("}", right_start)] assert "flex-wrap: nowrap;" in topbar
assert "justify-content: flex-start;" in overflow_right assert "justify-content: flex-start;" in topbar
def test_desktop_tool_rail_keeps_long_tool_names_readable(): def test_desktop_tool_rail_keeps_long_tool_names_readable():
+5 -3
View File
@@ -160,8 +160,10 @@ def test_attachment_cache_backfill_preserves_message_id(tmp_path, monkeypatch):
def test_single_email_tag_has_no_more_control(): def test_single_email_tag_has_no_more_control():
library = open("static/js/emailLibrary.js", encoding="utf-8").read() library = open("static/js/emailLibrary.js", encoding="utf-8").read()
group = library[library.index("function _emailTagGroupHtml("):library.index("function _fitEmailCardTags(")]
assert 'class="email-tags-more email-tags-more-single"' not in library assert "if (visible.length === 1) return visible[0];" in group
assert "if (visible.length === 2) return visible.join('');" in group
assert group.index("if (visible.length === 2)") < group.index("email-tags-more-single")
def test_email_folder_and_filter_pickers_treat_their_buttons_as_inside_clicks(): def test_email_folder_and_filter_pickers_treat_their_buttons_as_inside_clicks():
@@ -181,7 +183,7 @@ def test_empty_reply_has_two_editable_rows_and_reply_survives_compact_toolbar():
fit_start = library.index("function _fitReaderActions") fit_start = library.index("function _fitReaderActions")
fit_end = library.index("const _readerActionFitObserver", fit_start) fit_end = library.index("const _readerActionFitObserver", fit_start)
fit = library[fit_start:fit_end] fit = library[fit_start:fit_end]
assert '[data-act="ai-reply"], [data-act="reply-all"]' in fit assert '[data-act="reply-all"], [data-act="forward"]' in fit
assert '[data-act="reply"]' not in fit assert '[data-act="reply"]' not in fit
+1 -1
View File
@@ -16,7 +16,7 @@ def test_folder_chip_stays_with_date_and_moves_down():
folder_rule_start = css.index(".email-folder-chip {", first_folder_rule + 1) folder_rule_start = css.index(".email-folder-chip {", first_folder_rule + 1)
folder_rule = css[folder_rule_start:][:220] folder_rule = css[folder_rule_start:][:220]
assert "position: relative;" in folder_rule assert "position: relative;" in folder_rule
assert "top: 2px;" in folder_rule assert "top: 4px;" in folder_rule
group_rule = css[css.index(".email-meta-date-group {"):][:180] group_rule = css[css.index(".email-meta-date-group {"):][:180]
assert "display: inline-flex;" in group_rule assert "display: inline-flex;" in group_rule
assert "white-space: nowrap;" in group_rule assert "white-space: nowrap;" in group_rule
+4 -3
View File
@@ -127,15 +127,16 @@ def test_attachment_warning_only_checks_authored_reply_text():
assert "text.split(/^>|^On .* wrote:/m)" not in helper assert "text.split(/^>|^On .* wrote:/m)" not in helper
def test_email_send_saves_recovery_draft_before_send_and_closes_only_on_success(): def test_email_send_saves_recovery_draft_before_send_and_retains_it_on_failure():
source = (_REPO / "static/js/document.js").read_text(encoding="utf-8") source = (_REPO / "static/js/document.js").read_text(encoding="utf-8")
send = source[source.index("async function _sendEmail"):source.index("\n\n async function _saveDraft", source.index("async function _sendEmail"))] send = source[source.index("async function _sendEmail"):source.index("\n\n async function _saveDraft", source.index("async function _sendEmail"))]
assert "async function _saveEmailDraftForRecovery" in source assert "async function _saveEmailDraftForRecovery" in source
assert send.index("_saveEmailDraftForRecovery({") < send.index("fetch(`${API_BASE}/api/email/send`") assert send.index("_saveEmailDraftForRecovery({") < send.index("fetch(`${API_BASE}/api/email/send`")
assert send.index("if (isLibraryOpen()) closeLibrary();") > send.index("const sendRequest = fetch(")
assert send.index("if (isLibraryOpen()) closeLibrary();") < send.index("const res = await sendRequest")
success_branch = send[send.index("if (data.success) {"):] success_branch = send[send.index("if (data.success) {"):]
assert "closeLibrary()" in success_branch assert "fetch(`${API_BASE}/api/document/${sendDocId}`, { method: 'DELETE' })" in success_branch
assert send.index("closeLibrary()") > send.index("const res = await sendRequest")
assert "Draft kept in Drafts." in send assert "Draft kept in Drafts." in send
assert "recoveryDraft.draft_uid" in send assert "recoveryDraft.draft_uid" in send
@@ -10,8 +10,11 @@ def test_email_folder_and_filter_pickers_are_exclusive_and_escape_safe():
assert source.count("const filterMenu = document.getElementById('email-filter-menu');") == 1 assert source.count("const filterMenu = document.getElementById('email-filter-menu');") == 1
assert source.count("const folderMenu = document.getElementById('email-folder-menu');") == 1 assert source.count("const folderMenu = document.getElementById('email-folder-menu');") == 1
assert source.count("e.stopImmediatePropagation();") >= 2 assert source.count("e.stopImmediatePropagation?.();") >= 2
assert "_wireEmailPickerEscapeGuard();" in source assert "filterMenu?._dismiss?.();" in source
assert "window.addEventListener('keydown'" in source assert "folderMenu?._dismiss?.();" in source
escape_handler = source[source.index("state._libInnerEscHandler = (e) => {"):source.index("window.addEventListener('keydown', state._libInnerEscHandler, true)")]
assert "if (dismissTopMenu()) {" in escape_handler
assert "window.addEventListener('keydown', state._libInnerEscHandler, true)" in source
inbox = (ROOT / "static/js/emailInbox.js").read_text(encoding="utf-8") inbox = (ROOT / "static/js/emailInbox.js").read_text(encoding="utf-8")
assert re.search(r"from './emailLibrary\.js\?v=[A-Za-z0-9_-]+'", inbox) assert re.search(r"from './emailLibrary\.js\?v=[A-Za-z0-9_-]+'", inbox)
+1 -2
View File
@@ -5,10 +5,9 @@ import re
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
def test_original_harness_version_is_canonical_semver() -> None: def test_harness_version_is_canonical_semver() -> None:
version = (ROOT / "HARNESS_VERSION").read_text(encoding="utf-8").strip() version = (ROOT / "HARNESS_VERSION").read_text(encoding="utf-8").strip()
assert version == "0.20.18"
assert re.fullmatch(r"\d+\.\d+\.\d+", version) assert re.fullmatch(r"\d+\.\d+\.\d+", version)
+3 -3
View File
@@ -145,15 +145,15 @@ def test_final_response_skips_duplicate_end_of_stream_render():
"// --- Final render (skip if stream was ever backgrounded or currently in background) ---", "// --- Final render (skip if stream was ever backgrounded or currently in background) ---",
"} // end if (!_isBgFinal)", "} // end if (!_isBgFinal)",
) )
assert "if (!terminalFinalResponseRendered) _renderStream();" in post_loop assert "if (!terminalFinalResponseRendered && !_turnRendering.isVisible(roundHolder.querySelector('.body'), _terminalAnswerHtml(roundText, roundHolder.querySelector('.body')))) _renderStream();" in post_loop
assert "const finalDisplay = terminalFinalResponseRendered ? '' : _streamDisplayText" in post_loop assert "const finalDisplay = terminalFinalResponseRendered ? '' : _streamDisplayText" in post_loop
def test_only_rich_completed_turns_reload_saved_canonical_assistant_row(): def test_only_rich_completed_turns_reload_saved_canonical_assistant_row():
assert "if (_canonicalTerminalSaved && _savedAssistantMessageId && !_pendingContinue)" not in _CHAT assert "if (_canonicalTerminalSaved && _savedAssistantMessageId && !_pendingContinue)" not in _CHAT
assert "if (!_pendingContinue)" in _CHAT assert "if (!_pendingContinue)" in _CHAT
assert "fall back to its latest" in _CHAT assert "if (!streamSessionId || !_savedAssistantMessageId) return false;" in _CHAT
assert ": [...history].reverse().find(msg => msg && msg.role === 'assistant');" in _CHAT assert "String(msg.metadata?._db_id || '') === _savedAssistantMessageId" in _CHAT
assert "const _needsCanonicalTurnRebuild" in _CHAT assert "const _needsCanonicalTurnRebuild" in _CHAT
assert "lastToolThread" in _CHAT assert "lastToolThread" in _CHAT
assert "_streamTurnMarker.remove();" in _CHAT assert "_streamTurnMarker.remove();" in _CHAT
+1 -1
View File
@@ -172,4 +172,4 @@ class TestThinkSuppression:
"qwen35-9b-tool-router-v4-firstaction-noschema-adapter", "qwen35-9b-tool-router-v4-firstaction-noschema-adapter",
) )
assert "think" not in payload assert "think" not in payload
assert payload["max_tokens"] == 1024 assert payload["max_tokens"] == llm_core.LLMConfig.DEFAULT_MAX_TOKENS
@@ -87,6 +87,12 @@ def test_mobile_bulk_select_long_press_is_shared_across_card_types():
assert ".skill-card[data-skill-name]" in helper assert ".skill-card[data-skill-name]" in helper
assert ".task-card[data-id]" in helper assert ".task-card[data-id]" in helper
assert "const HOLD_MS = 450" in helper assert "const HOLD_MS = 450" in helper
assert "body:has(#memory-select-btn.active)" in css shared_buttons = (
assert "body:has(#skills-select-btn.active)" in css "#memory-select-btn,", "#skills-select-btn,",
assert "body:has(#tasks-select-btn.active)" in css "#notes-select-btn,", "#tasks-select-btn,",
)
shared_css = css.split("/* Shared bulk-selection trigger.", 1)[1]
selectors = re.findall(r":is\(([^)]*)\)(?:\.active)?::before", shared_css)
assert len(selectors) == 2
for selector in selectors:
assert all(button in selector for button in shared_buttons)
+2 -2
View File
@@ -9,7 +9,7 @@ def test_notes_sidebar_new_action_matches_library_structure_and_animation():
css = (ROOT / "static/style.css").read_text(encoding="utf-8") css = (ROOT / "static/style.css").read_text(encoding="utf-8")
assert 'class="list-item-plus-btn sidebar-new-item-btn" id="notes-new-note-btn"' in html assert 'class="list-item-plus-btn sidebar-new-item-btn" id="notes-new-note-btn"' in html
assert '<span class="list-item-plus-label">note</span>' in html assert '<span class="list-item-plus-label">new</span>' in html[html.index('id="notes-new-note-btn"'):]
assert "#tool-notes-btn:hover #notes-new-note-btn" in css assert "#tool-notes-btn:hover #notes-new-note-btn" in css
assert "#notes-new-note-btn:hover svg" in css assert "#notes-new-note-btn:hover svg" in css
@@ -72,7 +72,7 @@ def test_notes_body_and_tag_arrow_are_nudged_down():
assert css.count("padding: 10px 8px 8px") >= 2 assert css.count("padding: 10px 8px 8px") >= 2
assert ".notes-pane-body .doclib-chip-scroll-arrow.right" in css assert ".notes-pane-body .doclib-chip-scroll-arrow.right" in css
assert "top: calc(50% - 2px) !important" in css assert "top: calc(50% - 6px) !important" in css[css.index(".notes-pane-body .doclib-chip-scroll-arrow.right"):]
def test_notes_tag_strip_cannot_grow_into_blank_space(): def test_notes_tag_strip_cannot_grow_into_blank_space():
+14 -12
View File
@@ -15,6 +15,11 @@ NOTES_TOOLS = {
"ask_user", "ask_user",
"update_plan", "update_plan",
} }
GENERAL_COMPACT_TOOLS = {"ask_user", "web_search", "web_fetch"}
CALENDAR_COMPACT_TOOLS = {
"ask_user", "bash", "get_workspace", "manage_calendar", "manage_notes",
"python", "read_file", "web_fetch", "web_search",
}
def _collect(generator): def _collect(generator):
@@ -102,9 +107,7 @@ def test_odysseus_notes_mode_clamps_without_overriding_caller_denials(monkeypatc
assert {"manage_notes", "manage_calendar", "manage_tasks"} <= route["disabled_tools"] assert {"manage_notes", "manage_calendar", "manage_tasks"} <= route["disabled_tools"]
def test_odysseus_general_mode_disables_every_tool(monkeypatch): def test_odysseus_general_mode_uses_compact_core(monkeypatch):
from src.tool_policy import known_tool_names
prompt_calls, _ = _install_route_probe(monkeypatch) prompt_calls, _ = _install_route_probe(monkeypatch)
_run_probe( _run_probe(
@@ -113,11 +116,10 @@ def test_odysseus_general_mode_disables_every_tool(monkeypatch):
) )
route = prompt_calls[0] route = prompt_calls[0]
assert route["relevant_tools"] == set() assert route["relevant_tools"] == GENERAL_COMPACT_TOOLS
assert known_tool_names() <= route["disabled_tools"]
def test_odysseus_calendar_intent_uses_notes_mode(monkeypatch): def test_odysseus_calendar_intent_uses_compact_calendar_route(monkeypatch):
prompt_calls, _ = _install_route_probe(monkeypatch) prompt_calls, _ = _install_route_probe(monkeypatch)
_run_probe( _run_probe(
@@ -125,10 +127,10 @@ def test_odysseus_calendar_intent_uses_notes_mode(monkeypatch):
relevant_tools={"manage_notes", "manage_calendar", "manage_tasks", "bash"}, relevant_tools={"manage_notes", "manage_calendar", "manage_tasks", "bash"},
) )
assert prompt_calls[0]["relevant_tools"] == NOTES_TOOLS assert prompt_calls[0]["relevant_tools"] == CALENDAR_COMPACT_TOOLS
def test_odysseus_calendar_followup_keeps_notes_mode(monkeypatch): def test_odysseus_calendar_followup_keeps_compact_calendar_route(monkeypatch):
prompt_calls, _ = _install_route_probe(monkeypatch) prompt_calls, _ = _install_route_probe(monkeypatch)
messages = [ messages = [
{"role": "user", "content": "Add lunch tomorrow to my calendar."}, {"role": "user", "content": "Add lunch tomorrow to my calendar."},
@@ -153,7 +155,7 @@ def test_odysseus_calendar_followup_keeps_notes_mode(monkeypatch):
relevant_tools={"manage_notes", "manage_calendar", "manage_tasks", "bash"}, relevant_tools={"manage_notes", "manage_calendar", "manage_tasks", "bash"},
) )
assert prompt_calls[0]["relevant_tools"] == NOTES_TOOLS assert prompt_calls[0]["relevant_tools"] == CALENDAR_COMPACT_TOOLS
def test_agent_route_passes_workspace_to_system_prompt(monkeypatch): def test_agent_route_passes_workspace_to_system_prompt(monkeypatch):
@@ -169,7 +171,7 @@ def test_agent_route_passes_workspace_to_system_prompt(monkeypatch):
assert prompt_calls[0]["workspace"] == "/tmp/example-repo" assert prompt_calls[0]["workspace"] == "/tmp/example-repo"
def test_odysseus_qwen_temperature_is_capped_for_agent_requests(monkeypatch): def test_odysseus_compact_primary_uses_deterministic_temperature(monkeypatch):
_, stream_calls = _install_route_probe(monkeypatch) _, stream_calls = _install_route_probe(monkeypatch)
_run_probe( _run_probe(
@@ -178,7 +180,7 @@ def test_odysseus_qwen_temperature_is_capped_for_agent_requests(monkeypatch):
temperature=1.2, temperature=1.2,
) )
assert stream_calls[0]["temperature"] == 0.2 assert stream_calls[0]["temperature"] == 0.0
def test_qwen_fallback_candidate_gets_capped_temperature(monkeypatch): def test_qwen_fallback_candidate_gets_capped_temperature(monkeypatch):
@@ -214,7 +216,7 @@ def test_non_qwen_fallback_keeps_requested_temperature(monkeypatch):
fallbacks=[("https://backup.example/v1", "gpt-4o", {})], fallbacks=[("https://backup.example/v1", "gpt-4o", {})],
) )
assert stream_calls[0]["temperature"] == 0.2 assert stream_calls[0]["temperature"] == 0.0
factory = stream_calls[0]["candidate_request_factory"] factory = stream_calls[0]["candidate_request_factory"]
request = asyncio.run(factory(1, "https://backup.example/v1", "gpt-4o", {})) request = asyncio.run(factory(1, "https://backup.example/v1", "gpt-4o", {}))
assert request["kwargs"]["temperature"] == 1.2 assert request["kwargs"]["temperature"] == 1.2
+16 -7
View File
@@ -1,6 +1,7 @@
"""Regression coverage for full-height Deep Research history expansion.""" """Regression coverage for full-height Deep Research history expansion."""
from pathlib import Path from pathlib import Path
import re
ROOT = Path(__file__).resolve().parent.parent ROOT = Path(__file__).resolve().parent.parent
@@ -11,7 +12,11 @@ def test_history_list_participates_in_shared_library_expansion_layout():
css = (ROOT / "static/style.css").read_text(encoding="utf-8") css = (ROOT / "static/style.css").read_text(encoding="utf-8")
assert 'id="research-past-list" class="doclib-grid memory-list research-jobs-list"' in panel assert 'id="research-past-list" class="doclib-grid memory-list research-jobs-list"' in panel
assert "width:min(560px, 90vw);max-height:78vh" in panel card = css[css.index("#research-pane .research-history-card {"):]
card = card[:card.index("}")]
assert "flex: 1 1 0;" in card
assert "min-height: 0;" in card
assert "overflow: hidden;" in card
assert 'class="memory-tab-panel research-tab-panel"' in panel assert 'class="memory-tab-panel research-tab-panel"' in panel
assert 'class="admin-card research-new-job"' in panel assert 'class="admin-card research-new-job"' in panel
assert 'id="research-history-filters" class="skills-summary-strip"' in panel assert 'id="research-history-filters" class="skills-summary-strip"' in panel
@@ -21,7 +26,11 @@ def test_history_list_participates_in_shared_library_expansion_layout():
assert "pane.classList.toggle('research-results-view', tab !== 'research')" in panel assert "pane.classList.toggle('research-results-view', tab !== 'research')" in panel
assert "display: flex; flex-direction: column; gap: 10px;" in css assert "display: flex; flex-direction: column; gap: 10px;" in css
assert ".research-tabs {\n flex: 0 0 auto;\n margin: -4px -4px 0;" in css assert ".research-tabs {\n flex: 0 0 auto;\n margin: -4px -4px 0;" in css
assert "font-size:11px; letter-spacing:0;" in css title = css[css.index("#research-pane .research-history-title-row h2 {"):]
title = title[:title.index("}")]
assert "letter-spacing: 0;" in title
desc = css[css.index("#research-pane .research-history-desc {"):]
assert "font-size: 11px;" in desc[:desc.index("}")]
assert "font: inherit; font-size: 12px; cursor: pointer; text-align: left;" in css assert "font: inherit; font-size: 12px; cursor: pointer; text-align: left;" in css
assert "#research-pane .research-history-search-wrap .memory-search-input" in css assert "#research-pane .research-history-search-wrap .memory-search-input" in css
assert "height: 30px;" in css assert "height: 30px;" in css
@@ -65,8 +74,8 @@ def test_research_panel_uses_one_versioned_module_instance():
renderer = (ROOT / "static/js/chatRenderer.js").read_text(encoding="utf-8") renderer = (ROOT / "static/js/chatRenderer.js").read_text(encoding="utf-8")
index = (ROOT / "static/index.html").read_text(encoding="utf-8") index = (ROOT / "static/index.html").read_text(encoding="utf-8")
version = "20260902researchhistoryalign34" panel_version = re.search(r"research/panel\.js\?v=([^'\"]+)", app)
assert f"research/panel.js?v={version}" in app asset_version = re.search(r"/static/app\.js\?v=([^'\"]+)", index)
assert renderer.count(f"research/panel.js?v={version}") == 2 style_version = re.search(r"/static/style\.css\?v=([^'\"]+)", index)
assert f"style.css?v={version}" in index assert panel_version and renderer.count(f"research/panel.js?v={panel_version.group(1)}") == 2
assert f"app.js?v={version}" in index assert asset_version and style_version and asset_version.group(1) == style_version.group(1)
+6 -6
View File
@@ -25,18 +25,18 @@ def test_research_settings_use_custom_pickers_and_shared_provider_icons():
assert "provider === 'google' ? 'google_pse'" in icons assert "provider === 'google' ? 'google_pse'" in icons
first_picker_offset = style.split(".research-setting:has(#research-rounds),", 1)[1].split("}", 1)[0] first_picker_offset = style.split(".research-setting:has(#research-rounds),", 1)[1].split("}", 1)[0]
assert ".research-setting:has(#research-category)" in first_picker_offset assert ".research-setting:has(#research-category)" in first_picker_offset
assert "top: -4px;" in first_picker_offset assert "top: 0;" in first_picker_offset
def test_completed_research_keeps_primary_and_utility_actions_visible_without_format_icon(): def test_completed_research_keeps_primary_and_utility_actions_visible_without_format_icon():
panel = (ROOT / "static/js/research/panel.js").read_text(encoding="utf-8") panel = (ROOT / "static/js/research/panel.js").read_text(encoding="utf-8")
assert "research-job-format-icon" not in panel assert "research-job-format-icon" not in panel
assert "Visual Report" in panel assert 'data-action="report" title="Open visual report"' in panel
assert "Discuss" in panel assert 'data-action="chat" title="Open follow-up chat with this research as context"' in panel
assert 'data-action="copy" title="Copy report to clipboard"' in panel assert "{ action: 'copy', icon: _copyIcon, label: 'Copy report' }" in panel
assert 'data-action="dismiss" title="Clear from list"' in panel assert "{ action: 'dismiss', icon: _cancelIcon, label: 'Hide from list' }" in panel
assert 'data-action="delete" title="Delete from disk"' in panel assert "{ action: 'delete', icon: _trashIcon, label: 'Delete from disk', danger: true }" in panel
def test_research_format_survives_live_and_reconnected_jobs(): def test_research_format_survives_live_and_reconnected_jobs():
+2 -1
View File
@@ -40,7 +40,8 @@ def test_tasks_filter_chips_include_active_paused_switch():
assert "mkChip(`active (${activeCount})`, 'active', _taskStatusFilter === 'active', 'status');" in src assert "mkChip(`active (${activeCount})`, 'active', _taskStatusFilter === 'active', 'status');" in src
assert "mkChip(`paused (${pausedCount})`, 'paused', _taskStatusFilter === 'paused', 'status');" in src assert "mkChip(`paused (${pausedCount})`, 'paused', _taskStatusFilter === 'paused', 'status');" in src
assert "if (_taskStatusFilter && String(t.status || '').toLowerCase() !== _taskStatusFilter) return false;" in src assert "if (_taskStatusFilter && String(t.status || '').toLowerCase() !== _taskStatusFilter) return false;" in src
assert "if (value === null) _taskStatusFilter = null;" in src assert "_taskStatusFilter = _taskStatusFilter === value ? null : value;" in src
assert "_taskStatusFilter = null;" in src[src.index("if (kind === 'status')"):src.index("_renderList();", src.index("if (kind === 'status')"))]
def test_tasks_completed_view_exposes_active_paused_shortcuts(): def test_tasks_completed_view_exposes_active_paused_shortcuts():
+4 -4
View File
@@ -155,12 +155,12 @@ def test_every_changed_approval_module_is_cache_busted_together():
assert found, f"missing cache-busted reference for {module_name}" assert found, f"missing cache-busted reference for {module_name}"
assert len(set(found)) == 1, f"split module graph for {module_name}: {found}" assert len(set(found)) == 1, f"split module graph for {module_name}: {found}"
# These shared modules are imported throughout the graph. Keep their URL # Shared modules must have one URL apiece. ui.js is consistently versioned
# canonical and unversioned; mixing a query URL with plain relative imports # throughout the graph; the other shared modules remain unversioned.
# creates a second singleton with separate state and listeners. for module_name in ("sessions.js", "memory.js", "markdown.js", "models.js"):
for module_name in ("sessions.js", "ui.js", "memory.js", "markdown.js", "models.js"):
assert any(module_name in source for source in sources) assert any(module_name in source for source in sources)
assert not versions(module_name), f"split module graph for {module_name}" assert not versions(module_name), f"split module graph for {module_name}"
assert len(set(versions("ui.js"))) == 1
compare_stream = (root / "static/js/compare/stream.js").read_text(encoding="utf-8") compare_stream = (root / "static/js/compare/stream.js").read_text(encoding="utf-8")
compare_vote = (root / "static/js/compare/vote.js").read_text(encoding="utf-8") compare_vote = (root / "static/js/compare/vote.js").read_text(encoding="utf-8")