Files
openhuman/docs/tinyagents-migration-plan-2026-07-22.md

32 KiB
Raw Permalink Blame History

TinyAgents Migration — Current-State Audit & Consolidated Plan (2026-07-22)

Status: audit + plan (supersedes the stale status/phasing in tinyagents-port-plan.md, tinyagents-inference-migration-plan.md, and tinyagents-phase3-router-registry-design.md; the drift ledger tinyagents-drift-ledger.md remains the row-level ledger but its anchors are behind — see §2). Scope: move the remaining generic inference + agent-framework code from src/openhuman/ down into the vendored tinyagents crate (vendor/tinyagents), delete the in-tree duplicates, migrate/retire the affected tests, and clean up every dangling doc/code reference left behind by earlier phases. Method: fresh four-way audit of (1) the crate surface, (2) src/openhuman/inference/, (3) the agent domains + the src/openhuman/tinyagents/ seam, (4) the existing docs/tests — all against the working tree at main (5b8a9f269, 2026-07-22).

Execution status: active on feat/tinyagents-provider-cleanup. WP-0 discovered and corrected an additional cross-crate constraint: once the vendored manifest honestly reports 2.1, tinyflows must also require TinyAgents 2.1 or Cargo resolves a second 1.9 copy and splits trait identity. The deletion ledger is tinyagents-full-migration-plan/99-deletion-ledger.md.


1. Executive summary

The migration is much further along than any existing doc records, and the remaining work is now well-bounded:

  • The agent loop has run on tinyagents since #4249/#4399; the drift ledger's Phase 0 rows are all CLOSED and Phase 1 is mostly closed.
  • Since the docs were last touched, PRs #4769, #4780, #4782, #4783, #4784 landed the model-layer inversion: the managed backend, wire-equivalent BYOK slugs, and openai/codex/custom slugs are all crate-native ChatModels; the crate ModelRouter is adopted; and compatible*.rs is already deleted (collapsed into a single legacy_provider.rs facade).
  • What remains falls into six work packages (§5): finish the model-layer cutover and delete the legacy Provider stack (~910k LOC); record that the legacy run_turn_engine was already retired; consolidate routing/, tool_timeout/, tool_status/, model_council/ onto crate primitives; reconcile the tool model (the one genuinely design-gated package); shrink the seam; and a housekeeping package (version-pin reconciliation + broken-link cleanup) that should go first because the current pin state is misleading.

Nothing in this plan touches the CEF shell, the frontend, or the compile-time feature gates; the crate stays impossible to gate away (26+ domains consume it).


2. Ground truth: version pins (WP-0 reconciled)

Fact Value Where
Host requirement tinyagents = { version = "2.1", features = ["sqlite"] } root Cargo.toml:107
Path override [patch.crates-io] tinyagents = { path = "vendor/tinyagents" } Cargo.toml:677
Historical fork patch Removed in WP-0; TinyCortex now declares crates.io 2.1, so the existing host path patch unifies its dependency too root and Tauri manifests; TinyCortex #121
Vendored crate version = "2.1.0", tag v2.1.0 / 2583fcc, edition 2024, GPL-3.0-only vendor/tinyagents/Cargo.toml, gitlink
Included since the audit bytes bump (#59), BarrierRelief graph fan-in primitive (#62), v2.0/v2.1 release commits submodule history
TinyFlows requirement tinyagents = "2.1"; prevents Cargo resolving a second 1.9 crate vendor/tinyflows/Cargo.toml
TinyCortex requirement tinyagents = "2.1"; its repo-local patch serves standalone development while host patches select the canonical copy vendor/tinycortex/Cargo.toml
Drift ledger Current pin v2.1.0 / 2583fcc docs/tinyagents-drift-ledger.md §Anchors

WP-0 bumped the gitlink to the released v2.1.0 manifest, regenerated both Cargo worlds, removed the unused fork-source patch, and aligned TinyFlows and TinyCortex to 2.1. Before those transitive alignments, correct dependency resolution introduced separate TinyAgents 1.9 and nested-path 2.0 packages; the lockfiles now prove the root, TinyFlows, and TinyCortex all use the one vendored 2.1 package.


3. What the crate ships (v2.1.0)

Full module map from the crate audit; the items relevant to the remaining work:

  • Model layer: harness::model::{ChatModel<State>, ModelRegistry, ProviderError} (vendor/tinyagents/src/harness/model/types.rs:524,563,450), MODEL_CONTEXT_PATTERNS context-window table (model/mod.rs:51).
  • OpenAI-compatible client: harness::providers::openai::{OpenAiModel, AuthStyle, ReasoningTagExtraction} with SSE streaming, the /v1/responses API + codex knobs (#51), configurable auth styles/static headers (#44), temperature suppression (#47), merge_system_into_user (#48), prompt-guided tool calling for non-native models (#55), stream→JSON fallback (#56), and the whole #57 local-model hardening wave (inline <think> extraction, 400-degrade of tool_choice/json_object, malformed tool-call recovery). This is the replacement for everything legacy_provider.rs still does.
  • Retry/fallback/error classification: harness::retry::{RetryPolicy, FallbackPolicy, ProviderFailureClass, classify_provider_failure, is_retryable} (harness/retry/types.rs:28, retry/mod.rs:170,396) — already wired into the crate's transport and SSE paths.
  • Routing: registry::router::{ModelRouter, WorkloadRoute} (#54) — adopted host-side by #4783; plus registry::catalog::ModelCatalog (windows, pricing, capability flags, offline snapshot at docs/modules/registry/model-catalog.snapshot.json).
  • Tools: harness::tool::{Tool<State>, ToolSchema} + schema validation (harness/tool/types.rs:344, tool/schema.rs), ToolTimeout, tool-policy middleware (harness/middleware/library/tool_policy.rs).
  • Subagents/orchestration: harness::subagent::{SubAgent, SubAgentSession, SubAgentTool}, graph::orchestration::{TaskStore, SteeringRegistry, OrchestrationTool, InMemoryTaskStore, JsonlTaskStore}, graph::subagent_node, graph::parallel::map_reduce, and (post-bump) BarrierRelief fan-in.
  • Embeddings: provider implementations ported at HEAD (#58 — openai, cohere, voyage, ollama, cloud, rate-limit/retry-after helpers).
  • Observability: harness + graph journals/status stores, JsonlSink, RedactingSink, Langfuse client with nested run trees (#53).
  • Also present: summarization (Summarizer, CompressionFailurePolicy), steering, workspace isolation, response cache, cost/usage accounting (parses cached_tokens), graph checkpointing (SQLite via the sqlite feature the host enables), and offline MockModel/testkit conventions.

~25 public traits are the extension points; the seam already implements 11 of them (§4.3).


4. Audit: what remains host-side

4.1 src/openhuman/inference/ — 112 files, ~46.5k LOC

The model-layer inversion (#4727 "Motion B") is scaffolded and mostly cut over, but the legacy Provider stack is still present and still the default construction path in places:

Still-duplicating cluster (delete in WP-1):

File LOC State
provider/traits.rs (+traits_tests.rs) 779 + 501 The Provider trait + ChatMessage/ChatRequest/ChatResponse/ProviderDelta/UsageInfo. Still central; ~10 impls remain.
provider/reliable.rs (+reliable_tests.rs) 952 + 1,228 Retry/backoff Provider wrapper. Crate RetryPolicy covers it; the interactive turn path already stopped wrapping in ReliableProvider (tinyagents/mod.rs:122).
provider/router.rs (+router_tests.rs) 310 + 524 RouterProvider hint-table routing. Crate ModelRouter adopted by #4783; this is the residual legacy path.
provider/legacy_provider.rs 343 The collapsed remnant of the 15 compatible*.rs files (provider/mod.rs:14 aliases pub use legacy_provider as compatible;). Superseded by crate OpenAiModel once WP-1 flips the default.
provider/error_classify.rs + error_code.rs 1,001 + 349 Split (WP-1): generic retryability/status classification → crate classify_provider_failure; openhuman semantics (Sentry demotion, budget messaging, config_rejection.rs, billing_error.rs) stay as a host classifier layered on crate errors.
provider/crate_provider.rs 327 CrateBackedProvider — the temporary reverse adapter (crate ChatModel → legacy Provider). Deleted last, when no consumer needs Provider.

Crate-native scaffolding already in place (finish in WP-1):

  • provider/crate_openai.rs (347) — host AuthStyle → crate OpenAiModel builder; self-described "Status: scaffolding" — complete and unit-tested but not yet the factory default. Flipping it (with per-provider wire parity validation) is the gating step.
  • provider/openhuman_backend_model.rs (325) — managed backend as crate ChatModel (cut over; coexists with the legacy openhuman_backend.rs twin, which can go once nothing constructs it).
  • provider/factory.rs (2,850) — the host↔crate boundary; already returns Arc<dyn ChatModel<()>> via create_chat_model*, but bespoke slugs still route "→ a ProviderModel over the host provider" (factory.rs:1458-1511).
  • model_context.rs — already falls through to the crate table (context_window_for_model_id, model_context.rs:77); keeps host config overrides. Done; keep the thin shim.
  • ops.rs, local/ops.rs, http/server.rs already build crate ModelRequest/Message types.

Seam concerns mis-housed under provider/ (re-home in WP-1): temperature.rs (261), thread_context.rs (120), resolved_route.rs (113), auth_error_registry.rs (166).

Host-owned, stays (no action): all of local/ (~14k — Ollama/LM Studio/ Whisper/Piper runtime + installers + service admin), voice/ (~2.4k), openai_oauth/ (~1.5k), http/ (0.7k /v1 server), provider/ops/ (RPC), bespoke Provider/ChatModel impls (claude_code/ ~2.7k, claude_agent_sdk/, openai_codex.rs, openhuman_backend*.rs), and the root host files (schemas.rs, presets.rs, model_ids.rs, paths.rs, parse.rs, sentiment.rs, device.rs).

Blast radius: 187 files import openhuman::inference; 158 import inference::provider (grown from the old plan's 170/151). Top consumers: agent/harness/session/tests.rs (33 hits), core/observability.rs (31), tinyagents/mod.rs (15), web_chat/web_errors.rs, routing/factory.rs, agent/harness/subagent_runner/ops/{graph,runner}.rs, voice/, flows/ops.rs, config/ops/model.rs, channels/context.rs.

4.2 Agent domains

Domain Files / LOC Disposition
agent/ 144 / 66.9k Mostly stays (product brain). 37 files already crate-backed. WP-3 verified that session/turn/core.rs is the product turn-preparation shell and subagent_runner/ops/graph.rs unconditionally calls run_turn_via_tinyagents_shared; the legacy loops and runtime escape hatches were removed before this audit. Heaviest coupling in the tree (config=31, memory=20, event_bus=13 files).
agent_orchestration/ 64 / 27.9k Engine already on tinyagents::graph (workflow runs, teams, delegation, map_reduce); what remains is the product layer (ledgers, RPC). Residual upstream item: detached-subagent TaskStore lifecycle — WP-5. 25 files crate-backed.
routing/ 8 / 2.7k Deleted in WP-2. A repository-wide reference audit found no consumer outside the module; #4783's crate ModelRouter already owns the live path, so retaining the nominally host-specific health/provider files would preserve an unreachable parallel stack.
model_council/ + council_registry/ 8 / 1.7k Deleted after WP-2 audit. Generic fan-out already used crate parallel::map_reduce; upstream dead-code cleanup removed the remaining unreachable product and registry surfaces.
tool_timeout/ 1 / 316 HOST-OWNED. TinyAgents harness::tool::ToolTimeout is declarative per-tool metadata; it has no process-global value to receive OpenHuman config. This module owns UI/config + env precedence and the actual tokio::time::timeout deadline used by the host-tool adapter — WP-2 audit closed.
tool_status/ 3 / 0.7k HOST-OWNED. Its serialized UI/persistence taxonomy, OpenHuman security markers, retry categories, and user-facing remediation copy are product semantics. TinyAgents tool outcomes remain the generic execution input — WP-2 audit closed.
tools/ 98 / 40.9k The Tool trait + ToolSpec mechanics (traits.rs:255), schema.rs, policy.rs, orchestrator_tools.rs, user_filter.rs are framework-shaped; all of tools/impl/* + RPC (schemas.rs 985, ops.rs 1,407) are product. Design-gated (port-plan §2 blockers still apply) — WP-4. Note: ToolResult/ToolContent are re-exported from skills::types (~236 consumer files) — moving those types is the highest-blast-radius single step in the whole migration and must be its own slice. Security coupling: 49 files.
tool_registry/ 7 / 1.8k Read-only cross-surface discovery + RPC. Stays.
agent_registry/, agent_experience/, agent_memory/, agent_tool_policy/, agentbox/, orchestration/ All host/product (definitions-as-data, RPC controllers, marketplace HTTP, remote-brain client — orchestration/ talks to the hosted backend, not the local crate). Stay. agent_tool_policy overlaps crate tool_policy middleware mechanically but encodes host channel-permission policy — stays, mechanism may thin post-WP-4.

4.3 The seam — src/openhuman/tinyagents/ (25 files, ~17.1k LOC)

The seam is healthy: 23/25 files use the crate; it implements Middleware (13×), ToolMiddleware (4×), ModelMiddleware (3×), ChatModel (2×), Summarizer, Tool, EventListener (2×), PayloadSummarizer, HarnessStatusStore, EmbeddingModel, and GraphEventSink. Post-migration it shrinks but remains host-owned. Specific shrink targets:

  • model.rs: ProviderModel is deleted. The former convert.rs was split: tool-schema conversion remains as the 34-line WP-4 seam, while durable-message conversion moved to agent/message_convert.rs. The execution audit found that ChatMessage is OpenHuman's versioned JSONL/thread persistence record (including message ids and product metadata), not a duplicate provider request type; replacing it directly with the crate enum would change existing on-disk data.
  • middleware.rs (4,702): the WP-5 audit records all 18 concrete types found at audit time (the tool-exposure shadow was added after the 17-type snapshot) in docs/tinyagents-drift-ledger.md. SchemaGuard is now deleted in favor of TinyAgents 2.1 InvalidArgsPolicy::ReturnToolError, leaving 17. ArgRecovery overlaps crate #45/#71 normalization. RepeatProgress now uses the merged #72 crate tracker; only the thin OpenHuman signature/exemption and halt-projection adapter remains. Upstream the generic ones; host-policy ones (ApprovalSecurity, CredentialScrub, CliRpcOnly, MemoryProtocol, CostBudget) stay — WP-5.
  • routes.rs UsageCarry/FallbackObserver thin out as usage/fallback become fully crate-native.

4.4 Broken/dangling references (resolved in WP-0)

WP-0 retargeted SDK-gap references to vendor/tinyagents/docs/sdk-gaps.md, made the provider schema src/openhuman/config/schema/cloud_providers.rs authoritative, created docs/tinyagents-full-migration-plan/99-deletion-ledger.md, replaced the phantom numbered-plan links with this plan's WP-5/C4 sections, and retargeted the TinyCortex analogy to this current audit. The three historical plans now carry explicit superseded banners.

4.5 Test inventory (what moves, dies, or stays)

  • Dies with WP-1 (bound to the legacy Provider stack): provider/traits_tests.rs (501), reliable_tests.rs (1,228), router_tests.rs (524) — these define 10+ mock impl Provider doubles. factory_tests.rs (3,149) shrinks and retargets to ChatModel construction. In tests/raw_coverage/: the three inference_compatible_* files (~2.2k LOC) are pinned to the deleted wire client — retire or rewrite the still- meaningful assertions against OpenAiModel via wiremock.
  • Retargets: tests/inference_provider_e2e.rs (568, wiremock-based — OpenAI-compat chat/streaming, Anthropic auth headers, temperature suppression, Ollama /v1) — keep the scenarios, point them at the crate- native factory path; these become the wire-parity gate for flipping the default.
  • Moves upstream (as crate tests, offline MockModel convention): parity coverage for anything upstreamed in WP-2/WP-5 (routing policy/quality, council graph, middleware behaviors). The crate's CI is fmt → clippy (-D warnings, both feature sets) → build → cargo test + --all-features, no network.
  • Stays host-side: seam tests (tinyagents/tests.rs 799 + 19 inline), tests/agent_harness_e2e.rs (130 KB), tests/json_rpc_e2e.rs (576 KB), agentbox_e2e, orchestration_*, embeddings_rpc_e2e, ollama_lifecycle_e2e, openai_oauth/flow_tests.rs, all local/*_tests, and the raw_coverage family except the compatible trio.
  • Runner impact: scripts/test-rust-with-mock.sh:52 had a stale comment advertising removed OPENHUMAN_AGENT_GRAPH_* escape hatches. WP-3 removes that documentation; the runner behavior itself was already crate-only.

5. The plan — six work packages

Ordering rationale: WP-0 is pure hygiene and unblocks honest review of everything else; WP-1 is the largest deletion and already 80% scaffolded; WP-2/WP-3 are independent of each other and of WP-1's tail; WP-4 is the only design-gated package; WP-5 is opportunistic shrink; WP-6 is the exit gate. Every WP follows the repo's standing rules: failing-before/passing-after regression tests, small validated commits on a feature branch per submodule, drift-ledger rows updated before deletions (the ledger's gate rule stays in force).

WP-0 — Version + docs housekeeping (no behavior change)

  1. Bump vendor/tinyagents submodule to tag v2.1.0 (fast-forward; picks up BarrierRelief #62 and the bytes bump). Regenerate root and app/src-tauri lockfiles. cargo check both worlds + the slim disabled build (--no-default-features --features tokenjuice-treesitter) per repo convention.
  2. Update tinyagents-drift-ledger.md Anchors (pin row → v2.1.0; add rows closing out #4780/#4782/#4783/#4784 which the ledger still lists as pending/deferred; mark the Phase-3 "compatible*.rs remains" text CLOSED).
  3. Stamp superseded-by banners on tinyagents-port-plan.md, tinyagents-inference-migration-plan.md, tinyagents-phase3-router-registry-design.md pointing here (keep them — their disposition tables and gap lists are still the reference detail).
  4. Fix the §4.4 broken references, create the deletion ledger, and replace the phantom numbered-plan references with real WP-5/C4 anchors.
  5. Remove the stale fork-source patch after verifying that no dependency uses it. Align TinyCortex's nested path dependency through a crates.io 2.1 declaration plus its repo-local development patch, so the host's canonical path patch produces one trait identity (TinyCortex #121).

Exit: Cargo.toml, submodule, lockfiles, and ledger all agree on one version; zero dangling docs/tinyagents* references (grep -rn clean).

WP-1 — Finish the model-layer cutover; delete the legacy Provider stack

The continuation of #4727 Motion B / drift-ledger P1-8/P1-9. Slices:

  1. Flip the factory default to crate_openai.rs construction for every OpenAI-compatible slug. Gate: the retargeted inference_provider_e2e.rs wire-parity suite (§4.5) green against the crate path, per provider family (managed, BYOK, ollama/lm-studio local, codex/responses).
  2. Route bespoke providers as ChatModelsclaude_code, claude_agent_sdk, openai_codex, openhuman_backend get direct ChatModel impls (the pattern openhuman_backend_model.rs already proves), removing the last factory.rs:1458-1511 ProviderModel wraps. Delete the legacy openhuman_backend.rs twin when nothing constructs it.
  3. Error-taxonomy split: generic classification call sites move to crate classify_provider_failure/ProviderError; error_classify.rs shrinks to the openhuman-semantic layer (config_rejection, billing_error, Sentry demotion). Upstream any status codes the crate misclassifies (drift-ledger rows, then crate PR + version bump).
  4. Delete, in dependency order: router.rsreliable.rslegacy_provider.rs (+ the as compatible alias in provider/mod.rs:14) → provider/traits.rs → seam ProviderModel/MaxTokensModel (tinyagents/model.rs) → the reverse adapter crate_provider.rs last. Re-home the durable transcript adapter beside the agent persistence DTO; retain only tool-schema conversion in the seam until WP-4. Each deletion is its own commit with its test fallout (§4.5) handled in the same commit.
  5. Consumer sweep: migrate the 187 importing files to crate types (Message, ModelRequest, Usage, TinyAgentsError). Mechanical for most; the hot spots are core/observability.rs, web_chat/web_errors.rs, voice/, flows/ops.rs, config/ops/model.rs.
  6. Re-home temperature.rs, thread_context.rs, resolved_route.rs, auth_error_registry.rs out of provider/ into the seam (or the factory module) so provider/ ends as: factory + bespoke models + ops/RPC.

Exit criteria: no impl Provider anywhere; grep -rn "ProviderModel" src/ empty; inference/provider/ ≤ ~8k LOC (from ~15.9k + tests); inference_provider_e2e + agent_harness_e2e + full scripts/test-rust-with-mock.sh green. Estimated net deletion: ~910k LOC (code + dead tests).

WP-2 — Consolidate parallel implementations onto crate primitives

Independent, individually shippable slices:

  1. routing/registry::router — complete by deletion. The execution audit found the entire module self-contained: no production or test caller outside routing/ constructed its provider or consumed its health signals. #4783's crate ModelRouter already owns live workload routing, so WP-2 removed the unreachable parallel stack and its self-tests.
  2. tool_timeout/ — HOST-OWNED (audit closed). The similarly named crate ToolTimeout is per-tool policy metadata, not a global timeout store or executor. OpenHuman must retain config/env precedence, live UI updates, seconds clamping, grace handling, and the adapter's hard deadline. The seam already projects host policy into crate ToolRuntime; there is no duplicate crate implementation to delete.
  3. model_council/ — complete by deletion. Generic member fan-out already ran through tinyagents::graph::parallel::map_reduce; upstream dead-code cleanup removed the remaining unreachable council and registry product surfaces.
  4. tool_status/ — HOST-OWNED (audit closed). The classifier is tied to OpenHuman security markers, serialized thread/UI types, retry categories, localized-copy keys, and remediation language. TinyAgents owns generic tool outcomes; mapping those outcomes into product status remains in the host.

Exit: complete. routing/, model_council/, and council_registry/ are deleted; timeout and status are explicitly HOST-OWNED. Ledger rows record the audit evidence.

WP-3 — Retire the legacy turn engine

Audit result: complete before this plan was written. The filenames cited by the initial audit survived, but their legacy engines did not:

  1. session/turn/core.rs performs OpenHuman turn preparation and calls the TinyAgents session path; it contains no run_turn_engine definition.
  2. subagent_runner/ops/graph.rs documents the removed run_inner_loop / run_turn_engine and unconditionally calls run_turn_via_tinyagents_shared.
  3. No runtime or test code reads OPENHUMAN_AGENT_GRAPH_*; only this plan and a stale test-runner comment mentioned those names. The stale comment is now removed.

Exit satisfied: one TinyAgents turn engine; source and scripts contain no OPENHUMAN_AGENT_GRAPH_* reference. Historical/parity comments mentioning the former engine remain intentionally as provenance, not executable branches.

WP-4 — Tool-model reconciliation (design-gated; do not start on autopilot)

The openhuman Tool trait (tools/traits.rs:255) vs crate Tool<State> unification. The port-plan §2 design blockers still stand, plus two audited constraints:

  • ToolResult/ToolContent live in skills::types as the deliberately ungated type carve-out consumed by ~236 files (MCP, runtime_node, every Tool impl). Any move must preserve that carve-out property (inert, dep-free, compiled in all feature combinations) — either the types move into the crate and skills::types re-exports them, or they stay and the crate bridge continues via SharedToolAdapter.
  • tools/ has the tree's heaviest security coupling (49 files) — execution gating (classify_command, approval, sandbox) must stay host-side regardless of where the trait lives.

Recommended shape: a short design doc (successor to the port-plan §2 list) deciding (a) trait unification vs permanent adapter, (b) the ToolResult/ToolContent home, (c) ToolScope::AgentOnly gating (deferred "Phase 2" per traits.rs:14-19) — then slices. Until then, the SharedToolAdapter seam is cheap and correct; do not delete it prematurely.

The proposed decision is recorded in tinyagents-tool-model-decision-2026-07-23.md. It selects a permanent ownership-boundary adapter, keeps the host's structured result types in the always-compiled carve-out while preserving them through TinyAgents raw, and defines the required scope-enforcement matrix. WP-4 code changes remain gated on explicit approval of that proposal.

WP-5 — Seam shrink + orchestration lifecycle upstreaming

  1. Middleware audit (§4.3): per-middleware ledger rows; SchemaGuard is deleted through the existing crate invalid-args policy. TinyAgents #72 is merged and RepeatProgress now delegates generic streak accounting to the crate SuccessfulRepeatTracker; the host duplicate guard and thresholds are deleted, while the thin product adapter remains. ArgRecovery still awaits the #71 crate equivalent; keep host-policy middlewares.
  2. Detached-subagent lifecycle: move the generic detached-run registry mechanics (agent_orchestration/running_subagents.rs, subagent_control.rs) onto crate TaskStore/SteeringRegistry fully; host keeps ledgers + RPC. This restores the lifecycle consolidation intent recorded by the earlier audit without relying on a phantom design doc. Cutover implemented: TinyAgents PR #75 adds the generic ownership-aware DetachedTaskRegistry; OpenHuman now delegates snapshots, waits, steering lookup, cancellation/abort, terminal sweeping, and lock-error handling to it. The host retains durable TaskStore projection, product metadata, RPC, and the RunQueue compatibility fallback. All 17 focused running_subagents tests pass. TinyAgents #75 merged as d548657, and the canonical vendored pointer 4358efe includes it, closing the generic lifecycle cutover.
  3. Finish the C4 journal-progress-parity plan (S2S6): journal-backed progress projection, then delete agent/progress_tracing.rs (1,272) + progress_tracing/langfuse.rs (825) in favor of crate observability — respecting the recorded S2a replayability blocker.

WP-6 — Exit gate

  • Full suite: scripts/test-rust-with-mock.sh (all targets incl. raw_coverage_all), cargo test --all-features in vendor/tinyagents, slim disabled build + cargo test --lib --no-default-features --features tokenjuice-treesitter core:: (repo standing rule), pnpm rust:check.
  • Deletion ledger totals reconciled against the port-plan's projection (~30k deleted / ~1215k upstreamed).
  • Docs: inference/README.md, gitbooks/developing/architecture/ {agent-harness,orchestration,flows-on-tinyagents}.md updated to the post-cutover reality; drift ledger phases marked CLOSED; this plan stamped done.

6. Risks and standing gotchas

  • Wire parity is the whole risk in WP-1. The legacy client accumulated provider quirks for years; the crate's #44#57 wave was built to match them, but the flip must be gated on the wiremock parity suite per provider family, not on unit tests. Keep CrateBackedProvider as the rollback seam until the parity suite has soaked on main.
  • GPL/crates.io boundary: tinyagents is publicly redistributed — only genuinely generic code moves down; no product policy, backend phrasing as API, or key material (port-plan rule, still in force).
  • Usage fidelity (old gap G1): verify crate Usage carries the USD/cached-token fields the cost tracker needs before deleting UsageInfo; routes.rs UsageCarry is the current compensator.
  • RUST_MIN_STACK=16777216 in the mock runner exists because of the subagent runner's large futures — deep-graph changes in WP-3/WP-5 can resurface stack overflows on Apple Silicon (see composio_list_tools_stack_overflow_regression test).
  • Whisper/GGML on Apple Silicon: any cargo validation of the root crate locally needs GGML_NATIVE=OFF (unrelated to this migration but will bite every WP's validation loop).
  • Two Cargo worlds: every vendor bump must update both the root and app/src-tauri lockfiles (until the workspace convergence tracked in #3877).

7. Quick reference — disposition of every audited module

Module Verdict
inference/provider/{traits,reliable,router,legacy_provider,crate_provider}.rs DELETE (WP-1)
inference/provider/{error_classify,error_code}.rs SPLIT: generic → crate; host semantics stay (WP-1)
inference/provider/{crate_openai,openhuman_backend_model,factory}.rs KEEP — becomes the host↔crate boundary (WP-1 finishes)
inference/provider/{temperature,thread_context,resolved_route,auth_error_registry}.rs RE-HOME to seam (WP-1)
inference/{local,voice,http,openai_oauth}/, provider/ops/, bespoke providers, root host files STAYS
tinyagents/model.rs (ProviderModel) DELETED (WP-1)
tinyagents/convert.rs message layer RE-HOMED to agent/message_convert.rs; durable JSONL/thread compatibility is product-owned. Tool-schema conversion remains for WP-4.
tinyagents/middleware.rs generic middlewares UPSTREAM case-by-case (WP-5)
tinyagents/ remainder (seam) STAYS, shrinks
agent/ legacy run_turn_engine + escape hatches ALREADY DELETED; WP-3 corrected the stale audit and runner documentation
agent/ remainder, agent_registry/, agent_experience/, agent_memory/, agent_tool_policy/, agentbox/, orchestration/, tool_registry/ STAYS (product/host)
routing/ DELETED; #4783 crate router already owned the only live path (WP-2)
tool_timeout/ HOST-OWNED: config/env state + hard-deadline enforcement; crate timeout is metadata only (WP-2 closed)
tool_status/ classification HOST-OWNED: OpenHuman UI/security/recovery taxonomy (WP-2 closed)
model_council/, council_registry/ DELETED after crate-backed fan-out audit and upstream dead-code cleanup (WP-2 closed)
tools/ trait mechanics DESIGN-GATED (WP-4)
tools/impl/*, all schemas.rs RPC controllers STAYS
agent_orchestration/ detached-run mechanics UPSTREAM to TaskStore (WP-5)
agent/progress_tracing* DELETE after C4 S2S6 (WP-5)