Summary
Define the Compression behaviour interface and option normalization for message history compression strategies.
Context
This issue establishes the foundation for pluggable compression strategies. The Compression behaviour defines how turn history is rendered into LLM messages, while normalize/1 handles the various ways users can configure compression (nil, true, false, Module, {Module, opts}).
Spec: message-history-optimization-architecture.md (Roadmap Issue #12)
Requirements
ARC-003: Compression behaviour with callbacks
Compression behaviour defines strategy interface with to_messages/3 and name/0 callbacks.
ARC-004: Compression is pure render function
Compression is a pure render function - same input always produces same output, no side effects.
ARC-006: Turn count from length(turns)
Turn count derived from length(turns), not messages. Message array length varies by compression strategy.
API-001: compression: true enables default strategy
compression: true enables compression with default strategy. Uses SingleUserCoalesced.
API-002: compression: {Strategy, opts} custom strategy
compression: {Strategy, opts} enables with custom strategy and options. e.g., {SingleUserCoalesced, println_limit: 10}.
API-003: compression: false/nil disables
compression: false or nil disables compression (default).
API-004: Default println_limit
Default println_limit is 15. Most recent println calls shown.
API-005: Default tool_call_limit
Default tool_call_limit is 20. Most recent tool calls shown.
API-006: normalize/1 returns tuple
Compression.normalize/1 returns {strategy, opts} tuple. Handles nil, true, false, Module, {Module, opts}.
API-007: Options inherited
Options inherited like other SubAgent options.
CMP-003: Compression at render time
Compression happens at start of each new turn (not storage time). Pure render function.
Implementation
File to create
lib/ptc_runner/sub_agent/compression.ex
Behaviour definition
defmodule PtcRunner.SubAgent.Compression do
@moduledoc """
Behaviour for message history compression strategies.
"""
alias PtcRunner.Turn
@type message :: %{role: :system | :user | :assistant, content: String.t()}
@type opts :: [
mission: String.t(),
system_prompt: String.t(),
tools: map(),
data: map(),
println_limit: non_neg_integer(),
tool_call_limit: non_neg_integer(),
turns_left: non_neg_integer()
]
@doc "Human-readable name for this strategy."
@callback name() :: String.t()
@doc "Render turns into LLM messages."
@callback to_messages(
turns :: [Turn.t()],
memory :: map(),
opts :: opts()
) :: [message()]
end
Normalize function
Pattern matching approach (see ToolNormalizer for similar pattern):
@spec normalize(boolean() | module() | {module(), keyword()} | nil) ::
{module() | nil, keyword()}
def normalize(nil), do: {nil, []}
def normalize(false), do: {nil, []}
def normalize(true), do: {SingleUserCoalesced, default_opts()}
def normalize(module) when is_atom(module), do: {module, default_opts()}
def normalize({module, opts}) when is_atom(module) and is_list(opts),
do: {module, Keyword.merge(default_opts(), opts)}
defp default_opts, do: [println_limit: 15, tool_call_limit: 20]
Note: SingleUserCoalesced reference will be the module from issue #620, which this issue blocks.
Acceptance Criteria
Test Cases
# normalize/1 tests
test "normalize(nil) returns {nil, []}"
test "normalize(false) returns {nil, []}"
test "normalize(true) returns {SingleUserCoalesced, default_opts}"
test "normalize(CustomStrategy) returns {CustomStrategy, default_opts}"
test "normalize({CustomStrategy, println_limit: 5}) merges with defaults"
Dependencies
Blocked by: #634 (Turn struct) - CLOSED
Blocks: #620 (SingleUserCoalesced compression strategy)
Files
Create:
lib/ptc_runner/sub_agent/compression.ex
Complexity
Size: S (1-2h) - Behaviour definition + normalize function with tests.
Automation State
| Field |
Value |
| Status |
SUCCESS |
| PR |
#647 |
| Branch |
claude/619-compression-behaviour |
| Attempts |
1 |
Details: Implementation complete. Created Compression behaviour with to_messages/3 and name/0 callbacks, plus normalize/1 function handling all configuration variants (nil, false, true, Module, {Module, opts}).
Files Created:
lib/ptc_runner/sub_agent/compression.ex
test/ptc_runner/sub_agent/compression_test.exs
Summary
Define the
Compressionbehaviour interface and option normalization for message history compression strategies.Context
This issue establishes the foundation for pluggable compression strategies. The
Compressionbehaviour defines how turn history is rendered into LLM messages, whilenormalize/1handles the various ways users can configure compression (nil, true, false, Module, {Module, opts}).Spec: message-history-optimization-architecture.md (Roadmap Issue #12)
Requirements
ARC-003: Compression behaviour with callbacks
Compressionbehaviour defines strategy interface withto_messages/3andname/0callbacks.ARC-004: Compression is pure render function
Compression is a pure render function - same input always produces same output, no side effects.
ARC-006: Turn count from length(turns)
Turn count derived from
length(turns), not messages. Message array length varies by compression strategy.API-001: compression: true enables default strategy
compression: trueenables compression with default strategy. UsesSingleUserCoalesced.API-002: compression: {Strategy, opts} custom strategy
compression: {Strategy, opts}enables with custom strategy and options. e.g.,{SingleUserCoalesced, println_limit: 10}.API-003: compression: false/nil disables
compression: falseornildisables compression (default).API-004: Default println_limit
Default
println_limitis 15. Most recent println calls shown.API-005: Default tool_call_limit
Default
tool_call_limitis 20. Most recent tool calls shown.API-006: normalize/1 returns tuple
Compression.normalize/1returns{strategy, opts}tuple. Handlesnil,true,false,Module,{Module, opts}.API-007: Options inherited
Options inherited like other SubAgent options.
CMP-003: Compression at render time
Compression happens at start of each new turn (not storage time). Pure render function.
Implementation
File to create
lib/ptc_runner/sub_agent/compression.exBehaviour definition
Normalize function
Pattern matching approach (see
ToolNormalizerfor similar pattern):Note:
SingleUserCoalescedreference will be the module from issue #620, which this issue blocks.Acceptance Criteria
@behaviourdefined with@callback to_messages(turns, context, opts)and@callback name()normalize/1handles:nil->{nil, []}normalize/1handles:false->{nil, []}normalize/1handles:true->{SingleUserCoalesced, default_opts}normalize/1handles:Module->{Module, default_opts}normalize/1handles:{Module, opts}->{Module, merged_opts}{strategy | nil, opts}tupleprintln_limit: 15andtool_call_limit: 20@type message/0and@type opts/0Test Cases
Dependencies
Blocked by: #634 (Turn struct) - CLOSED
Blocks: #620 (SingleUserCoalesced compression strategy)
Files
Create:
lib/ptc_runner/sub_agent/compression.exComplexity
Size: S (1-2h) - Behaviour definition + normalize function with tests.
Automation State
SUCCESSclaude/619-compression-behaviourDetails: Implementation complete. Created Compression behaviour with
to_messages/3andname/0callbacks, plusnormalize/1function handling all configuration variants (nil, false, true, Module, {Module, opts}).Files Created:
lib/ptc_runner/sub_agent/compression.extest/ptc_runner/sub_agent/compression_test.exs