Skip to content

feat(orchestration): plan template caching for LLM planner cost reduction (#1856)#2068

Merged
bug-ops merged 4 commits intomainfrom
issue-1856-plan-caching
Mar 20, 2026
Merged

feat(orchestration): plan template caching for LLM planner cost reduction (#1856)#2068
bug-ops merged 4 commits intomainfrom
issue-1856-plan-caching

Conversation

@bug-ops
Copy link
Owner

@bug-ops bug-ops commented Mar 20, 2026

Summary

  • Store completed TaskGraph plans as PlanTemplate skeletons in SQLite (plan_cache table, migration 040)
  • On repeated or similar goals, match via in-process cosine similarity on goal embeddings and adapt the cached template with a single LLM call instead of full re-decomposition
  • Graceful degradation: any cache error falls back to full Planner::decompose()

Implementation

  • Goal normalization: Unicode-aware trim + collapse whitespace + lowercase (ch.to_lowercase() iteration)
  • Deduplication: BLAKE3 hash on normalized goal with INSERT OR REPLACE ON CONFLICT(goal_hash)
  • Embedding BLOB: LE-encoded f32 bytes via flat_map(|f| f.to_le_bytes()) / chunks_exact(4) + f32::from_le_bytes (no bytemuck)
  • Model invalidation: on PlanCache::new(), rows with a different embedding_model are deleted
  • Eviction: TTL phase (expired rows) then LRU phase (trim to max_templates) on every store
  • Config: [orchestration.plan_cache] section with enabled, similarity_threshold, ttl_days, max_templates; PlanCacheConfig::validate() enforces sane bounds on config load

Files changed

  • crates/zeph-orchestration/src/plan_cache.rs — new (1000 lines, 23 tests)
  • crates/zeph-memory/migrations/040_plan_cache.sql — new migration
  • crates/zeph-config/src/experiment.rsPlanCacheConfig + validate()
  • crates/zeph-config/src/loader.rs — call plan_cache.validate() when enabled
  • crates/zeph-orchestration/src/planner.rs — expose convert_response_pub() for adapt_plan
  • crates/zeph-orchestration/src/lib.rs — re-export public API
  • crates/zeph-orchestration/Cargo.toml — add blake3, sqlx deps

Test plan

  • cargo +nightly fmt --check — clean
  • cargo clippy -p zeph-orchestration -p zeph-config -- -D warnings — clean
  • cargo nextest run -p zeph-orchestration -p zeph-config — 232 passed, 0 skipped
  • Live agent session with config/testing.toml and orchestration.plan_cache.enabled = true to verify end-to-end cache hit logging

@bug-ops bug-ops enabled auto-merge (squash) March 20, 2026 20:49
@github-actions github-actions bot added documentation Improvements or additions to documentation memory zeph-memory crate (SQLite) rust Rust code changes enhancement New feature or request dependencies Dependency updates size/XL Extra large PR (500+ lines) labels Mar 20, 2026
bug-ops added a commit that referenced this pull request Mar 20, 2026
Resolves CI build failure in PR #2068 where blake3::hash() was used without
importing the blake3 crate. Local builds passed due to transitive imports,
but clean CI builds revealed the missing import.
@github-actions github-actions bot added the tests Test-related changes label Mar 20, 2026
bug-ops added 4 commits March 20, 2026 22:37
Store completed TaskGraph plans as PlanTemplate skeletons in SQLite,
matched via in-process cosine similarity on goal embeddings. On a
cache hit, templates are adapted via a single LLM call instead of full
re-decomposition, reducing planner cost for repeated or similar goals.

Key implementation details:
- BLAKE3 goal hash for deduplication with INSERT OR REPLACE semantics
- Unicode-aware goal normalization (trim + collapse whitespace + lowercase)
- Embedding stored as LE-encoded f32 BLOB (bytemuck-free, chunk-based decode)
- Embedding model invalidation on PlanCache::new() startup
- TTL + LRU two-phase eviction
- plan_with_cache() wrapper with graceful degradation on any cache error
- PlanCacheConfig::validate() with bounds checked on config load
- Migration 040_plan_cache.sql with UNIQUE constraint on goal_hash
Resolves CI build failure in PR #2068 where blake3::hash() was used without
importing the blake3 crate. Local builds passed due to transitive imports,
but clean CI builds revealed the missing import.
The cast_signed() method doesn't exist in Rust's standard library.
Replaced with standard as i64 cast, with clippy allow for safe Unix timestamp
conversion that won't overflow for centuries.
…egration test

The plan caching feature added `plan_cache: PlanCacheConfig` to
`OrchestrationConfig`. The integration test's `default_config()` helper
constructed the struct via an exhaustive literal and did not include the
new field, causing E0063 in CI (which compiles `--tests`) while local
`--lib --bins` runs were unaffected.

Use struct update syntax (`..OrchestrationConfig::default()`) to fill
any default fields so future additions do not require updating this
helper.
@bug-ops bug-ops force-pushed the issue-1856-plan-caching branch from 7954e10 to 88fa5d5 Compare March 20, 2026 21:37
@bug-ops bug-ops merged commit 93fb98c into main Mar 20, 2026
25 checks passed
@bug-ops bug-ops deleted the issue-1856-plan-caching branch March 20, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Dependency updates documentation Improvements or additions to documentation enhancement New feature or request memory zeph-memory crate (SQLite) rust Rust code changes size/XL Extra large PR (500+ lines) tests Test-related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

research(orchestration): agentic plan caching for LLM planner cost reduction (APC)

1 participant