Upgrading

This page is for an operator or library consumer moving a deployment or dependency from v0.9.x to v0.10.0. It orients you to what changed and points you at the authoritative record; it does not duplicate that record's full detail.

The authoritative, exhaustive record of every behavioral change, Rust API change, schema migration, configuration surface, HTTP surface change and the full upgrade checklist is the root MIGRATION.md file. Read this page first for orientation, then consult MIGRATION.md for the complete §9.1–§9.8 detail, including worked code examples for each behavioral change.

Behavioral changes

Every v0.10.0 change an operator can observe without touching their own code, condensed from MIGRATION.md §9.1 to one line each. See that section for the full "who is affected" / "required user action" detail and worked examples.

IDChangeRequired action
M-B-01EdgeCondition::Custom(name) no longer silently evaluates to true when no evaluator is registered (BUG-01 fix) — an unregistered custom edge now fails graph validation before any node executes.Register an evaluator for each custom condition name, or replace the condition with Contains/Regex/Always.
M-B-02Graceful shutdown: on SIGTERM/SIGINT the process now waits up to shutdown_grace (default 30s) for in-flight engine runs to halt before exiting.Set terminationGracePeriodSeconds to at least 60 (twice the default grace) in every Deployment manifest.
M-B-03No behavioral change to the default policy — tool_error_mode names the v0.9 behavior (FeedToModel) rather than introducing a new one, and the fed-back error text is now redacted-then-bounded before the model sees it.None required to keep today's behavior. Set tool_error_mode = FailRun to opt into failing the run on a tool error instead.
M-B-04Any graph executed through the new WarEngine writes one Waypoint (a full Battlefield snapshot) after every superstep by default. Legacy Formation/Phalanx/Campaign/Commander execution paths are completely unaffected — they write no Waypoints.Only applies if you adopt the new WarEngine/WarGraph APIs: choose a WaypointPort backend and review WaypointDurability and WaypointRetentionConfig.

Upgrade checklist

One ordered, copy-pasteable checklist for upgrading a v0.9.0 deployment to v0.10.0, mirrored from MIGRATION.md §9.8.

  1. Back up state. Snapshot every state directory and database this deployment uses: the waypoint store (SqliteWaypointStore/PostgresWaypointStore's backing file or database), the run store (RunStoreConfig's SQLite file or PostgreSQL database), the Garrison SQLite database if used, and any Citadel state files. There is no destructive migration to reverse a bad upgrade against; a restored backup plus the v0.9.0 binary is the rollback path.
  2. Apply migrations — by starting the new binary, not a separate command. Every migration this program added runs automatically at adapter construction via sqlx::migrate!; there is no sqlx migrate run step to invoke by hand. Start the new paladin-server binary once against the restored backup and confirm it comes up cleanly. The same automatic-migration mechanism applies to the PostgreSQL-backed adapters — no separate manual migration step is needed there either.
  3. Update config — nothing is required. Every new v0.10 config surface defaults to today's behavior, proven by the v0_9_config_boot integration test: a v0.9 configuration file boots this binary with every new subsystem inert. No config.yml edit is required to preserve v0.9 behavior; add a section only when actually adopting a new capability.
  4. Raise terminationGracePeriodSeconds. Set it to at least 60 in every Deployment manifest before rolling out this upgrade (M-B-02). The shipped manifests (k8s/deployment.yaml, k8s/server/deployment.yaml, k8s/server/worker-deployment.yaml) already carry terminationGracePeriodSeconds: 60; a forked or hand-written manifest needs the same change.
  5. Register a custom evaluator for every EdgeCondition::Custom name in use. M-B-01's fix makes an unregistered custom edge condition a validation failure, not a silent always-true. Register one via CampaignExecutionService::with_evaluator("name", Arc::new(evaluator)) on the legacy execution path, or WarEngine::with_edge_evaluator("name", Arc::new(evaluator)) on the WarEngine path, before calling execute/start.
  6. Deploy. Roll out the new binary and manifests with the grace period and evaluator registrations from steps 4-5 already in place.
  7. Verify. Run paladin-cli setup-check --verbose for an environment/toolchain/provider/ service connectivity check; if the deployment uses the Maneuver flow DSL, run paladin-cli maneuver validate against its flow configuration; and run paladin-cli eval run <glob> against a representative scenario glob for a behavioral post-deploy check. GraphCommands exposes exactly one subcommand, export (paladin-cli graph export --format mermaid|dot), for inspecting a graph's structure — there is no separate command for a runtime probe.

Token usage carriers

Every place a Paladin run's token usage is reported now carries the full prompt/completion split plus optional cache-read/cache-write/reasoning sub-counts, instead of a single bare count (ACCT-01/ACCT-02/ACCT-03). PaladinResult.usage, NodeExecutionRecord.usage, TraceEvent::NodeFinished.usage, TraceEvent::RunFinished.usage, StreamingResponse.usage, ChunkMetadata.usage, and the HTTP ExecuteResponse.usage all replace their former token_count/total_tokens field with a TokenUsage. TokenUsage::from_total — the total-only constructor — is deleted outright with no deprecated replacement; construct a TokenUsage via TokenUsage::new(prompt, completion) plus the with_cache_read/ with_cache_write/with_reasoning builders instead. Two under-reports are also corrected: the battalion per-Paladin split was previously zeroed, and Anthropic's prompt_tokens previously excluded cached input. See MIGRATION.md §9.2 for the full per-type register and the CHANGELOG.md [0.10.0] entry for the corrected figures.

Token primitives

Two duplications in the token-counting/window-resolution primitives are collapsed to one each in v0.10.0 (PRIM-01…PRIM-04). TokenCounterPort gained fn is_exact(&self) -> bool { false } — the counting port now declares its own exactness, so Commissary::new and Commissary::from_port no longer take a caller-supplied is_exact_counter: bool argument; Commissary reads Stockpile.exact_tally live from the injected counter's is_exact() instead. The legacy fallible garrison::TokenCounter trait and its TokenCounterFactory are removed outright, with no deprecated replacement — TiktokenCounter survives as the sole implementor of TokenCounterPort, which is now the only counting contract in the workspace. Separately, both context-window precedence walks (Commissary::new's inline fallback guard and HistoryTrimmer::resolve_limit) now call the same shared paladin_llm::window::resolve_context_window function instead of each maintaining its own. See MIGRATION.md §9.2 for the full per-type register.

Separately, in v0.10.0 (Phase 33, COMM-01…03), RagRetrievalService::retrieve_context and retrieve_context_with_timeout change their return type to a result struct carrying the Commissary's shed record, and format_for_prompt changes its parameter to that struct; a new with_token_counter builder mirrors PaladinExecutionService::with_token_counter. Read .memories and .shed off the returned result rather than the old Vec. See the paladin-memory | RagRetrievalService and paladin-memory | retrieve_context_with_timeout rows in MIGRATION.md §9.2.

Full migration record

For every behavioral change's worked examples, the complete Rust API change register, schema migrations, configuration and environment variable reference, and the HTTP API compatibility notes, see the root MIGRATION.md file.