This document describes the current local integration test suite in packages/sdk/test/local/.
It is intentionally different from the broader planning document in docs/contributors/local-integration-test-plan.md:
- the plan describes the target coverage model
- this spec describes the tests that actually exist today, what they assert, and where the suite can be hardened
The inventory below covers all current local test files under:
packages/sdk/test/local/*.test.jspackages/sdk/test/local/sub-agents/*.test.js
It also notes the current test entry points used by the local runner:
./scripts/run-tests.shpackages/sdk/package.jsontest:local:*scripts
Purpose:
- basic end-to-end SDK behavior on a single worker/session
Tests:
Simple Q&A- sends a basic prompt
- asserts the answer contains the expected fact
- validates CMS/event persistence at a basic level
Tool Calling- registers a simple math tool
- asserts the response includes the expected result
Multi-turn Conversation- sends two turns with memory dependence
- asserts the second turn recalls information from the first turn
Event Persistence- reads persisted events from CMS
- asserts events exist, expected types exist, and sequence numbers increase
Session Resume- resumes a session by ID after a prior turn
- asserts a follow-up turn can still reference earlier conversation state
send() + wait()- exercises the split send/wait path instead of
sendAndWait - asserts a response is still returned
- exercises the split send/wait path instead of
Primary assertions:
- basic response correctness
- event existence and monotonic sequence order
- session resume works for an ordinary warm path
Hardening ideas:
- replace loose substring checks for memory tests with prompts that force an exact single-token answer
- avoid fixed sleeps when waiting for event persistence; prefer polling helpers with explicit failure messages
- assert exact expected event types and minimum counts for each path
Purpose:
- API-surface coverage for session listing, info, delete, and subscriptions
Tests:
Session List- creates multiple sessions
- asserts both appear in
listSessions()
Session Info- checks
getInfo()before and after a turn - asserts status/iteration fields move as expected
- checks
Session Delete- deletes a session
- asserts it disappears from CMS-backed session listing
session.on() Events- subscribes to session events
- asserts events are delivered to the callback
Event Type Filter- subscribes to filtered event types
- asserts only the requested event types are delivered
Primary assertions:
- client-facing APIs return sensible metadata
- delete removes session visibility
- event subscriptions receive the correct scope of events
Hardening ideas:
- replace fixed waits with polling on event counts
- add negative-path tests for invalid session IDs and repeated delete calls
- assert event ordering more explicitly in subscription tests
Purpose:
- durability behavior for waits, input-required flows, continue-as-new, and repeated turns
Tests:
Short Wait (in-process)- uses a short wait below the durable threshold
- asserts correct final answer and minimum elapsed time
Durable Timer (abort + resume)- forces the durable path using a zero wait threshold
- asserts a wait can complete and return the expected answer
Durable Timer CMS States- asserts CMS state passes through
waitingand then returns toidleorcompleted
- asserts CMS state passes through
User Input (input_required)- triggers an
ask_userflow - asserts the user-input callback is invoked and the final response uses the supplied answer
- triggers an
Continue-as-new After Idle- performs multiple turns and checks recall after idle/continue-as-new behavior
Multiple Iterations- performs repeated turns
- asserts session iteration count rises across turns
Primary assertions:
- durable timer path still returns the correct answer
input_requiredround-trip is functional- iteration count continues rising across turns
Hardening ideas:
- tighten memory assertions so a generic mention of a token does not count as success
- assert exact CMS states for each transition instead of allowing broad alternates where possible
- add explicit validation that continue-as-new actually happened, not just that later turns still worked
Purpose:
- shared-store and shared-session-state behavior across multiple workers
- strict create-vs-resume lifecycle coverage
Tests:
Two Workers Observe Same Session- creates a session while two workers are present
- asserts the session is visible in CMS and answers correctly
Session Survives Graceful Restart- worker A creates a memory-bearing session, gracefully dehydrates, worker B resumes
- asserts the remembered value survives across workers
- asserts the session archive exists before recovery
Multiple Sessions Across Two Workers- creates several sessions and drives independent prompts
- asserts each session answers correctly and all appear in the session list
Worker Handoff After Stop- stops worker A and continues the same session on worker B
- asserts later turns still succeed and iteration increases
Turn 0 Resets Stale Stored Session- pre-seeds stale Copilot session state for a fixed session ID
- starts a brand-new turn-0 session with that same ID
- asserts stale state is discarded and a fresh session is created
Turn 1+ Fails Without Stored Session- establishes a prior session, deletes all resumable state, then attempts a resumed turn
- asserts the session fails rather than silently creating a new Copilot session
- asserts CMS reflects the failure
Primary assertions:
- valid handoff/recovery works
- stale turn-0 state is purged
- missing turn-1+ state is fatal
Hardening ideas:
- add explicit assertions that work is actually distributed across workers instead of merely sharing a store
- add a direct assertion that the resumed path used archive-backed hydration rather than a warm local directory
- add a crash-path equivalent for the strict turn-1+ failure rule, not only graceful-stop plus deletion
Purpose:
- orchestration command and command-response behavior without the TUI
Tests:
get_info Command- sends a command and polls for the command response
- asserts a response exists and is correlated to the command
/done Command- sends a completion command
- asserts command success
/done During Idle Window- sends a prompt and then issues
/doneduring the post-turn idle window - asserts the command still succeeds
- sends a prompt and then issues
Primary assertions:
- command responses are emitted and retrievable
/donecan complete a session from user-visible states
Hardening ideas:
- assert exact command response payload contents, not only
ok - add tests for duplicate command IDs and already-completed sessions
- replace arbitrary polling sleeps with a reusable command-response wait helper
Purpose:
- management client behavior for session operations
Tests:
sendMessage via Management- sends a message through the management path
- asserts orchestration status version changes and the turn progresses
Management Session Operations- lists sessions, renames a session, and verifies the new title
Cancel Session- cancels a session and polls for a terminal state
Primary assertions:
- management API can drive sessions and rename them
- cancel changes session state
Hardening ideas:
- tighten cancel assertions to a single expected state where the product contract is precise
- assert rename persistence through both
listSessions()andgetInfo()in the same test - add negative tests for unknown session IDs and double-cancel
Purpose:
- hybrid KV/customStatus transport coverage
Tests:
Response Written to response.latest- asserts completed responses are available through the KV path
CustomStatus Available- asserts custom status versions advance
Command Response via KV- asserts command responses are written to KV
Response Versions Monotonic- asserts response version numbers rise monotonically across turns
waitForStatusChange Detects Updates- asserts the status wait path detects orchestration progress
Primary assertions:
- KV response and command transport works
- versioning allows clients to dedupe updates
Hardening ideas:
- validate the full shape of
response.latestand command payloads, not only a few fields - add cases for repeated continue-as-new and command-response races
- explicitly test the fallback/compatibility path for older orchestration status payloads
Purpose:
- event persistence and event filtering in CMS
Tests:
Events Seq Strictly Increasing- asserts event sequences rise strictly
Expected Event Types Persisted- asserts expected persisted event types exist
No Transient Events Persisted- asserts delta/transient event types are not written to CMS
User Message Event Data- asserts stored user-message payloads contain the expected prompt data
Primary assertions:
- persisted event history is stable and ordered
- transient event types are excluded from CMS
Hardening ideas:
- remove fixed sleeps by polling for expected event count
- strengthen event data assertions to exact payload values where stable
- add coverage for tool events and child/session-management events
Purpose:
- CMS state transitions, title handling, soft delete, and iteration tracking
Tests:
Session State Transitions- asserts state evolves from pending into an active/idle state after a turn
Title Update via Management- asserts a management rename persists in the database
Session Iteration Count- asserts iteration increases across turns
Soft Delete Hides Session- asserts deleted sessions disappear from primary reads
Rename Visible In List And Info- asserts renamed titles appear in list and info views
Rename Persists Across Resume- asserts rename survives resume
Rename Truncates Long Title- asserts long titles are truncated to the expected maximum
Primary assertions:
- CMS remains the authoritative read model for state and titles
- rename and delete semantics are consistent across APIs
Hardening ideas:
- replace
>=iteration assertions with exact expected counts where the turn count is deterministic - add negative rename tests for empty or invalid titles if the API contract defines them
- explicitly assert
updatedAtchanges on state and title transitions
Purpose:
- runtime contract checks for tools, prompts, agents, and worker-loaded assets
Tests:
Worker-Registered Tool By Name- asserts a worker-registered tool can be referenced by
toolNames
- asserts a worker-registered tool can be referenced by
Registry + Per-Session Tools Combined- asserts worker-level tools and per-session tools are both available
Tool Update After Eviction- evicts a session, changes its tool set, and asserts the new tool set is effective on later turns
Mode Replace Keeps Base Prompt- asserts replace-mode system messages do not strip core runtime prompt behavior
Worker Exposes Loaded Agents- asserts worker exposes loaded system agents
Worker Skill Dirs Loaded- asserts worker exposes loaded skill directories
Primary assertions:
- runtime tool resolution and session config updates work
- base prompt behavior is preserved under
mode: "replace"
Hardening ideas:
- add explicit assertions that tools were actually called rather than guessed by the model
- strengthen loaded-agent checks to assert exact expected agents in test setups
- add schema or name-conflict tests for tool registration
Purpose:
- local restart and interruption scenarios without AKS
Tests:
Worker Restart During Long WaitStop Both Workers Then RestartSession Delete During CompletionRapid Worker Stop/StartConcurrent Sessions Under Worker Restart
Primary assertions:
- sessions remain visible and usable across abrupt stop/start cycles
- delete during an active or recently-completed path is handled safely
Hardening ideas:
- strengthen result assertions beyond non-null/non-empty responses
- add more explicit state verification during interruptions
- consider child-process workers for more realistic crash semantics
Purpose:
- guardrail enforcement for session-creation policy and system-session deletion
Tests:
Agent NamespacingList Agents Omits SystemClient Rejects Generic When DisallowedClient Allows Named AgentClient Rejects Unknown AgentClient Rejects System AgentDeletion Protects System SessionsOrch Rejects Generic When Disallowed
Primary assertions:
- client and orchestration both enforce policy
- system sessions cannot be deleted through normal APIs
Hardening ideas:
- add stronger exact-match error assertions instead of substring-only checks
- add qualified-name and mixed-plugin negative cases to the guard suite itself
- cover more than one system session in delete-protection tests
Purpose:
- behavioral consequences of policy configuration and plugin composition
Tests:
No Policy (Open)Open Policy Allows GenericMultiple Plugin Dirs MergeLast Policy WinsNamed Agent Title PrefixSystem Agent Title Not PrefixedOrch Allows Named AgentOrch Allows Sub-Agent SpawnsQualified Name ResolutionApp System Agents CoexistNamed Agent Title After Summarization
Primary assertions:
- policy composition and override behavior are coherent
- agent/session title behavior stays consistent before and after summarization
Hardening ideas:
- replace the hardcoded 65-second summarization wait with a hookable/testable summarize trigger
- make the system-agent lookup path more deterministic so the test does not risk silent environmental dependence
- tighten the qualified-name test to verify actual spawn resolution, not only loaded metadata
Purpose:
- single-session crash/restart recovery coverage
Tests:
Orchestration Survives Worker Crash- asserts later turns still work after worker replacement
CMS Consistency Across Crash- asserts state and iteration continue coherently across a crash
Tool Works On Replacement Worker- asserts worker-registered tools still function after worker replacement
Primary assertions:
- ordinary crash recovery works for sessions and tools
Hardening ideas:
- strengthen answer correctness checks so model guessing does not count as tool/path success
- compare pre-crash and post-crash orchestration/CMS state more directly
- add a case where the crash happens mid-turn rather than only between turns
Purpose:
- staggered and repeated restart coverage, including local-state deletion with persisted archives
Tests:
Staggered Crashes — Multiple Sessions- establishes multiple sessions across repeated worker crashes
- asserts all remain visible and at least one can resume successfully
Deleted Local State Recovered From Store- establishes a session, persists an archive, deletes only local state, resumes on a new worker
- asserts recovery succeeds from store-backed state
Double Crash — Two Consecutive Restarts- drives the same session across three workers
- asserts later turns still succeed and iteration reaches 3+
Primary assertions:
- stored archives can recover deleted local state
- repeated crash/restart cycles do not break session continuity
Hardening ideas:
- explicitly verify archive-backed restore occurred, not just later-turn success
- tighten iteration checks where exact counts are deterministic
- add the complementary negative case where both local and stored state are deleted and failure is expected
Purpose:
- model recording and per-session model selection behavior
Tests:
Create Session With Explicit ModelModel Recorded In CMS After TurnDifferent Models On Same WorkerDefault Model Recorded
Primary assertions:
- chosen model names are recorded in CMS and session info
Hardening ideas:
- add normalization and invalid-model rejection cases
- add assertions that child/sub-agent model inheritance and override are preserved in the general suite as well as the specialized sub-agent file
Purpose:
- auto-start lifecycle for built-in management/system agents
Tests:
Pilotswarm Root Agent Created- asserts the root system session appears with deterministic metadata and splash
Child System Agents Spawned- asserts pilotswarm spawns sweeper and resource manager children
Child Agent Titles- asserts expected fixed titles for system children
Child Agent Splash Screens- asserts splash banners exist and contain expected content
Child Agent CMS Metadata- asserts system child metadata and parent/child linkage in CMS
Primary assertions:
- built-in system agent tree comes up automatically and writes correct metadata
Hardening ideas:
- replace long manual polling loops with reusable wait helpers that surface the last observed state on failure
- add partial-spawn diagnostics so failures identify which child agent is missing and what pilotswarm last emitted
- add deterministic-id restart assertions to prove system children are reused rather than recreated incorrectly
The sub-agent suite is split into dedicated files under packages/sdk/test/local/sub-agents/.
Purpose:
- ad hoc custom sub-agent spawn by task only
Tests:
Spawn Custom Sub-Agent- asserts a child session is created for a custom task-only spawn
Hardening ideas:
- assert the child actually completes the requested task, not only that it exists
Purpose:
- custom sub-agent spawn without a preconfigured skill or named agent definition
Tests:
Custom Agent Without Skill- asserts a child is created and does not get an
agentId
- asserts a child is created and does not get an
Hardening ideas:
- assert the absence of named-agent metadata more comprehensively
Purpose:
- parent/child metadata and descendant lookup
Tests:
Child Session CMS Metadata- asserts
parentSessionIdis set correctly and the child appears in descendant queries
- asserts
Hardening ideas:
- add multi-child and grandchild descendant assertions
Purpose:
check_agentsorchestration behavior
Tests:
Check Agents Returns Child Status- spawns a child then calls
check_agents - asserts status reporting works and the parent turn advances
- spawns a child then calls
Hardening ideas:
- assert the response includes the child session ID and status text rather than only completing
Purpose:
- multiple children under one parent session
Tests:
Multiple Sub-Agents- spawns more than one child and asserts multiple CMS children exist
Hardening ideas:
- assert each child corresponds to a distinct task
- assert completion/update handling for both children, not only creation
Purpose:
- named-agent spawning through
agent_name
Tests:
Spawn Named Agents By agent_name- asserts named children resolve to canonical agent metadata, titles, splash, and system flags
Hardening ideas:
- add negative tests for unknown or malformed
agent_namevalues - validate actual tool-call parameters if available in events
Purpose:
- child model inheritance/override behavior
Tests:
Child Inherits Parent Model- asserts a child inherits the parent model when not explicitly overridden
Hardening ideas:
- add explicit override acceptance and explicit invalid-override rejection assertions in this same file
Purpose:
- nested sub-agent spawning and max-depth enforcement
Tests:
Depth 2 Nesting (Grandchild)- spawns a child which spawns a grandchild
- asserts the root → child → grandchild parent chain exists in CMS
Depth 3 Denied (Max Nesting)- asserts no depth-3 sessions are created when depth 2 is the maximum
Execution check:
- this file executes normally
- the tests are not swallowing failures
- assertions are direct and would fail the file if conditions are not met
- there are no broad catch-and-ignore blocks in the test body
Hardening ideas:
- replace the fixed 5-second post-turn sleep with a wait helper based on child/grandchild CMS appearance
- make the depth-3-denied case more direct by asking for an explicit depth-3 spawn attempt and asserting rejection, not only absence
Several files still use fixed waits such as 500ms, 2s, 5s, or 65s. These are the biggest source of avoidable flakiness.
Prefer helpers that poll for:
- expected event count
- expected CMS state
- expected child count
- expected title change
- expected command response version
Many tests currently pass if the response merely contains a token like 4, 56, Alice, or X123 anywhere.
Prefer prompts that force:
- a single-word answer
- a single-token answer
- an exact JSON or exact quoted response
That reduces false positives from model verbosity.
For tool tests, response correctness alone is not enough because the model can guess.
Where possible, also assert:
- tool execution events were emitted
- expected tool names were called
- child/tool metadata changed as expected
After the strict session lifecycle change, tests need to distinguish clearly between:
- recoverable state loss: local files deleted, store archive still exists
- unrecoverable state loss: memory, local files, and store are all gone
Both paths should have explicit tests and should never be conflated.
A lot of tests use >= for iteration counts.
That is fine for some asynchronous flows, but for deterministic turn counts many should assert exact expected values. Otherwise regressions that double-execute a turn can still pass.
The multi-worker and reliability suites prove that behavior still works, but not always that the intended path was used.
Useful additions:
- assert archive existence and disappearance at the right times
- assert local session directory presence/absence during handoff
- assert host/worker identity changes across turns where relevant
The named-agent summarization test currently waits more than a minute to cross the summarization threshold.
That is expensive and brittle. Better options:
- injectable summarize delay in test mode
- a direct management/command trigger for summarize in tests
- a special worker default override only used in the suite
There is good positive coverage for named agents and model inheritance. The suite should also assert:
- unknown
agent_nameis rejected clearly - malformed qualified names are rejected clearly
- invalid or unqualified child model overrides are rejected clearly
Current local runner surfaces are:
./scripts/run-tests.shnpm run test:localinpackages/sdk
Current grouped npm scripts are:
test:local:smoketest:local:durabilitytest:local:multi-workertest:local:commandstest:local:managementtest:local:sub-agentstest:local:kv-transporttest:local:cmstest:local:contractstest:local:chaostest:local:system-agentstest:local:session-policytest:local:reliability
One improvement here would be to add a dedicated grouped runner for nested-spawn or other especially slow/high-risk sub-agent scenarios when debugging regressions locally.
If we want the biggest reliability payoff quickly, the best next set of improvements is:
- Replace all fixed sleeps in local tests with polling helpers that report the final observed state.
- Tighten memory and math response assertions to exact-answer prompts.
- Add explicit negative tests for unknown named agents and invalid model overrides in the specialized sub-agent files.
- Add direct assertions that multi-worker handoff used archive-backed recovery where intended.
- Add a deterministic summarize trigger or shorter test-only summarize interval.