ulysses/tests
botinate 69b9bb0869
fix(agent): execute fenced tool calls with inline args and route bare email tool names (#3681)
* fix(agent): execute fenced tool calls with inline args and bare email tool names

Two bugs made local (Ollama) models unable to use email tools, leaving
raw fences like ```list_email_accounts {}``` in the chat:

1. _TOOL_BLOCK_RE required a newline right after the fence tag, so a
   tool call with args on the same line ("```list_email_accounts {}")
   never matched and was never executed. The fence now matches with
   optional spaces/newline after the tag.

2. Even when parsed, bare email tool names had no dispatch branch in
   tool_execution.py and fell through to "Unknown tool type". They now
   route to the email MCP server as mcp__email__<name>, matching how
   function_call_to_tool_block already maps them for native callers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(security): block all bare email tool names for non-admins; harden fence-tag regex

Review follow-up on #3681 (thanks @vgalin):

1. Routing bare email names made 10 of the 14 email tools executable by
   non-admin owners — is_public_blocked_tool() runs on the bare name
   before dispatch, and NON_ADMIN_BLOCKED_TOOLS only listed 4. Define the
   full email tool set once (BUILTIN_EMAIL_TOOLS in tool_security.py) and
   derive the blocklist, the fence tags (TOOL_TAGS), the bare-name
   dispatch, and the native-call mapping from it so they can't drift.
   This also fixes 4 tools (search_emails, draft_email, draft_email_reply,
   ai_draft_email_reply) that were missing from the old tool_schemas copy
   and therefore unreachable even for native function-calling models.

2. The relaxed fence regex from the previous commit could prefix-match
   longer fence tags: ```python3 parsed as tool "python" with content
   "3\nprint(...)" and executed as code. Add a (?![\w-]) boundary after
   the tag.

Tests: test_public_agent_policy_blocks_sensitive_tools now covers all 14
bare email names + the mcp__email__ form; new tests/test_fenced_inline_args.py
pins inline-args parsing, the python3/hyphenated-tag non-matches, and
strip/parse display mirroring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(security): gate bare and mcp-qualified email names together; stop executing Markdown info strings

Review follow-up on #3681 (thanks @RaresKeY):

1. P1: execute_tool_block() checked disabled_tools / the turn ToolPolicy
   only against the incoming block name, then the bare-email branch
   qualified it to mcp__email__<name> and called the MCP manager. Plan
   mode and the MCP settings toggle write the QUALIFIED name into the
   denylist, so a bare fence like ```list_emails``` sailed past a
   mcp__email__list_emails entry. Both gates now match on both
   spellings (bare <-> mcp__email__-qualified), in either direction.

2. P2: the relaxed fence regex accepted arbitrary same-line text after
   a recognized tag, which made ordinary Markdown info strings
   executable: ```python title="example.py" ran as a python tool call.
   Same-line content now only counts as tool input when it starts with
   { or [ (JSON args); anything else leaves the fence as display text,
   and strip_tool_blocks mirrors that (the fence stays visible).

Tests: disabled-tools alias regression (qualified entry blocks bare
name and vice versa, never reaching the MCP manager), ToolPolicy alias
regression, python/bash title="..." non-execution + display retention,
and inline JSON-array args still parsing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(security): reject brace-style fence metadata; cover the full email set in the friendly toggle

Review follow-up round 3 on #3681 (thanks @RaresKeY):

1. Brace-style fence metadata no longer executes. The previous narrowing
   still treated any same-line {/[ after a recognized tag as tool input,
   so ```bash {title="setup"} ran as a bash call. The fence header is now
   captured separately and judged by one predicate shared between
   parse_tool_blocks and strip_tool_blocks (_fenced_tool_call), so the
   execute and display decisions can't disagree: same-line content only
   counts as inline args when the tag is NOT a code tag (bash/python
   never take same-line args — that text is Markdown fence attributes)
   AND the inline text (plus any continuation lines) parses as standalone
   JSON. ```bash {title="setup"}, ```python {"title":"example.py"} and
   ```list_emails {title="x"} all stay visible and inert.

2. The friendly `disable_tool email` toggle covered 3 of the 14 email
   tools (mcp__email__{list_emails,read_email,send_email}); the other
   bare aliases this PR routes stayed executable after an operator
   disabled email. The alias now derives from BUILTIN_EMAIL_TOOLS in
   BOTH spellings — bare (function-schema hiding, bare-fence dispatch)
   and mcp__email__* (MCP schema hiding, qualified runtime blocks) —
   so the toggle and the runtime gate can't drift apart.

Tests: brace/bracket metadata regressions for parse and strip symmetry
(code tags, invalid-JSON inline on a JSON tool, multi-line inline JSON
still parsing), and disable_tool/enable_tool email covering all 14 names
in both spellings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(email): close remaining email-tool registry drift; classify every email tool for plan mode

Deep self-review follow-up on #3681. Three review rounds each found another
hand-maintained copy of the email tool list that had drifted; this commit
hunts down ALL remaining copies and pins them to BUILTIN_EMAIL_TOOLS.

The same 5 tools (search_emails, draft_email, draft_email_reply,
ai_draft_email_reply, download_attachment) were missing from every
advertising surface, so they were dispatchable but never offered:

- FUNCTION_TOOL_SCHEMAS: native function-calling models never saw them
  (the round-1 fix covered dispatch only); schemas added, mirroring the
  email server's inputSchema definitions.
- TOOL_SECTIONS: fenced-block models were never told about them; prompt
  sections added.
- tool_index: absent from the RAG embedding registry (never retrievable),
  the email keyword hints, and the scheduled assistant's always-available
  set — the latter two now derive from BUILTIN_EMAIL_TOOLS.
- agent_loop._DOMAIN_TOOL_MAP["email"], tool_policy._COMMON_TOOL_NAMES,
  the assistant tool-selector UI groups (assistant.js), and the default
  Assistant crew seed (task_scheduler) now derive from / cover the set.

Plan mode now classifies every email tool explicitly:

- list_email_accounts and search_emails join PLAN_MODE_READONLY_TOOLS.
  Without this, list_email_accounts sat in the plan-mode bare denylist
  (schema-derived) while its qualified form passed the MCP read-only
  filter — and the round-2 bare/qualified alias gate would have blocked
  the qualified call too, regressing read-only email discovery in plan
  mode.
- draft_email, draft_email_reply, ai_draft_email_reply, and
  download_attachment join the fail-closed mutator backstop (drafts
  create documents; download_attachment writes to disk).

Tests: tests/test_email_registry_sync.py pins every registry (including
the email server source and assistant.js) to BUILTIN_EMAIL_TOOLS and
asserts the plan-mode partition, so the next email tool can't drift; a
parse/strip mirror grid covers 192 fence shapes (tag x header x body)
asserting executed <=> stripped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: move the email alias rule into tool_security; extract the assistant seed constant

Code-quality pass over the PR's own changes:

- The bare<->qualified email aliasing rule lived inline in the generic
  dispatcher (_execute_tool_block_impl). It is policy knowledge, so it
  moves next to BUILTIN_EMAIL_TOOLS as email_tool_policy_names(); the
  dispatcher just consumes it, and the rule gets its own unit test
  (including the mcp__email__<not-a-tool> and mcp__other__ non-alias
  cases).

- The default Assistant's enabled_tools list was an inline literal
  inside the CrewMember seed, and its registry-sync test asserted a
  source-code substring. Extracted to DEFAULT_ASSISTANT_ENABLED_TOOLS
  so the test imports and checks the actual value.

- _fenced_tool_call return type tightened to Optional[Tuple[str, str]].

No behavior change; suite green (3295 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* revert: move the email registry consolidation to a follow-up PR

Per review feedback on scope, this PR stays narrow: fenced inline-args
parsing, bare email tool routing, and the directly required safety
gates. This commit reverts the registry/advertising consolidation from
db29046 and 016ce47 (native schemas, prompt sections, RAG description
index + keyword hints, assistant always-available set, guide-only
known-names union, frontend tool-selector groups, default assistant
seed, and their sync tests) — all of that moves to a dedicated
follow-up PR together with the _EMAIL_TOOL_HINTS finding.

Kept here because the narrow scope needs them:
- email_tool_policy_names() in tool_security + its use in the
  execute_tool_block gates and its unit test (refactor of this PR's own
  round-2 alias fix),
- list_email_accounts in PLAN_MODE_READONLY_TOOLS (the alias gate works
  both ways, and the schema-derived plan-mode bare denylist would
  otherwise block the qualified read-only call too),
- the parse/strip mirror grid test (parser scope),
- the narrow registry sync tests (email server <-> BUILTIN_EMAIL_TOOLS
  match, fence-tag coverage, non-admin blocklist coverage).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(email): execute empty email fences with empty args; reject non-object JSON args

Two gaps found by replaying captured local-model traffic against the
narrowed branch:

1. ```list_email_accounts``` with NO body — a shape gemma really emits
   for no-arg tools — was silently dropped (parse skips empty content),
   so the model concluded email was broken: the original #337 symptom
   through a different door. Empty fences whose tag is a built-in email
   tool now dispatch with {} args and the tool's own validation answers
   (e.g. an empty send_email returns "to is required" instead of
   silence). Empty bash/python/other fences keep skipping, and strip
   stays mirrored (the fence was executed, so it is removed).

2. The fence parser accepts JSON arrays as inline args, but the email
   dispatch parsed only objects — an array silently became {} args.
   Non-object JSON now returns a correctable "arguments must be a JSON
   object" error before reaching the MCP server (same class as #3966).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(security): classify all email tools for plan mode statically; reject invalid email JSON bodies

Review follow-up round 5 on #3681 (thanks @RaresKeY):

1. This PR makes every BUILTIN_EMAIL_TOOLS name fence-taggable, so each
   one must be explicitly classified for plan mode — the draft tools and
   download_attachment were in neither the read-only allowlist nor the
   static denylist, leaving their bare-alias plan-mode safety dependent
   on the MCP read-only inventory being present and current.
   search_emails joins PLAN_MODE_READONLY_TOOLS (explicit, not
   allowed-by-omission); draft_email, draft_email_reply,
   ai_draft_email_reply, and download_attachment join the fail-closed
   _PLAN_MODE_KNOWN_MUTATORS backstop. (Moved back from the #4053 split:
   the partition is directly required for this PR to merge
   independently.)

2. The classic tag/body fence form reaches execution unvalidated (only
   INLINE args are JSON-checked by the parser), so a body like
   {account: "work"} silently became {} args and read the DEFAULT
   mailbox instead of the intended one. JSON-looking bodies that fail to
   parse now return a correctable "not valid JSON" error before reaching
   the MCP server.

Tests: a partition invariant (every email tool is explicitly read-only
or plan-mode-denied), a mutating-alias probe that uses only the static
denylist with a fake MCP manager (no inventory layer), and the
body-form invalid-JSON regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(tool-dispatch): decode inline JSON args for legacy MCP tools; reject all non-object email bodies

Review follow-up round 6 on #3681 (thanks @RaresKeY) — both pre-existing
on this branch, surfaced by the relaxed inline-args parser:

1. The relaxed parser accepts inline JSON for every non-code tag, but
   the legacy line-based arg builders (web_search/web_fetch/read_file/
   write_file/generate_image/manage_memory) wrapped the whole JSON
   string as the query/url/path/prompt — so `web_search {"query": "x"}`
   executed as a search for the literal string `{"query": "x"}`.
   _build_mcp_args now uses a fenced JSON object directly when it carries
   the tool's primary arg key (query/url/path/prompt/action). Keyed off
   membership so it can't drift; an object without the primary key (e.g.
   a freeform JSON query, or bare object content for write_file) falls
   through to the line parser unchanged. Also fixes the same corruption
   for the classic newline-JSON form.

2. The bare-email dispatch only rejected bodies starting with { or [, so
   a non-empty non-JSON body like `account: work` still fell through to
   {} args and silently read the DEFAULT mailbox. Now ANY non-empty body
   must decode to a JSON object or it returns a correctable error; only a
   truly empty body keeps the no-arg path (```list_email_accounts```).

Tests: inline-JSON arg decoding for the five legacy tools plus the
freeform and missing-primary-key fallbacks; the email body rejection
extended to cover the brace-looking and bare `key: value` shapes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(tool-dispatch): drop dead manage_memory JSON-decode entry; pin the live-path invariant

Self-audit catch on the round-6 fix. manage_memory was added to
_MCP_JSON_PRIMARY_KEYS, but _build_mcp_args is only reached via
_call_mcp_tool, which only runs for _MCP_TOOL_MAP tools — and
manage_memory isn't one (its tag routes through dispatch_ai_tool ->
do_manage_memory, which line-parses). So the round-6 decode for
manage_memory was dead code: the unit test exercising _build_mcp_args
passed while a real `manage_memory {"action": ...}` fence still parsed
the whole JSON blob as the action.

Remove the dead entry and add test_mcp_json_primary_keys_are_all_live,
which asserts every JSON-primary tool is in _MCP_TOOL_MAP so a dead
decode can't be added again. The same inline-JSON corruption for
manage_memory and the other tools that route through positional
dispatchers (create_session, ui_control, send_to_session, search_chats,
the document tools, etc.) is pre-existing (dev corrupts their newline
JSON form too) and tracked separately; the proper fix there is to route
fenced JSON through function_call_to_tool_block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(tool-dispatch): decode inline JSON in WriteFileTool (its live path); round-6 fix was on the dead MCP path

Self-audit: round 6 claimed to fix inline JSON args for write_file via
_build_mcp_args, but there is no filesystem MCP server, so write_file
always runs through _direct_fallback -> WriteFileTool, never through
_build_mcp_args. WriteFileTool — unlike its siblings ReadFileTool /
WebSearchTool / WebFetchTool, which all decode JSON — took lines[0] as
the path, so `write_file {"path": "/tmp/x", "content": "y"}` wrote to a
file literally named with the JSON blob. The round-6 _build_mcp_args
entry decoded correctly but on a path that never executes (same class
as the manage_memory dead entry), and the round-6 unit test passed on
that dead path.

WriteFileTool now decodes a JSON object carrying "path" (matching
ReadFileTool directly above it), and the comment on _MCP_JSON_PRIMARY_KEYS
records that only generate_image has a live MCP server today — the other
entries are defense-in-depth for the MCP path; the live fix for each
server-less tool is in its handler.

Test: test_write_file_inline_json_args drives the LIVE path
(execute_tool_block with no MCP) and asserts the intended path is used —
verified to fail without the handler fix. web_search/web_fetch/read_file
were already correct (their handlers decode); write_file was the gap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(strip-fence): derive the live-strip TOOL_TAGS from the real set

Semantic conflict from the dev merge that textual auto-merge didn't flag:
dev added test_live_strip_email_tool_fences.py whose _tool_tags() helper
source-scrapes only the TOOL_TAGS literal `{...}`, which worked on dev
because the email tool names were listed inline there. This branch makes
TOOL_TAGS the single source — `{...} | BUILTIN_EMAIL_TOOLS` — so the email
names are no longer in the literal and the scraper missed them, leaving the
email-fence strip assertions failing even though TOOL_TAGS does contain them
at runtime.

Import the real TOOL_TAGS instead of scraping source, so the test mirrors
exactly what GET /api/tools serves (sorted(TOOL_TAGS)) and the live
EXEC_FENCE_RE derives from — robust to however the set is composed. The
source-level frontend/route guards in the same file are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: botinate <285686135+botinate@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 16:50:32 +01:00
..
cli Skip invalid notes CLI item rows (#2005) 2026-06-29 14:26:46 +01:00
helpers test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
streaming fix(chat): stop code-block button flicker during streaming (#3023) 2026-06-06 04:08:54 -06:00
tools test: add oversized test split plan (#3987) 2026-06-16 02:28:03 +00:00
_taxonomy.py test(taxonomy): auto-mark tests by area and sub-area (#3491) 2026-06-09 01:13:28 +02:00
bombadil-spec.ts Odysseus v1.0 2026-05-31 23:58:26 +09:00
conftest.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
LAYOUT_INVENTORY.md fix(devops): harden docker config defaults (#4349) 2026-06-16 04:03:43 +01:00
markdown_codefence_placeholder_regression.mjs Render emoji shortcodes as icons in chat (#345) (#629) 2026-06-05 02:28:42 +02:00
OVERSIZED_TEST_SPLIT_PLAN.md test: add oversized test split plan (#3987) 2026-06-16 02:28:03 +00:00
README.md fix(devops): harden docker config defaults (#4349) 2026-06-16 04:03:43 +01:00
run_focus.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
run_order_report.py test: add report-only order-sensitivity runner (#3982) 2026-06-15 15:49:47 +09:00
test_action_intents.py fix(agent): honor explicit web search requests 2026-06-15 15:02:10 +09:00
test_action_intents_shell_verbs.py Anchor shell-verb intent patterns to imperative or can-you position (#1664) 2026-06-03 14:23:10 +09:00
test_active_document_clear.py refactor(tools): extract document tools to handle registry (#3666) 2026-06-10 10:41:52 +02:00
test_admin_device_flow_static.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_admin_tools_registry.py refactor(tools): split tool_implementations.py into src/tools/ package (#4423) 2026-06-26 15:40:04 +01:00
test_admin_wipe_gallery.py Admin: wipe gallery albums with images 2026-06-02 20:35:57 +09:00
test_agent_loop.py fix: improve uploaded document retrieval and deep research reuse (#4784) 2026-06-27 19:24:17 +01:00
test_agent_loop_tool_output_truncation.py fix: use _truncate for tool output display limits in agent_loop (#3831) 2026-06-11 17:05:13 +01:00
test_agent_migration_manifest.py docs: add agent migration manifest helper (#3028) 2026-06-15 15:57:33 +09:00
test_agent_rounds_exhausted.py feat: round-limit handling — Continue affordance at the cap + configurable cap (#1999) 2026-06-04 22:36:05 +02:00
test_agent_tool_budget_nonnumeric.py fix(chat): guard non-numeric agent tool budget setting 2026-06-27 19:20:48 +01:00
test_agent_tools_truncate_nonstring.py fix: agent_tools._truncate crashes on non-string input (#1624) 2026-06-03 14:06:39 +09:00
test_ai_image_url_safety.py fix(ai): validate generated image result URLs (#4289) 2026-06-15 16:40:49 +02:00
test_ai_interaction_owner_scope.py fix(ai): offload model resolution from async paths 2026-06-28 00:48:35 +01:00
test_amd_gpu_check_args.py Parse all AMD GPU check args (#1586) 2026-06-03 08:56:48 +09:00
test_anthropic_response_parse.py fix: Anthropic responses with multiple text blocks lose all but the first (#1255) 2026-06-03 00:57:20 +09:00
test_api_call_integration_routing.py fix(agent): index api_call so RAG tool selection can retrieve it (#3923) 2026-06-18 08:43:25 +00:00
test_api_chat_security.py test: add fire_and_forget to API chat webhook stub (#4383) 2026-06-16 03:15:14 +00:00
test_api_key_file_permissions.py fix(security): restrict API-key encryption key file to 0o600 2026-06-15 15:00:11 +09:00
test_api_key_manager_atomic_save.py fix: use atomic write in APIKeyManager.save() to prevent credential data loss (#4591) (#4597) 2026-06-23 23:28:53 +02:00
test_api_key_manager_corrupt_load.py fix: APIKeyManager.load crashes app startup on a corrupt/wrong-shape api_keys.json (#1565) 2026-06-03 08:11:37 +09:00
test_api_key_manager_resilience.py fix(api-keys): preserve encrypted keys when saving providers (#1920) 2026-06-11 18:23:54 +01:00
test_api_token_routes.py fix(api): normalize non-object JSON bodies to empty dict in token PATCH (#3976) 2026-06-15 18:05:15 +01:00
test_api_token_user_route_gate.py fix(auth): gate api tokens from user routes (#2992) 2026-06-07 12:55:01 +02:00
test_app.py Fix fresh checkout test failures 2026-06-01 02:22:17 +00:00
test_app_initializer_memory_vector_degraded.py fix(health): report unhealthy memory vector store as degraded 2026-06-27 22:25:13 +01:00
test_app_static_mime.py fix: normalize JS static MIME types on Windows 2026-06-02 01:32:00 +02:00
test_archived_sessions_model_filter.py fix(tests): make archived session filter test multipart-independent 2026-06-05 10:12:47 +01:00
test_ask_user_persistence.py fix ask-user choices across reloads (#4669) 2026-06-22 20:49:49 +02:00
test_ask_user_tool.py fix ask-user choices across reloads (#4669) 2026-06-22 20:49:49 +02:00
test_atomic_io.py Reject non-string atomic text writes (#1819) 2026-06-29 14:36:21 +01:00
test_auth_config_lock_concurrency.py fix(auth): fail closed when deleting user tokens fails (#3733) 2026-06-10 16:24:27 +02:00
test_auth_disabled_document_access.py fix: document read fails with 403 when auth is disabled (#4623) 2026-06-22 21:01:11 +02:00
test_auth_event_loop.py fix: avoid double bcrypt on login by using create_session_trusted (#3236) 2026-06-07 15:10:53 +02:00
test_auth_policy.py fix(auth): tie remember-me cookie lifetime to TOKEN_TTL (#4472) 2026-06-18 21:15:48 +02:00
test_auth_regressions.py fix(endpoint): import ModelEndpoint from core database 2026-06-04 11:51:47 +01:00
test_auth_require_privilege_nondict.py fix: require_privilege 500s on a non-dict privileges blob from auth.json (#1693) 2026-06-03 13:37:54 +09:00
test_auth_session_revocation.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_aux_llm_owner_scope.py refactor(routes): move research domain into routes/research/ subpackage 2026-06-28 14:34:11 +01:00
test_backup_cli_security.py refactor(tests): finish shared CLI loader adoption 2026-06-05 06:00:05 +01:00
test_backup_import_cross_user_dedup.py fix: backup import drops a user's memory when its text matches another user's (#1743) 2026-06-03 13:29:14 +09:00
test_backup_import_skills.py fix: restore backup import after skills migration (#2980) 2026-06-06 21:46:32 +01:00
test_backup_import_skills_dedup.py fix: backup import dropping a user's skill on cross-tenant title/id collision (#2057) 2026-06-09 08:04:22 +02:00
test_bg_job_tools.py feat(agent): add manage_bg_jobs tool to inspect and kill background bash jobs (#4577) 2026-06-19 00:28:22 -07:00
test_bg_jobs_store.py Ignore invalid background job store rows (#1261) 2026-06-03 14:07:14 +09:00
test_bg_monitor_stream.py Ignore non-string background stream deltas (#1549) 2026-06-03 14:11:45 +09:00
test_blind_compare_redaction.py refactor(tests): add import-state isolation helper 2026-06-05 07:30:14 +01:00
test_budget_auto_sentinel.py fix(agent): don't let a materialized default budget defeat context-window scaling (#4122) 2026-06-15 15:17:28 +09:00
test_build_user_content_pdf_marker.py fix(documents): restore PDF library metadata and preview (#2483) 2026-06-07 23:23:27 +02:00
test_builtin_actions_cookbook_serve_state.py fix(cookbook): preserve scheduled serve server metadata (#4545) 2026-06-27 16:48:53 +01:00
test_builtin_actions_nonstring.py fix: builtin_actions heuristics crash on a truthy non-string input (#1639) 2026-06-03 08:59:16 +09:00
test_builtin_actions_owner_scope.py CI test fixes for dev sync 2026-06-22 02:20:15 +00:00
test_builtin_mcp_bg_tasks.py fix(mcp): retain builtin startup tasks and reap npx probe 2026-06-28 01:18:17 +01:00
test_builtin_mcp_npx_cache.py fix(mcp): detect npx cache entries before probing (#4034) 2026-06-15 15:14:48 +09:00
test_builtin_memory_consolidation.py CI test fixes for dev sync 2026-06-22 02:20:15 +00:00
test_cache_affinity_local_only.py fix(endpoints): normalize URL handling (#4338) 2026-06-16 03:59:18 +01:00
test_caldav_bidirectional_sync.py refactor(tools): split tool_implementations.py into src/tools/ package (#4423) 2026-06-26 15:40:04 +01:00
test_caldav_google_principal_url.py fix(caldav): disable redirects on the sync/write-back DAVClient (SSRF) (#2663) 2026-06-07 05:05:24 +01:00
test_caldav_prune_parse_failure.py fix(caldav): skip the prune when any object fails to parse (#3454) 2026-06-08 18:59:14 +02:00
test_caldav_redirect_hardening.py fix(caldav): disable redirects on the sync/write-back DAVClient (SSRF) (#2663) 2026-06-07 05:05:24 +01:00
test_caldav_sync_prune_local_events.py fix(caldav): don't prune locally-created events on sync (#2706) 2026-06-05 02:48:03 +02:00
test_caldav_sync_uid_scope.py fix(calendar): scope CalDAV event lookup by calendar 2026-06-04 04:01:21 +01:00
test_caldav_url_hardening.py fix(caldav): disable redirects on the sync/write-back DAVClient (SSRF) (#2663) 2026-06-07 05:05:24 +01:00
test_caldav_url_nonstring.py Harden DAV outbound URL validation (#2819) 2026-06-05 13:22:21 +02:00
test_caldav_writeback.py Harden CalDAV write-back with retries (#1193) 2026-06-15 15:59:31 +09:00
test_caldav_writeback_route.py Harden CalDAV write-back with retries (#1193) 2026-06-15 15:59:31 +09:00
test_calendar_batch_events.py fix: handle batch events format in manage_calendar tool (#3503) 2026-06-10 19:13:08 +02:00
test_calendar_cli_overlap.py Fix odysseus-calendar list dropping in-progress / multi-day events (#2065) 2026-06-16 14:04:56 +02:00
test_calendar_css_url_escape_js.py fix(security): escape backslashes in calendar bg-image CSS url() (#4712) 2026-06-22 21:17:52 +02:00
test_calendar_event_contrast.py Improve calendar event text contrast (#1184) 2026-06-02 23:14:52 +09:00
test_calendar_import_zero_duration.py fix(calendar): keep imported events with non-positive duration visible (#4484) 2026-06-27 16:52:40 +02:00
test_calendar_list_range_aliases.py fix(calendar): accept list event range aliases 2026-06-06 03:47:18 -06:00
test_calendar_owner_scope.py Harden CalDAV write-back with retries (#1193) 2026-06-15 15:59:31 +09:00
test_calendar_parse_dt_naive.py test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
test_calendar_parse_dt_time_first.py fix(calendar): accept time-first datetimes in _parse_dt 2026-06-27 18:51:18 +01:00
test_calendar_parse_dt_tonight.py fix: _parse_dt does not understand 'tonight' so event start/end breaks (#1488) 2026-06-03 14:14:41 +09:00
test_calendar_recurrence.py test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
test_calendar_reminder_minutes_parsing.py fix(calendar): parse "mins"/"hrs" reminder offsets in manage_calendar (#4266) 2026-06-15 17:37:28 +02:00
test_calendar_rrule.py refactor(tests): add temp sqlite helper (#2930) 2026-06-07 23:44:16 +02:00
test_calendar_rrule_until_utc.py test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
test_calendar_update_event_tz.py refactor(tests): add temp sqlite helper (#2930) 2026-06-07 23:44:16 +02:00
test_calendar_utils_dates_js.py Ignore non-string calendar date inputs (#1649) 2026-06-03 14:16:58 +09:00
test_canvas_coords_empty_touches_js.py fix: canvasCoords crashes on empty touch list (mobile race) (#2045) 2026-06-17 10:25:39 +02:00
test_carddav_password_encryption.py fix(security): encrypt CardDAV password at rest in settings.json (#1741) 2026-06-15 15:58:14 +09:00
test_censor_pref_js.py Ignore censor preference storage errors (#1652) 2026-06-03 14:16:55 +09:00
test_cerebras_cache_affinity.py fix(llm-core): prevent cache-affinity fields from reaching Cerebras 2026-06-27 18:07:12 +01:00
test_chat_attachment_picker.py Chat attachments: allow picker to choose any file type 2026-06-02 20:55:30 +09:00
test_chat_cached_model_normalization.py Chat: use cached endpoint model ids before probing 2026-06-02 21:00:58 +09:00
test_chat_helpers.py fix: improve uploaded document retrieval and deep research reuse (#4784) 2026-06-27 19:24:17 +01:00
test_chat_helpers_bg_tasks_tracked.py fix(chat): track chat hot-path background tasks for strong references (#4443) (#4444) 2026-06-18 21:26:11 +02:00
test_chat_image_routing.py Fix Windows Cookbook background tasks, exit statuses, and empty SSH logs wrapper (#1389) 2026-06-05 14:41:07 +02:00
test_chat_metrics.py fix(chat): show requested and actual reply models 2026-06-06 04:30:16 -06:00
test_chat_preprocess_tool_policy.py fix(agent): enforce guide-only tool policy (#3088) 2026-06-06 18:48:24 -06:00
test_chat_processor_web_search.py fix(search): use generated query for chat mode web search #4547 (#4557) 2026-06-27 19:04:46 +01:00
test_chat_route_tool_policy.py fix(agent): honor explicit web search requests 2026-06-15 15:02:10 +09:00
test_chat_stream_scope.py Fix chat stream recovery and PDF library indexing (#468) 2026-06-01 22:33:35 +09:00
test_chat_tool_screenshot_xss.py Harden chat streaming DOM sinks (#2498) 2026-06-04 20:49:37 +02:00
test_chat_upload_limit_config.py fix(upload): configure chat attachment size limit (#2439) 2026-06-07 22:42:24 +02:00
test_chatgpt_subscription_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_check_outbound_url_nonstring.py fix: check_outbound_url crashes on a truthy non-string URL (#1623) 2026-06-03 08:59:49 +09:00
test_checkin_digest_owner_scope.py fix: check-in calendar digest leaks every user's events (missing owner scope) (#1925) 2026-06-16 02:42:41 +01:00
test_chroma_client.py fix: ChromaDB unreachable blocks app startup for 30-60s (#326) (#476) 2026-06-01 22:22:41 +09:00
test_claim_ownerless_json.py Reject blank ownerless claim owner (#4929) 2026-06-28 10:57:11 +01:00
test_classify_events_memory_text.py fix(tasks): read Memory.text in classify_events personal context (#3640) 2026-06-10 19:03:45 +02:00
test_cleanup_owner_scope.py tests: cover cleanup owner scope 2026-06-02 20:42:21 +09:00
test_cleanup_service_utcnow.py Replace cleanup service datetime.utcnow calls (#1494) 2026-06-03 14:14:27 +09:00
test_code_nav_tools.py fix(tools): prune skipped dirs before descending in glob tool (#4538) 2026-06-18 22:02:29 +02:00
test_codex_cookbook_admin_gate.py fix(security): gate codex cookbook routes behind admin check for cookie sessions (#4554) 2026-06-27 14:09:32 +01:00
test_codex_ssh_host_validation.py fix: improve uploaded document retrieval and deep research reuse (#4784) 2026-06-27 19:24:17 +01:00
test_compact_truncate_tool_call_args.py fix(compactor): shrink oversized tool_calls arguments so trim_for_context can fit a tool-only turn (#2949) 2026-06-05 20:23:38 +02:00
test_compaction_summary_failure.py fix(test): tolerate owner kwarg in compaction summary resolve_endpoint mock (#3304) 2026-06-07 17:23:06 +02:00
test_companion_pairing.py refactor(constants): single source of truth for data dir (#3368) 2026-06-08 09:58:52 +02:00
test_companion_readonly.py fix(companion): require chat scope for model inventory (#4319) 2026-06-16 01:15:05 +02:00
test_compare_endpoint_owner_scope.py fix(tests): isolate compare endpoint owner-scope test 2026-06-04 19:17:15 +01:00
test_compare_js.py Fix duplicate compare modal on repeated clicks (#491) 2026-06-01 22:24:27 +09:00
test_compare_stop_disconnect_poll.py fix(compare): stream Compare panes directly to stop upstream promptly 2026-06-08 01:13:45 +01:00
test_composer_arrow_up_recall_js.py feat(chat): recall last user message on empty composer ArrowUp (#1175) 2026-06-08 13:06:05 +02:00
test_compute_next_run_monthly_clamp.py fix: monthly tasks scheduled for day 29-31 skip every short month (#1668) 2026-06-03 14:23:01 +09:00
test_consolidate_memory_explicit_drops.py CI test fixes for dev sync 2026-06-22 02:20:15 +00:00
test_contacts_add_null_name.py fix: POST /api/contacts/add crashes on JSON null name/email (None.strip()) (#1544) 2026-06-03 14:23:34 +09:00
test_contacts_carddav_security.py Harden DAV outbound URL validation (#2819) 2026-06-05 13:22:21 +02:00
test_contacts_import_nonstring.py fix(contacts): tolerate non-string body in /api/contacts/import (#3638) 2026-06-10 17:50:22 +02:00
test_contacts_vcard_parse.py fix(contacts): parse Apple/iCloud item-grouped vCard EMAIL/TEL properties (#1438) 2026-06-03 14:24:04 +09:00
test_context_budget.py Ignore invalid context budget numbers (#1831) 2026-06-29 19:56:17 +01:00
test_context_cache_per_endpoint.py fix(agent): don't let a materialized default budget defeat context-window scaling (#4122) 2026-06-15 15:17:28 +09:00
test_context_compactor.py fix(research): keep Discuss chats grounded on their report (#4006) 2026-06-15 20:31:57 +09:00
test_context_compactor_nonstring.py fix: context_compactor token helpers crash on non-string message text (#1634) 2026-06-03 14:12:14 +09:00
test_cookbook_agent_tool_ssh_validation.py fix(cookbook): validate agent SSH targets (#4429) 2026-06-18 21:41:33 +02:00
test_cookbook_cpu_only_serve.py fix(cookbook): treat local Windows as Windows for serve commands (#3975) 2026-06-26 13:13:01 +01:00
test_cookbook_dead_download_status.py fix(cookbook): report dead finished downloads as completed instead of stopped (#4025) 2026-06-15 15:26:55 +09:00
test_cookbook_dependency_completion_regression.py fix(cookbook): load user-site pth hooks for runtime installs 2026-06-28 01:01:44 +01:00
test_cookbook_deps_recipes.py fix(cookbook): pull llama.cpp from the ggml-org GHCR namespace (#4457) (#4490) 2026-06-18 21:29:47 +02:00
test_cookbook_diagnosis.py fix(cookbook): diagnose sglang native deps (#4112) 2026-06-15 15:14:37 +09:00
test_cookbook_diagnosis_js.py fix(cookbook): diagnose sglang native deps (#4112) 2026-06-15 15:14:37 +09:00
test_cookbook_download_toast_duration.py Keep Cookbook download-failure toasts visible long enough to read (#1412) 2026-06-03 03:48:25 +09:00
test_cookbook_endpoint_registration.py Fix Cookbook container-local model endpoints (#1223) 2026-06-03 00:09:48 +09:00
test_cookbook_error_feedback.py fix(cookbook): surface backend diagnosis when serve fails in background (#1636) 2026-06-05 09:52:07 +01:00
test_cookbook_error_tail_lines.py fix: expand cookbook error output tail from 12 to 50 lines (#1538) 2026-06-11 17:55:33 +01:00
test_cookbook_gemma4_thinking_template.py feat(cookbook): add Gemma4 thinking chat template (#2955) 2026-06-05 22:43:31 +02:00
test_cookbook_helpers.py fix(cookbook): accept $(find) subshells in serve command validation 2026-06-28 14:00:49 +01:00
test_cookbook_hf_token.py fix: detect HuggingFace token when downloading cookbook models (#3459) 2026-06-11 21:53:16 +01:00
test_cookbook_package_detection.py fix(cookbook): allow local Windows Diffusers serving (#4077) 2026-06-15 15:21:01 +09:00
test_cookbook_port_parsing_js.py fix(cookbook): only block model launch on real port collisions (#4760) 2026-06-24 19:44:09 +02:00
test_cookbook_progress_signal_js.py Don't falsely declare a dependency build stale (#1568) (#1768) 2026-06-03 13:23:35 +09:00
test_cookbook_remote_windows_diffusers.py fix(cookbook): harden remote serve host handling (#4345) 2026-06-16 03:46:32 +01:00
test_cookbook_same_host_server_profiles_js.py CI test fixes for dev sync 2026-06-22 02:20:15 +00:00
test_cookbook_serve_lifecycle.py fix(cookbook): only persist successfully stopped scheduled serves (#4267) 2026-06-15 17:30:18 +02:00
test_cookbook_windows_stop_tree_js.py fix(cookbook): stop Windows process trees (#4283) 2026-06-19 00:28:25 -07:00
test_copilot.py feat(provider): add GitHub Copilot provider with device-flow auth (#1480) 2026-06-04 21:13:14 +02:00
test_copilot_routes.py feat(provider): add GitHub Copilot provider with device-flow auth (#1480) 2026-06-04 21:13:14 +02:00
test_copy_message_strips_thinking_js.py Cookbook model workflow fixes 2026-06-21 11:02:35 +00:00
test_cors_preflight.py Fix: CORS preflight 401'd by AuthMiddleware before CORSMiddleware (#3262) 2026-06-07 15:23:23 +02:00
test_database_utcnow.py Replace core database utcnow defaults (#1457) 2026-06-04 02:50:19 +01:00
test_db_stubs_helper.py test: pilot core database stub helper (#3685) 2026-06-09 22:23:33 +02:00
test_ddg_redirect_resolution.py Match host, not substring, when resolving DuckDuckGo redirects (#886) 2026-06-02 12:25:56 +09:00
test_deep_research_date_context.py Inject current date into deep research planning and query prompts (#1347) 2026-06-03 03:00:52 +09:00
test_deep_research_extraction_controls.py fix(research): track analyzed URLs separately (#3125) 2026-06-10 12:08:22 +01:00
test_deep_research_parse_json_array_echo.py fix: deep research runs the prompt's example queries when the model echoes them (#1666) 2026-06-03 14:23:07 +09:00
test_deep_research_search_error.py Research: report empty search provider results clearly 2026-06-02 20:34:25 +09:00
test_deep_research_synthesis_resilience.py Don't lose deep-research findings when synthesis times out (#1551) (#1562) 2026-06-03 08:11:44 +09:00
test_delete_message_no_session.py Let the output "x" delete work when no model/session exists (#1431) 2026-06-03 04:20:48 +09:00
test_delete_user_invalidates_token_cache.py fix(auth): fail closed when deleting user tokens fails (#3733) 2026-06-10 16:24:27 +02:00
test_delete_user_revokes_api_tokens.py fix(auth): fail closed when deleting user tokens fails (#3733) 2026-06-10 16:24:27 +02:00
test_deleted_session_sidebar_regression.py Fix stale deleted sessions in sidebar (#1203) 2026-06-02 23:52:22 +09:00
test_derive_title_nonstring.py fix: _derive_title crashes on non-string content instead of returning Untitled (#1751) 2026-06-03 13:25:41 +09:00
test_device_flow_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_diagnostics_logs.py feat(ui): add real-time diagnostic logs console (#974) 2026-06-15 10:32:51 +02:00
test_diagnostics_service_route.py feat(diagnostics): add consolidated service health endpoint for degraded-state reporting (#964) 2026-06-09 16:00:24 +01:00
test_dialog_aria.py feat: add dismiss (×) button to all toast notifications (#1355) (#1755) 2026-06-26 14:02:35 +01:00
test_diffusion_server_security.py test(diffusion-server): exercise security middleware wiring (#3214) 2026-06-07 23:42:11 +02:00
test_digest_windows.py fix: calendar check-in digest drops events 7-8 days out (#1249) 2026-06-03 01:03:58 +09:00
test_direct_upload_limits.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_doc_library_open_orphaned.py Let orphaned documents be reopened from the library (#1602) (#1761) 2026-06-03 13:28:31 +09:00
test_docker_devops_hardening.py CI test fixes for dev sync 2026-06-22 02:20:15 +00:00
test_docs_no_orphan_images.py Remove stray PR screenshots accidentally committed under docs/ (#1351) 2026-06-03 03:31:09 +09:00
test_docs_query_nondict_rows.py fix: docs RAG query crashes on a non-dict row from the index (#1706) 2026-06-03 13:35:01 +09:00
test_document_actions_nonstring.py fix: document_actions title/content helpers crash on non-string input (#1621) 2026-06-03 08:59:55 +09:00
test_document_ai_preview_refresh_js.py fix document preview refresh after AI edits (#2259) 2026-06-07 22:33:01 +02:00
test_document_close_clears_active_route.py refactor(tools): extract document tools to handle registry (#3666) 2026-06-10 10:41:52 +02:00
test_document_deeplink.py refactor(tools): extract document tools to handle registry (#3666) 2026-06-10 10:41:52 +02:00
test_document_diff_discard_on_update_js.py fix(documents): discard pending AI diff before switching active doc (#2484) 2026-06-07 22:35:35 +02:00
test_document_editor_scroll.py fix: drop thinking deltas from background agent loops 2026-06-15 15:03:09 +09:00
test_document_library_delete_counters.py fix(documents): refresh library counters after removal (#1924) 2026-06-04 04:42:23 +01:00
test_document_library_language_facet.py fix: document library language facet undercounts text documents (#1758) 2026-06-03 13:28:38 +09:00
test_document_library_pdf_metadata.py fix(documents): restore PDF library metadata and preview (#2483) 2026-06-07 23:23:27 +02:00
test_document_pdf_marker.py Documents: strip PDF marker without corrupting text 2026-06-02 20:35:27 +09:00
test_document_processor_attachment_budget.py Cap inline attachment context across files (#1498) 2026-06-03 14:23:43 +09:00
test_document_render_pdf_iframe.py fix(document): allow render-pdf to be framed and 503 cleanly on missing PyMuPDF (#2103) 2026-06-18 06:25:26 +00:00
test_document_session_owner_scope.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_document_tidy_null_timestamp.py fix: document tidy crashes on a duplicate with NULL timestamps (#1772) 2026-06-03 13:23:01 +09:00
test_document_tool_owner_scope.py refactor(tools): extract document tools to handle registry (#3666) 2026-06-10 10:41:52 +02:00
test_edit_file.py refactor(tools): migrate execution logic to src/agent_tools/ package with handler registry (#3435) 2026-06-09 14:35:36 +01:00
test_editor_draft_payload.py Ignore invalid editor draft payloads (#1533) 2026-06-03 14:07:03 +09:00
test_email_account_port_validation.py fix(email): validate IMAP/SMTP ports instead of crashing with 500 (#4464) 2026-06-26 20:32:56 +02:00
test_email_decode_header.py fix(email): guard _decode_header against unknown MIME charset (#1354) 2026-06-03 14:24:20 +09:00
test_email_envelope_recipients.py fix: SMTP envelope recipients split on commas inside display names (#1464) 2026-06-03 14:23:58 +09:00
test_email_fallback_reconnect.py Reconnect after a failed SEARCH ALL so the email poller doesn't desync IMAP (#1613) (#1748) 2026-06-03 13:28:53 +09:00
test_email_gmail_fetch_flags.py fix(email): keep FETCH attributes Gmail sends after the header literal (all Gmail mail showed as unread) (#3785) 2026-06-11 16:12:39 +02:00
test_email_helpers_decode_header_spaces.py fix(email): decode headers without injected spaces (#2433) 2026-06-07 16:56:20 +02:00
test_email_imap_timeout.py Use shared IMAP timeout for account tests (#1088) 2026-06-02 23:11:04 +09:00
test_email_library_bulk_actions.py Email: persist bulk read state to provider 2026-06-02 20:28:01 +09:00
test_email_linkify_security_js.py Harden email HTML URL sanitization (#2496) 2026-06-04 20:47:47 +02:00
test_email_oauth.py feat(email): add Google OAuth2 for Google Workspace / .edu IMAP & SMTP (#237) 2026-06-15 17:02:58 +01:00
test_email_owner_scope.py fix(email): enforce MCP owner boundaries (#4335) 2026-06-16 04:31:24 +01:00
test_email_polly_imap_leak.py fix(tests): allow multiple logout calls when IMAP fallback reconnects (#1976) 2026-06-04 02:56:05 +01:00
test_email_registry_sync.py fix(agent): execute fenced tool calls with inline args and route bare email tool names (#3681) 2026-06-30 16:50:32 +01:00
test_email_send_only_no_inbox.py fix(email): don't probe IMAP for send-only (SMTP-only) accounts (#4830) 2026-06-27 21:52:26 +01:00
test_email_smtp_security.py Email: add explicit SMTP security mode 2026-06-02 13:15:06 +09:00
test_email_split_border_css.py fix(ui): contain email split divider (#1194) 2026-06-02 23:28:24 +09:00
test_email_thread_parser_nonstring.py Ignore non-string email thread bodies (#1654) 2026-06-03 14:06:31 +09:00
test_embedding_cache_confinement.py Constrain embedding model cache paths (#2849) 2026-06-05 10:46:48 +02:00
test_embedding_endpoint_config.py Ignore non-object embedding endpoint config (#1260) 2026-06-03 14:12:41 +09:00
test_embedding_lane_ndarray_restore.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embedding_lanes.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embedding_lanes_legacy.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embedding_lanes_memory.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embedding_lanes_rag.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embedding_lanes_tool_index.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_embeddings.py Add support for EMBEDDING_API_KEY (#2691) 2026-06-05 14:47:24 +02:00
test_embeddings_client.py Retry oversized embedding requests (#1106) 2026-06-26 14:21:27 +01:00
test_emoji_shortcodes_js.py Render emoji shortcodes as icons in chat (#345) (#629) 2026-06-05 02:28:42 +02:00
test_emoji_svg_hardening.py Harden emoji SVG proxy responses (#2842) 2026-06-05 10:31:58 +02:00
test_endpoint_owner_scope_followup.py refactor(routes): move research domain into routes/research/ subpackage 2026-06-28 14:34:11 +01:00
test_endpoint_probing.py fix(model-routes): harden _probe_endpoint against malformed model-list responses (#4789) 2026-06-24 19:05:31 +02:00
test_endpoint_resolver_headers.py test: split endpoint resolver tests (#4957) 2026-06-28 00:49:43 +02:00
test_endpoint_resolver_models.py test: split endpoint resolver tests (#4957) 2026-06-28 00:49:43 +02:00
test_endpoint_resolver_urls.py test: split endpoint resolver tests (#4957) 2026-06-28 00:49:43 +02:00
test_esc_menu_stack_js.py fix: make transient dropdown/popup menus close on Escape 2026-06-01 14:23:22 -04:00
test_estimate_tokens_tool_calls.py fix(model-context): count tool_calls in estimate_tokens so compaction sees real size (#2751) 2026-06-05 15:56:54 +02:00
test_extract_quotes.py fix: extract_quotes accepts mismatched opening/closing quotes (#1113) 2026-06-02 22:34:52 +09:00
test_extract_skill_json_nonstring.py fix: _extract_skill_json crashes on a truthy non-string teacher response (#1630) 2026-06-03 08:59:36 +09:00
test_extract_statistics.py fix: extract_statistics drops large numbers and trailing % signs (#1153) 2026-06-02 22:35:30 +09:00
test_extract_urls.py fix(chat): keep balanced trailing ')' when extracting URLs (#3406) 2026-06-08 21:33:29 +02:00
test_fastembed_cache_path.py fix(embeddings): fall back to default cache dir when FASTEMBED_CACHE_PATH is empty (#3434) 2026-06-16 03:11:48 +01:00
test_fenced_example_not_executed_for_native_models.py fix: tool results misthreaded to the wrong tool_call_id when a native call fails to convert (#1917) 2026-06-27 19:31:17 +01:00
test_fenced_inline_args.py fix(agent): execute fenced tool calls with inline args and route bare email tool names (#3681) 2026-06-30 16:50:32 +01:00
test_fenced_invoke_no_raw_xml.py fix: route misfenced web lookups to web tools 2026-06-06 03:46:31 -06:00
test_font_routes.py Keep compact font family names together (#1263) 2026-06-03 14:24:30 +09:00
test_fork_session_metadata.py fix(sessions): copy message metadata when forking a session (#3409) 2026-06-08 20:49:15 +02:00
test_form_markdown_roundtrip.py fix(forms): keep PDF-form export from dropping values when the label has '*' (#1407) 2026-06-03 14:24:07 +09:00
test_forwarded_message_divider.py Email: recognize forwarded message dividers 2026-06-02 20:32:56 +09:00
test_function_call_non_object_args.py fix(email): enforce MCP owner boundaries (#4335) 2026-06-16 04:31:24 +01:00
test_gallery_album_owner_scope.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_gallery_delete_file_ordering.py test(gallery): point delete-ordering tests at the tmp image dir (#4300) 2026-06-15 14:07:49 +00:00
test_gallery_endpoint_matching.py Scope gallery image endpoints by owner (#3001) 2026-06-07 12:51:21 +02:00
test_gallery_endpoint_ssrf.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_gallery_exif_orientation.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_gallery_filename_confinement.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_gallery_image_endpoint_owner_scope.py Scope gallery image endpoints by owner (#3001) 2026-06-07 12:51:21 +02:00
test_gallery_image_privileges.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_gallery_null_user_routes.py fix(gallery): fail closed for null-user owner scope (#3613) 2026-06-09 20:20:21 +02:00
test_gallery_owner_filter_single_user.py fix(gallery): fail closed for null-user owner scope (#3613) 2026-06-09 20:20:21 +02:00
test_gallery_result_image_ssrf.py fix(gallery): validate upstream result image URLs 2026-06-15 15:01:28 +09:00
test_gallery_routes_shim.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_generated_image_confinement.py Constrain generated-image paths to image root (#2837) 2026-06-05 10:33:47 +02:00
test_gmail_quote_attribution_js.py Parse standard Gmail quote attribution dates 2026-06-03 13:45:56 +09:00
test_gpu_compose_standalone.py CI fixes for cookbook workflow sync 2026-06-22 02:08:25 +00:00
test_group_character_dropdown.py fix: group selection drop-downs recreation and repopulation logic (#3424) 2026-06-26 13:35:25 +01:00
test_group_chat_storage.py Keep group chat session cache loading (#1418) 2026-06-03 04:05:40 +09:00
test_harmonize_masks_invalid_layers_js.py Ignore invalid harmonize mask layers (#1829) 2026-06-29 19:16:26 +01:00
test_helpers_import_state.py refactor(tests): centralize fake endpoint resolver cleanup 2026-06-05 13:23:46 +01:00
test_hex_to_rgb_js.py fix: theme color parsing breaks on #rgb shorthand hex (#1213) 2026-06-03 00:30:03 +09:00
test_history_compact_tool_calls.py Scope auxiliary LLM endpoints by owner (#2996) 2026-06-07 14:47:44 +02:00
test_history_db_fallback_hidden.py fix: history DB fallback returned hidden (compaction) messages to the client (#1726) 2026-06-03 13:30:11 +09:00
test_history_order_by_timestamp_regression.py Fix HTTP 500 in history routes: order ChatMessage by timestamp, not created_at (#1673) 2026-06-03 14:22:51 +09:00
test_history_topics_owner_scope.py fix(history): scope topic analysis to authenticated owner only (#744) 2026-06-02 11:36:01 +09:00
test_hwfit_amd.py Cookbook fit: steer consumer AMD to GGUF recommendations 2026-06-02 21:01:42 +09:00
test_hwfit_apple_bandwidth.py test(hwfit): fix non-Apple guard to assert the Apple matcher (unblocks pytest gate) (#4303) 2026-06-15 14:01:05 +00:00
test_hwfit_bandwidth_nonstring.py fix: _lookup_bandwidth crashes on a truthy non-string gpu_name (#1641) 2026-06-03 14:11:10 +09:00
test_hwfit_container_visibility_warning.py feat(cookbook): surface Docker hardware visibility warnings (#3658) 2026-06-15 15:51:04 +09:00
test_hwfit_cpu_arch_detection.py fix(hwfit): normalize CPU arch for fallback estimates (#4441) 2026-06-18 20:26:22 +02:00
test_hwfit_cpu_only_fallback.py fix(hwfit): normalize CPU arch for fallback estimates (#4441) 2026-06-18 20:26:22 +02:00
test_hwfit_gemma4_12b.py feat(catalog): add Gemma 4 12B/QAT entries and RTX 3050 bandwidth (#4728) 2026-06-23 18:23:46 +02:00
test_hwfit_gpu_count_nonnumeric.py fix(hwfit): tolerate non-numeric gpu_count in /api/hwfit/models (#3639) 2026-06-11 01:01:58 +02:00
test_hwfit_macos.py fix(hwfit): normalize CPU arch for fallback estimates (#4441) 2026-06-18 20:26:22 +02:00
test_hwfit_manual_backend.py fix(hwfit): honor manual "metal" backend in the hardware simulator (#1090) 2026-06-02 23:12:34 +09:00
test_hwfit_native_quant_labels.py fix: hwfit native quant labels miss the cost maps and over-estimate VRAM (#1690) 2026-06-03 14:22:42 +09:00
test_hwfit_params_b_malformed.py fix: params_b crashes the whole ranking on a malformed parameter_count (#1550) 2026-06-03 14:23:30 +09:00
test_hwfit_quant_formats.py Fix native Cookbook quant classification 2026-06-02 13:07:20 +09:00
test_hwfit_remote_validation.py test(hwfit): cover SSH target validation regressions (#4279) 2026-06-16 04:18:21 +01:00
test_hwfit_unified_nvidia.py fix(platform): Improve WSL SSH remote compatibility (#3316) 2026-06-08 00:33:50 +02:00
test_hwfit_windows.py fix(hwfit): repair remote Windows hardware scan over SSH (#4674) 2026-06-22 20:59:09 +02:00
test_icloud_imap_full_fetch.py Fetch full messages with BODY.PEEK[] so read_email works on iCloud IMAP (#1961) (#1963) 2026-06-04 03:53:14 +01:00
test_ics_escape.py test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
test_ics_export_escaping.py fix: ICS export — escape X-WR-CALNAME and honour is_utc on DTSTART/DTEND (#1174) 2026-06-02 23:02:28 +09:00
test_ics_import_dedup_tz.py fix: re-importing an ICS file duplicates every tz-aware timed event (#1683) 2026-06-03 14:22:49 +09:00
test_image_models_nondict_system.py fix: image model ranking crashes when system is not a dict (#1900) 2026-06-04 03:23:59 +01:00
test_image_models_nonstring_search.py fix: image model ranking crashes on a non-string search filter (#1898) 2026-06-04 03:26:35 +01:00
test_imap_leak_fixes.py fix(email): close IMAP socket when connect/login fails (#3174) (#3363) 2026-06-08 21:21:41 +02:00
test_imap_mailbox_quoting.py fix: quote IMAP mailbox arguments (#2170) 2026-06-05 16:00:20 +02:00
test_inside_base_dir_nonstring.py fix: inside_base_dir raises TypeError on a non-string path instead of failing closed (#1619) 2026-06-03 09:00:04 +09:00
test_integrations_api_call_truncation.py fix(endpoints): normalize URL handling (#4338) 2026-06-16 03:59:18 +01:00
test_integrations_store_shape.py fix(endpoints): normalize URL handling (#4338) 2026-06-16 03:59:18 +01:00
test_internal_api_base.py refactor(tools): split tool_implementations.py into src/tools/ package (#4423) 2026-06-26 15:40:04 +01:00
test_is_youtube_url_nonstring.py fix: is_youtube_url crashes on a non-string url (#1752) 2026-06-03 13:24:33 +09:00
test_is_youtube_url_nonstring_svc.py fix: is_youtube_url (services) crashes on a non-string url (#1753) 2026-06-03 13:24:24 +09:00
test_keybind_altgr_js.py Ignore AltGr keystrokes in Ctrl+Alt keyboard shortcuts (#825) 2026-06-02 11:12:54 +09:00
test_kimi_code_hosts.py fix(kimi): resolve Kimi Code API 403 errors and User-Agent restrictions (#3549) 2026-06-15 15:56:54 +09:00
test_kimi_code_user_agent.py fix(kimi): resolve Kimi Code API 403 errors and User-Agent restrictions (#3549) 2026-06-15 15:56:54 +09:00
test_kv_cache_invalidation_2927.py fix(api): attribute bearer-token actions to the token owner on owner-scoped routes (#4054) 2026-06-15 23:56:22 +02:00
test_lang_icon_null_opts_js.py fix: langIcon throws on an explicit null opts argument (#1740) 2026-06-03 13:29:21 +09:00
test_launcher.py feat(launcher): add portable windows launcher (#976) 2026-06-16 04:58:16 +01:00
test_live_strip_email_tool_fences.py fix(agent): execute fenced tool calls with inline args and route bare email tool names (#3681) 2026-06-30 16:50:32 +01:00
test_llama_server_models_url.py fix(agent): don't let a materialized default budget defeat context-window scaling (#4122) 2026-06-15 15:17:28 +09:00
test_llamacpp_discovery.py feat(discovery): detect llama.cpp servers and label local providers (#4729) 2026-06-23 23:39:56 +02:00
test_llm_core_anthropic_cache.py Add Anthropic prompt caching to the agent loop (#812) 2026-06-02 11:14:31 +09:00
test_llm_core_anthropic_temp_clamp.py Clamp Anthropic temperature to [0.0, 1.0] in _build_anthropic_payload (#1737) 2026-06-03 13:29:36 +09:00
test_llm_core_anthropic_temp_omit.py fix: omit temperature for Opus 4.7+ on native Anthropic path (#3117) 2026-06-11 16:27:40 +03:00
test_llm_core_concurrency.py Make LLM host health maps thread-safe 2026-06-02 05:54:23 +09:00
test_llm_core_connect_timeout.py fix(llm): make connect timeout configurable 2026-06-15 15:11:38 +09:00
test_llm_core_fallback.py Don't attempt the same (url, model) route twice in the fallback chains (#1733) 2026-06-03 13:33:50 +09:00
test_llm_core_mistral_content.py fix(llm): detect mistral.ai provider and support reasoning_effort (#4698) 2026-06-23 10:28:17 +02:00
test_llm_core_ollama.py fix(llm): normalize OpenAI-compatible chat URLs 2026-06-28 15:30:15 +01:00
test_llm_core_ollama_thinking.py fix(llm): suppress thinking mode for qwen3/gemma4 on Ollama /v1 endpoint (#3228) 2026-06-09 07:35:15 +02:00
test_llm_core_reasoning.py fix(llm): route gpt-oss harmony commentary channel without leaking markers/tool-args (#4523) 2026-06-18 21:12:25 +02:00
test_llm_core_reasoning_content_fallback.py fix: surface reasoning_content when content is empty (thinking models) (#1233) 2026-06-03 01:41:24 +09:00
test_llm_core_sanitize_tool_calls.py Isolate untrusted context from visible user prompts (#3584) 2026-06-27 13:50:04 +01:00
test_llm_core_sse_no_space.py fix: streaming drops providers that emit SSE data lines with no space (#1701) 2026-06-03 13:37:14 +09:00
test_llm_core_streaming.py fix(llm): guard against null arguments in streaming tool-call accumulator (#2923) 2026-06-05 20:57:36 +02:00
test_llm_core_system_msg_missing_content.py fix: degrade missing/None content key in system messages to empty string (#2570) 2026-06-05 00:10:11 +02:00
test_llm_core_temperature_anthropic.py test: split llm-core temperature tests (#4935) 2026-06-27 22:02:41 +02:00
test_llm_core_temperature_moonshot.py test: split llm-core temperature tests (#4935) 2026-06-27 22:02:41 +02:00
test_llm_core_temperature_reasoning.py test: split llm-core temperature tests (#4935) 2026-06-27 22:02:41 +02:00
test_llm_core_usage_finish_delta.py fix: SSE stream parser crashes with NoneType on providers sending null choice/usage/tc entries (#2389) 2026-06-04 13:53:10 +01:00
test_lmstudio_discovery.py Discover LM Studio via host/port scanning and native-API fingerprint (#1126) 2026-06-02 23:04:58 +09:00
test_lmstudio_models_url.py fix(endpoints): normalize URL handling (#4338) 2026-06-16 03:59:18 +01:00
test_lmstudio_vision.py Use LM Studio-reported vision capability for image passthrough (#1130) 2026-06-02 23:01:04 +09:00
test_load_features_permission_error.py fix(settings): degrade load_features to defaults on PermissionError 2026-06-11 21:20:10 +01:00
test_local_endpoint_api_key_js.py Models: allow API keys for local endpoints 2026-06-02 20:36:54 +09:00
test_local_endpoint_js.py fix: don't bill self-hosted models reached by a container/service hostname (#596) 2026-06-02 11:47:58 +09:00
test_log_safety.py fix(security): redact credential-bearing URLs and PII from logs (#4750) 2026-06-22 23:12:39 +02:00
test_loop_breaker_runaway.py fix(agent): don't abort legitimate tool batches as runaway loops (#3183) 2026-06-07 16:16:17 +02:00
test_manage_mcp_command_allowlist.py refactor(tools): migrate config/integration admin tools to the registry (#4742) 2026-06-24 09:29:10 +02:00
test_manage_memory_list.py fix(memory): return complete memory lists (#3885) 2026-06-15 20:28:25 +09:00
test_manage_notes_owner_gate.py Tighten manage notes owner checks (#3002) 2026-06-07 12:50:10 +02:00
test_manage_settings_token_budget.py refactor(tools): migrate config/integration admin tools to the registry (#4742) 2026-06-24 09:29:10 +02:00
test_markdown_dom_xss_helpers.py Harden markdown raw HTML sanitization (#2497) 2026-06-04 20:46:10 +02:00
test_markdown_rendering_js.py fix(markdown): preserve URLs inside inline code spans (#4681) 2026-06-22 17:23:55 +02:00
test_markdown_table_row_js.py Ignore non-string markdown table rows (#1648) 2026-06-03 14:17:02 +09:00
test_markitdown_format_nonstring.py fix: is_markitdown_format crashes on a non-string path (#1618) 2026-06-03 09:00:10 +09:00
test_markitdown_runtime.py Add optional markitdown extraction for Office/EPUB documents (#766) 2026-06-02 11:28:52 +09:00
test_match_model_key_js.py fix: model cost/info matches first substring key (gpt-4o-mini billed as gpt-4o) (#1439) 2026-06-04 03:05:37 +01:00
test_mcp_cache_invalidation.py fix(mcp): invalidate tool prompt cache on connect/disconnect/error (#1235) 2026-06-03 00:49:29 +09:00
test_mcp_common_truncate.py refactor(tools): consolidate duplicated _truncate and get_mcp_manager into src/tool_utils (#3478) 2026-06-09 01:05:30 +02:00
test_mcp_email_decode_header_spaces.py fix(email): enforce MCP owner boundaries (#4335) 2026-06-16 04:31:24 +01:00
test_mcp_manager.py feat(mcp): add Streamable HTTP transport with OAuth 2.0 (#1033) 2026-06-05 02:40:52 +02:00
test_mcp_memory_owner_scope.py fix(mcp): scope memory server by owner (#4315) 2026-06-16 03:18:17 +01:00
test_mcp_oauth.py feat(mcp): add Streamable HTTP transport with OAuth 2.0 (#1033) 2026-06-05 02:40:52 +02:00
test_mcp_param_hint_hardening.py fix(mcp): sanitize and cap rendered MCP tool param hints (#2682) 2026-06-05 03:00:22 +02:00
test_mcp_reconnect_args.py refactor(tools): migrate config/integration admin tools to the registry (#4742) 2026-06-24 09:29:10 +02:00
test_mcp_tool_params_in_prompt.py fix(mcp): expose MCP tool input parameters to the agent 2026-06-04 12:51:31 +00:00
test_memory_audit_timeout.py fix(memory): exempt audits from request timeout (#3886) 2026-06-15 20:27:46 +09:00
test_memory_bullet_extraction.py Fix memory bullet extraction in service copy 2026-06-03 13:41:46 +09:00
test_memory_extract_chat_nondict.py fix: chat memory extraction crashes on a non-dict message (#1749) 2026-06-03 13:25:48 +09:00
test_memory_extraction_parse.py fix(memory): make auto-memory extraction reliable for reasoning models (#3190) 2026-06-08 19:57:44 +02:00
test_memory_extractor_rows.py Skip invalid memory extractor rows (#1535) 2026-06-03 14:07:00 +09:00
test_memory_extractor_vector_cross_tenant.py Stub llm_core via monkeypatch.setitem so the cross-tenant test does not leak its fake into later test modules 2026-06-05 00:04:15 +01:00
test_memory_extractor_vector_degraded.py Update degraded-vector dedup test for owner-scoped vector match 2026-06-04 23:45:13 +01:00
test_memory_fallback_dislike.py fix(memory): record dislikes as dislikes, not preferences (#2435) 2026-06-07 16:36:07 +02:00
test_memory_imports.py refactor(memory): canonicalize memory imports (#50) 2026-06-04 05:31:15 +01:00
test_memory_owner_isolation.py test(memory): cover owner isolation for memory search 2026-06-11 22:21:30 +01:00
test_memory_provider.py feat(memory): add provider interface (#72) 2026-06-04 16:26:11 +01:00
test_memory_recall_nondict_rows.py fix: memory recall crashes on a non-dict row from the vector store (#1705) 2026-06-03 13:35:09 +09:00
test_memory_routes_session_owner.py fix(routes): normalize session owner fallback helpers (#4313) 2026-06-16 06:07:42 +01:00
test_memory_validate_entries_nondict.py fix: memory entry validation crashes on a non-dict row from memory.json (#1691) 2026-06-03 13:38:02 +09:00
test_merge_last_assistant_rows.py fix: merge-last-assistant deletes tool/system rows from the DB (history desync) (#1929) 2026-06-04 19:47:08 +02:00
test_migrate_faiss_to_chroma.py Skip invalid FAISS migration JSON (#1547) 2026-06-03 14:11:49 +09:00
test_misfenced_read_file_tool_call.py fix(agent): parse misfenced read_file calls (#4799) 2026-06-23 23:20:13 +02:00
test_modal_dock_composer_clearance.py fix(ui): keep minimized windows above composer (#1197) 2026-06-02 23:31:09 +09:00
test_model_context.py fix(endpoints): normalize URL handling (#4338) 2026-06-16 03:59:18 +01:00
test_model_defaults.py feat: Allow admins to choose if they want to share defaults (#4752) 2026-06-23 23:06:45 +02:00
test_model_discovery_status.py Reject invalid Tailscale discovery JSON (#1556) 2026-06-03 14:11:31 +09:00
test_model_helper_owner_scope.py Scope model helper endpoint resolution (#3007) 2026-06-07 12:40:23 +02:00
test_model_interaction_registry.py refactor(tools): move model-interaction tools to the agent_tools registry (#4445) 2026-06-18 05:56:37 +00:00
test_model_name_tooltip.py Add hover tooltips for clipped model names (#1982) (#1985) 2026-06-07 19:23:44 +02:00
test_model_routes.py fix(model-routes): harden _probe_endpoint against malformed model-list responses (#4789) 2026-06-24 19:05:31 +02:00
test_model_sort_js.py Ignore invalid model sort inputs (#1653) 2026-06-03 14:16:52 +09:00
test_native_tool_result_threading.py fix: tool results misthreaded to the wrong tool_call_id when a native call fails to convert (#1917) 2026-06-27 19:31:17 +01:00
test_new_chat_clears_input.py Clear the composer draft when entering the New Chat / welcome state (#1408) 2026-06-03 04:07:31 +09:00
test_new_chat_model_preference.py Chat: prefer active model for new desktop chats 2026-06-02 21:00:50 +09:00
test_nix_upload_text.py fix: treat Nix files as readable uploads (#2249) 2026-06-04 12:06:24 +02:00
test_note_reminder_fire_scope.py Harden note reminder dispatch ownership (#2999) 2026-06-07 12:52:27 +02:00
test_notes_dom_xss_helpers.py Guard image and QR DOM attributes (#2500) 2026-06-04 20:51:23 +02:00
test_notes_fail_closed_auth.py fix(notes): fail closed when an unauthenticated request reaches owner-scoped routes (#4062) 2026-06-15 17:43:28 +02:00
test_notes_search_reset_on_reopen_js.py fix(notes): reset search filter on panel reopen so stale query doesn't hide notes (#2920) 2026-06-15 11:55:46 +02:00
test_notes_select_esc_listener_js.py fix(notes): track + remove the select-mode Esc keydown listener so it doesn't leak per open (#2792) 2026-06-05 16:25:05 +02:00
test_notes_update_due_date.py Notes: parse natural-language due dates on update 2026-06-02 20:51:16 +09:00
test_notes_z_order_js.py fix(ui): share one z-order stack across Notes and modals (#3798) 2026-06-17 12:15:48 +02:00
test_null_owner_gates.py test: localize calendar recurrence helper import (#4944) 2026-06-28 19:04:15 +02:00
test_odysseus_dispatcher.py refactor(tests): reuse CLI loader in more tests (#2571) 2026-06-05 02:42:10 +01:00
test_og_image_extraction.py fix: source thumbnails dropped for http-only og:image URLs (#667) 2026-06-02 11:41:33 +09:00
test_ollama_multimodal.py fix: Images cannot be seen by model that is vision capable (#4726) 2026-06-23 10:32:57 +02:00
test_ollama_port_detection.py Add Ollama port path detection regressions (#883) 2026-06-02 12:24:18 +09:00
test_ordinal_suffix_js.py fix: monthly schedule label shows 21th/22th/31th (ordinal suffix for days >20) (#1577) 2026-06-03 08:57:47 +09:00
test_owned_document_query.py refactor(tools): extract document tools to handle registry (#3666) 2026-06-10 10:41:52 +02:00
test_parse_due_time_first.py fix(notes): handle time-first due_date phrases in parse_due_for_user (#3319) 2026-06-07 19:15:38 +02:00
test_parse_msg_content_jsonlike_string.py Fix _parse_msg_content corrupting JSON-array-like text messages on reload (#2060) 2026-06-27 14:31:51 +01:00
test_pdf_runtime.py Show a clear message when PyMuPDF is missing 2026-06-01 18:27:17 +09:00
test_personal_delete_file_confinement.py fix(personal): scope RAG file delete to the caller's own upload dir (#4602) 2026-06-20 00:50:15 +02:00
test_personal_dir_symlink_escape.py fix: personal-docs path confinement used abspath, allowing symlink escape (#1728) 2026-06-03 13:29:57 +09:00
test_personal_docs_exclusions.py Docs: respect path boundary when clearing exclusions 2026-06-02 20:35:44 +09:00
test_personal_docs_keyword_nondict.py Ignore non-string personal doc text (#1832) 2026-06-29 19:24:29 +01:00
test_personal_docs_lists.py Save only string personal doc paths (#1566) 2026-06-03 08:37:29 +09:00
test_personal_docs_office_index.py Add optional markitdown extraction for Office/EPUB documents (#766) 2026-06-02 11:28:52 +09:00
test_personal_docs_pdf_index.py Fix chat stream recovery and PDF library indexing (#468) 2026-06-01 22:33:35 +09:00
test_personal_docs_state_store.py Ignore invalid personal docs state (#1401) 2026-06-03 04:02:16 +09:00
test_personal_remove_dir_confinement.py fix(personal): confine remove_directory_from_rag to PERSONAL_DIR 2026-06-15 15:00:35 +09:00
test_personal_upload_isolation.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_personal_upload_privilege.py fix(personal): require document privilege for rag upload (#2990) 2026-06-07 12:56:53 +02:00
test_plan_mode.py feat: Add plan mode to the chat agent (#638) 2026-06-05 16:32:25 +02:00
test_platform_compat.py feat(launcher): add portable windows launcher (#976) 2026-06-16 04:58:16 +01:00
test_popup_opener_isolation_js.py Isolate HTML popup openers (#2501) 2026-06-04 20:52:41 +02:00
test_portal_dropdown_z_js.py fix(ui): route tasks.js + skills.js dropdowns through topPortalZ() (#4768) 2026-06-24 22:29:36 +02:00
test_pr_blocker_audit.py tools: add read-only PR blocker audit helper 2026-06-04 12:51:48 +01:00
test_prefs_atomic_write.py Persist user prefs atomically (#1840) 2026-06-04 03:55:22 +01:00
test_prefs_routes.py Ignore non-object prefs JSON (#1257) 2026-06-03 14:12:45 +09:00
test_prefs_single_user_no_clobber.py fix: disabling auth wipes all users' preferences on next pref save (#1764) 2026-06-03 13:23:50 +09:00
test_preset_atomic_save.py fix(presets): persist presets atomically to avoid corruption on crash (#2169) 2026-06-08 19:16:37 +02:00
test_preset_expand_owner_scope.py fix(presets): scope expand-prompt model resolution to owner (#3477) 2026-06-08 21:12:02 +02:00
test_preset_fill_missing_defaults.py Presets: fill missing built-in defaults on load 2026-06-02 20:32:08 +09:00
test_preset_local_storage_js.py Keep presets loading with bad local state (#1417) 2026-06-03 04:09:28 +09:00
test_preset_store_shape.py Fall back from invalid preset stores (#1402) 2026-06-03 14:12:31 +09:00
test_promote_image_fields.py fix(images): render agent-generated images in chat (#2809) 2026-06-05 13:04:33 +02:00
test_prompt_security.py fix(security): harden untrusted_context_message against delimiter spoofing (#3086) 2026-06-07 22:15:50 +01:00
test_provider_classification.py feat(discovery): detect llama.cpp servers and label local providers (#4729) 2026-06-23 23:39:56 +02:00
test_provider_classification_errors.py test: split provider classification tests (#4392) 2026-06-16 09:54:07 +00:00
test_provider_classification_token_params.py test: split provider classification tests (#4392) 2026-06-16 09:54:07 +00:00
test_provider_detection_builders.py test: split provider detection tests (#4933) 2026-06-27 21:46:33 +01:00
test_provider_detection_detect.py test: split provider detection tests (#4933) 2026-06-27 21:46:33 +01:00
test_provider_detection_host_match.py test: split provider detection tests (#4933) 2026-06-27 21:46:33 +01:00
test_provider_device_flow_js.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_provider_endpoints_headers.py test: split provider endpoint tests (#4961) 2026-06-28 19:05:38 +02:00
test_provider_endpoints_models.py test: split provider endpoint tests (#4961) 2026-06-28 19:05:38 +02:00
test_provider_endpoints_normalization.py test: split provider endpoint tests (#4961) 2026-06-28 19:05:38 +02:00
test_provider_endpoints_tailscale.py test: split provider endpoint tests (#4961) 2026-06-28 19:05:38 +02:00
test_provider_endpoints_url_building.py test: split provider endpoint tests (#4961) 2026-06-28 19:05:38 +02:00
test_provider_label_js.py feat(discovery): detect llama.cpp servers and label local providers (#4729) 2026-06-23 23:39:56 +02:00
test_providers_mixtral_logo_js.py fix: Mixtral and Ministral models render with no provider logo (#1640) 2026-06-03 14:23:21 +09:00
test_public_blocked_tool_nonstring.py fix: is_public_blocked_tool crashes on a truthy non-string tool name (#1620) 2026-06-03 14:11:14 +09:00
test_question_type_detection.py fix: research query misclassifies 'whatsapp'/'however' as questions (#1247) 2026-06-03 01:10:06 +09:00
test_rag_keyword_fallback_owner.py fix: RAG keyword fallback leaked owner-less documents across users (#1722) 2026-06-03 13:31:33 +09:00
test_rag_manager_owner_compat.py fix(rag): forward owner through manager wrapper (#2991) 2026-06-07 12:56:57 +02:00
test_rag_remove_directory_scope.py Fix RAG remove_directory wiping the entire shared collection (#1660) (#1734) 2026-06-03 13:29:51 +09:00
test_rag_server_directory_nonstring.py fix: rag_server add/remove_directory crashes on a non-string directory arg (#1614) 2026-06-03 08:36:45 +09:00
test_rag_vector_id_stability.py fix(tests): use current python for rag id stability (#1817) 2026-06-04 03:49:59 +01:00
test_rag_vector_rename_owner.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_rate_limiter.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
test_readiness.py feat: add /api/ready readiness probe (DB, data dir, local-first) (#1200) 2026-06-02 23:33:22 +09:00
test_readme_ascii_fenced.py test: align README presentation guards with the #4306 refresh (#4311) 2026-06-15 16:25:38 +01:00
test_realesrgan_torchvision_compat.py fix(image): patch realesrgan torchvision compatibility (#4110) 2026-06-15 15:16:41 +09:00
test_redos_cal_extract.py fix(security): prevent exponential ReDoS in email→calendar extract regex (#4708) 2026-06-22 17:18:34 +02:00
test_redos_llm_parsers.py fix(security): prevent ReDoS in LLM-output tool/think parsers (#4704) 2026-06-27 10:12:28 -07:00
test_redos_think_blocks.py fix(security): prevent ReDoS in agent_loop <think> stripping (#4877) 2026-06-27 04:32:42 +01:00
test_redos_verdict_continuation.py fix(security): prevent ReDoS in verdict-prose and continuation matchers (#4943) 2026-06-28 11:42:20 +01:00
test_redos_xml_tool_parsers.py fix(security): prevent ReDoS in XML and args tool-call parsers (#4941) 2026-06-27 15:42:55 -07:00
test_rename_user_case_insensitive.py refactor(tests): reuse import-state helper in auth tests 2026-06-05 11:10:41 +01:00
test_rename_user_owner_sync.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_rename_user_token_cache.py fix: renaming a user leaves their API tokens resolving to the old owner (#1932) 2026-06-04 20:37:59 +02:00
test_replace_messages_multimodal.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
test_reply_all_cc_nonstring_js.py fix: reply-all Cc builder crashes on a non-string To or Cc field (#1700) 2026-06-03 13:37:22 +09:00
test_reply_recipients_js.py fix: reply-all Cc's the user's own other addresses (multi-account) (#672) 2026-06-02 11:42:20 +09:00
test_research_chat_stream_owner.py fix: pass owner to start_research in chat stream path (#1265) 2026-06-03 02:32:38 +09:00
test_research_endpoint_owner_scope.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_research_handler_analyzed_urls.py fix(research): track analyzed URLs separately (#3125) 2026-06-10 12:08:22 +01:00
test_research_handler_path_confinement.py Constrain research handler JSON paths (#2846) 2026-06-05 13:20:02 +02:00
test_research_handler_raw_nondict.py fix: a non-dict finding silently drops all raw research findings (#1739) 2026-06-03 13:29:29 +09:00
test_research_handler_sources_nondict.py fix: research source extraction crashes on a non-dict finding (#1714) 2026-06-03 13:34:40 +09:00
test_research_owner_scope_routes.py refactor(constants): single source of truth for data dir (#3368) 2026-06-08 09:58:52 +02:00
test_research_probe_errors.py Surface deep research probe errors (#1086) 2026-06-02 22:51:25 +09:00
test_research_query_fallback.py Deep research: don't treat a bare 'yes' as the research topic (#858) 2026-06-02 11:30:53 +09:00
test_research_report_read.py Route "read that report" to manage_research instead of the HTML render (#1375) 2026-06-03 03:24:09 +09:00
test_research_routes_shim.py refactor(routes): move research domain into routes/research/ subpackage 2026-06-28 14:34:11 +01:00
test_research_service.py Skip invalid research service sources (#1583) 2026-06-03 08:57:09 +09:00
test_research_session_id_validation.py fix(research): validate session_id to block path traversal 2026-06-01 23:25:38 +01:00
test_research_source_link_xss.py Whitelist research source links (#2499) 2026-06-04 20:41:35 +02:00
test_research_status_avg_duration.py fix(research): stop rescanning the research dir on every status poll (#3637) 2026-06-10 17:40:44 +02:00
test_research_utils.py fix: deep research discards valid sources mentioning cookies/copyright (#481) 2026-06-01 22:26:37 +09:00
test_research_utils_low_quality_nonstring.py Treat non-string research summaries as low quality 2026-06-03 13:42:24 +09:00
test_resend_message_nondestructive.py fix(chat): make resend message non-destructive 2026-06-15 15:02:48 +09:00
test_reserved_username_admin_escalation.py test(auth): cover reserved username sentinel gate (#4276) 2026-06-16 04:09:58 +01:00
test_resolve_endpoint_fallbacks.py fix(routes): normalize session owner fallback helpers (#4313) 2026-06-16 06:07:42 +01:00
test_resolve_model_offloaded.py fix(ai): offload model resolution from async paths 2026-06-28 00:48:35 +01:00
test_resolve_session_auth_chatgpt.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_resolve_upload_path_nondict.py fix: _resolve_user_upload_path crashes on a non-dict resolve_upload result (#1715) 2026-06-03 13:34:33 +09:00
test_review_regressions.py fix(agent): execute fenced tool calls with inline args and route bare email tool names (#3681) 2026-06-30 16:50:32 +01:00
test_rewrite_persist_column.py fix(tests): add endpoint URLs to remaining session fixtures 2026-06-04 03:14:43 +01:00
test_route_validators.py fix(hwfit): validate remote SSH detection targets (#3718) 2026-06-11 00:43:49 +02:00
test_run_focus.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_run_order_report.py test: add report-only order-sensitivity runner (#3982) 2026-06-15 15:49:47 +09:00
test_runtime_paths.py feat(paths): abstract runtime path logic for frozen distribution packages (#969) 2026-06-15 17:44:10 +01:00
test_sanitize_multimodal_merge.py fix: merging consecutive user messages corrupts multimodal (image) content (#1277) 2026-06-03 01:21:57 +09:00
test_sanitize_preserves_reasoning.py fix: preserve reasoning_content in sanitized messages for Moonshot/Kimi (#3152) 2026-06-09 21:44:38 +01:00
test_schedule_email_offset_normalization.py Normalize scheduled email offsets before storage 2026-06-03 13:44:18 +09:00
test_scheduler_prompt_cache_time.py fix(tasks): keep scheduled-task prompt cache stable 2026-06-28 00:05:02 +01:00
test_scheduler_restart_doublefire.py Replace task scheduler utcnow calls (#1456) 2026-06-03 14:14:30 +09:00
test_scheduler_scheduled_time_validation.py fix(scheduler): fail closed on malformed scheduled_time instead of 500 (#1410) 2026-06-03 14:12:07 +09:00
test_search_analytics_defaults.py refactor(search): make src analytics a service shim (#2264) 2026-06-04 18:57:24 +02:00
test_search_cache_invalidation.py Fix invalidate_search_cache using a key that never matches stored entries (#852) 2026-06-02 10:53:33 +09:00
test_search_config_no_key_leak.py Stop GET /api/search/config from leaking the Brave API key (#1661) (#1750) 2026-06-03 13:24:17 +09:00
test_search_config_provider_key.py Report provider-specific search API keys correctly (#1202) 2026-06-02 23:37:15 +09:00
test_search_content_block_source_index.py fix: web search content blocks numbered by fetch completion order break citations (#1672) 2026-06-03 14:22:55 +09:00
test_search_content_extraction_parity.py fix(search): add download budgets to web_fetch with truncation notice and hard ceiling (#3955) 2026-06-15 17:38:09 +00:00
test_search_content_url_guards.py chore: deduplicate src/search modules (cache, content, query) into shims (#2506) 2026-06-04 18:10:55 +02:00
test_search_module_consolidation.py chore: deduplicate src/search modules (cache, content, query) into shims (#2506) 2026-06-04 18:10:55 +02:00
test_search_provider_json.py fix(search): degrade to empty results on non-JSON provider responses (#1129) (#1352) 2026-06-03 14:24:23 +09:00
test_search_query.py Fix year extraction in research queries 2026-06-01 23:09:41 +09:00
test_search_query_entities_nonstring.py fix: _extract_entities crashes on a non-string query (#1724) 2026-06-03 13:30:28 +09:00
test_search_query_nonstring.py fix: search query helpers crash on a non-string query (#1604) 2026-06-03 08:36:01 +09:00
test_search_ranking.py Reapply "Merge branch 'main' of github.com:pewdiepie-archdaemon/odysseus" 2026-06-03 22:47:00 +09:00
test_search_ranking_recency.py Reapply "Merge branch 'main' of github.com:pewdiepie-archdaemon/odysseus" 2026-06-03 22:47:00 +09:00
test_search_ranking_sports_substring.py fix: sports-hint ranking penalty fires on 'transport'/'passport' substrings (#1473) 2026-06-03 14:23:52 +09:00
test_search_ranking_subject_substring.py Word-boundary match for snippet and subject-term ranking (#1473 follow-up) (#2556) 2026-06-05 08:04:31 +01:00
test_search_service_nondict_rows.py fix(tests): update search service mock to match current API signature (#2334) 2026-06-04 14:19:51 +01:00
test_searchservice_search_call.py fix: SearchService.search() calls comprehensive_web_search incorrectly (broken public API) (#1720) 2026-06-03 13:33:56 +09:00
test_searxng_image_pinned.py Pin the SearXNG image so a broken :latest can't block startup (#1419) 2026-06-03 03:56:54 +09:00
test_security_headers_middleware.py fix(security): add HSTS and Permissions-Policy to SecurityHeadersMiddleware (#3081) 2026-06-07 04:58:33 +01:00
test_security_headers_pdf_preview.py fix(documents): restore PDF library metadata and preview (#2483) 2026-06-07 23:23:27 +02:00
test_security_regressions.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_select_dropdown_theme_css.py Normalize native select option theming (#1178) 2026-06-02 23:09:15 +09:00
test_sender_signature_skip_roles.py fix: signature learning never skips support@/info@/admin@ senders (#1773) 2026-06-03 13:22:52 +09:00
test_serve_html_with_nonce.py fix(routes): log and cleanly 500 on unreadable HTML page (#4637) 2026-06-23 16:12:32 +02:00
test_serve_profiles.py Ignore invalid serve profile inputs (#1827) 2026-06-29 18:47:19 +01:00
test_service_health.py feat(diagnostics): add consolidated service health endpoint for degraded-state reporting (#964) 2026-06-09 16:00:24 +01:00
test_service_search_provider_guards.py chore: Switch duckduckgo-search to ddgs (#3143) 2026-06-10 17:59:47 +02:00
test_services_research_low_quality_sources.py fix: services research lists junk no-content pages as cited sources (#1669) 2026-06-03 14:22:58 +09:00
test_services_search_analytics_defaults.py Merge search analytics defaults in services copy 2026-06-03 13:45:07 +09:00
test_session_actions_cleanup.py fix(sessions): keep fresh chats during auto tidy (#1871) 2026-06-09 01:06:20 +01:00
test_session_concurrent.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
test_session_context_excludes_slash.py fix: exclude slash-command/setup messages from LLM context (#2634) (#2640) 2026-06-04 21:42:23 +02:00
test_session_endpoint_owner_scope.py fix(api): attribute bearer-token actions to the token owner on owner-scoped routes (#4054) 2026-06-15 23:56:22 +02:00
test_session_export_filename.py fix: _sanitize_export_filename crashes on a non-string session name (#1607) 2026-06-03 08:35:47 +09:00
test_session_export_nonstring_content.py Fix session export 500 on multimodal/None message content (#1984) 2026-06-04 12:53:44 +01:00
test_session_ghost_delete.py allow user who disable auth to use chat (#2548) 2026-06-05 22:54:19 +02:00
test_session_list_owner_scope.py fix(auth): clean up rename and null-owner ownership (#4340) 2026-06-16 03:33:02 +01:00
test_session_manager.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
test_session_manager_cleanup.py Fix session cleanup cutoff timezone (#2488) 2026-06-05 09:52:34 +02:00
test_session_manager_persist_guard.py Guard session message persistence after delete (#1451) 2026-06-03 14:24:01 +09:00
test_session_mode_helpers.py Fix database stubs in regression tests (#301) 2026-06-01 16:55:09 +09:00
test_session_owner_attribution.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_session_search.py feat(search): unify session transcript search (#2877) 2026-06-05 18:08:31 -06:00
test_session_search_batch_fetch.py fix(search): batch FTS hit lookups into one query (N+1) (#3909) 2026-06-11 16:31:54 +02:00
test_session_tools_registry.py refactor(tools): move session tools to the agent_tools registry (#4454) 2026-06-19 11:55:22 +02:00
test_set_admin.py feat(auth): add per-user admin promote/demote toggle (#3078) 2026-06-15 10:44:27 +00:00
test_settings_error_paths.py fix(settings): catch PermissionError in load_settings + error-path tests (#1570) 2026-06-03 14:23:27 +09:00
test_settings_scrub.py fix(settings): scrub camelCase secret keys (#3707) 2026-06-11 12:53:33 +02:00
test_settings_store_shape.py Fall back from invalid settings stores (#1416) 2026-06-03 03:53:05 +09:00
test_setup_admin_user.py fix(setup): load .env so a pre-seeded admin password is honored on native installs (#4787) 2026-06-23 20:08:05 +02:00
test_setup_device_auth_static.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_setup_llamacpp_hint_js.py feat(discovery): detect llama.cpp servers and label local providers (#4729) 2026-06-23 23:39:56 +02:00
test_shell_routes.py fix(image): patch realesrgan torchvision compatibility (#4110) 2026-06-15 15:16:41 +09:00
test_shell_service.py fix: use running loop for shell stream deadlines (#1694) 2026-06-03 13:37:46 +09:00
test_signature_fold_js.py Ignore non-string signature fold metadata (#1655) 2026-06-03 14:16:48 +09:00
test_signature_fold_self_closing_br_js.py fix: signature delimiter fold misses self-closing <br/> breaks (#1774) 2026-06-03 13:22:46 +09:00
test_signature_route_hardening.py Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
test_signature_settings_dom_xss.py Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
test_skill_edit_no_collapse_on_outside_click_js.py fix(skills): keep edit mode open on outside-the-textarea click (#4011) 2026-06-15 20:31:11 +09:00
test_skill_extractor_json.py fix(memory): reject ambiguous multi-object outputs during skill extraction (#3985) 2026-06-15 10:44:43 +00:00
test_skill_extractor_rows.py Skip invalid skill extractor rows (#1546) 2026-06-03 14:06:53 +09:00
test_skill_extractor_stray_brace.py fix(memory): reject ambiguous multi-object outputs during skill extraction (#3985) 2026-06-15 10:44:43 +00:00
test_skill_importer.py feat(skills): import SKILL.md bundles from public GitHub URLs (#2576) 2026-06-05 19:48:23 +02:00
test_skill_index_prompt_injection.py test: stop test_skill_index_prompt_injection leaking a stub prefs_routes (#4387) 2026-06-18 20:54:15 +02:00
test_skill_index_toolset_gating.py fix(agent): skill-prescribed tools never reach the model's schema list (#4008) 2026-06-15 20:32:43 +09:00
test_skill_save_no_rename.py fix(skills): markdown save must not rename the skill, so delete keeps working (#1333) (#1365) 2026-06-03 03:16:11 +09:00
test_skills_delete_owner.py Skills: delete owner-scoped skills with owner 2026-06-02 20:28:36 +09:00
test_skills_manager_owner_isolation.py Scope skills usage by owner (#1312) 2026-06-03 02:27:43 +09:00
test_skills_routes_nondict.py fix: skill test-task / precision helpers crash on a non-dict skill (#1638) 2026-06-03 08:59:24 +09:00
test_skills_routes_owner_update.py Fix owner-scoped skill updates (#1240) 2026-06-03 00:42:56 +09:00
test_skills_tag_token_match.py fix: skill retrieval boosts on tag substrings (e.g. 'ai' tag for any 'email' query) (#1406) 2026-06-03 14:24:11 +09:00
test_slash_autocomplete_static.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
test_slash_setup_provider_aliases.py fix: add OpenCode setup provider aliases (#4700) 2026-06-22 17:33:02 +02:00
test_snap_other_layers_nonarray_js.py Keep snap helper safe without context (#1828) 2026-06-29 18:54:44 +01:00
test_speech_service_toggles.py Honor disabled speech service toggles (#814) 2026-06-02 10:44:39 +09:00
test_split_chunks_no_duplicate_tail.py fix(tests): use non-repeating split chunk fixture 2026-06-04 18:11:42 +01:00
test_sqlite_foreign_keys.py refactor(tests): centralize fake database import-state cleanup 2026-06-05 12:27:44 +01:00
test_src_search_query_nonstring.py chore: deduplicate src/search modules (cache, content, query) into shims (#2506) 2026-06-04 18:10:55 +02:00
test_streaming_segmenter_js.py fix(chat): stop code-block button flicker during streaming (#3023) 2026-06-06 04:08:54 -06:00
test_strip_reasoning_prose_dataloss.py fix: _strip_reasoning_prose discards the answer when reasoning trails it (#1643) 2026-06-03 14:23:15 +09:00
test_strip_think.py fix: normalize Gemma 4 thought-channel output (#2224) 2026-06-04 19:26:58 +02:00
test_stt_leak.py STT: clean temp audio files on transcription failure 2026-06-02 20:43:24 +09:00
test_task_chain_owner_scope.py Enforce task chain owner scope (#3006) 2026-06-07 12:43:43 +02:00
test_task_endpoint_normalization.py fix(tasks): normalize task endpoint URL to /chat/completions before model call (#4619) 2026-06-24 18:02:31 +02:00
test_task_scheduler_cancel.py Tasks: clean up queued cancellation state 2026-06-02 20:51:21 +09:00
test_task_scheduler_session_delivery.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
test_task_session_folder.py feat(tasks): assign folder='Tasks' at creation + backfill migration (#2834) 2026-06-07 15:33:17 +02:00
test_task_shell_tools.py fix(tasks): keep scheduled-task prompt cache stable 2026-06-28 00:05:02 +01:00
test_taxonomy.py test: split embedding lane tests (#4389) 2026-06-26 18:28:40 +02:00
test_teacher_audit_owner_scope.py fix(presets): scope expand-prompt model resolution to owner (#3477) 2026-06-08 21:12:02 +02:00
test_teacher_eval_nonstring_reply.py fix: evaluate_turn_regex crashes on a non-string agent_reply (#1723) 2026-06-03 13:31:26 +09:00
test_teacher_eval_tier2.py feat(teacher): add teacher_tier2_enabled setting and strict parser 2026-06-26 22:26:15 +05:30
test_tile_manager_snap_zones_js.py fix(ui): restore all-edge modal snap zones (#2260) 2026-06-15 12:36:34 +02:00
test_tls_overrides_scope.py Support extra CA bundle for private-CA LLM providers (#769) 2026-06-04 13:18:50 +01:00
test_toast_dismiss_pointer_events.py feat: add dismiss (×) button to all toast notifications (#1355) (#1755) 2026-06-26 14:02:35 +01:00
test_tool_implementations_shim.py refactor(tools): split tool_implementations.py into src/tools/ package (#4423) 2026-06-26 15:40:04 +01:00
test_tool_index_keyword_boundaries.py fix(tests): restore Python CI baseline regressions 2026-06-05 10:31:38 +01:00
test_tool_index_schema_parity.py fix(agent): index api_call so RAG tool selection can retrieve it (#3923) 2026-06-18 08:43:25 +00:00
test_tool_output_prompt_injection.py harden(agent-loop): wrap non-native tool results as untrusted data (#1629) 2026-06-16 13:35:07 +02:00
test_tool_parsing_nonstring.py fix: tool-block parsing crashes on a non-string input (#1628) 2026-06-03 08:59:42 +09:00
test_tool_path_confinement.py fix(tools): strict path confinement with sensitive-subpath deny list (#1072) 2026-06-02 23:13:30 +09:00
test_tool_policy.py refactor(tools): remove dead workspace-confinement plumbing (#3590) 2026-06-09 08:30:50 +02:00
test_tool_rag_contacts_domain.py fix(agent): add contacts domain to tool classifier 2026-06-15 15:03:19 +09:00
test_tool_rag_keyword_hints.py fix(agent): honor explicit web search requests 2026-06-15 15:02:10 +09:00
test_tool_support_heuristic.py CI fixes for cookbook workflow sync 2026-06-22 02:08:25 +00:00
test_tool_utils_import_clean.py refactor(tools): consolidate duplicated _truncate and get_mcp_manager into src/tool_utils (#3478) 2026-06-09 01:05:30 +02:00
test_topic_analyzer.py refactor(tests): centralize fake database import-state cleanup 2026-06-05 12:27:44 +01:00
test_totp_failclosed.py fix: 2FA bypassed when enabled but TOTP secret is missing (fail-open) (#1286) 2026-06-03 01:26:47 +09:00
test_truncate_message_count_regression.py fix: session context drifting — messages leaking between chats (#135) (#267) 2026-06-09 14:12:52 +01:00
test_tts_cache_stats.py TTS: include mp3 files in cache stats 2026-06-02 20:43:29 +09:00
test_tts_speed_malformed.py fix(tts): tolerate a malformed tts_speed instead of 500-ing (#1450) 2026-06-03 14:12:03 +09:00
test_ui_control_rag_toggle.py fix: ui_control rejects the advertised rag toggle (#1763) 2026-06-03 13:24:00 +09:00
test_unknown_tool_calls.py test(tool_execution): stop two tests leaking src.tool_execution into the suite (#2686) 2026-06-09 16:35:10 +01:00
test_update_database_script.py Remove duplicate update database body (#1584) 2026-06-03 08:57:03 +09:00
test_update_plan_tool.py feat: Add plan mode to the chat agent (#638) 2026-06-05 16:32:25 +02:00
test_upload_content_detection_magic.py fix(docker): install python-magic and libmagic for upload MIME sniffing 2026-06-27 17:31:46 +01:00
test_upload_error_surfaced.py Surface upload failures instead of silently dropping the files (#1425) 2026-06-03 04:12:23 +09:00
test_upload_handler_atomicity.py Ignore stale duplicate upload rows (#1256) 2026-06-03 00:59:01 +09:00
test_upload_handler_rename_owner.py fix(uploads): migrate upload ownership on rename (#3617) 2026-06-11 16:01:04 +02:00
test_upload_id_extension.py fix: uploads with _ or - in the extension become permanently unreadable (#1756) 2026-06-03 13:28:45 +09:00
test_upload_id_validation.py fix: uploaded files with no extension become permanently unresolvable (#1275) 2026-06-03 01:16:30 +09:00
test_upload_limits_centralized.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_upload_multifile.py Cookbook launch and gallery upload fixes 2026-06-22 01:49:15 +00:00
test_upload_routes_owner_scope.py fix(upload): handle corrupt uploads index and malformed vision JSON 2026-06-27 18:59:28 +01:00
test_url_safety.py Reject resolver results without IPs (#1826) 2026-06-29 16:32:32 +01:00
test_user_time.py fix(chat): stabilize system prompt, sequence memory extraction, and send stable session id to preserve KV cache (#3360) 2026-06-09 22:46:54 +01:00
test_vault_password_not_in_argv.py refactor(tools): split tool_implementations.py into src/tools/ package (#4423) 2026-06-26 15:40:04 +01:00
test_vcard_unfolding.py fix: vCard parser drops folded continuation lines, corrupting emails (#1870) 2026-06-27 14:41:57 +01:00
test_venice_hosts.py Treat Venice as a tool-capable SOTA cloud provider (#1173) 2026-06-02 23:03:46 +09:00
test_vision_model_detection.py Recognize gemma3/llama4/mistral-small3.1+/multimodal as vision models (#1430) 2026-06-03 04:17:40 +09:00
test_vision_owner_scope.py refactor(routes): move gallery domain into routes/gallery subpackage (#4903) 2026-06-28 10:40:34 +01:00
test_visual_report.py Fix visual report chapter navigation (#505) 2026-06-01 22:26:13 +09:00
test_visual_report_icon_url.py fix: visual report drops photos whose URL slug contains icon or logo (#1685) 2026-06-03 14:22:45 +09:00
test_visual_report_nonstring.py fix: visual_report markdown helpers crash on a non-string input (#1633) 2026-06-03 14:06:35 +09:00
test_visual_report_slug_unique.py fix(visual_report): make TOC heading slugs unique 2026-06-27 17:36:17 +01:00
test_visual_report_toc_code_fence.py fix(visual_report): ignore fenced headings in TOC extraction 2026-06-27 17:44:32 +01:00
test_warmup_ping_urls.py fix(startup): ping real endpoints in warmup/keepalive (#3641) 2026-06-10 19:21:45 +02:00
test_web_fetch_plaintext.py fix(search): add download budgets to web_fetch with truncation notice and hard ceiling (#3955) 2026-06-15 17:38:09 +00:00
test_web_fetch_size_caps.py fix(search): add download budgets to web_fetch with truncation notice and hard ceiling (#3955) 2026-06-15 17:38:09 +00:00
test_web_search_query_sanitization.py fix(chat): sanitize web search query to strip markdown and code blocks (#4863) 2026-06-28 01:23:08 +01:00
test_web_search_raw_json_tool_call.py fix(agent): parse raw json web search calls (#4088) 2026-06-15 15:19:38 +09:00
test_web_search_time_filter.py fix(tool-schemas): preserve web_search time_filter through native tool-call conversion (#2757) 2026-06-05 08:00:59 +01:00
test_web_search_tool_icon_js.py fix(ui): raw SVG markup displayed instead of search icon for web_search tool label (#3601) 2026-06-10 16:50:43 +02:00
test_web_user_agent_constant.py refactor(search): centralize the web-scraping User-Agent into one constant (#4325) 2026-06-16 01:33:47 +00:00
test_webhook_emitters_use_manager.py fix(webhooks): route public emitters through fire_and_forget (#3964) (#4336) 2026-06-16 00:41:45 +02:00
test_webhook_sanitize_error_ipv6.py fix(webhooks): redact IPv6 addresses in sanitized error messages (#3038) 2026-06-07 04:55:33 +01:00
test_webhook_ssrf_resilience.py fix(tests): make webhook SSRF test clean-worktree deterministic 2026-06-05 08:16:28 +01:00
test_webhook_task_refs.py fix(tests): isolate webhook task reference imports 2026-06-15 14:57:47 +09:00
test_webhook_trigger_auth_exempt.py Exempt task webhook trigger from session auth (#784) 2026-06-02 11:23:40 +09:00
test_windows_update_script.py Windows: add Docker update script 2026-06-02 20:45:32 +09:00
test_workspace_confine.py feat(agent): confine agent file/shell tools to a selectable workspace (#3665) 2026-06-11 18:17:54 +02:00
test_youtube_comments_timeout.py YouTube: enforce comment fetch timeout while waiting 2026-06-02 20:44:24 +09:00
test_youtube_extract_id_nonstring.py fix: extract_youtube_id crashes on a non-string url instead of returning None (#1689) 2026-06-03 13:38:11 +09:00
test_youtube_handler_consolidation.py fix(youtube): consolidate duplicate handler 2026-06-15 15:03:41 +09:00
test_youtube_svc_comments_nondict.py fix: youtube (services) comment formatter crashes on a non-dict comment (#1746) 2026-06-03 13:29:01 +09:00
test_youtube_transcript_seg_nondict.py fix: youtube transcript formatter crashes on a non-dict segment (#1745) 2026-06-03 13:29:08 +09:00
TESTING_STANDARD.md fix(devops): harden docker config defaults (#4349) 2026-06-16 04:03:43 +01:00

Test Suite Notes

Purpose

This file documents the shared test helpers and the review expectations that go with them. The suite is being refactored incrementally, so this is a working reference for that effort - not a claim that the suite is already fully organized. Read it before adding a new helper or before reviewing a PR that touches tests/helpers/.

For the broader rules - test taxonomy, determinism/isolation rules, the behavioral-vs-source-text policy, and helper/factory extraction rules - see TESTING_STANDARD.md. This file is the concrete helper reference; that file is the standard the refactor works toward.

Running focused subsets (taxonomy markers)

tests/conftest.py tags every test at collection time with two markers derived from its filename by tests/_taxonomy.py: an area_* marker (e.g. area_security) and a finer sub_* marker (e.g. sub_owner_scope). This adds markers only - it moves no files and changes no test behavior. Use them to run a focused slice:

./venv/bin/python -m pytest -m area_security
./venv/bin/python -m pytest -m "area_services and sub_cookbook"

Areas are security, routes, services, cli, js, helpers, unit, and uncategorized. Classification is conservative and token-based: a file that matches no area keyword falls back to area_uncategorized with its filename as the sub-area. The area_* names are registered in pyproject.toml; the dynamic sub_* names are registered before collection by pytest_configure in tests/conftest.py, so unknown-mark warnings still flag genuine typos.

For common focused runs, use tests/run_focus.py. It validates area and sub-area names, accepts sub-areas with or without the sub_ prefix, and passes extra pytest arguments after --:

./venv/bin/python tests/run_focus.py --area security
./venv/bin/python tests/run_focus.py --area services --sub-area cookbook
./venv/bin/python tests/run_focus.py --sub-area sub_cookbook
./venv/bin/python tests/run_focus.py --keyword taxonomy
./venv/bin/python tests/run_focus.py --last-failed
./venv/bin/python tests/run_focus.py --dry-run --area services --sub-area cookbook
./venv/bin/python tests/run_focus.py --area services -- --maxfail=1 -q

Fast lane and duration visibility

--fast runs the fast lane: the tests that are not marked slow (it adds the marker expression not slow). It composes with --area/--sub-area using and. Because no tests may be marked slow yet, --fast can initially match the full focused selection; it becomes a real speed-up as slow marks are added from duration evidence. Use it for quick local or reviewer feedback; it does not replace broader focused or full-suite validation before merge.

--durations N and --durations-min FLOAT add pytest's slowest-test reporting so you can see where time goes. They are reporting only and do not count as a focus selector, so --durations must be combined with a real selector (--area, --sub-area, --keyword, --last-failed, or --fast).

Use the project Python environment before running these commands. The examples use the repo's documented ./venv/bin/python path so they do not accidentally fall back to system Python.

./venv/bin/python tests/run_focus.py --fast
./venv/bin/python tests/run_focus.py --area services --fast
./venv/bin/python tests/run_focus.py --area services --durations 25
./venv/bin/python tests/run_focus.py --area services --fast --durations 25 --durations-min 0.05

The slow marker is opt-in. Mark a test slow only with duration evidence (from --durations), not by guessing - see the fast-lane policy in TESTING_STANDARD.md. --fast is for quick reviewer feedback and must not replace the full suite before merge. A slow mark only excludes a test from the fast lane; the test stays runnable directly, e.g.:

./venv/bin/python -m pytest tests/test_auth_config_lock_concurrency.py
./venv/bin/python -m pytest -m slow

Order-sensitivity reporting (report-only)

tests/run_order_report.py runs pytest with the collected test items shuffled by a seeded RNG, to surface order-sensitive tests (hidden coupling through shared import state, module caches, databases, etc.). It is report-only: it is not wired into CI, adds no gate, and changes no normal pytest collection or ordering - the shuffle exists only inside this runner. The seed is always printed, and pytest targets/options go after a literal --:

./venv/bin/python tests/run_order_report.py --seed 123 -- tests/cli/ -q
./venv/bin/python tests/run_order_report.py -- tests/cli/ -q   # generates and prints a seed

The same seed reproduces the same order when the reported working directory, pytest target arguments, and test environment are also the same. The runner prints all command arguments with shell-safe POSIX quoting and uses the invoking Python interpreter.

A generated-seed run starts with output like:

[order-report] working directory: /path/to/odysseus
[order-report] shuffling test order with seed 284734921
[order-report] reproduce from this working directory with the same test environment:
[order-report] reproduce with: /path/to/odysseus/venv/bin/python /path/to/odysseus/tests/run_order_report.py --seed 284734921 -- tests/cli/ -q

Run the printed command from the reported working directory to reproduce the same fixed-seed order:

[order-report] working directory: /path/to/odysseus
[order-report] shuffling test order with seed 284734921
[order-report] reproduce from this working directory with the same test environment:
[order-report] reproduce with: /path/to/odysseus/venv/bin/python /path/to/odysseus/tests/run_order_report.py --seed 284734921 -- tests/cli/ -q

Pytest output remains visible between the report header and footer. A failing run ends with pytest's normal failure report followed by:

FAILED tests/example_test.py::test_example - AssertionError
[order-report] seed 284734921: pytest exit code 1 (report-only; fix order-sensitive failures in separate scoped PRs)

Failures discovered this way are real isolation bugs: fix them in separate scoped PRs - do not silence them with skip/xfail, and do not "fix" them by depending on a particular order.

The runner propagates pytest's exit code, so it composes with normal local workflows; "report-only" means it is not a CI gate, not that failures are swallowed.

Core principles

  • Keep PRs small and homogeneous: one kind of change per PR.
  • Prefer explicit local setup over hidden global fixtures.
  • Avoid expanding the root conftest.py unless absolutely necessary.
  • Do not mix file moves with logic changes in the same PR.
  • Do not weaken tests with skip/xfail just to make CI pass.
  • Validate the focused files you changed, plus any neighboring or order-sensitive groups they interact with.

Helper conventions

The helpers below live under tests/helpers/. They exist to remove repeated boilerplate that already appeared across multiple tests. Reach for one only when your test matches its intended use; do not stretch a helper to cover a new case.

tests.helpers.cli_loader.load_script

Use when a test needs to import a script under scripts/ without repeating SourceFileLoader / importlib.util boilerplate.

  • Intended for script/CLI tests that load a single file from scripts/.
  • Not for arbitrary package imports - use a normal import for those.
  • When migrating an existing test to it, keep the existing stubs and assertions unchanged. Any sys.modules stubs the script needs at import time must still be injected (e.g. via monkeypatch) before calling load_script.

tests.helpers.import_state.clear_module

Use when a test must drop one cached module and its parent-package attribute before a fresh import.

  • Clears sys.modules[name].
  • Clears the parent-package attribute when present.
  • Good replacement for local sys.modules.pop(...) + delattr(parent, child) blocks.

tests.helpers.import_state.preserve_import_state

Use when a test temporarily installs stubs into sys.modules and needs deterministic cleanup afterward.

  • Context manager: restores both sys.modules entries and parent-package attributes on exit (normal or exception).
  • Useful around module-level stubs or temporary imports.
  • Prefer narrow, explicit module names over broad ones.

tests.helpers.import_state.clear_fake_database_modules

Use only for the guarded fake/stub database cleanup pattern.

  • Preserves a real-looking core.database (one with a string __file__).
  • Removes a fake/stub core.database and the related src.database state.
  • Do not use as a general database reset fixture.

tests.helpers.import_state.clear_fake_endpoint_resolver_modules

Use only for the guarded fake/stub src.endpoint_resolver cleanup pattern.

  • Preserves real resolver modules (those with a truthy __file__).
  • Evicts fake/stub resolver modules and the dependent route modules that were cached against them.
  • Accepts explicit extra dependent module names to evict alongside the defaults.

tests.helpers.sqlite_db.make_temp_sqlite

Use for the repeated file-backed temp sqlite setup in tests.

  • Only constructs (SessionLocal, engine, tmpfile) from the repeated block.
  • Does not patch modules and does not clean up the temp file.
  • The caller must bind SessionLocal explicitly onto whatever module the code under test reads, and must keep the returned objects alive.
  • Do not use it as a general DB fixture framework.

tests.helpers.db_stubs.make_core_db_stub

Use for small import-time core.database stubs with a placeholder SessionLocal.

  • Pass model names via models when MagicMock attributes are sufficient.
  • Pass attributes when an import needs exact placeholder values.
  • Set install_core_package=True only when the test also needs a fake parent core module stub.
  • Keep custom fake sessions and route-specific database behavior local.

What not to abstract yet

Some remaining patterns should stay as-is for now rather than being forced into helpers:

  • Large mixed files such as security/review regression files.
  • Broad setup-oriented sys.modules stub installers.
  • One-off custom module patching.
  • Custom DB session, route, and app setup.

Validation expectations

Run validation locally before opening or approving a PR. Practical checks:

  • git diff --check - catch whitespace and conflict-marker errors.
  • ./venv/bin/python -m py_compile <changed files> - confirm changed files compile.
  • Focused ./venv/bin/python -m pytest on the changed test files.
  • ./venv/bin/python -m pytest on neighboring or order-sensitive test groups that share import state with the changed files.
  • grep for the old boilerplate when replacing it, to confirm no stragglers remain.
  • A fresh audit worktree when changing the helpers themselves, so stale __pycache__ or import state cannot mask a regression.

Current roadmap

  1. Import-state cleanup - complete.
  2. Document helper conventions (this file).
  3. Pilot the repeated import-time core.database stub helper.
  4. Add further tiny helpers only when the repeated semantics are clear.
  5. Start low-risk file moves only after helper conventions are documented.
  6. Avoid moving high-risk security/route regression files first.