Skip to content

Enhanced context handoff: compression, versioning, I2I integration#5

Open
SuperInstance wants to merge 1 commit intomainfrom
superz/baton-enhance
Open

Enhanced context handoff: compression, versioning, I2I integration#5
SuperInstance wants to merge 1 commit intomainfrom
superz/baton-enhance

Conversation

@SuperInstance
Copy link
Copy Markdown
Owner

@SuperInstance SuperInstance commented Apr 13, 2026

T-016 integration + handoff improvements

flux-baton v3

New Features

  • Context compression: compress_context() and compress_handoff_text() with ratio tracking
  • Priority task queue: TaskQueue with heapq-based ordering, TASK_CLAIM/TASK_COMPLETE I2I v2 semantics
  • Handoff acknowledgment protocol: HandoffAckTracker with send/ack/reject/timeout lifecycle
  • Context versioning: ContextVersion (semver per generation) with content hash chain via ContextVersionTracker
  • Conflict resolution: ConflictResolver with 4 strategies (FCFS, highest confidence, priority, manual escalation)
  • Handoff metrics: HandoffMetrics — success rate, compression ratio, quality score, duration
  • I2I v2 integration: TASK_CLAIM, TASK_COMPLETE, BATON_PACKED, BATON_ACK, BATON_CLAIM_CONFLICT, BATON_CONTEXT_VERSION

Enhanced Baton Class

  • snapshot() now persists: CONTEXT_VERSION.json, TASK_QUEUE.json, COMPRESSED_CONTEXT.json, HANDOFF_METRICS.json
  • write_handoff() includes task queue summary, metrics, and context version
  • i2i_task_claim() / i2i_task_complete() for I2I v2 message processing
  • acknowledge_handoff() / check_handoff_timeouts() for ack protocol

Tests

  • 75 tests across 10 test classes, all passing

Staging: Open in Devin

flux-baton v3 — T-016 integration + handoff improvements

New features:
- Context compression: summarize previous agent state for handoff
  with ratio tracking (compress_context, compress_handoff_text)
- Priority task queue: heapq-based queue with I2I v2 TASK_CLAIM/COMPLETE
  semantics (TaskQueue, PrioritizedTask)
- Handoff acknowledgment protocol: send/ack/timeout lifecycle
  (HandoffAck, HandoffAckTracker)
- Context versioning: semver per generation with content hash chain
  (ContextVersion, ContextVersionTracker)
- Conflict resolution: 4 strategies for duplicate task claims
  (ConflictResolver: FCFS, highest confidence, priority, manual escalation)
- Handoff metrics: success rate, compression ratio, quality, duration
  (HandoffMetrics)
- I2I v2 integration: TASK_CLAIM, TASK_COMPLETE, BATON_PACKED,
  BATON_ACK, BATON_CLAIM_CONFLICT, BATON_CONTEXT_VERSION

Enhanced Baton class:
- v3 snapshot persists CONTEXT_VERSION, TASK_QUEUE, COMPRESSED_CONTEXT,
  HANDOFF_METRICS alongside existing files
- write_handoff includes task queue summary, metrics, context version
- i2i_task_claim() and i2i_task_complete() methods
- acknowledge_handoff() and check_handoff_timeouts() methods

Tests: 75 tests across 10 test classes, all passing
Copy link
Copy Markdown

@beta-devin-ai-integration beta-devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 5 additional findings in Devin Review.

Staging: Open in Devin

Comment thread flux_baton.py
if cv_json:
try:
cv_data = json.loads(cv_json)
cv = ContextVersion(**cv_data)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 ContextVersion deserialization always fails due to extra semver key in to_dict()

to_dict() at flux_baton.py:631 includes a "semver" key (a computed @property, not a constructor field). During restore() at flux_baton.py:1075, ContextVersion(**cv_data) is called with this dict, which raises TypeError: __init__() got an unexpected keyword argument 'semver' because the ContextVersion dataclass (flux_baton.py:569-579) has no semver field. The bare except: pass at line 1078 silently swallows this error, so context version is never successfully restored from persisted state — every restore silently loses the version tracking chain.

Suggested change
cv = ContextVersion(**cv_data)
cv_data = json.loads(cv_json)
cv_data.pop("semver", None)
cv = ContextVersion(**cv_data)
Staging: Open in Devin

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Comment thread flux_baton.py
Comment on lines +1290 to +1305
# Write 12: GENERATION (COMMIT MARKER — written LAST)
results.append(self._write(".baton/GENERATION",
str(new_gen), f"baton: GENERATION → {new_gen} (commit)"))

# Send I2I notification

# v3 Write 13: HANDOFF_METRICS.json
metrics_record = self.metrics.record_handoff(
generation=new_gen,
context_version=ctx_version.semver,
original_size=compressed.original_size_bytes,
compressed_size=compressed.compressed_size_bytes,
quality_score=quality.get("average", 0),
duration_seconds=time.time() - snapshot_start,
)
results.append(self._write(".baton/HANDOFF_METRICS.json",
json.dumps({"handoffs": self.metrics._handoffs}, indent=2),
f"baton: metrics gen-{new_gen}"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 GENERATION commit marker written before HANDOFF_METRICS.json, breaking atomicity guarantee

The module docstring (flux_baton.py:16) and the comment at line 1290 state that GENERATION is the atomic commit marker and must be written last. However, HANDOFF_METRICS.json (Write 13, lines 1294-1305) is written after GENERATION (Write 12, lines 1290-1292). This breaks the atomicity invariant: a reader could see the new generation number but find missing or stale metrics data. The metrics write should be moved before the GENERATION write.

Suggested change
# Write 12: GENERATION (COMMIT MARKER — written LAST)
results.append(self._write(".baton/GENERATION",
str(new_gen), f"baton: GENERATION → {new_gen} (commit)"))
# Send I2I notification
# v3 Write 13: HANDOFF_METRICS.json
metrics_record = self.metrics.record_handoff(
generation=new_gen,
context_version=ctx_version.semver,
original_size=compressed.original_size_bytes,
compressed_size=compressed.compressed_size_bytes,
quality_score=quality.get("average", 0),
duration_seconds=time.time() - snapshot_start,
)
results.append(self._write(".baton/HANDOFF_METRICS.json",
json.dumps({"handoffs": self.metrics._handoffs}, indent=2),
f"baton: metrics gen-{new_gen}"))
# v3 Write 12: HANDOFF_METRICS.json
metrics_record = self.metrics.record_handoff(
generation=new_gen,
context_version=ctx_version.semver,
original_size=compressed.original_size_bytes,
compressed_size=compressed.compressed_size_bytes,
quality_score=quality.get("average", 0),
duration_seconds=time.time() - snapshot_start,
)
results.append(self._write(".baton/HANDOFF_METRICS.json",
json.dumps({"handoffs": self.metrics._handoffs}, indent=2),
f"baton: metrics gen-{new_gen}"))
# Write 13: GENERATION (COMMIT MARKER — written LAST)
results.append(self._write(".baton/GENERATION",
str(new_gen), f"baton: GENERATION → {new_gen} (commit)"))
Staging: Open in Devin

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant