fix(server): restamp task watchdog mutation scope after the run's own writes (SPA-2178 / SPA-353) - #11111
Open
JamesSparkMojo wants to merge 2 commits into
Open
Conversation
|
✅ All checks passing — ready for Greptile review and maintainer approval. — commitperclip |
…rclip PR Review Adds the five required PR-template sections (Thinking Path, What Changed, Verification, Risks, Model Used) and the dedup-search checkbox. Re-runs the commitperclip PR Review workflow on the rebased head. No code change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thinking Path
Linked Issues or Issue Description
No public GitHub issue exists for this defect. The in-PR description follows the bug-report template.
What happened?
A task-watchdog run that posts its own evidence comment is locked out of every follow-up gated mutation in the same run. The watchdog writes a comment, the comment flips the watched subtree to
currentState: "live",revalidateMutationScopethen returns409 currentState: livefor every subsequent mutation the run attempts, and the run ends without a disposition. The error message says "refresh the source state", but no refresh route exists, so the recovery is permanently stranded.Expected behavior
A watchdog run should be able to complete a sanctioned multi-step recovery in one execution. The run should be able to post its evidence comment, patch the watched subtree, and resolve the recovery action. The third-party liveness guard should still block mutations when a third party has actually changed the watched subtree.
Steps to reproduce
recovery-actions/resolve.409 currentState: liveor409 stop fingerprint changed. The run ends without recording a disposition.Paperclip version or commit
Pull request head
5cb1e1eaefe46481539aa507f84865b009c16fb7againstmaster19be4cf9278b70bc151063778a94bf38bfd5c903.Deployment mode
Self-hosted server (the bug is server-side).
Related PRs (found while searching for duplicates)
These three open PRs all address the same watchdog deadlock family with different fix shapes. This PR takes the actor-aware restamp path: the smallest patch that resolves all three observed deadlock triggers in one service function, with no schema migration, no new route, and a unit test covering the invariant. None of them is a duplicate of this one.
What Changed
restampCurrentRunAfterOwnWrites(scope, classification, observedFingerprint, ...)toserver/src/services/task-watchdogs.ts. The helper re-stamps the in-flight run's stop fingerprint against the observed subtree after a write the run itself authored.revalidateMutationScopeinserver/src/services/task-watchdog-scope.tsso gated mutations re-bind to the freshly observed scope instead of the wake-time fingerprint.recovery-actions/resolvewrite paths inserver/src/services/issues.ts.server/src/__tests__/issue-watchdogs-routes.test.tscovering the three deadlock triggers and the cross-actor fencing invariant. The third-party run that flips the subtree must still be 409-ed after the restamp.Verification
pnpm --filter @paperclipai/server exec tsc --noEmitintroduces 0 net new errors. The PR CI jobTypecheck + Release Registryis green on the rebased head.issue-watchdogs-routes.test.tscases pass under the PRGeneral tests (server 1/5..5/5)shards.Typecheck + Release Registry,General tests (server 1/5..5/5),General tests (workspaces-a),General tests (workspaces-b),Build,Verify serialized server suites (1/5..5/5),Canary Dry Run,e2e shard (1/3..3/3),e2e,verify,policy,security/snyk (cryppadotta),Superagent Security Scan,Socket Security: Project Report,Socket Security: Pull Request Alerts,security-review, andContributor trust.recovery-actions/resolvein one execution without 409. A third-party run that flips the subtree still receives the 409 and cannot write past the live change.Risks
Low risk. A buggy re-stamp could let a stale run write past a real third-party liveness change. The re-stamp is scoped to two conditions at once: (a) the current runId only, and (b) writes this run itself authored in the current execution window. Third-party writes still invalidate. The new test asserts this invariant. No schema migration, no new route, no widening of the actor-identity surface. The diff does not touch
server/src/routes/issues.ts.Model Used
Codex-built. Provider OpenAI, model
codex(Cody-1, retired 2026-08-08). No extended thinking mode used. Context window used by the build was the standard Codex session context. Tool use was enabled for file edits and test execution. The patch was rebased onto currentmasterand re-verified locally before push. Cross-model Claude verify is required by the upstream reviewer workflow (commitperclip PR Review) before merge.Checklist
Fixes: #/Closes: #/Refs: #OR (b) described the issue in-PR following the relevant issue template#NNN/github.com/paperclipai/paperclipURLs)docs/...,fix/...) and contains no internal Paperclip ticket id or instance-derived details