fix: feat: agents flush context to scratch file before compaction (#262)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-20 20:12:45 +00:00
parent edfdae9ad8
commit 7199bbf9b5
7 changed files with 138 additions and 16 deletions

View file

@ -41,6 +41,7 @@ WORKTREE="${PROJECT_REPO_ROOT}"
PHASE_FILE="/tmp/action-session-${PROJECT_NAME:-harb}-${ISSUE}.phase"
IMPL_SUMMARY_FILE="/tmp/action-impl-summary-${PROJECT_NAME:-harb}-${ISSUE}.txt"
PREFLIGHT_RESULT="/tmp/action-preflight-${ISSUE}.json"
SCRATCH_FILE="/tmp/action-${ISSUE}-scratch.md"
log() {
printf '[%s] action#%s %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$ISSUE" "$*" >> "$LOGFILE"
@ -86,7 +87,7 @@ cleanup() {
agent_kill_session "$SESSION_NAME"
# Best-effort docker cleanup for containers started during this action
(cd "${PROJECT_REPO_ROOT}" 2>/dev/null && docker compose down 2>/dev/null) || true
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$PREFLIGHT_RESULT"
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$PREFLIGHT_RESULT" "$SCRATCH_FILE"
}
trap cleanup EXIT
@ -166,6 +167,24 @@ if [ -n "${_thread_id:-}" ]; then
>> "${MATRIX_THREAD_MAP:-/tmp/matrix-thread-map}" 2>/dev/null || true
fi
# --- Read scratch file (compaction survival) ---
SCRATCH_CONTEXT=""
if [ -f "$SCRATCH_FILE" ]; then
SCRATCH_CONTEXT="## Previous context (from scratch file)
$(cat "$SCRATCH_FILE")
"
fi
SCRATCH_INSTRUCTION="## Context scratch file (compaction survival)
Periodically (every 10-15 tool calls), write a summary of:
- What you have discovered so far
- Decisions made and why
- What remains to do
to: ${SCRATCH_FILE}
If you find this file exists when you start, read it first — it is your previous context.
This file is ephemeral — not evidence or permanent memory, just a compaction survival mechanism."
# --- Build initial prompt ---
PRIOR_SECTION=""
if [ -n "$PRIOR_COMMENTS" ]; then
@ -193,7 +212,7 @@ in the issue below.
## Issue #${ISSUE}: ${ISSUE_TITLE}
${ISSUE_BODY}
${SCRATCH_CONTEXT}
${PRIOR_SECTION}## Instructions
1. Read the action formula steps in the issue body carefully.
@ -235,6 +254,8 @@ ${PRIOR_SECTION}## Instructions
If the prior comments above show work already completed, resume from where it
left off.
${SCRATCH_INSTRUCTION}
${PHASE_PROTOCOL_INSTRUCTIONS}"
# --- Create tmux session ---
@ -264,16 +285,16 @@ case "${_MONITOR_LOOP_EXIT:-}" in
# Escalate to supervisor (idle_prompt already escalated via _on_phase_change callback)
echo "{\"issue\":${ISSUE},\"pr\":${PR_NUMBER:-0},\"reason\":\"idle_timeout\",\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \
>> "${FACTORY_ROOT}/supervisor/escalations-${PROJECT_NAME}.jsonl"
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE"
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE" "$SCRATCH_FILE"
;;
idle_prompt)
# Notification + escalation already handled by _on_phase_change(PHASE:failed) callback
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE"
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE" "$SCRATCH_FILE"
;;
done)
# Belt-and-suspenders: callback handles primary cleanup,
# but ensure sentinel files are removed if callback was interrupted
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE"
rm -f "$PHASE_FILE" "$IMPL_SUMMARY_FILE" "$THREAD_FILE" "$SCRATCH_FILE"
;;
esac