#2118

[BUG] pre-dispatch 500-path workspace budget is self-locking: writing .gitignore to reduce the delta is blocked by the same gate, and recovery_actions reference a UI affordance the renderer never calls

Openllanozeroopened 14d ago

Problem description

Provenance & confidence (please read first)

Produced with an AI-assisted investigation. This is the weakest-evidenced of our reports and should be read as design feedback, not as a defect claim:

  • Observed: the pre-dispatch refusal on our machine (2802 visible paths), the fact that editing .gitignore was itself refused, and that the preimage commit swept the whole remaining delta (f6623d4, 144 files, 108 of them binary).
  • Method-limited inference: "the renderer never calls POST /spaces/{id}/git/checkpoints" came from a string search over the shipped app.asar (2.7 GB, matched as binary). A zero result there is not proof the call is absent — it could be built dynamically or live in an unpacked chunk. Please treat that sentence as a question to confirm, and the user-visible half ("the version-history panel showed no way to checkpoint the pending paths") as the actual observation.
  • Not verified: whether the preimage sweep is intended to be unconditional. We are reporting the consequence we hit, not asserting the design is wrong.

WORKSPACE_PATH_LIMIT = 500 (backend/app/workspace_git/backend.py:31) is enforced by worktree_status() (:1203-1217) on a full git status --porcelain=v1 -z --untracked-files=all scan before dispatch of any mutating tool (mutation.py:344, :1159, :1267), so a Space with more than 500 git-visible delta paths refuses shell_exec (even echo), write_to_file, and terminal writes — while read-only tools keep working.

Two properties of that design combine into a deadlock:

  1. The count is git-visible paths, and ignored paths do not count — so the correct remedy is to extend .gitignore. But creating or editing .gitignore is itself a file mutation, gated by the same check. There is no way for the agent (or the documented recovery flow) to reduce the delta from inside.
  2. recovery_actions instructs the user to "Review existing content and checkpoint explicitly selected batches of at most 500 paths" (backend.py:95). In 1.0.6 the renderer never calls POST /spaces/{space_id}/git/checkpoints (the only route whose body accepts an explicit paths array, workspace_git_controller.py:75-77), and POST /git/save-point commits only pending_managed_paths — empty for never-admitted untracked files, so it raises NoCheckpointChangesError. The version-history panel therefore shows no checkbox list and no button.

Additionally, when the delta finally drops to ≤500, the first admission of the next Run commits all remaining visible paths as the Run preimage (mutation.py:1267-1276, message Save workspace before Task <id>). In our case that swept 144 paths / 108 binary files (~132 MB on disk) into history without any review step — i.e. the gate designed to force a content decision is bypassed at the moment it releases.

Suggested

  • Allow a narrow exception for editing ignore files when the budget is exceeded (it is the documented remedy), or expose a read-only path_budget-style preview plus an explicit "select paths to checkpoint" batch UI (the backend route already exists).
  • Reword recovery_actions to describe actions that are actually available in the shipping UI, and include the two counters that matter (visible delta vs limit, and how many are already managed).
  • Consider whether the preimage sweep should be limited to paths the user selected, rather than the full visible delta, so that crossing back under the budget is not itself an unreviewed bulk commit.

Activity

0

No activity yet.