Vectors re-vendored from CultLib de8a062a (answerTooLarge replay) #42
2 changed files with 234 additions and 0 deletions
|
|
@ -854,6 +854,33 @@ mod tests {
|
|||
assert_eq!(encode(&rmp_serde::from_slice::<ForkRefusal>(&bytes).unwrap()), bytes);
|
||||
}
|
||||
|
||||
/// CultLib de8a062a: `transport.answerTooLarge`. The request is a well-formed answer whose hash is not the
|
||||
/// fork's current card hash, so Huginn stores it `Refused(stale_fork)`; the vector's door response is the
|
||||
/// read-form `fork_too_large` refusal (422) over that stored outcome, uncounted. What Huginn can judge
|
||||
/// replays: the request decodes, its hash is stale against the fork's card in the vector, the refusal
|
||||
/// round-trips byte for byte with code `fork_too_large`, and the text (informational) names the fork and
|
||||
/// carries no order or cursor. The stored outcome itself is pinned by
|
||||
/// `a_stale_answer_then_the_read_cards_hash_counts` and the socket tests.
|
||||
#[test]
|
||||
fn the_answer_too_large_vector_replays_over_a_stale_answer() {
|
||||
let file = transport();
|
||||
let cases = file["answerTooLarge"].as_array().unwrap();
|
||||
assert_eq!(cases.len(), 1);
|
||||
let case = &cases[0];
|
||||
let request: ForkAnswerRequest = serde_json::from_value(case["request"].clone()).unwrap();
|
||||
let current = case["entries"].as_array().unwrap().iter().find(|entry| entry["card"]["fork_id"] == case["fork_id"]).unwrap();
|
||||
assert_eq!(request.fork_id, case["fork_id"].as_str().unwrap());
|
||||
assert_ne!(request.options_hash, current["card"]["options_hash"].as_str().unwrap(), "a stale answer");
|
||||
let bytes = bytes_of(case["refusalHex"].as_str().unwrap());
|
||||
let refusal: ForkRefusal = rmp_serde::from_slice(&bytes).unwrap();
|
||||
assert_eq!(encode(&refusal), bytes);
|
||||
assert_eq!(refusal.code, ForkRefusalCode::ForkTooLarge);
|
||||
let fork_id = case["fork_id"].as_str().unwrap();
|
||||
assert!(refusal.error.contains(fork_id) && !refusal.error.contains("order") && !refusal.error.contains("cursor"), "{}", refusal.error);
|
||||
assert_eq!(fork_too_large_read(fork_id).code, refusal.code);
|
||||
assert_eq!((case["httpStatus"].as_u64(), case["outcome"].as_str(), case["code"].as_str(), case["counted"].as_bool()), (Some(422), Some("Refused"), Some("stale_fork"), Some(false)));
|
||||
}
|
||||
|
||||
/// The contract pins no exact text for `fork_too_large`: the vector's `error` string is
|
||||
/// Huginn-independent, and a judge checks that the refusal names the entry the page would open
|
||||
/// with. So for each vector case Huginn's refusal is code `fork_too_large`, its text contains the
|
||||
|
|
|
|||
|
|
@ -7702,6 +7702,213 @@
|
|||
"fork_id": "gamecult-chat:question:q3"
|
||||
}
|
||||
],
|
||||
"answerTooLarge": [
|
||||
{
|
||||
"name": "a_stale_answer_whose_card_reread_is_past_the_cap_is_fork_too_large_over_a_stored_stale_refusal",
|
||||
"entries": [
|
||||
{
|
||||
"schemaVersion": "gamecult.fork.entry.v0",
|
||||
"card": {
|
||||
"schemaVersion": "gamecult.fork.card.v0",
|
||||
"fork_id": "gamecult-chat:question:q3",
|
||||
"title": "Fork 3",
|
||||
"context": "Should a slot mark be shared?",
|
||||
"options": [
|
||||
{
|
||||
"id": "yes",
|
||||
"text": "Share it."
|
||||
},
|
||||
{
|
||||
"id": "no",
|
||||
"text": "Keep it local."
|
||||
}
|
||||
],
|
||||
"recommendation": "no",
|
||||
"depends": [
|
||||
"gamecult-chat:question:file-zone-audience"
|
||||
],
|
||||
"leans": null,
|
||||
"flag": null,
|
||||
"raised_in": {
|
||||
"kind": "CutSpec",
|
||||
"id": "cultlib-gaps:cut_spec:cut-slot-tolerance.r4"
|
||||
},
|
||||
"deciders": [
|
||||
"e0d1c2b3-a495-4687-8879-6a5b4c3d2e1f"
|
||||
],
|
||||
"status": "open",
|
||||
"ruling": null,
|
||||
"ruled_from": [],
|
||||
"order": 3,
|
||||
"options_hash": "ced892eb663c22e3d7ece602708043ee545f56b9d4e4421d7f5bfaa86c418ce2"
|
||||
},
|
||||
"record": {
|
||||
"schemaVersion": "gamecult.fork.record.v0",
|
||||
"fork_id": "gamecult-chat:question:q3",
|
||||
"options_hash": "ced892eb663c22e3d7ece602708043ee545f56b9d4e4421d7f5bfaa86c418ce2",
|
||||
"counted_answer_id": null,
|
||||
"answers": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"schemaVersion": "gamecult.fork.entry.v0",
|
||||
"card": {
|
||||
"schemaVersion": "gamecult.fork.card.v0",
|
||||
"fork_id": "gamecult-chat:question:q2",
|
||||
"title": "Fork 2",
|
||||
"context": "Should a slot mark be shared?",
|
||||
"options": [
|
||||
{
|
||||
"id": "yes",
|
||||
"text": "Share it."
|
||||
},
|
||||
{
|
||||
"id": "no",
|
||||
"text": "Keep it local."
|
||||
}
|
||||
],
|
||||
"recommendation": "no",
|
||||
"depends": [
|
||||
"gamecult-chat:question:file-zone-audience"
|
||||
],
|
||||
"leans": null,
|
||||
"flag": null,
|
||||
"raised_in": {
|
||||
"kind": "CutSpec",
|
||||
"id": "cultlib-gaps:cut_spec:cut-slot-tolerance.r4"
|
||||
},
|
||||
"deciders": [
|
||||
"e0d1c2b3-a495-4687-8879-6a5b4c3d2e1f"
|
||||
],
|
||||
"status": "open",
|
||||
"ruling": null,
|
||||
"ruled_from": [],
|
||||
"order": 2,
|
||||
"options_hash": "5c7c2945e8e8689c6c928b11d7e0a033640b0c66afb7fcffb9e740c019d63e79"
|
||||
},
|
||||
"record": {
|
||||
"schemaVersion": "gamecult.fork.record.v0",
|
||||
"fork_id": "gamecult-chat:question:q2",
|
||||
"options_hash": "5c7c2945e8e8689c6c928b11d7e0a033640b0c66afb7fcffb9e740c019d63e79",
|
||||
"counted_answer_id": null,
|
||||
"answers": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"schemaVersion": "gamecult.fork.entry.v0",
|
||||
"card": {
|
||||
"schemaVersion": "gamecult.fork.card.v0",
|
||||
"fork_id": "gamecult-chat:question:q1",
|
||||
"title": "Fork 1",
|
||||
"context": "Should a slot mark be shared?",
|
||||
"options": [
|
||||
{
|
||||
"id": "yes",
|
||||
"text": "Share it."
|
||||
},
|
||||
{
|
||||
"id": "no",
|
||||
"text": "Keep it local."
|
||||
}
|
||||
],
|
||||
"recommendation": "no",
|
||||
"depends": [
|
||||
"gamecult-chat:question:file-zone-audience"
|
||||
],
|
||||
"leans": null,
|
||||
"flag": null,
|
||||
"raised_in": {
|
||||
"kind": "CutSpec",
|
||||
"id": "cultlib-gaps:cut_spec:cut-slot-tolerance.r4"
|
||||
},
|
||||
"deciders": [
|
||||
"e0d1c2b3-a495-4687-8879-6a5b4c3d2e1f"
|
||||
],
|
||||
"status": "open",
|
||||
"ruling": null,
|
||||
"ruled_from": [],
|
||||
"order": 1,
|
||||
"options_hash": "61959964bd214ea1b961554c43ec46a9faf156dd547cc50c8c16bbdcd55f223a"
|
||||
},
|
||||
"record": {
|
||||
"schemaVersion": "gamecult.fork.record.v0",
|
||||
"fork_id": "gamecult-chat:question:q1",
|
||||
"options_hash": "61959964bd214ea1b961554c43ec46a9faf156dd547cc50c8c16bbdcd55f223a",
|
||||
"counted_answer_id": null,
|
||||
"answers": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"schemaVersion": "gamecult.fork.entry.v0",
|
||||
"card": {
|
||||
"schemaVersion": "gamecult.fork.card.v0",
|
||||
"fork_id": "gamecult-chat:question:q0",
|
||||
"title": "Fork 0",
|
||||
"context": "Should a slot mark be shared?",
|
||||
"options": [
|
||||
{
|
||||
"id": "yes",
|
||||
"text": "Share it."
|
||||
},
|
||||
{
|
||||
"id": "no",
|
||||
"text": "Keep it local."
|
||||
}
|
||||
],
|
||||
"recommendation": "no",
|
||||
"depends": [
|
||||
"gamecult-chat:question:file-zone-audience"
|
||||
],
|
||||
"leans": null,
|
||||
"flag": null,
|
||||
"raised_in": {
|
||||
"kind": "CutSpec",
|
||||
"id": "cultlib-gaps:cut_spec:cut-slot-tolerance.r4"
|
||||
},
|
||||
"deciders": [
|
||||
"e0d1c2b3-a495-4687-8879-6a5b4c3d2e1f"
|
||||
],
|
||||
"status": "open",
|
||||
"ruling": null,
|
||||
"ruled_from": [],
|
||||
"order": 0,
|
||||
"options_hash": "1777bd06ffafdf6e81bed5979f37193c4b4e7c3d2504f904e9131012f0767a9d"
|
||||
},
|
||||
"record": {
|
||||
"schemaVersion": "gamecult.fork.record.v0",
|
||||
"fork_id": "gamecult-chat:question:q0",
|
||||
"options_hash": "1777bd06ffafdf6e81bed5979f37193c4b4e7c3d2504f904e9131012f0767a9d",
|
||||
"counted_answer_id": null,
|
||||
"answers": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"schemaVersion": "gamecult.fork.answer_request.v0",
|
||||
"fork_id": "gamecult-chat:question:q3",
|
||||
"options_hash": "14b8ffbdb61106dbc06f69f3fc8e2072af7a205d766e4cc040e89733013d54dc",
|
||||
"answer": {
|
||||
"choice": "yes",
|
||||
"note": "Keep it local: a slot mark is the author's call, and sharing it is a separate act."
|
||||
},
|
||||
"retracted": false,
|
||||
"retracts": null,
|
||||
"answered_at": "2026-11-12T19:02:00Z",
|
||||
"request_id": "0000a001-0000-4000-8000-00000000a001"
|
||||
},
|
||||
"refusal": {
|
||||
"schemaVersion": "gamecult.fork.refusal.v0",
|
||||
"code": "fork_too_large",
|
||||
"error": "fork_too_large: fork gamecult-chat:question:q3 alone is past the response budget"
|
||||
},
|
||||
"refusalHex": "83AD736368656D6156657273696F6EB867616D6563756C742E666F726B2E7265667573616C2E7630A4636F6465AE666F726B5F746F6F5F6C61726765A56572726F72D950666F726B5F746F6F5F6C617267653A20666F726B2067616D6563756C742D636861743A7175657374696F6E3A713320616C6F6E6520697320706173742074686520726573706F6E736520627564676574",
|
||||
"httpStatus": 422,
|
||||
"outcome": "Refused",
|
||||
"code": "stale_fork",
|
||||
"counted": false,
|
||||
"fork_id": "gamecult-chat:question:q3"
|
||||
}
|
||||
],
|
||||
"doorFaults": [
|
||||
{
|
||||
"name": "read_door_answers_request_id_conflict_the_client_sees_unavailable",
|
||||
|
|
|
|||
Loading…
Reference in a new issue