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
Three small fixes: the shared checkout's index lock, the website build, a dead module (#1791)
The daemon's data sync and the scheduler's tick each write .branches/agent-data
from their own process on the same 60-second clock; when their phases align,
git refuses the second with "index.lock: File exists" every minute until they
drift, and the scheduler loses the tick. A write cycle now waits out that one
refusal: reset, half a second, run again, three times at most.
Vike reads every +name.* file beside a page as page configuration, .md
included, so the +config.LOGIC.md and +config.BUG-ANALYSIS.md sidecars broke
the website build, and every deploy since 08-23 failed on it. The site's vite
config tells Vike's crawl to skip them.
cli.ts imported five names from maintenance.ts and used none; nothing else
imported the module. It goes, with its test and their sidecars.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: packages/agent-data/src/file-branch.LOGIC.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,7 @@ Implements a branch of the project's repository used as a file store: files that
28
28
-**The write cycle** - sync with origin, apply the change to the checkout, commit whatever changed under the caller's message, push whenever the branch is ahead of origin's copy.
29
29
-**Sync: rebase onto origin, and origin wins a conflict** - unpushed local commits are rebased onto origin's copy; when the rebase fails, the checkout is reset to origin's copy and those commits are dropped, unreported.
30
30
-**A push that loses a race re-applies the change once** - the attempt's commit is wound back, the cycle re-syncs and re-applies; a second failed push keeps the commit local and reports it, for the next cycle to carry out; never a force push.
31
+
-**Another process holding the index is waited out** - git's refusal to take the checkout's index lock, which two processes on one clone hand each other, resets the checkout, waits half a second and runs the cycle again, three times at most.
31
32
-**A failed change leaves the checkout clean** - any other failure, a timeout included, resets the checkout to its last commit, removes stray files, and is reported rather than thrown.
32
33
-**The pull** - a write cycle with no change, run on the daemon's clock so this machine converges on what others pushed and pushes what an earlier cycle left stranded; a repository with no remote is an error it names.
33
34
-**Reads from anywhere, and never a failure** - a file or a directory listing is read off the checkout, the local branch, or origin's copy, from any directory of the repository, an agent's checkout included; whatever is missing reads as absent.
@@ -116,6 +117,16 @@ Without a remote, a sync does nothing. With one, the branch is fetched from orig
116
117
117
118
The change is an intent and the commit only its serialization, so the caller's change must be safe to run again. When the push fails on the first attempt, the attempt's commit is wound back to the tip the cycle started from (when a commit was made), the cycle syncs again, bringing in what the other writer pushed, and runs the change again against the fresher files, so the change lands exactly once. When the push fails on the second attempt too (the network, most likely), the commit stays local in the checkout [2] and the cycle reports the failure as "the <branch> branch could not be pushed: <git's reason>", marked as committed: the next write cycle [3] or pull rebases that commit onto whatever origin has by then, and its push carries it out together with the new change. A push killed on its time budget counts as a failed push and may have landed anyway; the next sync's rebase absorbs a commit origin already has. The branch is never force-pushed.
118
119
120
+
### Another process holding the index is waited out
121
+
122
+
#### Context
123
+
124
+
**Problem**: the one-at-a-time rule is a process's own; two processes on one clone (the daemon's pull and a scheduler's, each on its own clock) can run a cycle on the same checkout at once, and git refuses the second with "Unable to create '…/index.lock': File exists" rather than waiting. On the scheduler's side a refused pull loses a whole tick.
125
+
126
+
#### Business logic
127
+
128
+
When a cycle fails with git's index-lock refusal, the checkout is reset as for any failure (next section), the cycle waits half a second and runs again, the change included, up to three more times. A lock that never lifts is then reported as the failure it is.
Copy file name to clipboardExpand all lines: packages/agent-data/src/file-branch.test.LOGIC.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,7 @@ What the tests cover, against real git repositories with a bare `origin` and a s
5
5
-**A write** - commits on the branch under the caller's message, pushes it to origin, and leaves `main` untouched; a change that writes nothing commits nothing and reports no change; in a repository with no remote the write lands locally and reports that nothing was pushed.
6
6
-**Stranded commits and conflicts** - a write syncs in what another machine pushed and carries out an earlier local-only commit together with its own; a stranded commit that conflicts with origin's version resolves toward origin, and the change is re-applied on top of origin's version.
7
7
-**A lost race** - a push rejected because another writer landed in between re-runs the change once against the fresher files: the change is on the branch exactly once, next to the other writer's file.
8
+
-**The index held by another process** - git's index-lock refusal is recognized and a plain push failure is not; a change refused twice runs a third time and lands on origin exactly once, as one commit; a lock that never lifts is reported with git's reason and leaves the checkout at its last commit.
8
9
-**The pull** - converges the checkout on what another machine pushed; in a repository with no remote it reports an error naming the missing remote.
9
10
-**One write at a time** - three concurrent writes run one after another, never interleaving, and all three land in order.
10
11
-**Reads** - a file reads off the checkout, from an agent's own checkout of the same repository too, which resolves to the project as its repository; a missing file reads as absent; after another machine moved origin on, a plain read still shows the checkout while a fresh read shows origin; a clone that holds no local branch reads origin's copy and lists a directory off it, and a missing directory lists as empty.
// git's own refusal, as the daemon and the scheduler hand it to each other on one clone.
218
+
constrefusal=newError("Command failed: git add -A\nfatal: Unable to create '/x/.git/worktrees/store/index.lock': File exists.\n\nAnother git process seems to be running in this repository")
Copy file name to clipboardExpand all lines: packages/framework/src/LOGIC.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,7 @@ Everything of The Framework that runs in Node: the `the-framework` command, the
33
33
-**The daemon** (`daemon.ts`, `daemon-runtime.ts`, `daemon-services.ts`, `daemon-tick.ts`, `loopback-host.ts`, `project-hooks.ts`) - one foreground process that serves the dashboard, gives each agent a checkout [5] and a process, runs every background job on one clock, and runs the shell lines each project's own `.the-framework/hooks.yml` names when the dashboard opens and closes.
34
34
-**Projects on this machine** (`registry.ts`, `project.ts`, `install.ts`, `layout.ts`, `framework-gitignore.ts`, `project-errors.ts`, `project-pass.ts`, `pick-directory.ts`, `config.ts`, `config-layers.ts`, `preference-defaults.ts`, `agent-options.ts`) - the one user file listing the projects and the preferences, what activating a repository does to it, the per-repository defaults that travel with the code, and the order in which the layers of a decision are resolved.
35
35
-**Checkouts and what may be removed** (`worktrees.ts`, `merged-worktrees.ts`, `agent-locks.ts`) - one checkout [5] per agent under `.branches/`, and one rule for reclaiming it: only what is already on the remote may go.
36
-
-**Spending** (`quota-boundary.ts`, `quota-poller.ts`, `maintenance.ts`, `handoff-level.ts`, `on-before-mergeable-prompt.ts`) - the share of the quota [6] week that may be spent by now, whether unattended work may start under it, the per-repository record of the last maintenance review, and the ladder a finished agent publishes itself by.
36
+
-**Spending** (`quota-boundary.ts`, `quota-poller.ts`, `handoff-level.ts`, `on-before-mergeable-prompt.ts`) - the share of the quota [6] week that may be spent by now, whether unattended work may start under it, and the ladder a finished agent publishes itself by.
37
37
-**Getting the work out** (`ci-watch.ts`, `update-check.ts`) - the pull requests The Framework opened are merged once their checks pass and fixed by an agent when they go red.
38
38
-**Work that runs somewhere else** (`cloud-work.ts`, `cloud-run-state.ts`, `cloud-scratch-refs.ts`, `bridge-browser.ts`) - a Claude Code cloud session is recognized by the commit its branch descends from, its state is worded the same way on every surface, and the daemon can run its own browser so the bridge works with no Chrome of the user's open.
39
39
-**The agent's browser** (`browser.ts`, `browser-stream.ts`) - a real Chrome an agent can drive, whose page the dashboard shows live and hands to the user at a login wall.
0 commit comments