fix(reliability): roll back partial artifact writes on current main - #410
fix(reliability): roll back partial artifact writes on current main#410seonghobae wants to merge 5 commits into
Conversation
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@opencode-agent review Please review the unchanged exact current head |
|
Exact-current-head read-only review request for @opencode-agent review |
Rate Limit Exceeded
|
|
@opencode-agent review Review exact head Review read-only; preserve independent reviewer identity. Do not mutate the branch, synthesize author approval, weaken protection, or merge. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
pr_number="410"
expected_head="ef4325940708de83b2e6375c5a0c6ad3b5ba63fd"
expected_base="961f44a19c4ced87f8062b3ab9842a9a08d05235"
echo "== Live pull request metadata =="
gh pr view "$pr_number" --repo "$repo" --json number,state,mergeable,headRefOid,baseRefOid,headRefName,baseRefName,reviews,statusCheckRollup \
--jq '{number,state,mergeable,headRefOid,baseRefOid,headRefName,baseRefName,reviews:[.reviews[]|{author:.author.login,state,commit:.commit.oid}],checks:[.statusCheckRollup[]|{name,conclusion,status}]}'
echo "== Exact head and base validation =="
actual_head="$(gh pr view "$pr_number" --repo "$repo" --json headRefOid --jq .headRefOid)"
actual_base="$(gh pr view "$pr_number" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
printf 'expected_head=%s\nactual_head=%s\nexpected_base=%s\nactual_base=%s\n' \
"$expected_head" "$actual_head" "$expected_base" "$actual_base"
echo "== Local checked-out commit and changed paths =="
git rev-parse HEAD
git cat-file -e "${expected_head}^{commit}"
git cat-file -e "${expected_base}^{commit}"
git diff --name-status "$expected_base" "$expected_head"
git diff --check "$expected_base" "$expected_head"
git merge-base --is-ancestor "$expected_base" "$expected_head" && echo "base_is_ancestor=true"
echo "== Candidate Java files =="
fd -a '^FileSystemArtifactStore\.java$' .
fd -a -i 'FileSystemArtifactStore.*(Test|IT)\.java$' .
echo "== Java structure =="
while IFS= read -r file; do
ast-grep outline "$file" --items all --type class,method --view expanded
done < <(fd -a '^FileSystemArtifactStore\.java$' .; fd -a -i 'FileSystemArtifactStore.*(Test|IT)\.java$' .)
echo "== Exact diff =="
git diff --find-renames --find-copies --unified=80 "$expected_base" "$expected_head" -- '*.java'
echo "== Live review threads =="
gh api graphql -F owner="ContextualWisdomLab" -F name="clearfolio" -F number="$pr_number" -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 20) { nodes { author { login } body path line } }
}
}
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {comments:[.comments.nodes[]|{author:.author.login,path,line,body}]}]'Length of output: 6637 🏁 Script executed: #!/bin/bash
set -euo pipefail
store="src/main/java/com/clearfolio/viewer/artifact/FileSystemArtifactStore.java"
regression="src/test/java/com/clearfolio/viewer/artifact/FileSystemArtifactStorePartialWriteTest.java"
base="961f44a19c4ced87f8062b3ab9842a9a08d05235"
head="ef4325940708de83b2e6375c5a0c6ad3b5ba63fd"
echo "== Structure: production store =="
ast-grep outline "$store" --items all --type class,method --view expanded || true
echo "== Structure: focused regression =="
ast-grep outline "$regression" --items all --type class,method --view expanded || true
echo "== Exact changed-file diff =="
git diff --find-renames --find-copies --unified=100 "$base" "$head" -- "$store" "$regression"
echo "== Production store, numbered source =="
cat -n "$store"
echo "== Focused regression, numbered source =="
cat -n "$regression"
echo "== Related test assertions and failure injection =="
rg -n -C 5 --type java \
'(FileSystemArtifactStore|rollback|suppressed|partial|replacement|metadata|Path|Files\.(move|write|delete)|assertThrows|assertArrayEquals)' \
src/test/java/com/clearfolio/viewer/artifact
echo "== Unresolved review threads =="
gh api graphql \
-F owner="ContextualWisdomLab" \
-F name="clearfolio" \
-F number="410" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 20) {
nodes { author { login } body path line }
}
}
}
}
}
}' \
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {comments:[.comments.nodes[]|{author:.author.login,path,line,body}]}]'Length of output: 125473
I found one blocking condition.
The inspected rollback flow otherwise restores both artifact paths independently and retains cleanup failures as suppressed exceptions. The focused regression also covers ordinary partial writes, replacement preservation, independent cleanup attempts, and a directory-based unreadable snapshot case. The live PR still matches the requested base and head. It is mergeable. The listed completed checks are successful. The unresolved-thread query returned zero threads. I did not approve, merge, or modify the branch.
|
|
Exact-current-head independent review request for The two-file filesystem atomicity slice is mergeable; CI, Security Scan, SAST Semgrep, and fuzz are terminal-success; unresolved inline findings are zero. Failed multi-file publication restores the exact prior PDF/metadata snapshot or removes newly created partial files, retains suppressed rollback evidence, and rejects missing document authority. Protected @opencode-agent review Review this exact head read-only. Do not mutate the branch, synthesize author approval, weaken protection, or merge. |
Rate Limit Exceeded
|
|
Queued @opencode-agent ; Already queued @cwl-noema-review on this exact request for PR #410 at head |
|
Queued @opencode-agent ; Already queued @cwl-noema-review on this exact request for PR #410 at head |
|
Queued @opencode-agent ; Already queued @cwl-noema-review on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
|
Already queued @cwl-noema-review and @opencode-agent on this exact request for PR #410 at head |
Objective
Preserve filesystem artifact atomicity and path authority on current protected
main: a failed multi-file write must not expose partial or replacement-corrupted bytes.Exact current-head evidence
961f44a19c4ced87f8062b3ab9842a9a08d05235;7b49e72281d7ca235b87f00aab3c7e56f8f8cb82;ef4325940708de83b2e6375c5a0c6ad3b5ba63fd;FileSystemArtifactStore.javaand its focused regression;Contract
Failed multi-file writes roll back newly published bytes, preserve the previously committed PDF and exact metadata during replacement failure, attempt cleanup independently, retain suppressed rollback evidence, fail closed on unreadable snapshots or missing document authority, and confine every resolved artifact path to the configured root.
Scope boundary
Standalone filesystem storage only. This does not provide distributed/object-store transactions, durable deletion receipts, generation fencing, Office conversion, or cross-instance coordination.
Merge gate
Keep this exact head unchanged. Auto-merge may act only after all live required checks remain successful, zero valid unresolved findings remain, and a qualifying independent non-author approval is attached to this exact head. Automated evidence and predecessor reviews do not transfer.