fix(state-integrity): make operational state updates transactional and outcome-aware — prevent stale, partial, or truncated results - #773
Closed
unohee wants to merge 6 commits into
Conversation
added 6 commits
September 10, 2026 04:16
This was referenced Sep 27, 2026
unohee
added a commit
that referenced
this pull request
Sep 28, 2026
…arness (#757 #771 #773 #777) (#786) * fix(state-integrity): salvage durable state fences and the review quality harness Salvages the still-unique work from four abandoned draft PRs (#757, #771, #773, #777) onto current main. Each PR's merge base is 172-247 commits behind, so only hunks absent from main were taken; work main already implemented independently was kept as-is. #757 (automation-state concurrency/recovery) - storeFileStamp(): the task-state cache stamp now includes the inode, so a same-size cross-process replacement (atomic rename) inside one mtime tick invalidates the cache instead of serving a stale snapshot forever. - validateExecution(): rejects incomplete step results and DAG-illegal lifecycle states before a workflow execution is persisted. - dev.ts: the close handler's reporting is wrapped in try/catch/finally so onComplete and activeTasks.delete always run. - memoryBridge.ts: one memory_linked event, not two (linkMemory already emits it). - linearBridge.ts: a failed SDK load no longer pins the rejected init promise, so the next call can retry. #771 (review quality harness) - New src/verify/qualityHarness.ts: full-tree, fail-closed static scan over every tracked source file plus isolated verify commands, wired into `review --max`, `--harness-only`, and the markdown audit report. - The harness test fixture put the empty catch body on its own line, which the per-line bs detector can never match — the detection assertion was vacuous. The fixture is single-line now and asserts a real finding. #773 (transactional state updates) - changeStatus()/updateIssue() read the effective status inside the write transaction so the event log's oldValue cannot be stamped stale. - saveExecution() gains a definitionStamp fence that refuses a snapshot whose workflow definition was replaced underneath it. - dailyReporter: bounded per-project retry; the watermark advances only when every project succeeded after that retry. - projectUpdater: buildBoundedProjectDescription() reserves room for the summary before truncating, so the 255-char limit cannot chop it off. - projectHandler: a failed quarantine surfaces as its own error instead of being reported as a successful preserve. #777 (issue/delivery mutation scope) - linearBridge: pendingLinearMappings recovery + idempotencyKey, so a failed local mapping persist cannot orphan-recreate a Linear issue. - sqliteStore.createIssue() honors the documented idempotent-id contract. - backlogGrooming: validIssueIds is mandatory at parse time and apply time, so a hallucinated id can never reach a mutation path. - workerValidationEvidence: EXECUTABLE_SOURCE_FILE_RE keeps shell/sql/etc. source under data dirs in scope for validation evidence. - projectUpdater: fetchProjectOverviewIssues surfaces missing/repeated cursors instead of silently truncating the page walk. * fix(issues): reject an idempotent create whose stored row is a different artifact CI caught a regression from the salvaged idempotent-createIssue guard: src/automation/taskSource.test.ts:174 "rejects an idempotent child collision when a retried plan changed" (6799 passed, 1 failed). The guard returned the existing row for any caller-supplied id, which erased SqliteTaskSource's deterministic duplicate-sibling guard (AGT-2908): its createSubIssue wraps createIssue in try/catch and relies on the UNIQUE(id) collision to distinguish "the same decomposition retried" (identical title+ description → reuse the child) from "the retried plan changed" (→ report `existing artifact does not match the requested plan`). Returning the stored row unconditionally made every changed-plan retry look like a successful reuse, so the caller got the OLD child's title back instead of `{ error }`. Reconciled rather than reverted: a caller-supplied id found in the store is only treated as an idempotent retry when the identity-bearing fields agree (title, description, parentId, projectId — via sameIssueContent). Otherwise createIssue throws an explicit collision error naming the id, so: - an identical retry returns the existing row (keeps #777's intent), and - a materially different artifact under the same id is rejected and NOT overwritten (keeps AGT-2908's invariant and its test green). The same comparison is applied to the concurrent-create catch branch, which previously also returned the winner's row unconditionally. sqliteStore.test.ts's salvaged case asserted the over-permissive behavior ("second.title === 'first'" for a changed title); it now asserts the real contract instead of being deleted, plus a new case pinning the rejection. * docs(changelog): record the salvaged state-integrity and quality-harness changes
Collaborator
Author
|
Closing: superseded — the salvageable work in this draft was rebased onto current main, verified, and re-published as a reviewed PR: absorbed into #786. Closing the stale draft instead of merging it, because it was 170-250 commits behind, carried scratch files, and (in several cases) reverted main's later hardening. |
unohee
deleted the
swarm/AGT-3489-fix-state-integrity-make-operational-sta
branch
September 28, 2026 07:02
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.
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.
Change shape
427 file(s): 212 source · 192 test · 6 docs · 17 other
Base freshness
Branch base is 171 commit(s) behind
mainat publication.⚠ Conflicts with
mainin:src/automation/dailyReporter.ts,src/orchestration/workflow.tsGitHub runs no
pull_requestworkflows on a PR it cannot merge, so any green checks here are not the verification gate. Opened as a draft; rebase before review.This branch changes files that other open PRs / active branches also touch. Coordinate before merging to avoid divergent parallel edits (INT-2388 #3):
src/orchestration/workflow.tshooks.jsonsrc/orchestration/workflow.tssrc/issues/sqliteStore.ts,src/orchestration/workflow.tssrc/cli/projectHandler.tshooks.json,src/issues/sqliteStore.ts,src/orchestration/workflow.tssrc/automation/dailyReporter.ts,src/orchestration/workflow.coverage.test.ts,src/orchestration/workflow.tshooks.json,lsLinear
Closes AGT-3489
🤖 Generated with OpenSwarm