Skip to content

fix(task-board): TASK_ADD_REPO returned success on an empty checkout - #6697

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/add-repo-false-clone
Aug 28, 2026
Merged

fix(task-board): TASK_ADD_REPO returned success on an empty checkout#6697
pedrofrxncx merged 1 commit into
mainfrom
fix/add-repo-false-clone

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

A Super Agent run "completed" in twenty seconds without reading a line of code.
Its transcript:

assistant  I'll start by cloning the repo.
tool       TASK_ADD_REPO { connectionId: … }
           → { "cloned": true, "files": ".deco\norg",
               "message": "… is checked out at your working directory
                           on branch sandbox/thread-…. Start working." }
tool       Bash  ls -a && find . -maxdepth 3 …
           → .  ..  .deco  .git  org
assistant  finish

The tool said the repository was there. It was not. The run did exactly what it
was told, found nothing to work on, and stopped.

The probe asked the wrong question

Readiness was "ls -A has an entry that isn't .git", on the reasoning
that a HEAD ref can land before the checkout does — so entries, not the marker,
were trusted.

But the checkout directory is never empty to begin with. The pod stages .deco
(the MCP tool stubs) and mounts org (the org filesystem) into it before any
clone starts
. Both survive the .git filter, both are present on the very
first probe, and neither ever changes — so the "stabilized across two probes"
guard agreed with them too. TASK_ADD_REPO returned cloned: true about a
second and a half in, having waited for nothing.

The 45s CLONE_TIMEOUT_MS and the stabilize guard were never reached, because
the condition they gate on was already true before the work began.

The fix

The marker is built from git ls-files and is now the sole readiness
signal. A non-empty index can only come from a checkout that actually wrote the
tree — no amount of pre-staged scaffolding can fake one, and unlike HEAD it
cannot be written ahead of the files.

-if git rev-parse HEAD >/dev/null 2>&1; then echo __CLONED__; fi; ls -A
+if [ -n "$(git ls-files 2>/dev/null | head -1)" ]; then echo __CLONED__; fi; ls -A

The listing is still returned — it is what the model reads to orient itself. It
just no longer gets a vote on whether the clone happened.

The stabilize guard keeps its meaning and gets a better one: it now measures
the listing settling after the checkout has begun, which is what it was
always trying to do.

Downstream

This is also why the card reached In Review with no reviewer. No PR was
opened, so the card took the repo-less path (advanceLinkedTasksToReviewOnThreadFinish),
which parks a task whose answer is its deliverable for a human. That path
behaved correctly — it was handed a run that had genuinely produced nothing.

Testing

  • The two tests that encoded the old rule are inverted, not appended. The
    first now asserts on the exact probe output that shipped the twenty-second
    task (.deco\norgnot cloned).
  • bun test apps/api/src/tools/task-board apps/api/src/tools/sandbox → 8
    pre-existing failures on origin/main, 8 on this branch, zero regressions.
  • bun run --cwd=apps/api check, bun run lint (0 errors), bun run fmt — clean.

Found on a live cluster, not in review.


Summary by cubic

Fixes TASK_ADD_REPO reporting a successful clone when the working directory was empty, which let Super Agent runs "complete" in seconds without reading any code. The probe now uses a git ls-files index marker as the sole readiness signal instead of trusting directory entries, since the pod pre-stages .deco and mounts org before any clone starts.

Bug Fixes

  • Pre-staged scaffolding no longer counts as evidence of a checkout; readiness requires a non-empty git index.
  • The directory listing is still returned to the model but no longer influences the cloned decision.
  • Inverted the two tests that encoded the old rule so the exact probe output that shipped the empty-checkout run now asserts as not cloned.

Written for commit f9fcc7e. Summary will update on new commits.

Review in cubic

The clone probe asked the wrong question. Readiness was "`ls -A` has an
entry that isn't .git", on the reasoning that a HEAD ref can land before the
checkout does — but the checkout directory is never empty to begin with. The
pod stages `.deco` (the MCP tool stubs) and mounts `org` (the org filesystem)
into it before any clone starts. Both survive the .git filter, both are present
on the very first probe, and neither ever changes, so the "stabilized across
two probes" guard agreed with them.

TASK_ADD_REPO therefore returned `cloned: true, files: ".deco\norg"` about a
second and a half in, having waited for nothing, and told the model 'is checked
out at your working directory. Start working.'

An autonomous run then did exactly what it was told: listed the directory,
found no repository in it, and finished. It opened no PR, so its card took the
repo-less path to In Review and sat there waiting for a person — a task
'completed' in twenty seconds without a line of code read.

The marker is built from `git ls-files` now and is the sole readiness signal:
a non-empty index can only come from a checkout, which no amount of pre-staged
scaffolding can fake. The listing is still returned — it is what the model
reads — it just no longer gets a vote on whether the clone happened.

The two tests that encoded the old rule are inverted rather than appended, and
the first one now asserts on the exact probe output that shipped the
twenty-second task.
@pedrofrxncx
pedrofrxncx enabled auto-merge (squash) August 28, 2026 15:47
@pedrofrxncx
pedrofrxncx merged commit 40df446 into main Aug 28, 2026
33 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/add-repo-false-clone branch August 28, 2026 16:05
decocms Bot pushed a commit that referenced this pull request Aug 28, 2026
PR: #6697 fix(task-board): TASK_ADD_REPO returned success on an empty checkout
Bump type: patch

- decocms (apps/api/package.json): 4.294.3 -> 4.294.4
- @decocms/native (apps/native/package.json): 4.294.3 -> 4.294.4

Deploy-Scope: server
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