Skip to content

fix(state-persistence): make state transitions atomic and recoverable — prevent lost, invalid, or permanently blocked updates - #587

Merged
unohee merged 6 commits into
mainfrom
swarm/AGT-3457-fix-state-persistence-make-state-transit
Sep 10, 2026
Merged

unohee merged 6 commits into
mainfrom
swarm/AGT-3457-fix-state-persistence-make-state-transit

Conversation

@unohee

@unohee unohee commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Published because this run stopped and needs a human: autonomous execution failed 4 times

It has not been reviewed and is very likely incomplete — this PR is a draft on purpose. It exists so the work is reviewable instead of sitting on a branch that was never pushed.

⚠️ File overlap with in-flight work

This branch changes files that other open PRs / active branches also touch. Coordinate before merging to avoid divergent parallel edits (INT-2388 #3):

Linear

Closes AGT-3457


🤖 Generated with OpenSwarm

@unohee
unohee force-pushed the swarm/AGT-3457-fix-state-persistence-make-state-transit branch from 8a46708 to e9d9dca Compare September 10, 2026 00:49
unohee added a commit that referenced this pull request Sep 10, 2026
… recurring

main currently tracks a symlink at the repository root:

    node_modules -> /work/OpenSwarm/node_modules

That path exists only inside the daemon's container, so every fresh clone
gets a dangling symlink where its dependencies go. It arrived through
#599 and is present in four more open branches (#581, #582, #587, and any
branch rebased onto main since).

The pattern let it through. A trailing slash restricts a gitignore pattern
to directories, and git records a symlink as a file, so `node_modules/`
never matched. Measured:

    pattern 'node_modules/'  ->  A  node_modules      (staged)
    pattern 'node_modules'   ->  (ignored)

Two changes, both needed: untrack the entry that is already committed, and
drop the slash so it cannot come back. Dropping the slash still ignores the
directory at any depth.

The worktree flows that create these symlinks deliberately — one install
shared across many worktrees — are unaffected. They need the link to exist,
not to be tracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
unohee added a commit that referenced this pull request Sep 10, 2026
)

* fix(gitignore): stop a node_modules symlink from being committable

PR #595 was opened by an autonomous run whose entire diff was a single
symlink at the repository root:

    node_modules -> /work/OpenSwarm/node_modules

That path exists only inside the daemon's container, so merging it would
have given every checkout a dangling symlink where its dependencies go.

The pattern let it through. A trailing slash restricts a gitignore pattern
to directories, and git records a symlink as a file, so `node_modules/`
never matched. Measured:

    pattern 'node_modules/'  ->  A  node_modules      (staged)
    pattern 'node_modules'   ->  (ignored)

Dropping the slash still ignores the directory at any depth, and now also
ignores the symlink. The worktree-based flows that create these symlinks
deliberately (to share one install across many worktrees) are unaffected —
they only need the link to exist, not to be tracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(gitignore): remove the committed node_modules symlink and stop it recurring

main currently tracks a symlink at the repository root:

    node_modules -> /work/OpenSwarm/node_modules

That path exists only inside the daemon's container, so every fresh clone
gets a dangling symlink where its dependencies go. It arrived through
#599 and is present in four more open branches (#581, #582, #587, and any
branch rebased onto main since).

The pattern let it through. A trailing slash restricts a gitignore pattern
to directories, and git records a symlink as a file, so `node_modules/`
never matched. Measured:

    pattern 'node_modules/'  ->  A  node_modules      (staged)
    pattern 'node_modules'   ->  (ignored)

Two changes, both needed: untrack the entry that is already committed, and
drop the slash so it cannot come back. Dropping the slash still ignores the
directory at any depth.

The worktree flows that create these symlinks deliberately — one install
shared across many worktrees — are unaffected. They need the link to exist,
not to be tracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@unohee
unohee merged commit 4d532e3 into main Sep 10, 2026
7 checks passed
@unohee
unohee deleted the swarm/AGT-3457-fix-state-persistence-make-state-transit branch September 10, 2026 01:06
unohee added a commit that referenced this pull request Sep 10, 2026
…eady ships

#587 landed first and solved the same problem in the same files: telemetry and
runnerState now serialise through `atomicWriteFileSync` plus liveness-aware
lock ownership (`processAppearsAlive` / `isProofCapableSpace`). This branch
replaced that with `proper-lockfile`. Merging both would put two locking
mechanisms in one file, so main's wins for the six overlapping paths —
telemetry.ts, runnerState.ts, dailyReporter.ts, the two telemetry suites, and
package.json. `proper-lockfile` is consequently unreferenced and the dependency
is not added.

`oauthPkce.ts` is reverted to main's too: this branch rebuilt `AuthProfile`
around `accessToken`/`refreshToken`/`store.save`, an API main replaced with
`type`/`provider`/`access`/`refresh`/`setProfile`. Applying it was a
regression, not a change.

What remains is this branch's own work and it stands on its own: GraphQL query
cost analysis, autolink resolvers, the github and memoryServer changes,
fileLock, openBrowser.

Two defects fixed while integrating:

  - The cost limit returned **500, not 400**. The check ran in `onParse`, and
    graphql-yoga masks a parse-phase replacement as an internal error — the
    `http: { status: 400 }` extension never reached the response, though it was
    right there in the log. Moved to `onValidate`, where a GraphQLError is a
    client error by definition.
  - `installIdStability`'s dead-lock test asserted the stale lock FILE is gone.
    telemetry.ts reclaims only when it can prove the owner is dead and
    otherwise refuses to steal the lock, so that assertion pinned the opposite
    of the shipped design. It now asserts the property that matters: a dead
    owner does not block the write.

Also dropped `cli.json`, `cursor/cli.json` and `.run-tests.sh` — agent-runtime
scratch that `git add -A` swept in. #605 purges the copies that reached main.

Verified: tsc 0, full suite 5747 passed / 0 failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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