Commit Graph
12 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Fable 5 5b141669ce feat(backend): T-4 — named sessions through the boilerroom wrapper
The flavor probe gains a third answer: the wrapper names itself on
/health, so behind OLLAMA_HOST tatlock now distinguishes boilerroom,
a bare llama-server, and Ollama. Through the wrapper each pipeline
phase is a named session with the decided eviction ranking —
tatlock-steward/-orchestrate/-synthesize at 40, librarian at 30,
lower parks sooner (webber will sit at 20; Open WebUI stays
session-less and can never evict anyone). Against a bare llama-server
the raw id_slot pins survive unchanged, Ollama gets neither, and an
unprobed flavor sends nothing rather than guessing — the backend
stays swappable by env alone. tool_choice through the wrapper follows
the llama-server rule, since that is who answers.

The wrapper's balancing and compaction-due signals are read
everywhere: an httpx response hook on the provider covers every
PydanticAI call, streams included, and the steward's raw call reads
the body extras. Acting on compaction_due is a future ticket — the
signal just must not pass silently.

Verified end to end against the live wrapper: the dev server probed
flavor=boilerroom, a full pipeline turn answered in 5.7 s, and
GET /sessions showed all three phase sessions resident at rank 40
with engine-reported occupancies. The demonstration also filled the
production slot map — session-less prod delegations would have 503d
— cleared by a wrapper restart and filed as boilerroom T-11 (sessions
need an exit). A latent test flaw surfaced too: the ollama
tool_choice test relied on the dev backend probing as ollama; it now
pins the flavor it claims to test.

27 selector tests (9 new), 677 total green; three mutations shown to
fail their tests (librarian rank, the wrapper branch, the no-nudge
set); the new wrapper contract class runs 10/10 against the live
boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-12 16:13:29 +02:00
jpmschweitzerandClaude Fable 5 23217bdb26 feat(backend): BACKEND_SLOT_PINNING — per-phase engine slot ownership
Each pipeline phase owns one llama-server slot (steward 0, orchestrator
1, synthesizer 2), carried as id_slot in extra_body through the same
mechanism tool_choice already uses, so the phase's stable prompt prefix
stays in that slot's KV cache and a turn re-prefills only its new
tokens. Off by default; a no-op on the Claude backend and ignored by
Ollama, so the flag is safe on any backend and the cutover itself stays
a pure env swap.

The merge helper preserves existing extra_body keys — mutation-checked
(dropping the merge fails exactly the test written for it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-11 22:25:53 +02:00
jpmschweitzerandClaude Fable 5 16b7edbc26 refactor(backend): speak only OpenAI-compat /v1 to the local backend
Three native-API touchpoints converted — steward /api/generate to
/v1/chat/completions, embeddings /api/embeddings to /v1/embeddings,
health /api/tags to /v1/models — so the backend behind OLLAMA_HOST is
swappable by env alone. This makes the serving plan's "tatlock needs
zero changes" claim true for the llama-server cutover and for forge
after it. EMBEDDING_HOST (default: OLLAMA_HOST) lets gen and embed
point at different servers, which the boilerroom stack needs.

The dead OllamaClient goes with it: a native-API client nothing
imported, whose presence would make the post-cutover "no native
endpoints" grep lie.

Contract tests rewritten to mirror the new requests and extended with
the embeddings shape (dim must match the configured Qdrant dimension).
All pass against live Ollama's /v1 — deployable before any cutover.
Both new assertions mutation-checked via env overrides (bogus model,
wrong dim: each fails). The Anthropic contract now skips on 401: the
configured key is deliberately revoked per workspace D-11, which is
"fallback disabled", not a boundary break. Embedding continuity across
backends was measured separately: same nomic bytes, cosine 1.0000.

663 unit tests pass; ruff clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-11 21:35:48 +02:00
jpmschweitzerandClaude eabf0f4a11 chore(types): annotate fifteen signatures mypy could not check
Twelve gain `-> None`, each confirmed by AST to contain no returning
`return` and no `yield` rather than by reading the name and assuming.
The three context-manager exits gain the canonical
type[BaseException]/BaseException/TracebackType argument triple.

Both files taking TracebackType needed the import, and inserting it
before the first import broke ruff's I001 — lint was exit 0 at the
baseline commit, verified by stashing this work and re-running, so that
breakage was mine. Fixed with `ruff check --fix` on the two files, which
placed the import in sorted position.

86 errors -> 75; no-untyped-def 29 -> 14.

Suite: 658 passed. The baseline was 657 passed with one failure in
test_tatlock_tool_call_logging_calculator, which asserts on the content
of a live model's reply. It passing here is nondeterminism, NOT evidence
this commit fixed anything, and it may fail again on the next run.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-20 00:18:35 +02:00
jpmschweitzerandClaude 78066fab1b style: apply ruff's automatic fixes and formatter
Mechanical only, and separated from the judgment calls that follow so the
reviewable changes are not buried in a 98-file whitespace diff.

227 automatic fixes: 60 blank lines carrying whitespace, 60 unsorted import
blocks, 34 Optional[X] to X | None, 28 unused imports, 16 deprecated typing
imports, 12 datetime.timezone.utc to datetime.UTC, and assorted smaller
modernisations. Then `ruff format` over src and tests: 98 files reformatted,
35 already conforming.

No file among the unused-import findings defines __all__ or is an __init__.py,
so nothing here removes a re-export.

`make test`: 658 passed, unchanged from HEAD.

Two things observed while verifying, neither addressed here:

`pytest tests/` cannot collect — tests/e2e/test_orchestration_e2e.py uses an
`e2e` marker that is not registered, and the config is strict about markers.
This fails identically at HEAD, so it predates this change; `make test` passes
because it ignores tests/e2e, tests/integration and tests/contracts.

test_tatlock_tool_call_logging_calculator is flaky. It failed once in a full run
with these changes and passed on the next, passes in isolation with them, and
fails in isolation at HEAD. It is order- or timing-dependent, not a regression
from this commit — established by running the full suite both ways rather than
by reasoning about which change could have caused it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-11 17:25:18 +02:00
jpmschweitzerandClaude Fable 5 033a1c01e8 feat: make Ollama/gemma4 the primary backend with Claude as fallback
Rolls back the claudification backend preference: PREFER_CLOUD_BACKEND now
defaults to false, resolve_backend() picks Ollama first and uses Claude when
explicitly preferred or when the new Ollama startup health check fails. The
Steward retries mid-request failures on the other backend in both directions.

Also hardens the fallback itself: Anthropic SDK imports are lazy so a broken
anthropic package degrades to Ollama-only instead of crashing at import time
(root cause of the production outage since April), anthropic is pinned to a
pydantic-ai-1.27-compatible range, ANTHROPIC_MODEL defaults to claude-sonnet-5
(sonnet-4-20250514 retired 2026-06-15), sampling parameters are stripped from
Claude calls (Sonnet 5 rejects them), and the Steward timeout is configurable
(STEWARD_TIMEOUT, default 60s) since gemma4 needs ~35s warm for analysis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 18:35:53 +02:00
jpmschweitzerandClaude Opus 4.5 496f37a538 feat: add Claude backend with automatic Ollama fallback (Claudification Phase 1)
Build and Push / release (release) Failing after 6s
Build and Push / build (release) Successful in 3m5s
All agents now prefer Claude API when ANTHROPIC_API_KEY is configured,
with automatic fallback to Ollama when offline or unconfigured. New
src/anthropic/ module provides model selection via get_model() factory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 07:19:29 +01:00
jpmschweitzerandClaude Opus 4.5 62eac3eb61 feat: integrate Paperless documents and volatile cache into Librarian
Build and Push / build (release) Successful in 54s
- Add Paperless document search to HybridRAG pipeline
- Add volatile cache (weather, forecast, news, stocks) to HybridRAG
- Add include_documents and include_volatile params to hybrid_search
- Add 📑 and ⚡ icons for document/volatile sources
- Update Librarian prompt with new data source awareness
- Fix Biographer routing: personal memory queries now route correctly
- Add location keywords to Steward pre-fetch logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:31:23 +01:00
jpmschweitzerandClaude Opus 4.5 74f47097c2 fix: complete web search integration with query enrichment
Build and Push / build (release) Successful in 52s
Fixes several issues with the web search migration to Librarian:

- Update Steward routing guidelines for web search/weather → Librarian
- Register search_web, read_url, read_urls_batch tools with Librarian agent
- Update Librarian system prompt with web search documentation
- Fix query enrichment not being passed to delegations (location context)
- Add URL reading keywords to RESEARCH action type detection

Weather queries now automatically include user's stored location from
the Biographer, enabling location-aware search results.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 22:51:18 +01:00
jpmschweitzerandClaude Opus 4.5 6cc0bd78b2 feat: update Steward prompt for clearer delegation instructions
Updates Steward's output format to structured delegation format:
- DELEGATE: [capability] to [action] [task]
- REASON: [explanation]
- COMPLEXITY: [simple/moderate/complex]
- CONTEXT: [relevant history or "none"]

Also adds guidance for conversation memory queries (handled by
Tatlock directly, not delegated to Librarian).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 12:46:51 +01:00
jpmschweitzerandClaude Opus 4.5 4efa717796 fix: improve Steward delegation instructions for Librarian
Build and Push / build (release) Successful in 10s
- Update Librarian capability description to highlight CREATE/UPDATE/SEARCH
- Add specific Steward guidelines for wiki creation, updates, and research
- Add dynamic time injection to user prompts for temporal awareness
- Expand domains to include 'create', 'write', 'update'
- Update test to match new capability description

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 21:55:17 +01:00
jpmschweitzerandClaude Sonnet 4.5 6eed5f4d13 feat: implement Phase 2 two-tier architecture with Steward
Add comprehensive two-tier architecture where Steward analyzes requests
and Tatlock executes with scoped tools. Includes full infrastructure for
request preprocessing, tool tracking, benchmarking, and streaming.

**Added:**
- Steward agent for request analysis and capability recommendation
- Household Registry for centralized capability management
- Request preprocessing pipeline (Steward → Tatlock flow)
- Tool usage tracking and benchmarking system
- Streaming transparency (Steward reasoning visible in streams)
- Structured logging with operation timing
- Redis benchmark storage with 30-day expiry
- Benchmark analysis CLI tools

**Infrastructure:**
- src/agents/steward/ - Steward agent implementation
- src/agents/tatlock_core/ - Tatlock capability domain
- src/core/preprocessing.py - Request preprocessing pipeline
- src/core/tool_tracking.py - Tool call tracking
- src/core/benchmarks.py - Benchmark recording system
- src/core/household_registry.py - Capability registry
- src/core/startup.py - Application startup coordination
- src/core/logging_config.py - Structured logging setup

**Integration:**
- Responses API uses Steward for Tatlock requests
- Chat Completions wraps Responses API for OpenAI compatibility
- Streaming coordinator supports Steward + Tatlock flow
- Tool scoping per request based on Steward recommendations

**Testing:**
- Integration tests for Steward-Tatlock flow
- Benchmark and registry unit tests
- Steward streaming tests

See PHASE2_PLAN.md and PHASE2_COMPLETE.md for detailed documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 15:39:20 +01:00