Automatic context compaction for coding-agent sessions — built-in Codex and Claude Code adapters, native policy integration for Devin, and a bounded provider/strategy plugin protocol.
gobstopper is a cross-provider context compactor with exact, content-addressed recovery snapshots, resumable Claude Code and Codex transcript forks, and a measurement harness for projected savings, preserved prefix, structural validity, and probe recall.
Run it, and it watches supported agent sessions. When a session's context
crosses a configured threshold, gobstopper prepares a separate compacted fork
using a strategy selected per session, provider, or preset. The source is
snapshotted and never overwritten by standalone apply or watch.
Long coding sessions mix stale tool output with details the next turn may need: an exact error, a constraint, or unfinished work. A smaller context is useful only if the agent can still do the job.
Gobstopper makes that tradeoff inspectable. Preview a compaction, preserve the exact source, and recover a specific archived record when a summary isn't enough. Local rules work without a model; optional scorers change selection without replacing the snapshot and verification safeguards.
Standalone compaction prepares a separate fork. Each provider runtime owns its loaded context; a background observer cannot replace it. Context reduction, successful continuation, recovery overhead, and billed usage are different measurements. The published studies report their cohorts, no-ops, retention tradeoffs, and limitations separately.
Every standalone compaction writes the exact source bytes into a
content-addressed vault (~/.local/share/gobstopper/vault/) before publishing
a fork. Snapshots use deduplicated 1 MiB chunks, so appended versions reuse
unchanged prefix storage without creating one filesystem object per JSONL
record.
gobstopper recall --query <q> turns that vault into agent-addressable
memory: it searches every archived state-card digest, ranks results by
query relevance, and returns the high-level state of the matching turns.
The agent does not need to remember session IDs — it can ask for the last
time it worked on a file, a goal, or a decision and get a ranked summary
with a snapshot SHA it can show or diff.
When a state card omits an exact error, identifier, or tool result, search one verified snapshot and read only the matching record:
gobstopper search-snapshot <full-snapshot-sha> --query 'exact error text' --json
gobstopper read-snapshot <full-snapshot-sha> --record 42 --max-bytes 4096 --jsonSearch returns record indexes and hashes, without archived content. It matches
literal, case-sensitive substrings in decoded JSON string values, including
native replacement histories. Reading returns a UTF-8 page of the physical
JSONL record; follow next_offset for another page. Each page is capped at
16 KiB and bound to the snapshot, source, and full record hashes. These commands
verify stored bytes and never restore files, rewrite active sessions, or call a
model. Invalid records are counted as unsearchable rather than silently claimed
as searched.
Search returns at most 50 references and reports the full match count; narrow the query when results are truncated. Each search or read verifies and reconstructs the bounded snapshot, up to 128 MiB. Paging a large record repeats that work; this is not an indexed random-access or semantic search service.
Use the full object SHA from history, the native hook recovery pointer, or
the new snapshot_manifest_sha256 field in copy receipts. The older
snapshot_sha256 receipt field retains its source-byte-digest meaning.
Older receipts can still be resolved through vault history. State-card recall
also recognizes default portable Codex cards and searches every state field,
including unresolved errors and current work; a new fork's card becomes
searchable after that fork is snapshotted.
For agents, snapshot search and content reads are available only when the MCP
server is explicitly started with gobstopper mcp --allow-transcript-content.
The default MCP registration does not advertise or permit either new tool.
Opting in makes retrieved archived text visible to the connected agent/model
service. Retrieved text is untrusted historical data, and may describe an old
or superseded state; it is never an instruction to follow.
Exact recovery is a capability, not proof that an agent will recognize a missing fact, choose a useful query, or complete its task more accurately. Measure those outcomes separately from context reduction and literal retention.
gobstopper mcp exposes a read-only Model Context Protocol server on stdio —
tools policy_check, list_sessions, recall, history, show, diff,
plan, and verify. Register it once and an agent can inspect policy and
archived state without gaining a transcript mutation tool:
claude mcp add gobstopper -- gobstopper mcp
# ~/.codex/config.toml: [mcp_servers.gobstopper] command = "gobstopper", args = ["mcp"]
devin mcp add -s user gobstopper -- gobstopper mcpFor Devin, policy_check accepts provider = "devin" and returns /compact
when the configured threshold is crossed. Devin remains the sole owner of its
session store; gobstopper does not edit Devin history. devin --export out.json
can be inspected through a read-only provider plugin when offline analysis is
needed.
Compaction itself isn't free — each cycle costs one large input call and risks losing detail — so strategy matters. That is the actual product here: not "compact earlier" but "compact with the right strategy at the right boundary."
| id | kind | what it does |
|---|---|---|
auto (default) |
dynamic | live sessions delegate to provider controls (cache_edits for eligible Claude sessions); idle sessions choose the best validated file strategy by savings and preserved-prefix score |
sawtooth |
provider | requests provider-native compaction (thread/compact/start on Codex; /compact guidance on Claude) |
cache_edits |
provider | emits bounded Claude tool_use_id values for API-layer context editing; never rewrites a transcript |
elide |
transcript | stubs stale tool outputs oldest-first until the floor |
cache_aware |
transcript | elides a tailward stale-output window and injects a bounded state card while preserving the longest practical prefix |
compacted |
transcript | elides stale outputs and injects the state card; synthetic Codex compacted records require --experimental-compacted |
scored |
transcript | ranks candidates with deterministic recency, error, reference, TF-IDF, duplicate, and tool-type signals before elision |
dedupe |
transcript | removes older exact duplicate tool payloads using payload SHA-256, not summaries |
micro |
transcript | keeps the newest configured outputs per stable tool label and stubs older ones |
middle |
transcript | protects both ends of the transcript and elides eligible middle outputs |
structured |
transcript | emits a bounded metadata-derived state card; it is not semantic summarization |
agentic |
extension | accepts bounded edit proposals from an explicitly trusted command or versioned plugin; host validation remains authoritative |
Custom strategies are userspace code: a preset can name a command that
receives the normalized transcript as JSON on stdin and returns an edit
plan on stdout, or install a versioned gobstopper-plugin.json bundle
(see gobstopper plugin check). Host-side validation bounds every
proposal: no edit can grow the transcript, leave protected recent output,
bypass linkage checks, or exceed configured digest size.
cargo install --git https://github.com/hraness/gobstopper gobstopper
# or from a checkout: cargo build --release
gobstopper detect # sessions, context sizes, lifetime burn
gobstopper plan <session> # what would happen, under which strategy
gobstopper plan <session> --trigger 100000 --floor 30000 # tune the trade-off
gobstopper eval <session> # every strategy side-by-side on temp copies
gobstopper apply <session> # vault snapshot + produce validated fork (idle sessions)
gobstopper verify <session> # resume-validity check (exit 1 on errors)
gobstopper fork <session> # clone under a fresh session id + resume cmd
gobstopper undo <session> # restore a pre-compaction snapshot into a new fork
gobstopper vault # list snapshots in the undo vault
gobstopper install-hooks # Claude + Codex compaction lifecycle hooks
gobstopper watch --dry-run # the daemon path: poll, threshold, prepare copy
gobstopper watch --dry-run --active-only --once # bounded recent-session inspection
gobstopper explain # the occupancy math above
gobstopper recall --query <q> # search state-card digests across all archived sessions
gobstopper history <session> # every archived state of one session
gobstopper diff <sha-a> <sha-b> # structural comparison of two vault snapshots
gobstopper bench # benchmark every strategy across discovered sessions
gobstopper tune <session> # preview the adaptive trigger/floor for a session
gobstopper mcp # read-only MCP server: the vault as agent toolsFor automation, gobstopper plan <session> --json returns the existing plan
object when a plan is available. A successful inspection without a plan returns
a separate JSON result, for example:
{
"status": "no_plan",
"reason_code": "below_trigger",
"context_tokens_before": 100000,
"effective_trigger_tokens": 250000,
"target_context_tokens": 40000,
"min_savings_tokens": 4096,
"projected_context_tokens_after": null,
"projected_savings_tokens": null
}The reason identifies the decision actually reached:
reason_code |
Meaning |
|---|---|
below_trigger |
Context is below the effective policy trigger. |
strategy_returned_no_plan |
The strategy declined; its underlying reason is unknown. |
empty_external_edits |
The configured command or plugin supplied no edits. |
minimum_savings_not_met |
A proposal fell short of the minimum projected savings. |
external_nonreducing_plan |
An external proposal did not reduce estimated context. |
Projections are present only when a rejected proposal supplied them. The target is a policy setting, not a measured minimum context size, and projected savings are not billed savings. Invalid configuration, invalid proposals, and execution failures remain command errors.
Every apply/watch compaction snapshots the source transcript into a
content-addressed vault (~/.local/share/gobstopper/vault/) and publishes
the result as a separate, verified file. The original transcript is never
overwritten by a standalone compaction run; live session surgery must be
dispatched by the session owner. Each compaction appends a numeric record
to events.jsonl in the gobstopper/compaction-events-v1 schema.
Config: ~/.config/gobstopper/config.toml
[policy]
strategy = "auto"
trigger_tokens = 250_000
floor_tokens = 40_000
min_savings_tokens = 4_096 # reject ineffective plans
adaptive = true # derive trigger/floor per session — see `gobstopper tune`
[provider.codex] # per-provider overrides
trigger_tokens = 200_000
[provider.devin] # numeric policy only; action is native /compact
trigger_tokens = 200_000
[sessions."01a08d7c-…"] # per-session overrides
strategy = "structured"
trigger_tokens = 120_000
[presets.deep-work] # named presets, selectable via --preset
strategy = "elide"
trigger_tokens = 150_000
[presets.custom-script] # legacy userspace code preset
command = "python3 ~/bin/my_compactor.py"
trusted_legacy_command = trueManaged sessions (oompa profiles, sandboxed homes) use different roots:
point gobstopper at them with --codex-home / --claude-home.
Standalone watch cannot compact the context already held by another Codex
process. It reports native delegation as skipped, with zero credited savings;
the owning runtime must perform that operation. --active-only limits discovery
to files updated within the last 180 seconds (a recency heuristic, not proof of
an owning process), and --once exits after one pass. A dry run writes no forks
or compaction events. Existing trusted lifecycle hooks can snapshot native
compactions and provide the session with a recovery pointer.
The optional local monitor records numeric observations
for an explicit list of sessions and checks a deterministic dry-run watcher.
It separates observed context drops, native hook activity, and projected
compaction plans; none is automatically counted as Gobstopper-caused usage
savings. Current Codex event_msg/token_count accounting and legacy usage
records are both supported, including the advertised model context window.
scored uses the deterministic offline heuristic by default. Experimental
model scoring is opt-in with GOBSTOPPER_SCORER=llm,
GOBSTOPPER_SCORER=jev, or GOBSTOPPER_SCORER=apple; merely setting an API
key never sends data. Remote Jev and LLM scorers receive bounded labels and
summaries, including tool arguments, short output tails, and user-prompt
snippets. These are transcript-derived text, not redacted metadata; enabling
a remote scorer sends them to its configured endpoint even when additional
content excerpts are disabled. Apple scoring runs on-device. All model
scorers retain deterministic heuristic scores whenever a model omits an
answer or a request fails. Hosted LLM settings are hard-capped
at 256 candidates, 64 items per batch, 16 batches, and a 100–30,000 ms
timeout. The built-in heuristic remains the recommended published path because
current live trials did not show a better plan from the LLM scorer.
The scored strategy also supports an optional keep-score cutoff. For example,
add this named preset to your config:
[presets.retained]
strategy = "scored"
keep_score_threshold = 0.5Inspect it with gobstopper plan <session-id> --preset retained; use the same
flag with gobstopper apply to create a fork. Candidates
at or above the cutoff are preserved, even if that prevents reaching the token
target. Missing, invalid, or duplicate candidate scores are also preserved.
The value must be finite and between 0.0 and 1.0. The heuristic score is a
ranking signal, not a calibrated probability; 0.5 is an experimental example,
not a tuned recommendation. Model scorers still use heuristic fallback for
partial or failed responses, so the cutoff does not guarantee provider
confidence. Set strategy = "scored" explicitly: auto, compacted, and other
strategies ignore the cutoff. Omitting it in a later configuration layer
inherits an earlier value rather than clearing it. The default configuration
has no cutoff and retains its existing behavior.
GOBSTOPPER_SCORER=jev scores with TypeSafe's System One API — typed
noul keep-probabilities without prose generation. Onboarding vaults the key
in the OS credential store
(macOS Keychain, Windows Credential Manager, Linux kernel keyring):
pbpaste | gobstopper auth jev # or run it bare to use the clipboard
gobstopper auth jev --status # key source + masked value + live check
gobstopper auth jev --delete # remove the stored keyThe key is verified against the API before it is stored; a rejected key
never reaches the keychain. Resolution order at scoring time is
TYPESAFE_API_KEY → GOBSTOPPER_JEV_API_KEY → OS keychain, so CI keeps
working from env alone. Linux kernel-keyring entries are session-scoped and
do not survive a reboot; use an environment variable for persistent
noninteractive Linux automation. On macOS, a self-built unsigned binary may
show a one-time keychain access prompt on first read. Remote scorers require
curl 8.3+: bearer credentials are imported from a child-only environment
variable and expanded inside curl, never placed in process argv; Gobstopper
also disables .curlrc for these calls so user defaults cannot enable verbose
header logging.
GOBSTOPPER_JEV_CONTENT_BYTES (default 0, maximum 1024) opts in to
attaching additional bounded per-candidate content excerpts to each question.
The remote scorer already receives the bounded labels and summaries described
above. A post-fix 141k-token A/B run selected the same six records with and
without 400-byte additional excerpts, so those excerpts remain off by default.
Every numeric runtime knob is clamped: 1–64 questions per call, 1–128 state
items, 100–30,000 ms timeout, 1–16 batches per scoring pass, and 1–4
concurrent calls (GOBSTOPPER_JEV_PARALLEL, default 2).
GOBSTOPPER_JEV_MAX_BATCHES defaults to 4. Only the newest
MAX_Q × MAX_BATCHES tailward candidates are sent; an older prefix keeps its
deterministic heuristic score. This caps the default at four calls and 256
remote-scored candidates even for unusually large transcripts. Identical
question texts within a pass are asked once: repeated tool outputs share a
single remote answer instead of being billed per item. Batches run through
a bounded worker pool: execution is parallel, but results are overlaid in
stable order, a failed or panicked batch retains heuristic scores, and
cached answers still overlay when a batch's remote half fails. Each pass logs one summary line
to stderr (candidates, unique/cached/sent questions, calls, failures,
elapsed). In a historical trial recorded on September 19, 2026, one three-batch
336k-token Claude session took 148.64s before bounded parallelism and 19.47s
afterward (about 7.6×). This single-session latency observation does not
establish current or provider-wide performance.
eval and bench now honor GOBSTOPPER_SCORER for their scored row, so
an A/B run measures the same Jev or Apple ranking used by plan rather than
silently substituting the heuristic. GOBSTOPPER_EVAL_JUDGE=jev adds a
separate semantic recall score to eval. Verbatim survivors are credited
locally; only up to 64 facts absent from the rewritten file become typed
noul questions. They are judged against at most 100,000 bytes of bounded
compaction evidence (state cards, elision stubs, and short tool records, with
a head+tail fallback), so semantic recall cannot be lower than verbatim
recall and an intact rewrite costs no judge request. The judge is off by
default because missed-fact evaluation sends that bounded evidence to the
remote API; failures simply omit the semantic score. Restricting the run to
--strategy scored uses at most one judge request:
GOBSTOPPER_SCORER=jev GOBSTOPPER_EVAL_JUDGE=jev \
gobstopper eval <session> --strategy scoredGobstopper reads the official answers.<id>.noul probability returned by
System One, while retaining bounded compatibility fallbacks for older response
shapes. Jev starts from the complete deterministic heuristic ranking and
overlays only valid remote answers; capped candidates, missing answers, and
failed or malformed chunks keep their heuristic scores. Semantic eval omits
its model score instead of crediting unknown facts. In one post-fix 80k-token
A/B run, Jev chose five smaller records where the heuristic chose four larger
ones, reclaimed about 649 more tokens, and both retained all 38 extracted
probes. At a more aggressive floor, one probe lost verbatim was not falsely
credited by the semantic judge (37/38 on both scores). This is single-session
qualification, not a general ranking-quality claim.
Successful Jev answers are cached in-process for five minutes under two
scopes. The scorer caches each question together with the complete scoring
state and model identifier. Unchanged polls reuse judgments, including across
different question batches. A changed goal or tail requires fresh answers
when that change is represented in the bounded scoring state; the cache cannot
detect task changes omitted from that state. The eval judge caches whole exact
requests.
Cache keys cover endpoint, credential identity, and question plus scoring
state or full request text; values are
parsed probabilities only (never transcript text), evict oldest-first at
512 questions and 64 requests, and failures are never cached. The
question layer also persists to
~/.local/share/gobstopper/jev-cache.json — only sha256 key digests
mapped to probability + timestamp, never text — so a cold plan inside
the TTL can reuse an answer when its question and scoring state match.
Older question-only cache entries cannot match the context-bound keys.
Transient
transport errors and HTTP 5xx responses are retried once; auth rejections
are not. The scorer and judge resolve the API key once per process, so
watch does not re-read the OS credential store every pass. Set
GOBSTOPPER_JEV_CACHE=0 or GOBSTOPPER_JEV_CACHE_TTL_SECS=0 to disable
both layers;
GOBSTOPPER_JEV_CACHE_PATH relocates the disk file;
the TTL maximum is 3,600 seconds.
GOBSTOPPER_SCORER=apple (macOS 26+, Apple Silicon) scores on-device with
Apple Intelligence Foundation Models via the shared apple-foundation
bridge — free, private, no API key. The bridge auto-builds to
~/.local/share/gobstopper/apple-bridge on first use (or set
GOBSTOPPER_APPLE_BRIDGE), requests queue through one persistent process
with guided JSON output, and any failure retains heuristic scores.
GOBSTOPPER_APPLE_TIMEOUT_MS, _MAX_CANDIDATES, _BATCH_SIZE, and
_MAX_BATCHES tune it, hard-capped at 100–600,000 ms, 256 candidates, 64
labels-only items per batch (8 with content), and 16 batches. Since inference
is local, the scorer also reads a bounded excerpt of each candidate record
(GOBSTOPPER_APPLE_CONTENT_BYTES, default and maximum 400; 0 restores
labels-only scoring) and shrinks its default batch sizes to fit the ~4k-token
context window. Each batch's guided schema contains one required p_<id> field
per candidate, so omitted or duplicate array IDs cannot silently distort the
ranking; a malformed batch retains its heuristic scores.
GOBSTOPPER_DIGEST=apple goes further: the injected state card is written
by the on-device model instead of keyword extraction. Because inference is
local, it may read bounded excerpts of the records being elided without a
remote request. Each field still
lands in the same DigestBlock shape via guided output, capped to a small
token overhead, and falls back to the mechanical card on any failure.
GOBSTOPPER_APPLE_DIGEST_ITEMS, _ITEM_BYTES, and _TOTAL_BYTES tune the
excerpt budget, hard-capped at 32 records, 2,048 bytes per record, and 16,000
bytes total; zero disables the model digest and preserves the mechanical card.
The same call also writes a one-line stub per excerpted record — e.g.
Script completed Wall time 4.4 seconds — stored in the elide edit's
per_item_stubs map and rendered verbatim in place of the {bytes}/{kind}
template where the payload was removed. Records the model did not cover
keep the generic stub; invalid or oversized stubs are dropped by validation.
Apple requests are cached in-process on the SHA-256 of the (prompt, schema)
pair: watch re-evaluates an unchanged transcript every poll interval, and
identical model inputs return the recorded response instead of another
generation — a live dry-run poll went from ~17s to milliseconds per re-eval.
The cache is bounded at 64 entries with oldest-first eviction;
GOBSTOPPER_APPLE_CACHE=0 disables both reads and writes. Scorer diagnostics
report cached batches separately from real model calls. The savings gate
also prices the residual stub text left behind by elision so
context_tokens_after doesn't overstate reclaim.
With adaptive = true, the effective trigger/floor are re-derived per
session at each decision point: the trigger is capped at a quarter of
the provider-advertised context window, backed off (bounded 2x) when
recent compactions reclaimed too little to be worth a cycle, and
tightened when most of the window is reclaimable tool output. The
adjustment is deterministic and its reasons appear in plan output and
telemetry. gobstopper tune <session> previews it.
oompa never parses provider transcript files — that boundary stays intact.
Integration is the policy-check subcommand: oompa already records
token_usage events (totalTokens, modelContextWindow) in its neutral
timeline, so it asks gobstopper what to do with them:
gobstopper policy-check --provider codex --context-tokens 300000 \
--session-active --json
# {"action":"provider_compact","control":"thread/compact/start", ...}oompa then invokes thread/compact/start on its own app-server
connection, or launches Claude sessions with --autocompact <tokens>.
Deeper transcript surgery stays gobstopper-side and publishes verified forks
for explicit resume. It never creates a second writer for an oompa-managed
session.
| lever | codex | claude code |
|---|---|---|
| auto-compact threshold | model_auto_compact_token_limit (config; ≤90% of window) |
--autocompact <100k–1M> argv |
| on-demand trigger | thread/compact/start (app-server v2) |
/compact [instructions] |
| compaction prompt | compact_prompt config |
/compact instructions |
| tool output cap | tool_output_token_limit |
— |
| live usage stream | thread/tokenUsage/updated notification |
message.usage per turn |
| transcript store | ~/.codex/sessions/**/rollout-*.jsonl |
~/.claude/projects/*/*.jsonl |
Codex persists compaction as a compacted rollout record carrying
replacement_history — the provider's own resume-time context swap.
gobstopper's parser and verifier understand that shape, including tool pairs
inside replacement_history. Synthetic records are experimental, pair-aware,
transactional, and available only behind --experimental-compacted; ordinary
apply uses the portable forked digest representation.
crates/gobstopper-core— normalized transcript model, theEditIR,Strategytrait, and all built-in strategies. No I/O.crates/gobstopper-adapters— bounded session discovery, Codex/Claude JSONL parsing and candidate rewriting, transactional no-clobber publication, verification, plugin hosting, and the snapshot vault.crates/gobstopper-cli—gobstopperbinary: detect / plan / apply / verify / undo / vault / history / show / recall / diff / bench / mcp / watch / policy-check / presets / explain.
The September 19, 2026 retrospective
evaluated 729 frozen sessions on one Mac. Portable compacted projected a
36.4% median reduction across 73 high-context archived Codex roots, with
76.9% sampled-string retention. Across all 729 sessions, 637 produced no
plan and the median reduction was 0%. These are offline projections, not
billing savings or task-accuracy measurements. The page includes all cohorts,
limitations, and downloadable aggregate results and methodology.
A separate paired scored-policy replay
reused the 114 archived roots with the corrected probe limit. This development
comparison is not held-out validation; the original baseline was already known.
On the 73
high-context tasks, a 0.35 cutoff increased sampled-string retention from
77.05% to 80.78% while median projected reduction fell from 36.44% to 34.96%.
Two tasks produced no plan, and their retention is derived from leaving the
source unchanged. All three registered cutoffs and both disabled baselines are
reported; the default remains unchanged. This is a limited retention/size
tradeoff, not a task-quality result or a recommended optimum.
The following single-session experiments were recorded in the repository on September 17 using earlier builds and workflows. They are separate from the 729-session retrospective and do not establish current provider-wide savings or general task quality. One 333k-token Claude session was asked the same resume question under four conditions, measuring provider tokens on that turn:
| condition | input tokens on resume | output tokens | recalled the standing task? |
|---|---|---|---|
| none (original) | 312,722 | 1,405 | yes — reported npm unification and stalled renames |
gobstopper elide |
219,167 | 1,052 | yes — same standing task, stalled renames |
gobstopper compacted |
220,447 | 621 | yes — same standing task from the state-card digest |
claude --autocompact 100 |
56,300 | 416 | no — incorrectly claimed the renames were already done and published |
gobstopper elide and compacted both cut the resume context by about
30% while keeping the answer accurate. Claude's native --autocompact 100
cut the resume context by ~82% but produced a confident, inaccurate
summary of the session.
The same question was then asked on a 101k-token Codex session:
| condition | input tokens on resume | output tokens | recalled the standing task? |
|---|---|---|---|
| none (original) | 101,275 | 244 | yes — Oh's memory benchmark and the 0.60 expansion gate |
gobstopper elide |
57,980 | 83 | yes — same 0.545 score and 0.60 gate |
gobstopper compacted |
34,503 | 159 | yes — same BEAM experiment and expansion gate |
On Codex, compacted cut resume input tokens by 66% and elide cut
them by 43%, both with accurate answers to that question. Provider-native
Codex compaction was not included in this historical trial.
The same-session cache_aware A/B (339k-token Claude session, floor 310k,
real provider cache counters):
| condition | cache_read |
cache_creation |
file-level prefix preserved | cost | accurate? |
|---|---|---|---|---|---|
| none (original) | 10,010 | 325,647 | — | $6.53 | yes |
gobstopper cache_aware |
13,536 | 258,517 | 107,884 tokens | $5.19 | yes |
gobstopper compacted |
13,536 | 257,505 | 6,639 tokens | $5.18 | yes |
In this trial, cache_aware and compacted had almost the same API cost and
both recorded 13,536 cache-read tokens, versus 10,010 in the baseline.
cache_aware preserved 16x more identical transcript prefix, an
auditability result; this trial did not establish extra provider cache savings
from the preserved prefix. Current compacted uses a portable forked digest;
synthetic Codex-native records require --experimental-compacted.
Snapshots and gobstopper diff make compaction inspectable and provide a
recovery path. They do not guarantee that omitted facts are unimportant or
that a continuation will retrieve them automatically.
- Codex custom
compactedrecord — a gobstopper-writtencompactedrecord with a correct window chain was accepted bycodex exec resumeand the model completed a real API turn recalling the elided commands. - Claude Code digest resume — an earlier qualification trial on a separate
333k-token test copy elided 43 stale tool records and injected a state card;
claude --resumesucceeded and recalled the standing task. Current releases preserve that evidence while exposing standalone application only through no-clobber fork publication.
The published safety posture is conservative: plan, eval, verify, MCP,
and provider inspection are read-only; standalone apply, watch, and undo
publish separate files and never overwrite a provider-owned source. Candidate
publication is source-hash-bound, no-clobber, snapshotted, structurally
verified, idempotent through durable receipts, and bounded to 128 MiB/100,000
records. The default deterministic strategies and built-in Codex/Claude
adapters are covered by unit, regression, property, and live-resume evidence.
Direct provider controls still belong to the live session owner. Synthetic
Codex compacted records, external model scoring, and semantic editor plugins
remain explicitly experimental or trusted extension paths. Devin support is a
native numeric policy/MCP handoff to /compact, not direct transcript surgery.
See docs/design.md, docs/roadmap.md,
docs/plugin-protocol.md, and
docs/devin.md for the boundaries.
MIT OR Apache-2.0