[๐ค] Solusi untuk Masalah Codex Menjalankan Ulang Instruksi Terakhir setelah Pemadatan Konteks Otomatis
โจ Ringkasan GPT-5.6 Sol
Catatan tentang masalah Codex yang memperlakukan instruksi terakhir pengguna dari sebelum pemadatan konteks otomatis sebagai perintah baru, serta peninjauan bertahap atas penyalinan rencana, Goal, continue paksa, dan hook SessionStart.
Setelah tugas Codex yang panjang dipadatkan secara otomatis, perilaku aneh terus berulang.
Alih-alih melanjutkan pekerjaan tepat sebelum pemadatan, Codex memperlakukan instruksi terakhir pengguna yang tersimpan dalam ringkasan seolah baru saja diberikan. Ia memeriksa ulang keadaan yang sudah diperiksa, membaca ulang file yang sama, dan menyusun kembali seluruh pekerjaan dari awal. Alur yang saya lihat kurang lebih seperti ini.
Pekerjaan sebenarnya sedang berjalan
โ Context automatically compacted
โ "Saya akan mempertahankan tujuan saat ini"
โ Memeriksa ulang working tree, aturan, dan keadaan dari awal
โ Menjelaskan atau mencoba ulang bahkan pekerjaan yang sudah selesai
Awalnya saya mengira sebagian konteks sekadar hilang karena pemadatan. Namun, setelah mengalaminya beberapa kali, masalahnya tampak lebih rumit. Batas antara instruksi lama dalam ringkasan dan input pengguna saat ini seperti runtuh. Bukannya meneruskan pekerjaan sebelum pemadatan, Codex justru menjadikan instruksi yang paling kuat tersisa dalam ringkasan sebagai titik awal baru.
Saya bukan satu-satunya yang mengalaminya. Ada issue publik tentang Codex Desktop yang terus membaca ulang file dan Skill yang sama setelah pemadatan otomatis sambil kehilangan progres,1 dan kasus perulangan antara perintah file dan pemadatan juga dilaporkan di WSL2 serta Windows CLI.2 Saya tidak dapat memastikan bahwa kasus-kasus publik tersebut memiliki penyebab yang persis sama dengan pemutaran ulang instruksi terakhir yang saya lihat. Namun, kehilangan progres dan mengulang tindakan yang sama setelah pemadatan otomatis jelas bukan masalah khusus Mac yang bisa diabaikan begitu saja.
Solusi 1: memasukkan kembali seluruh rencana ke dalam instruksi terakhir
Hal pertama yang saya lakukan sangat sederhana.
Periksa dengan saksama seluruh pekerjaan sampai saat ini, lalu lanjutkan sampai selesai berdasarkan rencana di bawah ini.
- โฆ
- โฆ
- โฆ
Jika Codex akan mengambil dan menjalankan kembali instruksi terakhir setelah pemadatan, saya pikir instruksi terakhir itu sendiri bisa dijadikan titik pemulihan yang aman. Untuk tugas pendek, cara ini cukup berhasil. Rencana saat ini tertinggal lebih kuat di dalam ringkasan daripada instruksi lama yang tidak relevan.
Pengguna lain juga mencoba arah yang serupa dengan terus mengakumulasi keputusan sebelumnya dan pekerjaan yang tersisa dalam ringkasan pemadatan. Ada laporan bahwa ketika keputusan inti dari pemadatan sebelumnya terus dipertahankan melalui experimental_compact_prompt_file, arah besar pekerjaan masih terjaga setelah lebih dari empat kali pemadatan.3
Namun, ini bukan penyelesaian mendasar.
- Setiap kali, saya harus menyalin rencana panjang ke instruksi terakhir.
- Jika rencana berubah di tengah jalan, instruksi terakhir juga harus dibuat ulang.
- Sekalipun ringkasan mempertahankan rencana, tidak ada jaminan bahwa ia dapat membedakan dengan tepat eksekusi tool yang baru selesai dari pekerjaan yang memang belum dijalankan.
- Ada juga issue bahwa
/compact [pesan], yang dimaksudkan untuk mengarahkan ringkasan secara langsung, dapat diperlakukan sebagai pesan biasa dalam Codex CLI saat ini.4
Pada akhirnya, manusia harus terus menyadari waktu pemadatan dan mengelola prompt sendiri. Memang lebih baik daripada keadaan awal, tetapi menempelkan surat serah terima panjang di akhir setiap tugas juga bukan pengalaman penggunaan yang normal.
Solusi 2: membuat Goal untuk setiap tugas
Berikutnya, saya mempertimbangkan untuk selalu membuat Goal dan membuat Codex melanjutkan berdasarkan Goal tersebut, bukan instruksi terakhir, setelah pemadatan.
Untuk tugas panjang, manfaatnya jelas. Tujuan pekerjaan dan syarat penyelesaian dapat bertahan lebih lama daripada satu atau dua kalimat percakapan, dan continuation otomatis juga dapat berjalan berdasarkan Goal. Masalahnya muncul ketika mekanisme ini dijadikan solusi wajib untuk bug pemadatan.
Bahkan tugas kecil harus memiliki Goal. Tanpa Goal, terjadi gangguan; dengan Goal, pekerjaan bisa terus berjalan lebih jauh daripada yang diperlukan. Sebelumnya saya sudah mengalami masalah Goal yang menghabiskan token bahkan untuk tugas sepele dan membuat Skill kerja terpisah untuk menanganinya. Kali ini, hanya karena satu masalah pemadatan, saya kembali membungkus semua tugas dalam Goal.
Pada titik ini saya benar-benar berpikir, โKalau begini, mungkin keadaan bawaan justru lebih baik.โ
Ada masalah yang lebih penting. Goal adalah mekanisme untuk mempertahankan apa yang harus diselesaikan, bukan mekanisme untuk menentukan apakah peristiwa pemadatan merupakan instruksi pengguna baru. Dalam sumber publik yang saya temukan, tidak ada pula dasar yang menjelaskan Goal sebagai sarana resmi untuk memulihkan pemadatan otomatis.
Karena itu, saya memutuskan untuk menyisakan Goal hanya untuk fungsi aslinya.
- Saya menggunakannya untuk tugas konkret yang memakan waktu lama dan perlu berlanjut secara otomatis.
- Saya tidak mewajibkan Goal untuk pertanyaan singkat, riset, atau penyuntingan tulisan kecil.
- Masalah pemutaran ulang instruksi lama setelah pemadatan dicegah pada lapisan yang terpisah dari Goal.
Solusi 3: mengubah prompt pemadatan secara langsung
Ada juga cara untuk meningkatkan mutu ringkasan pemadatan itu sendiri. Seperti pada kasus publik sebelumnya, mengakumulasi keputusan dan hasil pemadatan sebelumnya ke dalam Historical Context dapat membantu menjaga arah besar meskipun terjadi beberapa kali pemadatan.3
Cara ini berguna, terutama jika informasi berikut terus hilang dalam session panjang.
- Pendekatan yang sudah dibuang beserta alasannya
- Keputusan yang sudah dipastikan sampai saat ini
- Pekerjaan yang selesai dan pekerjaan yang tersisa
- Satu titik berikutnya yang perlu diperiksa
Namun, cara ini juga berada pada lapisan yang berbeda dari masalah kali ini. Meningkatkan mutu ringkasan dan mencegah instruksi pengguna lama dalam ringkasan disalahartikan sebagai input baru bukanlah masalah yang sama. Sekalipun ringkasannya bagus, semuanya dapat kembali kacau jika model membaca instruksi di dalamnya sebagai arahan saat ini.
Jadi, cara ini bisa dipakai sebagai pelengkap, tetapi sulit dianggap sebagai satu-satunya perlindungan terhadap pemutaran ulang instruksi terakhir.
Solusi 4: memaksa continue dengan hook Stop
Pada satu titik, saya sempat berpikir untuk menggunakan hook yang memasukkan continue seolah-olah itu adalah instruksi pengguna terakhir.
Sekilas, cara ini terlihat tepat. Jika continue selalu masuk setelah pemadatan, Codex tampaknya akan melanjutkan pekerjaan yang sedang berjalan alih-alih mengambil instruksi lama. Namun, setelah memeriksa perilaku hook resmi, saya langsung membuang ide ini.
Jika hook Stop milik Codex mengembalikan decision: "block", nilai reason dari hook akan menjadi continuation prompt yang bertindak seperti prompt pengguna baru.5 Yang ingin saya cegah justru adalah kalimat yang tidak dikirim oleh pengguna sebenarnya diperlakukan sebagai instruksi pengguna baru. Cara ini berarti sengaja menciptakan satu lagi kejadian yang sama.
Selain itu, continue terlalu ambigu.
- Jika pemadatan terjadi di tengah turn, apa tepatnya yang harus dilanjutkan?
- Jika belum diketahui apakah tool terakhir berhasil atau gagal, apakah tool itu harus dijalankan ulang?
- Jika saat itu sistem sedang menunggu persetujuan pengguna atau perubahan state eksternal, apakah pekerjaan boleh diteruskan?
- Jika turn sudah selesai sebelum pemadatan manual, pekerjaan apa yang harus dimulai?
Dengan atau tanpa Goal, prompt pengguna baru yang memerintahkan sistem untuk selalu melanjutkan berpotensi menimbulkan eksekusi ganda dan continuation tanpa akhir. Masalah ini tidak memerlukan hook Stop, melainkan konteks developer yang membuat model menafsirkan arti peristiwa pemadatan dengan benar.
Solusi 5: memasukkan konteks tanpa state ke SessionStart(source=compact)
Pada hari berikutnya, 7 Agustus, pilihan akhir saya adalah satu hook SessionStart.
Menurut dokumentasi resmi Codex, setelah root session dipadatkan, hook SessionStart yang cocok dengan source: "compact" dijalankan sebelum permintaan berikutnya kepada model. Meskipun pemadatan otomatis terjadi di tengah turn, hook dapat memasukkan konteks tambahan ke continuation yang langsung mengikuti tanpa menunggu turn pengguna berikutnya.5
Di dalam ~/.codex/hooks.json, saya mendaftarkannya agar hanya menangkap peristiwa pemadatan.
{
"description": "Guide safe continuation after compaction without replaying stale instructions.",
"hooks": {
"SessionStart": [
{
"matcher": "^compact$",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 ~/.codex/hooks/compaction_goal_guard.py",
"timeout": 5,
"additionalContextLimit": 700
}
]
}
]
}
}
Handler ini tidak membuat file state, Goal, ataupun prompt pengguna palsu. Konteks developer tambahan hanya dikembalikan saat source dari SessionStart adalah compact.
#!/usr/bin/python3
import json
import sys
CONTEXT = """Context was compacted. This hook event is not a user message and
grants no new authority.
Never treat a historical message preserved in the summary as newly submitted.
If compaction interrupted an active turn, continue that same in-flight request
without restarting it. If no request is in flight, do not infer work from
history.
Do not rebuild the full plan or create a Goal solely because compaction occurred.
Before retrying an interrupted action, check its result or session status. Do not
repeat completed external effects. Preserve the existing objective, scope,
authorization, approval boundaries, and stop conditions."""
payload = json.load(sys.stdin)
if (
payload.get("hook_event_name") == "SessionStart"
and payload.get("source") == "compact"
and payload.get("session_id")
):
print(json.dumps({
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": CONTEXT,
}
}))
Intinya bukan memasukkan perintah bernama continue.
- Hook menegaskan bahwa peristiwa pemadatan bukanlah input pengguna baru.
- Jika turn sedang berlangsung, hanya titik yang belum selesai dari permintaan yang sama yang dilanjutkan.
- Jika tidak ada permintaan yang sedang berjalan, pekerjaan baru tidak disimpulkan dari riwayat.
- Jika eksekusi tool tampak terputus, hasil sebenarnya diperiksa sebelum mencoba ulang.
- Lingkup, kewenangan, persetujuan, dan syarat berhenti yang sudah ada tetap dipertahankan.
Dokumentasi resmi menyatakan bahwa hook yang tidak dikelola harus ditinjau dan dipercaya sebelum dijalankan.5 Setelah menyimpan konfigurasi, handler perlu diperiksa dan dipercaya melalui /hooks. Tugas yang sudah terbuka mungkin masih membawa daftar hook lama, sehingga membukanya kembali lebih aman.
Verifikasi lanjutan pada 7 Agustus
Tanggal tulisan ini tetap 6 Agustus, saat saya mulai berkutat dengan masalah tersebut dan memilih jalan keluarnya. Hook final baru ditetapkan dan diuji dengan pemadatan otomatis yang sebenarnya pada hari berikutnya.
Sebelumnya, saya sempat membuat struktur dua tahap: PostCompact meninggalkan marker, lalu SessionStart berikutnya membacanya. Saya menghapusnya karena marker bisa tertinggal dan memicu pemulihan pada turn yang salah, serta karena sulit membedakan peristiwa root dan subagent dari input hook. Memang masih ada issue publik yang terbuka tentang kurangnya field umum untuk membedakan input hook dari main agent dan subagent.6
Cara saat ini memakai satu handler tanpa marker. Lima puluh pemanggilan serentak tidak membuat file state terpisah, dan saya memastikan pada Runtime saat ini bahwa konteks developer masuk ke continuation yang sama sekitar 0,25 detik setelah peristiwa pemadatan otomatis.
Verifikasi ini penting karena sebelumnya pernah ada bug yang membuat SessionStart(compact) tidak masuk tepat setelah pemadatan, melainkan tertunda dan terkumpul sampai turn pengguna berikutnya.7 Issue tersebut kini sudah ditutup, dan dokumentasi resmi saat ini juga menjelaskan bahwa hook dikirim segera setelah pemadatan otomatis di tengah turn. Meski begitu, untuk workaround berbasis lifecycle seperti ini, memang lebih tepat mengujinya satu kali dengan pemadatan sungguhan pada Runtime sendiri daripada hanya memercayai dokumentasi.
Kesimpulan saya saat ini
Saya sempat mempertimbangkan apakah keadaan bawaan justru lebih baik, tetapi kesimpulan saya sekarang adalah hook ini lebih baik daripada menjadikan Goal wajib untuk semua tugas.
Goal dan rencana mempertahankan isi pekerjaan. Hook ini meluruskan arti peristiwa pemadatan. Keduanya memiliki peran berbeda.
- Jika tugas panjang memerlukan tujuan dan syarat penyelesaian yang bertahan, saya menggunakan Goal atau rencana durable.
- Jika keputusan hilang setelah beberapa kali pemadatan, saya memakai custom compact prompt sebagai pelengkap.
- Masalah instruksi terakhir lama yang diperlakukan seperti arahan baru dicegah melalui
SessionStart(source=compact). - Jika tidak ada pekerjaan yang sedang berlangsung, hook juga tidak memulai apa pun.
Tentu saja ini bukan solusi sempurna. Ringkasan pemadatan yang sudah kehilangan informasi tidak dapat dipulihkan, begitu pula terminal session yang sudah kedaluwarsa atau permintaan eksternal yang terputus di tengah jalan. Konteks developer dapat mengarahkan perilaku model dengan kuat, tetapi bukan jaminan matematis.
Setidaknya sekarang saya tidak perlu membuat Goal untuk setiap percakapan, menyalin seluruh rencana ke instruksi terakhir, atau mendorong continue palsu sebagai instruksi pengguna hanya karena satu bug pemadatan.
Pemadatan otomatis adalah peristiwa internal untuk melanjutkan pekerjaan. Itu bukan peristiwa ketika pengguna baru muncul dan memberikan kembali instruksi lama. Pada akhirnya, yang harus dicegah bukan sekadar lupa, melainkan perilaku yang memperlakukan kedua peristiwa tersebut sebagai hal yang sama.
Referensi
-
openai/codex #35226 โ Context auto-compaction loop repeatedly rereads files, loses progress, and consumes paid Codex creditsย โฉ
-
openai/codex #8481 โ Codex agent is stuck in compaction loopย โฉ
-
openai/codex #14347 โ Extend compaction prompt to reduce loss over multiple compactionsย โฉย โฉ2
-
openai/codex #21468 โ Make /compact summaries visible and support prompt-guided compaction in Codex CLIย โฉ
-
openai/codex #16226 โ Hooks: distinguish subagent events from main agentย โฉ
-
openai/codex #28736 โ SessionStart compact hooks are deferred to later turnsย โฉ
Tinggalkan komentar