[Bug] /compact says a compaction is active when the agent is simply mid-turn #6223
Replies: 1 comment
|
Confirmed against master (c291e79) — every claim checks out and nothing has changed:
So an active compaction, a mid-turn agent (including the post-response window while turn-stopping hooks such as title generation still run — your log's 2.5 s / 45 s split is consistent with that), an unmatched bracket, and admission failures all collapse into Practical answer: the refusal itself is correct — compaction genuinely requires an idle agent, the claim is a real exclusion ( Your boundary-classifier direction is sound and cheap to land: the |
Uh oh!
There was an error while loading. Please reload this page.
Summary. A manual
/compactthat arrives while the agent is still finishing a turn is refused with a message that names the wrong cause — and the error classification makes the two cases indistinguishable for every consumer, not just/compact.Found on DSH Desktop (harness 0.1.2-rc.1). The same code path is still present on
master, so I'm reporting it rather than assuming it is known.What the user sees
That is the single
busyarm ofexpectedFailureinpackages/compaction/command-compact/src/index.ts:29.Why the message is wrong for this case. The refusal users actually hit is the agent loop rejecting the maintenance claim:
compactNowcatches everything and reports one code for all of it:So "another compaction is in progress" (what the copy leads with), "the agent is not idle" (vague, but the real cause), a live unmatched bracket, and an unavailable admission all arrive as
busy. The message leads with the case a user is least likely to have hit.Evidence from a real session log (
session.jsonl.zstd,tsin epoch ms):step/endof the answered turncommand/run compactcommand/donekind=errorturn/startThe refusal landed 2.5 s after the turn's final step and 45 s before the next turn began:
phase.kindwas stillrunning. Worth adding why the user thought the agent was idle —agent/turn-stoppinghooks (title generation) run beforeturn/end, so the response visibly ends tens of seconds before the phase does. That window is exactly when someone reaches for/compact, and exactly when the message is wrong.Suggested change. Classify at the boundary, then let each consumer name its own cause:
command-compactgains anagent-busyarm — "the agent is still working on this session. Wait for the turn to finish, then run /compact again." — andbusynarrows to the claim conflicts it already describes.Tests that currently encode the conflation (these need updating, not just adding alongside):
packages/compaction/compaction-basic/tests/manual-compaction.spec.ts:213— the fake agent throws the agent-loop string verbatim:if (release === undefined) throw new Error('agent already has active work'). The testkit comment calls it "a fake idle agent whose maintenance claim is scripted per test", so the string is effectively a contract.…/manual-compaction.spec.ts:345—reports busy without summarizing when a prompt already owns the next turn, assertingcode === 'busy'at:354; also the cases at:710({ name: 'busy', …, release: undefined }) and:884.packages/compaction/command-compact/tests/command-compact.spec.ts:209— pins the current user-facing string in a table.Working implementation, if useful. I implemented this against the 0.1.2-rc.1 published artifacts, shipped it in our desktop shell, and added a test pinning the classifier, both refusal messages, and the patch: dataelement/dsh-desktop#381
Out of scope / open question. This fixes only the diagnosis —
/compactstill will not start mid-turn. Making it wait for idle changesrunMaintenancesemantics for every maintenance caller (the scheduler currently defers when the claim is busy), so it reads like a separate product decision. Which direction would you prefer?All reactions