Skip to content

M8-06 Binding of imported session references

No Date Ruling Reason
D-M8-06-1 2026-10-24 The sessions file of --sessions is JSON lines (blank lines skipped) with exactly the members discord_thread (digits), agent (a handle), external_session_ref (non-empty, textcheck.DisplayText, at most the maximum of agent.session_ref_max_bytes, because the tool cannot read the server's configured value; a longer reference under the configured value is refused by the server with 400 at /items/<i>/data/earlier_session/external_session_ref) and optionally cost_baseline_micros (an integer from 0 to 2^53 - 1) and currency (^[A-Z]{3}$, required for a baseline above 0). An unknown member, a bad value, a duplicate discord_thread and an agent handle the server does not have end the run with exit 2 before any write, naming the line and the member, never a value of the reference. A line whose thread is not part of the run is ignored and counted in one report note; a line whose agent is not the planned_operator of the thread's channel in the mapping (or of a channel without one) is dropped and counted as sessions_discarded. A dry run validates and counts accepted lines of threads in scope as sessions_taken ("would take over"); --follow sends a line with the thread item of a new thread. The report gains sessions_present and sessions_late next to sessions_taken and sessions_discarded, so a repeated run shows why nothing was written; the text column is "Sessions taken/present/discarded/late". Design note 1, 22 9 step 1, 10.1, 11.
D-M8-06-2 2026-10-24 agents.ImportedSessions.CreateEarlier(ctx, EarlierSession) (string, error) runs in the batch transaction without authorization, audit entry or event: dropped_late (nothing written) when the thread has a current row or a row whose end_reason is not import; already_present when an import row of the same thread, agent and reference exists; else the row of requirement 11 (created_at = ended_at = the clock time, model NULL, cumulative_cost_micros = 0, the baseline, the currency or the column default) through the existing InsertSession query and taken_over. The agent must be threads.operator_agent_id (400 at /agent_id, which the importer reports as /items/<i>/data/earlier_session/agent_id). The outcome is a string with the constants agents.EarlierTakenOver, EarlierAlreadyPresent and EarlierDroppedLate instead of a type Outcome (D-W-100). agentstest.InsertImportedSession keeps its direct insert: M2-12 tests place import rows of threads without an operator check, which CreateEarlier would refuse. Design note 2, 22 9 steps 1 and 6, 14.
D-M8-06-3 2026-10-24 ImportThreadData gains the optional member earlier_session (ImportEarlierSession: agent_id, external_session_ref, cost_baseline_micros, currency); the importer checks its shape and applies it after a new thread is created and for a posted thread (also a later run with the file reaches it), never for a skipped thread. ImportItem gains session (taken_over, already_present, dropped_late) on such a thread item. stats.server counts sessions_taken_over, sessions_already_present and sessions_dropped_late for every applied member, also on a replayed batch (like source_changed), so such a batch appends import.progress. The thread item carries no content_sha256, so adding the member to an earlier posted thread is no source change. Design note 3.
D-M8-06-4 2026-10-24 AgentSession (REST) and SessionJSON (payload of agent_session.changed and the session object of agent.invocation) show cost_baseline_micros and currency exactly when the baseline is above 0; cost.currency stays. The Claude Code runner applies the baseline when it has no stored values for the session (a fresh usage.json), in every session mode instead of only bind, because a bound run that ended before it stored its values would otherwise book the old amount on the next resume: it keeps the remaining baseline in usage.json (written atomically with the values and the pending reports), subtracts it from the sum of a run's amount differences in proportion to the model amounts (floor shares, the leftover micros one by one in model order, never below zero per model), clears it on a counter reset (the negative-difference rule) and ignores a baseline in another currency than USD with the warning cost_baseline_currency_ignored. Tokens are not reduced: 03 stores no token baseline, so the token counts of the first runs after a binding can include the old session's tokens (09 18.7). Design note 4, 09 4.10 and 18.7, RK-75.
D-M8-06-5 2026-10-24 The importer depends on agents.ImportedSessions, which the runs part of internal/wire builds (AgentSessions, order 1320) before the importer (order 1380); module_importer.go passes s.runs.Sessions.Service and refuses to start without it. No table, migration, action, event type, configuration key or make target is added. Design note 5; PL/28.