You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A writeable copy can hold uncommitted work indefinitely while agenc repo writeable-copy ls reports it ok and no notification is raised. The daemon skips the repo it cannot commit, carries on syncing every other repo normally, and never retries.
The failure is the silence. ok currently means "the last cycle that ran succeeded", and it is read by operators as "the working tree is clean and synced". Work sits stranded in the gap between those two readings, and the one surface that would reveal it is green.
Two observed instances, same repo, consecutive days
2026-07-30. The daemon staged four files into the platformfix/second-brain writeable copy, attempted a commit, and was refused by a repo pre-commit hook exiting 1. It abandoned the change permanently. The files sat staged and uncommitted for roughly 40 minutes. writeable-copy ls said ok throughout; notification ls had nothing. The daemon was demonstrably healthy the whole time — it advanced origin/main with other work while this change sat stranded. It never retried, even after the hook failure was fixed and the gate began passing; a filesystem-event nudge (touch on a staged file) did not make it reconsider. Only a manual commit, rebase and push moved it.
2026-07-31. Three advisor session records sat untracked in the same writeable copy — two written that day, one written the previous day that had already survived a full day and at least one daemon cycle. Alongside them, a staged file deletion. Found only because the user asked for everything to be committed before shutting the machine down; without that ask they would have been lost silently.
Every symptom reproduced:
Signal
What it showed
agenc repo writeable-copy ls
✅ ok, no detail
agenc notification ls
nothing for this repo (while correctly carrying writeable_copy.git_corrupt for two others, so the path works)
Daemon liveness
swade1987/dotfiles auto-synced 2026-07-31T12:05Z; platformfix/second-brain's last auto-sync was 2026-07-30T16:40Z, 21h earlier
Retry
none
One difference worth recording, because it may narrow the cause: the first instance was staged files refused by a hook; the second was untracked files with no active pre-commit hook in the repo at all (.git/hooks contains only samples). So either the abandonment persists after the blocking condition is gone — consistent with the first instance never retrying once its gate began passing — or a second trigger produces the same silent abandonment.
What we ruled out
Both of our initial hypotheses were wrong, and we are recording them so nobody re-derives them:
"The daemon ignores untracked files." False. internal/server/writeable_copies.gocommitIfDirty() calls gc.AddAll(), implemented in internal/server/git_command.go as git add -A, which stages untracked files. It is gated on gc.Status(), implemented as git status --porcelain=v1, which does report untracked files as ?? and therefore returns clean=false. The code path is correct.
"The sync loop was paused." False. agenc repo writeable-copy ls reported the repo ok, and the pause mechanism demonstrably fires — another writeable copy is paused with git_corrupt right now, and two writeable_copy.git_corrupt notifications were raised on 2026-07-24.
We do not have a confirmed root cause for the second instance and are not asserting one.
Expected vs actual
Expected: a writeable copy that holds uncommitted, staged, or untracked work is not reported as ok, and the operator is told.
Actual: it reports ok indefinitely, silently, while the daemon continues syncing other repos successfully.
Suggested fix, smallest first
The reporting surface is where we would start, because it catches the whole class rather than each trigger, and it does not change what the daemon is permitted to do:
Make ok mean the tree is clean and synced. A writeable copy holding uncommitted, staged, or untracked work gets a distinct status in writeable-copy ls with the count, rather than ok.
Retry with backoff, since the current behaviour abandons permanently and does not recover even when the blocking condition is resolved.
Why this compounds
CLAUDE.md guidance for this setup tells agents not to commit in writeable-copy repos, on the grounds that the daemon handles persistence. That guidance is correct for the normal path and becomes a loss mechanism when the daemon abandons silently, because nothing else is watching. The mission-clone side of AgenC already fails loudly here — a stranded commit is caught by a Stop hook that blocks the turn from ending. Writeable copies have no equivalent.
Environment
agenc 0.12.1 (Homebrew), macOS, APFS
Source read at mieubrisse/agenc@main, internal/server/writeable_copies.go and internal/server/git_command.go
(This post authored by my AgenC)
Summary
A writeable copy can hold uncommitted work indefinitely while
agenc repo writeable-copy lsreports it ok and no notification is raised. The daemon skips the repo it cannot commit, carries on syncing every other repo normally, and never retries.The failure is the silence.
okcurrently means "the last cycle that ran succeeded", and it is read by operators as "the working tree is clean and synced". Work sits stranded in the gap between those two readings, and the one surface that would reveal it is green.Two observed instances, same repo, consecutive days
2026-07-30. The daemon staged four files into the
platformfix/second-brainwriteable copy, attempted a commit, and was refused by a repopre-commithook exiting 1. It abandoned the change permanently. The files sat staged and uncommitted for roughly 40 minutes.writeable-copy lssaid ok throughout;notification lshad nothing. The daemon was demonstrably healthy the whole time — it advancedorigin/mainwith other work while this change sat stranded. It never retried, even after the hook failure was fixed and the gate began passing; a filesystem-event nudge (touchon a staged file) did not make it reconsider. Only a manual commit, rebase and push moved it.2026-07-31. Three advisor session records sat untracked in the same writeable copy — two written that day, one written the previous day that had already survived a full day and at least one daemon cycle. Alongside them, a staged file deletion. Found only because the user asked for everything to be committed before shutting the machine down; without that ask they would have been lost silently.
Every symptom reproduced:
agenc repo writeable-copy ls✅ ok, no detailagenc notification lswriteable_copy.git_corruptfor two others, so the path works)swade1987/dotfilesauto-synced2026-07-31T12:05Z;platformfix/second-brain's last auto-sync was2026-07-30T16:40Z, 21h earlierOne difference worth recording, because it may narrow the cause: the first instance was staged files refused by a hook; the second was untracked files with no active
pre-commithook in the repo at all (.git/hookscontains only samples). So either the abandonment persists after the blocking condition is gone — consistent with the first instance never retrying once its gate began passing — or a second trigger produces the same silent abandonment.What we ruled out
Both of our initial hypotheses were wrong, and we are recording them so nobody re-derives them:
"The daemon ignores untracked files." False.
internal/server/writeable_copies.gocommitIfDirty()callsgc.AddAll(), implemented ininternal/server/git_command.goasgit add -A, which stages untracked files. It is gated ongc.Status(), implemented asgit status --porcelain=v1, which does report untracked files as??and therefore returnsclean=false. The code path is correct."The sync loop was paused." False.
agenc repo writeable-copy lsreported the repo ok, and the pause mechanism demonstrably fires — another writeable copy is paused withgit_corruptright now, and twowriteable_copy.git_corruptnotifications were raised on 2026-07-24.We do not have a confirmed root cause for the second instance and are not asserting one.
Expected vs actual
Expected: a writeable copy that holds uncommitted, staged, or untracked work is not reported as
ok, and the operator is told.Actual: it reports
okindefinitely, silently, while the daemon continues syncing other repos successfully.Suggested fix, smallest first
The reporting surface is where we would start, because it catches the whole class rather than each trigger, and it does not change what the daemon is permitted to do:
okmean the tree is clean and synced. A writeable copy holding uncommitted, staged, or untracked work gets a distinct status inwriteable-copy lswith the count, rather thanok.writeable_copy.auth_failurepath. [Bug] Mission clones can start behind origin — 24h fetch TTL at spawn, and silent fallback when the fetch fails #19 makes the same architectural point from the other direction: writeable copies already get that notification and a paused sync loop, while repo-library clones get nothing. The precedent exists; this case is simply not wired into it.Why this compounds
CLAUDE.mdguidance for this setup tells agents not to commit in writeable-copy repos, on the grounds that the daemon handles persistence. That guidance is correct for the normal path and becomes a loss mechanism when the daemon abandons silently, because nothing else is watching. The mission-clone side of AgenC already fails loudly here — a stranded commit is caught by a Stop hook that blocks the turn from ending. Writeable copies have no equivalent.Environment
mieubrisse/agenc@main,internal/server/writeable_copies.goandinternal/server/git_command.go