frontend-patterns/research/evaluations/language-replication-03/scenarios.json
tegwick f8c3ce3938 Freeze replication-03 with clarified criteria (FEP-WP-0009-T02)
Owner decisions D1-D3 applied; execution not authorized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 182330@bnt-lap001
Assistant-Session: 242866cf-789d-4e24-ac5e-0a1d7b47a701
2026-10-20 00:19:00 +02:00

519 lines
23 KiB
JSON

[
{
"id": "R03-S01",
"source_scenario": "R02-S01",
"title": "Support ticket attachments after access withdrawal",
"brief": "A help-desk agent edits a confidential incident ticket offline. The application acknowledged a local save of the text and attachments. On reconnect, the authority explicitly rejects upload because the agent lost access. A teammate suggests leaving the editor open forever and exporting a recovery archive. The only stated product rule is that rejected edits should be recoverable; there is no rule about local viewing, retention, export or deletion after access withdrawal. Recommend the next states and actions.",
"criteria": [
{
"id": "A1",
"requirement": "Distinguish the acknowledged local save from the explicitly denied remote upload.",
"placement": "anywhere",
"qualifies": [
"'saved on this device; the server refused the upload'"
],
"does_not_qualify": [
"'sync failed' with no statement that the local save exists"
],
"change_from_r02": "unchanged wording; examples added"
},
{
"id": "A2",
"requirement": "Stop the denied upload; do not retry it unchanged under the same access.",
"placement": "recommendation",
"qualifies": [
"'do not retry until access is restored or re-authorised'"
],
"does_not_qualify": [
"rejecting retry only because of duplication risk, without reference to the denial (pilot-01 S03-U ambiguity)"
],
"change_from_r02": "clarified: reason must be the denial"
},
{
"id": "A3",
"requirement": "Name the missing rule on keeping local copies after access withdrawal.",
"placement": "anywhere",
"qualifies": [
"'the product must decide whether a withdrawn user may keep the local copy'"
],
"does_not_qualify": [
"'clarify requirements' or 'define the contract' without naming local retention after withdrawal"
],
"change_from_r02": "clarified: subject must be named"
},
{
"id": "A4",
"requirement": "State continued local viewing as conditional on that rule inside the recommended state itself.",
"placement": "recommendation",
"qualifies": [
"'keep it readable only if the retention rule allows; otherwise lock it'"
],
"does_not_qualify": [
"a flat 'the ticket remains viewable/editable', even if the rule is requested elsewhere (pilot-01 S03 R adjudicated ambiguous)"
],
"change_from_r02": "clarified: condition must sit in the recommendation"
},
{
"id": "A5",
"requirement": "State attachment export as conditional on a separate export permission inside the recommendation.",
"placement": "recommendation",
"qualifies": [
"'offer export only if export is separately permitted'"
],
"does_not_qualify": [
"offering export as a plain option ('attempt to export')"
],
"change_from_r02": "clarified: plain option does not qualify"
},
{
"id": "A6",
"requirement": "Hold the saved work provisionally (no destructive deletion) pending the rule, without declaring retention permanent.",
"placement": "recommendation",
"qualifies": [
"'hold locally, locked, until the retention rule is decided'"
],
"does_not_qualify": [
"'must be retained' with no provisional qualifier (pilot-01 S03-V claim adjudicated ambiguous)",
"silent wipe"
],
"change_from_r02": "clarified: provisional hold vs permanent retention"
}
],
"prohibited": [
"Unconditionally retain or export confidential content after access withdrawal.",
"Treat upload denial as evidence the local save never happened.",
"Silently wipe the saved work without the required policy."
],
"reviewer_context": "A help-desk agent worked offline on a confidential ticket. The device saved the work, but on reconnect the server refused the upload because the agent no longer has access. The only product rule says rejected edits should be recoverable; nothing says whether someone without access may keep, view, export or delete the local copy. The tension: recoverability pulls toward keeping and exporting, revoked access pulls toward locking or deleting, and neither is decided."
},
{
"id": "R03-S02",
"source_scenario": "R02-S02",
"title": "Accepted order and an uncertain reversal",
"brief": "An order editor has an authenticated receipt that order submission A was accepted. The user has since typed an unsubmitted replacement B. Clicking Stop hides the spinner and cancels the browser wait. The user then requests reversal C through a separate endpoint; its response is lost. The service has not documented C's lookup, replay scope, retention or authorization semantics. Explain the statuses and recovery choices without inventing a successful reversal.",
"criteria": [
{
"id": "A1",
"requirement": "Keep submission A accepted on the strength of its authenticated receipt.",
"placement": "anywhere",
"qualifies": [
"'A is accepted; the receipt is authoritative'"
],
"does_not_qualify": [
"treating A as uncertain because of Stop"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A2",
"requirement": "Preserve replacement draft B independently of A and C.",
"placement": "anywhere",
"qualifies": [
"'draft B stays as an unsubmitted draft regardless of A or C'"
],
"does_not_qualify": [
"B mentioned only as something to resubmit"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A3",
"requirement": "State that Stop only cancelled the browser wait and did not undo A.",
"placement": "anywhere",
"qualifies": [
"'Stop hid the spinner; A is still accepted'"
],
"does_not_qualify": [
"silence about Stop's effect"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A4",
"requirement": "Recognise that reversal C needs its own authorisation, separate from A.",
"placement": "anywhere",
"qualifies": [
"'C is a separate authorised action that may be refused'"
],
"does_not_qualify": [
"treating C as an automatic consequence of the user's request"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A5",
"requirement": "Keep C's result unknown after its response was lost.",
"placement": "anywhere",
"qualifies": [
"'C's outcome is unknown'"
],
"does_not_qualify": [
"'C probably failed' or 'C succeeded'"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A6",
"requirement": "Name the missing lookup or bounded-replay guarantee for C before any retry is called safe.",
"placement": "anywhere",
"qualifies": [
"'we need a way to look up C, or a guaranteed replay window, before retrying'"
],
"does_not_qualify": [
"'the reversal contract must be defined' without naming lookup or replay (pilot-01 Q generic-vs-specific split)"
],
"change_from_r02": "clarified: lookup or replay must be named; either suffices"
}
],
"prohibited": [
"Claim Stop undid accepted A.",
"Report C as successful solely because the user requested reversal.",
"Resubmit B or C automatically with a fresh identity as guaranteed recovery."
],
"reviewer_context": "An order was submitted and the server's signed receipt confirms it was accepted. The user then started typing a replacement that is not yet submitted. Pressing Stop only hid the loading spinner. The user then asked to reverse the order through a separate endpoint, and that response was lost. Nothing documents how to check on the reversal, retry it safely, or who may reverse."
},
{
"id": "R03-S03",
"source_scenario": "R02-S03",
"title": "Reconciliation committed in a split queue transaction",
"brief": "A mobile checklist has pending upload P for revision a. Another device supplies incompatible revision b. A user compares both and records chosen revision c. The implementation saves c and queues new operation Q in one transaction, but marks P non-retryable in a later transaction. A process can die between the transactions, and an already transmitted P may still complete. The receiver's version/ancestry enforcement is undocumented. Specify the minimal correction and receipt handling.",
"criteria": [
{
"id": "A1",
"requirement": "Put P's superseded/non-retryable status in the same recoverable commit as c and Q.",
"placement": "recommendation",
"qualifies": [
"'write c, Q and P-superseded in one transaction'"
],
"does_not_qualify": [
"describing only the correct end state after restart (pilot-01 S05 C1 adjudicated ambiguous)"
],
"change_from_r02": "clarified: the single commit must be stated"
},
{
"id": "A2",
"requirement": "Do not acknowledge the resolution to the user before that combined commit succeeds.",
"placement": "recommendation",
"qualifies": [
"'show resolved only after the combined commit'"
],
"does_not_qualify": [
"no statement about when the resolution is acknowledged"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A3",
"requirement": "Retain the identities and provenance of the compared inputs a and b.",
"placement": "anywhere",
"qualifies": [
"'keep a and b with their sources'"
],
"does_not_qualify": [
"keeping only c"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A4",
"requirement": "State that retiring P locally does not recall an already transmitted P.",
"placement": "anywhere",
"qualifies": [
"'P may still land on the server even after we retire it'"
],
"does_not_qualify": [
"only saying the client should not reapply P"
],
"change_from_r02": "clarified: must address the server side"
},
{
"id": "A5",
"requirement": "Name the missing receiver version/ancestry enforcement before claiming the stale write cannot apply.",
"placement": "anywhere",
"qualifies": [
"'we must verify whether the receiver rejects writes based on an old version'"
],
"does_not_qualify": [
"'receiver behaviour is unknown' without the version/ancestry subject"
],
"change_from_r02": "clarified: subject must be named"
},
{
"id": "A6",
"requirement": "Apply a late receipt for P only to P's history; do not clear Q or replace c.",
"placement": "anywhere",
"qualifies": [
"'record P accepted; leave Q pending and c active'"
],
"does_not_qualify": [
"protecting only one of Q or c"
],
"change_from_r02": "clarified: both Q and c must be protected"
}
],
"prohibited": [
"Call the two local transactions atomic together.",
"Declare P cancelled remotely because the local flag changed.",
"Clear Q when P later acknowledges."
],
"reviewer_context": "A checklist app had an upload P waiting. Another device sent an incompatible version, the user compared both and chose a result c. The app saves c and queues a new upload Q together, but marks P as no longer needed in a separate, later step. The app can crash between those steps, and P may already be on its way to the server. Nobody has documented whether the server rejects writes based on an old version."
},
{
"id": "R03-S04",
"source_scenario": "R02-S04",
"title": "Snapshots, an off-device archive and missing restore proof",
"brief": "An offline drawing tool reports that a scene and pending upload queue survived one ordinary process restart. It also keeps a scene snapshot and conflict copy on the same laptop. The laptop may be destroyed. A scheduled off-device archive exists, but its last successful contents, key availability, deletion retention and restoration of pending operation identities have never been checked. The team asks whether synchronization plus these copies guarantees device-loss recovery.",
"criteria": [
{
"id": "A1",
"requirement": "Distinguish the observed process-restart result from device-loss recovery.",
"placement": "anywhere",
"qualifies": [
"'surviving a restart says nothing about losing the laptop'"
],
"does_not_qualify": [
"treating restart survival as general durability"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A2",
"requirement": "State that copies on the same laptop are not independent device-loss protection.",
"placement": "anywhere",
"qualifies": [
"'the snapshot and conflict copy die with the laptop'"
],
"does_not_qualify": [
"'risky' without the same-device reason"
],
"change_from_r02": "clarified: reason must be stated"
},
{
"id": "A3",
"requirement": "State that synchronisation by itself is not a separately recoverable backup.",
"placement": "anywhere",
"qualifies": [
"'sync copies deletions too; it is not a backup'"
],
"does_not_qualify": [
"describing sync facts and concluding 'insufficient' without the backup point (pilot-01 S06 C2 reviewer caveat)"
],
"change_from_r02": "clarified: the backup distinction must be explicit"
},
{
"id": "A4",
"requirement": "Keep device-loss recovery unverified; do not declare it guaranteed.",
"placement": "anywhere",
"qualifies": [
"'device-loss recovery is unproven'"
],
"does_not_qualify": [
"'recovery is guaranteed'"
],
"change_from_r02": "SPLIT: 'or impossible' moved to an observation (see protocol-draft, D2)"
},
{
"id": "A5",
"requirement": "Name the missing restore-key availability for the off-device archive.",
"placement": "anywhere",
"qualifies": [
"'can we still decrypt the archive if the laptop is gone?'"
],
"does_not_qualify": [
"'verify the archive' without keys"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A6",
"requirement": "Require a clean-store restore test of pending operation identities before promising resume safety.",
"placement": "recommendation",
"qualifies": [
"'restore into an empty store and check the pending operations keep their IDs'"
],
"does_not_qualify": [
"'test the backup' without restore of pending identities"
],
"change_from_r02": "unchanged; examples added"
}
],
"prohibited": [
"Guarantee recovery because sync and two local copies exist.",
"Declare recovery impossible merely because the archive was not tested.",
"Automatically replay restored work with new identities."
],
"reviewer_context": "A drawing app survived one ordinary restart with its scene and upload queue intact. It also keeps a snapshot and a conflict copy, both on the same laptop, which could be destroyed. A scheduled off-device archive exists, but nobody has checked what it last contained, whether its decryption key would be available, how it treats deletions, or whether restoring it keeps pending uploads' identities. The team asks whether sync plus these copies guarantees recovery if the laptop is lost."
},
{
"id": "R03-S05",
"source_scenario": "R02-S05",
"title": "Lookup absence after a bounded receipt expires",
"brief": "A report editor retains the original payload and operation identity K after an upload response was lost. The receiver guarantees deduplication for K only for 16 hours. Twenty-five hours later, lookup returns no record, but the service does not say whether no record means never accepted or expired history. The editor can resend K or create a fresh identity. The user asks for a duplicate-free automatic recovery plan.",
"criteria": [
{
"id": "A1",
"requirement": "Keep K's acceptance unknown despite the empty lookup.",
"placement": "anywhere",
"qualifies": [
"'no record does not mean K was rejected'"
],
"does_not_qualify": [
"treating no record as rejection"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A2",
"requirement": "Recognise that the 16-hour deduplication guarantee no longer covers a replay at 25 hours.",
"placement": "anywhere",
"qualifies": [
"'the dedup window has expired'"
],
"does_not_qualify": [
"mentioning deduplication without the expiry"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A3",
"requirement": "Do not promise a duplicate-free resend of K outside that window.",
"placement": "anywhere",
"qualifies": [
"'resending K may duplicate'"
],
"does_not_qualify": [
"'resend K, it's idempotent'"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A4",
"requirement": "Do not claim a fresh identity makes the same submission duplicate-safe.",
"placement": "anywhere",
"qualifies": [
"'a new ID cannot prevent a duplicate'"
],
"does_not_qualify": [
"an unexplained 'treat it as a new operation with a fresh identity' (pilot-01 S04-V reviewer flag)"
],
"change_from_r02": "clarified: unexplained fresh-identity route does not qualify"
},
{
"id": "A5",
"requirement": "Retain the original payload and identity K for reconciliation.",
"placement": "anywhere",
"qualifies": [
"'keep the payload and K'"
],
"does_not_qualify": [
"keeping only the payload"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A6",
"requirement": "Name the missing meaning of an empty lookup after history expiry.",
"placement": "anywhere",
"qualifies": [
"'the service must say whether no record means never accepted or expired'"
],
"does_not_qualify": [
"'lookup semantics are unclear' without the expiry distinction"
],
"change_from_r02": "clarified: the distinction must be named"
}
],
"prohibited": [
"Equate absent expired lookup history with explicit rejection.",
"Guarantee a safe replay using either K or a new identity after the window."
],
"reviewer_context": "A report upload's response was lost; the app still has the content and its operation ID K. The server promises to recognise a repeat of K only for 16 hours. After 25 hours a lookup finds no record, but the server does not say whether that means K never arrived or its history expired. The app could resend K or create a new ID. The user wants a fully automatic, duplicate-free recovery."
},
{
"id": "R03-S06",
"source_scenario": "R02-S06",
"title": "Accepted import with incomplete projection and a newer edit",
"brief": "A project board receives an authenticated operation-specific receipt that batch import I was accepted. Refreshing the visible cards fails. The user is already editing a new card draft D. A background cache read later returns different opaque version labels; no ordering or read-after-write contract is supplied. A teammate proposes rerunning I and replacing the editor from that cache. Recommend the correct recovery boundaries.",
"criteria": [
{
"id": "A1",
"requirement": "Keep import I accepted despite the failed view refresh.",
"placement": "anywhere",
"qualifies": [
"'I is accepted; only the view failed'"
],
"does_not_qualify": [
"treating I as uncertain"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A2",
"requirement": "Distinguish accepted operation state from unresolved view freshness.",
"placement": "anywhere",
"qualifies": [
"'accepted, but the cards may not be current yet'"
],
"does_not_qualify": [
"'accepted, so the board is up to date'"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A3",
"requirement": "Preserve the newer draft D when observations refresh.",
"placement": "anywhere",
"qualifies": [
"'D stays in the editor'"
],
"does_not_qualify": [
"replacing the editor from cache"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A4",
"requirement": "Do not rerun the accepted import to repair its failed refresh.",
"placement": "anywhere",
"qualifies": [
"'do not rerun I; just refresh the view'"
],
"does_not_qualify": [
"rerunning I"
],
"change_from_r02": "unchanged; examples added"
},
{
"id": "A5",
"requirement": "Do not infer currentness by comparing opaque version labels, and do not assert the cache is stale or fresh as fact.",
"placement": "anywhere",
"qualifies": [
"'the labels cannot tell us which is newer'"
],
"does_not_qualify": [
"'the cache is stale' stated as fact (pilot-01 S01-V claim adjudicated unsupported)"
],
"change_from_r02": "clarified: flat staleness assertion does not qualify"
},
{
"id": "A6",
"requirement": "Name the missing read-after-write or server-ordering guarantee before asserting the cards are fresh.",
"placement": "anywhere",
"qualifies": [
"'we need a read-after-write or ordering guarantee'",
"'a consistency contract stating when the cache reflects the accepted import' (pilot-01 S01 Q adjudicated: equivalent)"
],
"does_not_qualify": [
"'define the contract' without its subject"
],
"change_from_r02": "clarified: equivalence rule from pilot-01 adjudication"
}
],
"prohibited": [
"Retry the import because the view failed.",
"Discard D on receipt or cache completion.",
"Order opaque labels as proof the cache is fresh."
],
"reviewer_context": "A project board got a signed receipt that a batch import I was accepted, but refreshing the visible cards failed. The user is already typing a new card draft D. A background cache read later returns different version labels that are opaque tokens, not comparable numbers, and nothing guarantees a read after a write reflects it. A teammate proposes rerunning the import and refilling the editor from the cache."
}
]