Repository navigation
feat: conversation folders, per-conversation sampling and GC - #18
Merged
Merged
Conversation
EVALSHIFT_CAPTURE_LAYOUT=flat (or layout="flat") keeps the 0.6 layout. Needs evalshift CLI 1.6.0 or later to read. R10: @capture.agent captures stay flat: a decorator's conversation_id is static. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…newest turns, skip unreadable folders The count rule now runs on the files the TTL leaves, ordered unit by unit newest first: the newest units are kept whole while they fit, the unit at the boundary keeps its newest turns, older units go whole. One newer write no longer evicts a whole live conversation. A folder or file that cannot be read (or vanished mid-scan) is skipped instead of disabling the suite's GC. Flat-only suites still keep their newest max_captures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lled alongside CLI 1.5.x declares evalshift-sdk>=0.4.0 with no upper bound, so it can pull this SDK in unasked and then cannot see conversation folders. When neither a sink's layout= nor EVALSHIFT_CAPTURE_LAYOUT picks a layout, the SDK now checks once per process for an installed evalshift CLI older than 1.6, writes flat if it finds one and logs one warning. EVALSHIFT_CAPTURE_LAYOUT=conversation opts in anyway. A failed lookup means no guard; the check never raises. Also closes two test gaps: the async session's per-conversation sampling draw, and layout= on both sinks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GC: the TTL goes first and the count runs on what it leaves; the newest conversations are kept whole while they fit, the one at the boundary keeps its newest turns, older ones go whole. Layout: an evalshift CLI older than 1.6 installed alongside makes the SDK write flat with one warning, EVALSHIFT_CAPTURE_LAYOUT=conversation overrides it, and an older CLI elsewhere can't be detected. Sampling samples the conversation_id. DECISIONS D-conv-layout leads with the agent_session wording; the CHANGELOG GC bullet says flat capture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 tasks done
…ders Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requires evalshift CLI 1.6.0 or later. Don't merge this until CLI 1.6.0 is on PyPI. The CLI half is evalshift/evalshift-cli#60, which reads both layouts. This PR is a draft until then.
What this changes
Ships as evalshift-sdk 0.7.0. A conversation, not a turn, becomes the unit of capture storage.
capture.agent_session/agent_session_asyncturn with aconversation_idis written tocaptures/<suite>/conv_<16 hex of sha256(conversation_id)>/cap_<hex>.json. The relative path is the same on disk (FileSink) and in a bucket (ObjectStoreSink). Captures stay flat atcaptures/<suite>/cap_<hex>.jsonin these cases:@capture.agentdecorator captures, even with aconversation_id. That id is fixed when the function is decorated, so it names no conversation. Without this, a static-id agent would put its whole suite in one never-ending folder. The envelope still carries the id.EVALSHIFT_CAPTURE_LAYOUT=flat, orlayout="flat"on either sink, restores the 0.6 layout. This is also the rollback lever.evalshift-sdk>=0.4.0with no upper bound, so a fresh install of a pinned 1.5 would otherwise pull in 0.7.0 without anyone choosing it.EVALSHIFT_CAPTURE_LAYOUT=conversationoverrides the guard. An older CLI in a different environment, such as CI pinned to 1.5, can't be detected; the CHANGELOG says to upgrade it first.EVALSHIFT_SAMPLE_RATEset, anagent_sessionthat has aconversation_idis sampled by a hash of that id, so every turn is kept or dropped together in every process. The decorator, runs without an id, and the LangChain handler still draw at random.max_captures/capture_ttl, per suite directory):max_capturesturns.conversation_idandturn_index.DECISIONS.mdentry, D-conv-layout. It records the problem, the decision and why we rejected one mutable file per conversation, the trade-offs, and the compatibility rule. D-6, D-6a, D-toolset and D-stores are amended in place.Compatibility
capture cleancan sweep their toolset sidecars. Hence "upgrade the CLI first".EVALSHIFT_CAPTURE_LAYOUT=flatRelease order:
chore/release-0.7.0PR bumpspyproject.tomland__version__.v0.7.0, after checking the PyPI trusted publisher.Test plan
ruff check,ruff format --checkandmypy(107 files) are clean;pytest: 888 passed.New tests:
c1→conv_d0f631ca1ddba8db,planner:session-1→conv_e1961a13f5bd6642);Cross-repo smoke, with this branch writing and the CLI #60 branch reading, from disk and through a bucket, in a scratch venv with both editable installs.
EVALSHIFT_CAPTURE_LAYOUT=conversation):agent_sessionturns landed inplanner/conv_e1961a13f5bd6642/, while the standalone and@capture.agentcaptures stayed flat;capture syncpromoted all 5, and the last turn's history was rebuilt from the two earlier ones;FileSinktree, withteam/supportlanding inteam_support/conv_d0f631ca1ddba8dband 0 keys malformed.Per-task reviews, a whole-branch review, and a scoped re-review of its fixes. The whole-branch review found:
All three are fixed above. A probe compared the new GC rule with an independent reference on 3,000 random suites and found no mismatch.
Known trade-offs (documented in D-conv-layout)
max_captures, at the GC boundary, or older thancapture_ttlloses its oldest turns locally.capture cleanempties a folder just as another process writes into it, that one capture is dropped, fail-open.conversation_iditself. A user id passed asconversation_idsamples users.🤖 Generated with Claude Code