Skip to content

fix(compaction): name the real reason a manual compaction is refused - #381

Open
Kunstderfug wants to merge 1 commit into
dataelement:mainfrom
Kunstderfug:fix/compaction-busy-classification
Open

fix(compaction): name the real reason a manual compaction is refused#381
Kunstderfug wants to merge 1 commit into
dataelement:mainfrom
Kunstderfug:fix/compaction-busy-classification

Conversation

@Kunstderfug

Copy link
Copy Markdown

What

/compact answered every refusal with one sentence:

Compaction is unavailable because this process has an active compaction, or the agent is not idle.

That folds two unrelated conditions into one message. The ordinary case — running /compact while the agent is still finishing the turn it just answered — was indistinguishable from a real compaction-lock conflict, so the copy sent the reader hunting for a compaction that did not exist.

Evidence from a real session log

From a DSH Desktop session log (session.jsonl.zstd, ts fields, epoch ms):

event ts delta
last step/end of the answered turn 1789070593953
command/run compact 1789070596493 +2.5 s
command/done kind=error 1789070596498 +5 ms
next turn/start 1789070640640 +45 s

The refusal landed 2.5 s after the turn's last step and 45 s before the next turn started: the agent was still running. (Title-generation hooks run before turn/end, which is why the UI can look idle when the phase is not.) The rejection came back in 5 ms, so the classifier is the only thing that could have told the two causes apart — and it did not.

Change

Both packages are host-side plugins and the desktop shell pins the 0.1.2-rc.1 artifacts, so they ship as patch-package patches.

  • dsh-compaction-basic — recognises the agent loop's already has active work refusal as its own agent-busy code. busy keeps its real meaning: an actual claim or lock conflict.
  • dsh-command-compact — one message per code. agent-busy now reads "Compaction did not start: the agent is still working on this session. Wait for the turn to finish, then run /compact again.", and busy names the lock instead of claiming the agent is not idle.

Verification

  • Each patch applies to the pristine published 0.1.2-rc.1 tarball and reproduces the installed bundle byte-for-byte: dsh-compaction-basic 42a4c68e…, dsh-command-compact 9223f3ad….
  • npx vitest run test/compaction-refusal.test.ts — 6 passed on this branch alone.
  • npm test — 810 passed / 95 files. npm run typecheck clean.

Scope

This corrects the diagnosis, not the timing: /compact still will not start mid-turn. Making it wait for idle changes AgentLoop.runMaintenance semantics for every maintenance caller (the scheduler currently defers when the claim is busy), so it belongs in its own change.

/compact answered every refusal with "Compaction is unavailable because
this process has an active compaction, or the agent is not idle." That
folds two unrelated conditions into one sentence, so a user who runs
/compact while the agent is still finishing a turn -- the common case --
is told to look for a compacting process that does not exist.

compaction-basic now recognises the agent loop's "already has active
work" refusal and reports it as its own agent-busy code, leaving the
generic busy code to mean an actual claim conflict. command-compact
answers each code with copy that names its own cause.

Both host packages ship as patch-package patches; the test pins the
classifier, the refusal copy for every code, and the presence of both
patch files.
Kunstderfug added a commit to Kunstderfug/dsh-desktop that referenced this pull request Sep 10, 2026
DeepSeek Harness declines external pull requests, so the finding went to a
Discussion instead. Keeping the posted body here records what was reported,
against which upstream commit it was verified, and how it relates to the fix
that ships in this repository (dataelement#381).
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