fix: bind Today progress retries to evidence (Closes #1056)
CI / lint (pull_request) Successful in 2m45s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 2m2s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-18 02:29:13 +00:00
1 parent 157d485685
commit 1410a66a36
4 files changed
+160 -21

No files matched your search

+38
View File
@@ -15,6 +15,44 @@ def run_node(script: str):
return json.loads(result.stdout)
def test_repeated_operation_id_rejects_a_different_comment_payload():
script = f"""
const createAuthoredOutbox = require({json.dumps(str(OUTBOX))});
const values = new Map();
const storage = {{getItem:key=>values.get(key)||null,setItem:(key,value)=>values.set(key,value)}};
const outbox=createAuthoredOutbox({{storage,getOwnerLogin:()=> 'timmy'}});
const original={{kind:'issue-comment',repository:'o/r',number:7,body:'Done',operationId:'stable',attachments:[{{filename:'before.jpg',contentType:'image/jpeg',note:'Before',operationId:'photo-1'}}]}};
const identical=outbox.enqueue(original);
let error='';
try {{ outbox.enqueue({{...original,attachments:[{{filename:'after.jpg',contentType:'image/jpeg',note:'After',operationId:'photo-2'}}]}}); }}
catch (caught) {{ error=caught.message; }}
process.stdout.write(JSON.stringify({{identical,error,items:outbox.list()}}));
"""
output = run_node(script)
assert output["identical"]["operationId"] == "stable"
assert output["error"] == "This operation ID is already bound to a different queued action."
assert len(output["items"]) == 1
assert output["items"][0]["attachment"]["operationId"] == "photo-1"
def test_repeated_pull_review_operation_uses_the_default_comment_decision():
script = f"""
const createAuthoredOutbox = require({json.dumps(str(OUTBOX))});
const values = new Map();
const storage = {{getItem:key=>values.get(key)||null,setItem:(key,value)=>values.set(key,value)}};
const outbox=createAuthoredOutbox({{storage,getOwnerLogin:()=> 'timmy'}});
const review={{kind:'pull-review',repository:'o/r',number:8,body:'Notes',expectedHeadSha:'abc',operationId:'review-op'}};
outbox.enqueue(review);
let error='';
try {{ outbox.enqueue(review); }} catch (caught) {{ error=caught.message; }}
process.stdout.write(JSON.stringify({{error,items:outbox.list()}}));
"""
output = run_node(script)
assert output["error"] == ""
assert len(output["items"]) == 1
assert output["items"][0]["decision"] == "comment"
def test_authored_outbox_quarantines_legacy_and_cross_account_messages():
script = f"""
const createAuthoredOutbox = require({json.dumps(str(OUTBOX))});
+47 -10
View File
@@ -123,25 +123,59 @@ process.stdout.write(JSON.stringify({{error,retained,after:progress.load(target.
}
def test_photo_cleanup_failure_retries_with_the_same_comment_operation():
def test_photo_payload_changes_rotate_the_progress_operation_identity():
script = f"""
const createProgress = require({json.dumps(str(TODAY_PROGRESS))});
const values = new Map(); const ids = ['progress-1', 'progress-2', 'progress-3'];
const storage = {{getItem:key=>values.get(key)||null,setItem:(key,value)=>values.set(key,value),removeItem:key=>values.delete(key)}};
const progress=createProgress({{storage,getLogin:()=> 'timmy',makeId:()=>ids.shift(),admit:async()=>({{}})}});
const identity='issue:stackchain/dashboard:12:';
const before={{filename:'proof.jpg',contentType:'image/jpeg',note:'Before',operationId:'photo-1'}};
const replacement={{filename:'proof.jpg',contentType:'image/jpeg',note:'After',operationId:'photo-2'}};
progress.save(identity, 'Repair complete', [before]);
const first=JSON.parse(values.values().next().value).drafts[identity].operation_id;
progress.save(identity, 'Repair complete', [before]);
const unchanged=JSON.parse(values.values().next().value).drafts[identity].operation_id;
progress.save(identity, 'Repair complete', [replacement]);
const replaced=JSON.parse(values.values().next().value).drafts[identity].operation_id;
replacement.note='Redacted replacement';
progress.save(identity, 'Repair complete', [replacement]);
const recaptioned=JSON.parse(values.values().next().value).drafts[identity].operation_id;
process.stdout.write(JSON.stringify({{first,unchanged,replaced,recaptioned}}));
"""
output = run_node(script)
assert output == {
"first": "progress-1",
"unchanged": "progress-1",
"replaced": "progress-2",
"recaptioned": "progress-3",
}
def test_photo_cleanup_failure_resumes_cleanup_without_readmitting_delivery():
script = f"""
const createProgress = require({json.dumps(str(TODAY_PROGRESS))});
const values=new Map();
const storage={{getItem:key=>values.get(key)||null,setItem:(key,value)=>values.set(key,value),removeItem:key=>values.delete(key)}};
const calls=[]; let cleanupFails=true;
const progress=createProgress({{storage,getLogin:()=> 'timmy',makeId:()=> 'stable-progress-op',admit:async message=>{{calls.push(message);return {{background:true}};}}}});
const calls=[]; let cleanupFails=true; let cleanupCalls=0;
const options={{storage,getLogin:()=> 'timmy',makeId:()=> 'stable-progress-op',admit:async message=>{{calls.push(message);return {{background:true}};}}}};
let progress=createProgress(options);
const target={{identity:'pull:stackchain/dashboard:22:',kind:'pull',repository:'stackchain/dashboard',number:22}};
const photo={{filename:'proof.webp',contentType:'image/webp',blob:{{size:9}},operationId:'photo-op'}};
const cleanup=async()=>{{if(cleanupFails)throw new Error('draft cleanup blocked')}};
let error='';
try {{await progress.post(target,'',[photo],cleanup);}} catch(caught){{error=caught.message;}}
const cleanup=async()=>{{cleanupCalls++;if(cleanupFails)throw new Error('draft cleanup blocked')}};
let error=''; let deliveryAdmitted=false;
try {{await progress.post(target,'',[photo],cleanup);}} catch(caught){{error=caught.message;deliveryAdmitted=caught.deliveryAdmitted===true;}}
progress=createProgress(options);
cleanupFails=false;
await progress.post(target,undefined,[photo],cleanup);
process.stdout.write(JSON.stringify({{error,calls,after:progress.load(target.identity)}}));
const recovered=await progress.post(target,'edited text must not be admitted',[{{...photo,operationId:'replacement'}}],cleanup);
process.stdout.write(JSON.stringify({{error,deliveryAdmitted,calls,cleanupCalls,recovered,after:progress.load(target.identity)}}));
"""
output = run_node("(async()=>{" + script + "})().catch(error=>{console.error(error);process.exit(1)})")
assert output["error"] == "draft cleanup blocked"
assert [call["operationId"] for call in output["calls"]] == ["stable-progress-op", "stable-progress-op"]
assert output["error"] == "Progress update is already queued; photo cleanup is pending."
assert output["deliveryAdmitted"] is True
assert len(output["calls"]) == 1
assert output["cleanupCalls"] == 2
assert output["recovered"]["alreadyAdmitted"] is True
assert output["after"] == ""
@@ -192,6 +226,9 @@ def test_mobile_progress_sheet_is_accessible_bundled_and_safe_area_aware():
assert "lanes:{ today:" in TODAY_PROGRESS.read_text()
assert "photos:todayProgressPhotos" in dashboard
assert "const controller = issueAttachment.mount" in TODAY_PROGRESS.read_text()
assert "const checkpointAttachments = await photos?.serialize?.() || [];" in TODAY_PROGRESS.read_text()
assert "progress.save(openedTarget.identity, body.value, checkpointAttachments)" in TODAY_PROGRESS.read_text()
assert "error.deliveryAdmitted" in TODAY_PROGRESS.read_text()
assert ".today-progress-panel" in css
assert "env(safe-area-inset-bottom)" in css
assert ".today-progress-actions button" in css and "min-height:44px" in css