honcho/tests
Tomas Sereikis 083ef01aab fix(llm): keep state-changing tool calls in the order the model asked for
Review on #1100 caught that the previous commit parallelised every tool call in
a turn, mutations included. `ctx.db_lock` makes the mutating handlers take turns
but does not decide whose turn comes first, so two writes from one assistant
turn could apply in an order the model did not request — `tool_results` stayed
ordered while the database did not.

Reads may still overlap freely, because they change nothing. So the loop now
splits the turn: anything named in `mutating_tools` runs one at a time in
request order, everything else runs concurrently alongside it.

`mutating_tools=None` is the default and means "assume every tool mutates",
which is the fully sequential behaviour that existed before this branch. A
caller opts in by naming its mutating set, so no existing caller changes
behaviour by being left alone.

`MUTATING_TOOL_NAMES` lives in agent_tools next to the dispatch table and lists
exactly the five names routing to a handler that takes `ctx.db_lock`:
create_observations, create_observations_deductive,
create_observations_inductive, update_peer_card, delete_observations.
`extract_preferences` and `finish_consolidation` are deliberately absent — both
only return text telling the model what to call next.

Dialectic passes that set rather than a "these are all reads" boolean. Its
loadout is reads today, but DIALECTIC_TOOLS already carries a commented-out
create_observations_deductive, so a flag would have gone quietly wrong the day
someone uncommented it. The parameter is threaded through honcho_llm_call
instead of imported inside src/llm, which keeps the llm layer free of tool
semantics and avoids the existing agent_tools <- dreamer.specialists cycle.

Two tests added: mutating calls are not reordered even when a later call
finishes first, and the default schedule is fully sequential.
2026-08-29 13:38:03 +03:00
..
alembic feat: make session_name nullable for documents and update related SDKs (#347) 2026-01-26 13:33:11 -05:00
bench telemetry: zero-initialize bounded-label metrics so an absent series means a broken scrape (#927) 2026-08-20 10:24:49 -04:00
crud fix: stop top_k=0 from reaching Turbopuffer on message search (#1084) 2026-08-26 17:07:41 -04:00
deriver fix(embedding): truncate in batch embed and return results breakdown (#1019) 2026-08-20 11:42:38 -04:00
dialectic Scopes Phase 2b: `scope` option on chat, representation, context, and search (#897) 2026-08-12 18:34:55 -04:00
dreamer Scopes Phase 2a: scope-kind peers, guardrails, and scopes CRUD routes (#884) 2026-08-12 16:21:40 -04:00
integration feat: defer embedding messages (#704) 2026-06-11 10:31:04 -04:00
live_llm fix(openai): fix content normalization in openai backend history adapter (#1064) 2026-08-26 12:14:32 -04:00
llm fix(llm): keep state-changing tool calls in the order the model asked for 2026-08-29 13:38:03 +03:00
reconciler telemetry: zero-initialize bounded-label metrics so an absent series means a broken scrape (#927) 2026-08-20 10:24:49 -04:00
routes feat: Add workspace-level chat (#931) 2026-08-24 15:54:23 -04:00
scripts feat: add new cloudevents for api routes (#637) 2026-05-20 18:25:30 -04:00
sdk Scopes SDK Changes (#1030) 2026-08-19 10:48:29 -04:00
sdk_typescript add read db (#773) 2026-06-10 13:28:36 -04:00
startup add read db (#773) 2026-06-10 13:28:36 -04:00
telemetry review: fix db_connections_open leak on the detach path; comment/doc polish 2026-08-24 14:37:20 -04:00
unified feat: Add workspace-level chat (#931) 2026-08-24 15:54:23 -04:00
utils fix: stop top_k=0 from reaching Turbopuffer on message search (#1084) 2026-08-26 17:07:41 -04:00
vector_store fix: stop top_k=0 from reaching Turbopuffer on message search (#1084) 2026-08-26 17:07:41 -04:00
webhooks Tighten Transaction Scopes (#525) 2026-04-08 11:14:50 -04:00
__init__.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
conftest.py fix(scopes): scope observer sessions in SQL instead of a fetched name list (#1065) 2026-08-25 13:24:31 -04:00
test_advanced_filters.py fix(filter): make ne on jsonb metadata keys null-safe (#1036) 2026-08-24 09:33:08 -04:00
test_cache_key_namespace.py perf(cache): hash-tag the cache namespace so an instance uses one shard (#1058) 2026-08-25 12:34:42 -04:00
test_cache_redaction.py Scopes Phase 2a: scope-kind peers, guardrails, and scopes CRUD routes (#884) 2026-08-12 16:21:40 -04:00
test_config.py fix(llm): support per-request provider timeouts (#832) 2026-08-04 12:43:00 -04:00
test_datetime_parsing.py Make embeddings configurable (#678) 2026-05-14 15:03:35 -04:00
test_db_resilience.py fix(deriver): increase deriver polling backoff (#1015) 2026-08-14 16:38:20 -04:00
test_dependencies.py add read db (#773) 2026-06-10 13:28:36 -04:00
test_dialectic_prompts.py fix(dialectic): revamp workspace and pair chat system prompts (#1066) 2026-08-25 12:30:06 -04:00
test_generate_jwt_script.py feat: add generate_jwt.py script for creating scoped JWTs (#757) 2026-06-09 13:49:55 -04:00
test_models_vector_dim.py feat: add new cloudevents for api routes (#637) 2026-05-20 18:25:30 -04:00
test_schema_validations.py Align API contract with DB contract for IDs (#684) 2026-05-14 16:37:39 -04:00
test_search.py fix(crud): preserve joined_at for active session peers (#1059) 2026-08-25 10:51:59 -04:00
test_security.py feat: Add workspace-level chat (#931) 2026-08-24 15:54:23 -04:00
test_session_allowlist.py fix(filter): make the filter DSL reject bad input instead of 500ing, and fix negation over unset fields (#947) 2026-08-13 10:39:19 -04:00
test_workspace_chat.py fix(dialectic): revamp workspace and pair chat system prompts (#1066) 2026-08-25 12:30:06 -04:00