{"abstract":"Nearly empty heaps shrink below the configured minimum.","category":"Garbage collector invariants","checks":7,"contract":"After each full collection with live bytes L and capacity C: if the free share (C - L) / C is below min_free percent, grow to the smallest capacity whose free share is at least min_free, i.e. ceil(L * 100 / (100 - min_free)), never shrinking and never above max_heap; if the free share exceeds max_free percent, compute ceil(L * 100 / (100 - max_free)) floored at min_heap and move shrink_pct percent of the way from C toward it (integer arithmetic). Otherwise keep C. Return the capacity after each collection.","contract_signature":"lives, cap0, min_heap, max_heap, min_free, max_free, shrink_pct","evaluation_group":"w2-garbage-collector-invariants-heap-resizing-policy","failed_approach":"Flooring at the initial capacity instead prevents legitimate shrinking.","family":"w2-garbage-collector-invariants-heap-resizing-policy-minimum-heap-floor","id":"FA-90826","implementations":{"attempt":{"sha256":"88b268d6b17973ea11781a01fd540b15d4fcf4bf036daee5a5db0a81768d36a6","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(lives, cap0, min_heap, max_heap, min_free, max_free, shrink_pct):\n    cap = cap0\n    out = []\n    for live in lives:\n        free = cap - live\n        if free * 100 < min_free * cap:\n            want = -(-live * 100 // (100 - min_free))\n            cap = min(max(want, cap), max_heap)\n        elif free * 100 > max_free * cap:\n            want = -(-live * 100 // (100 - max_free))\n            want = max(want, cap0)\n            cap = cap - (cap - want) * shrink_pct // 100\n        out.append(cap)\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression: grow, hold and shrink',\n   ([150, 150, 61, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 227, 164]),\n  ('growth target rounds up', ([102], 150, 100, 1000, 40, 70, 50), [170]),\n  ('growth clamped at the maximum heap', ([701, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([11, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([31], 600, 100, 1000, 40, 70, 25), [476]),\n  ('free ratio exactly at the minimum', ([120, 181], 200, 100, 1000, 40, 70, 50), [200, 302]),\n  ('control: within the band', ([101], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 62, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 229, 165]),\n  ('growth target rounds up', ([103], 150, 100, 1000, 40, 70, 50), [172]),\n  ('growth clamped at the maximum heap', ([702, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([12, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([32], 600, 100, 1000, 40, 70, 25), [477]),\n  ('free ratio exactly at the minimum', ([120, 182], 200, 100, 1000, 40, 70, 50), [200, 304]),\n  ('control: within the band', ([102], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 63, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 230, 165]),\n  ('growth target rounds up', ([104], 150, 100, 1000, 40, 70, 50), [174]),\n  ('growth clamped at the maximum heap', ([703, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([13, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([33], 600, 100, 1000, 40, 70, 25), [478]),\n  ('free ratio exactly at the minimum', ([120, 183], 200, 100, 1000, 40, 70, 50), [200, 305]),\n  ('control: within the band', ([103], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 64, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 232, 166]),\n  ('growth target rounds up', ([105], 150, 100, 1000, 40, 70, 50), [175]),\n  ('growth clamped at the maximum heap', ([704, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([14, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([34], 600, 100, 1000, 40, 70, 25), [479]),\n  ('free ratio exactly at the minimum', ([120, 184], 200, 100, 1000, 40, 70, 50), [200, 307]),\n  ('control: within the band', ([104], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 65, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 234, 167]),\n  ('growth target rounds up', ([106], 150, 100, 1000, 40, 70, 50), [177]),\n  ('growth clamped at the maximum heap', ([705, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([15, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([35], 600, 100, 1000, 40, 70, 25), [480]),\n  ('free ratio exactly at the minimum', ([120, 185], 200, 100, 1000, 40, 70, 50), [200, 309]),\n  ('control: within the band', ([105], 200, 100, 1000, 40, 70, 50), [200])]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"d5c13288206f4f253b2a17d71742cd613c2d96b690fa9e5c7802e3901feaf78f","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(lives, cap0, min_heap, max_heap, min_free, max_free, shrink_pct):\n    cap = cap0\n    out = []\n    for live in lives:\n        free = cap - live\n        if free * 100 < min_free * cap:\n            want = -(-live * 100 // (100 - min_free))\n            cap = min(max(want, cap), max_heap)\n        elif free * 100 > max_free * cap:\n            want = -(-live * 100 // (100 - max_free))\n            cap = cap - (cap - want) * shrink_pct // 100\n        out.append(cap)\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression: grow, hold and shrink',\n   ([150, 150, 61, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 227, 164]),\n  ('growth target rounds up', ([102], 150, 100, 1000, 40, 70, 50), [170]),\n  ('growth clamped at the maximum heap', ([701, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([11, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([31], 600, 100, 1000, 40, 70, 25), [476]),\n  ('free ratio exactly at the minimum', ([120, 181], 200, 100, 1000, 40, 70, 50), [200, 302]),\n  ('control: within the band', ([101], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 62, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 229, 165]),\n  ('growth target rounds up', ([103], 150, 100, 1000, 40, 70, 50), [172]),\n  ('growth clamped at the maximum heap', ([702, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([12, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([32], 600, 100, 1000, 40, 70, 25), [477]),\n  ('free ratio exactly at the minimum', ([120, 182], 200, 100, 1000, 40, 70, 50), [200, 304]),\n  ('control: within the band', ([102], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 63, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 230, 165]),\n  ('growth target rounds up', ([104], 150, 100, 1000, 40, 70, 50), [174]),\n  ('growth clamped at the maximum heap', ([703, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([13, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([33], 600, 100, 1000, 40, 70, 25), [478]),\n  ('free ratio exactly at the minimum', ([120, 183], 200, 100, 1000, 40, 70, 50), [200, 305]),\n  ('control: within the band', ([103], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 64, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 232, 166]),\n  ('growth target rounds up', ([105], 150, 100, 1000, 40, 70, 50), [175]),\n  ('growth clamped at the maximum heap', ([704, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([14, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([34], 600, 100, 1000, 40, 70, 25), [479]),\n  ('free ratio exactly at the minimum', ([120, 184], 200, 100, 1000, 40, 70, 50), [200, 307]),\n  ('control: within the band', ([104], 200, 100, 1000, 40, 70, 50), [200])],\n [('regression: grow, hold and shrink',\n   ([150, 150, 65, 20], 200, 100, 1000, 40, 70, 50),\n   [250, 250, 234, 167]),\n  ('growth target rounds up', ([106], 150, 100, 1000, 40, 70, 50), [177]),\n  ('growth clamped at the maximum heap', ([705, 900], 800, 100, 1000, 40, 70, 50), [1000, 1000]),\n  ('shrinking stops at the minimum heap', ([15, 10, 10], 400, 150, 1000, 40, 70, 50), [275, 213, 182]),\n  ('shrink moves part of the way', ([35], 600, 100, 1000, 40, 70, 25), [480]),\n  ('free ratio exactly at the minimum', ([120, 185], 200, 100, 1000, 40, 70, 50), [200, 309]),\n  ('control: within the band', ([105], 200, 100, 1000, 40, 70, 50), [200])]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic, bounded teaching model of one garbage-collector mechanism with stipulated rules; it is not a production collector and claims no conformance to any particular runtime. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-garbage-collector-invariants-heap-resizing-policy-minimum-heap-floor","generated_at":"2026-09-29T14:51:30.374533+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Heap sizing policies decide footprint and GC frequency; rounding and clamping errors oscillate or overshoot.","root_cause":"The shrink target is not floored at min_heap.","sha256":"d4c4c83766033652c2f54cad7627df344becc2711fe4b2e2526598776aa98dcf","title":"Heap resizing: shrinking goes below the minimum heap · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":40.603,"exit_code":1,"observations":[{"actual":[250,250,227,214],"check":"regression: grow, hold and shrink","expected":[250,250,227,164],"passed":false},{"actual":[170],"check":"growth target rounds up","expected":[170],"passed":true},{"actual":[1000,1000],"check":"growth clamped at the maximum heap","expected":[1000,1000],"passed":true},{"actual":[400,400,400],"check":"shrinking stops at the minimum heap","expected":[275,213,182],"passed":false},{"actual":[600],"check":"shrink moves part of the way","expected":[476],"passed":false},{"actual":[200,302],"check":"free ratio exactly at the minimum","expected":[200,302],"passed":true},{"actual":[200],"check":"control: within the band","expected":[200],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: grow, hold and shrink\", \"actual\": [250, 250, 227, 214], \"expected\": [250, 250, 227, 164], \"passed\": false}, {\"check\": \"growth target rounds up\", \"actual\": [170], \"expected\": [170], \"passed\": true}, {\"check\": \"growth clamped at the maximum heap\", \"actual\": [1000, 1000], \"expected\": [1000, 1000], \"passed\": true}, {\"check\": \"shrinking stops at the minimum heap\", \"actual\": [400, 400, 400], \"expected\": [275, 213, 182], \"passed\": false}, {\"check\": \"shrink moves part of the way\", \"actual\": [600], \"expected\": [476], \"passed\": false}, {\"check\": \"free ratio exactly at the minimum\", \"actual\": [200, 302], \"expected\": [200, 302], \"passed\": true}, {\"check\": \"control: within the band\", \"actual\": [200], \"expected\": [200], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":37.588,"exit_code":1,"observations":[{"actual":[250,250,227,147],"check":"regression: grow, hold and shrink","expected":[250,250,227,164],"passed":false},{"actual":[170],"check":"growth target rounds up","expected":[170],"passed":true},{"actual":[1000,1000],"check":"growth clamped at the maximum heap","expected":[1000,1000],"passed":true},{"actual":[219,127,81],"check":"shrinking stops at the minimum heap","expected":[275,213,182],"passed":false},{"actual":[476],"check":"shrink moves part of the way","expected":[476],"passed":true},{"actual":[200,302],"check":"free ratio exactly at the minimum","expected":[200,302],"passed":true},{"actual":[200],"check":"control: within the band","expected":[200],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: grow, hold and shrink\", \"actual\": [250, 250, 227, 147], \"expected\": [250, 250, 227, 164], \"passed\": false}, {\"check\": \"growth target rounds up\", \"actual\": [170], \"expected\": [170], \"passed\": true}, {\"check\": \"growth clamped at the maximum heap\", \"actual\": [1000, 1000], \"expected\": [1000, 1000], \"passed\": true}, {\"check\": \"shrinking stops at the minimum heap\", \"actual\": [219, 127, 81], \"expected\": [275, 213, 182], \"passed\": false}, {\"check\": \"shrink moves part of the way\", \"actual\": [476], \"expected\": [476], \"passed\": true}, {\"check\": \"free ratio exactly at the minimum\", \"actual\": [200, 302], \"expected\": [200, 302], \"passed\": true}, {\"check\": \"control: within the band\", \"actual\": [200], \"expected\": [200], \"passed\": true}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}