{
  "id": "P158",
  "slug": "bug-triage",
  "key": "P158-bug-triage",
  "title": "Bug triage",
  "summary": "Two findings with one shared cause patched where each was seen, one report with two causes patched to its own inputs, and a backlog that outruns its fixes worked in arrival order and worst first.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P158 - Bug triage\n\nThree ways a bug report misleads the people who fix it: two findings with\none cause, one report with two, and a backlog that grows faster than it is\nfixed.\n\n- `main.eml` - the menu, the two findings, the one report, and the backlog\n  worked two ways\n- `triage.eml` - the calendar screens and the date parser they share, the\n  states as fixes go in, the balance as shown and the fixes for it, the\n  findings in the backlog, and working them\n\nHow each part works:\n\n- As in the corpus case `two-findings-one-defect`, the weekly report\n  starts a day late and reminders come a day late. Each candidate cause is\n  run alone: the shared date parser makes the report, the reminder and the\n  audit log wrong; each screen's own code only itself. Only the parser\n  explains both findings, and it predicts a third nobody filed. Patched\n  where each was seen, both findings close and the audit log stays wrong;\n  fix the parser later and the two patches make their screens wrong again.\n- As in the corpus case `one-report-two-mechanisms`, one report of three\n  wrong balances - -4, 150, -7 - has two causes: the sign dropped and\n  anything past 99 clamped. Special-casing the reported inputs makes the\n  report pass and leaves 4 of 12 inputs wrong, each explained by one\n  mechanism run alone; fixing both mechanisms leaves none.\n- As in the corpus case `finding-outruns-fixing`, two findings arrive in\n  each of five periods. Fixing one a period, the queue never empties, and\n  working the worst first instead of in arrival order cuts the harm from\n  127 to 71 with the same fixes; fixing two a period, the queue empties and\n  the order changes nothing.\n\nWhat is checked: menu choices 1 to 4; fixes each period 1 or 2. An empty\nanswer cancels.\n\nSessions: `sessions/basic.in` gives:\n- the two findings and the one report;\n- the backlog at one fix a period and at two.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- fixes each period: a cancel, 3 and x; then the one report.\n\nBuilt on the verified corpus cases `two-findings-one-defect` (two symptoms\npatched locally over one shared cause), `one-report-two-mechanisms` (a\npatch fitted to the reported inputs) and `finding-outruns-fixing` (the\nsame fixing capacity in arrival order and by harm).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P158 bug triage: two findings with one cause, one report with two causes,\n# and a backlog that grows faster than it is fixed.\nimport triage\n\ndef plain(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef pad(s, n):\n    s => out\n    while len(out) < n:\n        out + \" \" => out\n    return out\n\ndef lpad(s, n):\n    s => out\n    while len(out) < n:\n        \" \" + out => out\n    return out\n\ndef listed(xs):\n    \"\" => out\n    for x in xs:\n        if out == \"\":\n            str(x) => out\n        else:\n            out + \", \" + str(x) => out\n    if out == \"\":\n        return \"none\"\n    return out\n\ndef wrong_screens(parser_bug, report_bug, reminder_bug):\n    [] => out\n    for d in triage.days():\n        if triage.report(d, parser_bug, report_bug) != d % 7:\n            out + [\"report\"] => out\n        if triage.reminder(d, parser_bug, reminder_bug) != d % 7:\n            out + [\"reminder\"] => out\n        if triage.audit(d, parser_bug) != d % 7:\n            out + [\"audit\"] => out\n    [] => names\n    for s in [\"report\", \"reminder\", \"audit\"]:\n        for x in out:\n            if x == s:\n                False => have\n                for n in names:\n                    if n == s:\n                        True => have\n                if not have:\n                    names + [s] => names\n    return names\n\ndef two_findings():\n    \"Two findings, filed a week apart: the weekly report starts a day late; reminders come a day late.\" ^0\n    \"Each candidate cause alone, and the screens it makes wrong on the days 3, 10, 17, 24 and 31:\" ^0\n    (\"  the date parser:      \" + listed(wrong_screens(True, False, False))) ^0\n    (\"  the report's code:    \" + listed(wrong_screens(False, True, False))) ^0\n    (\"  the reminder's code:  \" + listed(wrong_screens(False, False, True))) ^0\n    \"Only the parser explains both findings, and it predicts a third nobody filed: the audit log.\" ^0\n    \"Days right of 5, as the fixes go in:\" ^0\n    (\"  \" + pad(\"\", 28) + \"report  reminder  audit\") ^0\n    for st in triage.states():\n        (\"  \" + pad(st[0], 28) + lpad(str(triage.right_days(\"report\", st[1], st[2])), 6) + lpad(str(triage.right_days(\"reminder\", st[1], st[2])), 10) + lpad(str(triage.right_days(\"audit\", st[1], st[2])), 7)) ^0\n    \"Patched where seen, both findings close and the audit log stays wrong; fix the parser later and the two patches make their screens wrong again.\" ^0\n\ndef one_report():\n    \"One report, three wrong balances:\" ^0\n    for r in triage.reported():\n        (\"  \" + lpad(str(r), 5) + \" shows \" + lpad(triage.render(r, True, True), 4) + \", should be \" + triage.truth(r)) ^0\n    (\"Over the \" + str(len(triage.inputs())) + \" inputs \" + listed(triage.inputs()) + \":\") ^0\n    (\"  \" + pad(\"fix\", 22) + \"wrong\") ^0\n    for fx in [\"none\", \"fitted\", \"sign\", \"clamp\", \"both\"]:\n        [] => bad\n        for v in triage.inputs():\n            if triage.shown(v, fx) != triage.truth(v):\n                bad + [v] => bad\n        if fx == \"fitted\":\n            \"the reported inputs\" => name\n        elif fx == \"sign\":\n            \"keep the sign\" => name\n        elif fx == \"clamp\":\n            \"no clamp at 99\" => name\n        else:\n            fx => name\n        (\"  \" + pad(name, 22) + pad(str(len(bad)), 4) + listed(bad)) ^0\n    [] => s\n    [] => c\n    0 => left\n    for v in triage.inputs():\n        if triage.shown(v, \"fitted\") != triage.truth(v):\n            left + 1 => left\n            if triage.render(v, True, False) != triage.truth(v):\n                s + [v] => s\n            if triage.render(v, False, True) != triage.truth(v):\n                c + [v] => c\n    (\"Fitted to the report, the report passes and \" + str(left) + \" failures remain; each mechanism run alone accounts for its share:\") ^0\n    (\"  the sign dropped:      \" + listed(s)) ^0\n    (\"  past 99 clamped:       \" + listed(c)) ^0\n    \"The report could not show that two of its rows came from one cause and the third from another.\" ^0\n\ndef backlog():\n    plain(input(\"fixes each period (1 or 2)> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return\n    if t != \"1\" and t != \"2\":\n        \"Type 1 or 2.\" ^0\n        return\n    int(t) => cap\n    (\"Two findings arrive in each of periods 1 to 5; \" + t + \" fixed a period; the harm each does every period it waits is summed over 6 periods.\") ^0\n    triage.work(\"fifo\", cap, 6) => a\n    triage.work(\"harm\", cap, 6) => b\n    (\"  in arrival order:  harm \" + lpad(str(a[0]), 3) + \"; still open: \" + listed(a[2])) ^0\n    (\"  worst first:       harm \" + lpad(str(b[0]), 3) + \"; still open: \" + listed(b[2])) ^0\n    if a[0] != b[0]:\n        (\"The same number fixed each period, and the order changes the harm by \" + str(a[0] - b[0]) + \": once findings outrun fixes, the order is not a preference.\") ^0\n    else:\n        \"The order changes nothing here.\" ^0\n    if len(a[2]) == 0 and len(b[2]) == 0:\n        \"With fixes keeping up, the queue empties either way.\" ^0\n\n\"== Bug triage ==\" ^0\n\"Two findings with one cause, one report with two, and a backlog that outruns its fixes.\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) two findings  2) one report  3) the backlog  4) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        two_findings()\n    elif choice == \"2\":\n        one_report()\n    elif choice == \"3\":\n        backlog()\n    elif choice == \"4\":\n        False => running\n    else:\n        \"Pick a number from 1 to 4.\" ^0\n\"Bye.\" ^0\n",
      "python": "import triage\n\ndef plain(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef pad(s, n):\n    out = s\n    while len(out) < n:\n        out = out + \" \"\n    return out\n\ndef lpad(s, n):\n    out = s\n    while len(out) < n:\n        out = \" \" + out\n    return out\n\ndef listed(xs):\n    out = \"\"\n    for x in xs:\n        if out == \"\":\n            out = str(x)\n        else:\n            out = out + \", \" + str(x)\n    if out == \"\":\n        return \"none\"\n    return out\n\ndef wrong_screens(parser_bug, report_bug, reminder_bug):\n    out = []\n    for d in triage.days():\n        if triage.report(d, parser_bug, report_bug) != d % 7:\n            out = out + [\"report\"]\n        if triage.reminder(d, parser_bug, reminder_bug) != d % 7:\n            out = out + [\"reminder\"]\n        if triage.audit(d, parser_bug) != d % 7:\n            out = out + [\"audit\"]\n    names = []\n    for s in [\"report\", \"reminder\", \"audit\"]:\n        for x in out:\n            if x == s:\n                have = False\n                for n in names:\n                    if n == s:\n                        have = True\n                if not have:\n                    names = names + [s]\n    return names\n\ndef two_findings():\n    print(\"Two findings, filed a week apart: the weekly report starts a day late; reminders come a day late.\")\n    print(\"Each candidate cause alone, and the screens it makes wrong on the days 3, 10, 17, 24 and 31:\")\n    print(\"  the date parser:      \" + listed(wrong_screens(True, False, False)))\n    print(\"  the report's code:    \" + listed(wrong_screens(False, True, False)))\n    print(\"  the reminder's code:  \" + listed(wrong_screens(False, False, True)))\n    print(\"Only the parser explains both findings, and it predicts a third nobody filed: the audit log.\")\n    print(\"Days right of 5, as the fixes go in:\")\n    print(\"  \" + pad(\"\", 28) + \"report  reminder  audit\")\n    for st in triage.states():\n        print(\"  \" + pad(st[0], 28) + lpad(str(triage.right_days(\"report\", st[1], st[2])), 6) + lpad(str(triage.right_days(\"reminder\", st[1], st[2])), 10) + lpad(str(triage.right_days(\"audit\", st[1], st[2])), 7))\n    print(\"Patched where seen, both findings close and the audit log stays wrong; fix the parser later and the two patches make their screens wrong again.\")\n\ndef one_report():\n    print(\"One report, three wrong balances:\")\n    for r in triage.reported():\n        print(\"  \" + lpad(str(r), 5) + \" shows \" + lpad(triage.render(r, True, True), 4) + \", should be \" + triage.truth(r))\n    print(\"Over the \" + str(len(triage.inputs())) + \" inputs \" + listed(triage.inputs()) + \":\")\n    print(\"  \" + pad(\"fix\", 22) + \"wrong\")\n    for fx in [\"none\", \"fitted\", \"sign\", \"clamp\", \"both\"]:\n        bad = []\n        for v in triage.inputs():\n            if triage.shown(v, fx) != triage.truth(v):\n                bad = bad + [v]\n        if fx == \"fitted\":\n            name = \"the reported inputs\"\n        elif fx == \"sign\":\n            name = \"keep the sign\"\n        elif fx == \"clamp\":\n            name = \"no clamp at 99\"\n        else:\n            name = fx\n        print(\"  \" + pad(name, 22) + pad(str(len(bad)), 4) + listed(bad))\n    s = []\n    c = []\n    left = 0\n    for v in triage.inputs():\n        if triage.shown(v, \"fitted\") != triage.truth(v):\n            left = left + 1\n            if triage.render(v, True, False) != triage.truth(v):\n                s = s + [v]\n            if triage.render(v, False, True) != triage.truth(v):\n                c = c + [v]\n    print(\"Fitted to the report, the report passes and \" + str(left) + \" failures remain; each mechanism run alone accounts for its share:\")\n    print(\"  the sign dropped:      \" + listed(s))\n    print(\"  past 99 clamped:       \" + listed(c))\n    print(\"The report could not show that two of its rows came from one cause and the third from another.\")\n\ndef backlog():\n    t = plain(input(\"fixes each period (1 or 2)> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return\n    if t != \"1\" and t != \"2\":\n        print(\"Type 1 or 2.\")\n        return\n    cap = int(t)\n    print(\"Two findings arrive in each of periods 1 to 5; \" + t + \" fixed a period; the harm each does every period it waits is summed over 6 periods.\")\n    a = triage.work(\"fifo\", cap, 6)\n    b = triage.work(\"harm\", cap, 6)\n    print(\"  in arrival order:  harm \" + lpad(str(a[0]), 3) + \"; still open: \" + listed(a[2]))\n    print(\"  worst first:       harm \" + lpad(str(b[0]), 3) + \"; still open: \" + listed(b[2]))\n    if a[0] != b[0]:\n        print(\"The same number fixed each period, and the order changes the harm by \" + str(a[0] - b[0]) + \": once findings outrun fixes, the order is not a preference.\")\n    else:\n        print(\"The order changes nothing here.\")\n    if len(a[2]) == 0 and len(b[2]) == 0:\n        print(\"With fixes keeping up, the queue empties either way.\")\n\nprint(\"== Bug triage ==\")\nprint(\"Two findings with one cause, one report with two, and a backlog that outruns its fixes.\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) two findings  2) one report  3) the backlog  4) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        two_findings()\n    elif choice == \"2\":\n        one_report()\n    elif choice == \"3\":\n        backlog()\n    elif choice == \"4\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 4.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "triage.eml",
      "eml": "# P158 bug triage - three ways a bug report misleads the people who fix it.\n# As in the corpus case two-findings-one-defect, two findings on two\n# screens, a report a day late and a reminder a day late, come from one\n# shared date parser; patched where each was seen, both go quiet, a third\n# consumer stays wrong, and fixing the parser later breaks the two patches.\n# As in the corpus case one-report-two-mechanisms, one report of three wrong\n# outputs has two causes underneath, and a patch fitted to the reported\n# inputs fixes the report and neither cause. As in the corpus case\n# finding-outruns-fixing, once findings arrive faster than they are fixed\n# the queue never empties, and the order it is worked in decides the harm.\n\ndef days():\n    return [3, 10, 17, 24, 31]\n\ndef weekday(day, parser_bug):\n    if parser_bug:\n        return (day + 1) % 7\n    return day % 7\n\ndef report(day, parser_bug, patched):\n    # the first weekday of the weekly report; the local patch takes a day off\n    weekday(day, parser_bug) => w\n    if patched:\n        return (w + 6) % 7\n    return w\n\ndef reminder(day, parser_bug, patched):\n    weekday(day, parser_bug) => w\n    if patched:\n        return (w + 6) % 7\n    return w\n\ndef audit(day, parser_bug):\n    return weekday(day, parser_bug)\n\ndef states():\n    # [name, parser bug, local patches]\n    return [[\"as shipped\", True, False], [\"patched where seen\", True, True], [\"parser fixed\", False, False], [\"parser fixed, patches left\", False, True]]\n\ndef right_days(screen, parser_bug, patched):\n    0 => n\n    for d in days():\n        if screen == \"report\":\n            report(d, parser_bug, patched) => v\n        elif screen == \"reminder\":\n            reminder(d, parser_bug, patched) => v\n        else:\n            audit(d, parser_bug) => v\n        if v == d % 7:\n            n + 1 => n\n    return n\n\ndef truth(v):\n    if v < 0:\n        return \"-\" + str(0 - v)\n    return str(v)\n\ndef render(v, sign_bug, clamp_bug):\n    # the balance as shown: the sign dropped, and anything past 99 clamped\n    v => x\n    if sign_bug and x < 0:\n        0 - x => x\n    if clamp_bug and x > 99:\n        99 => x\n    if x < 0:\n        return \"-\" + str(0 - x)\n    return str(x)\n\ndef reported():\n    return [0 - 4, 150, 0 - 7]\n\ndef inputs():\n    return [0 - 9, 0 - 4, 0, 3, 42, 99, 100, 150, 260, 0 - 7, 0 - 1, 77]\n\ndef shown(v, fix):\n    # the balance under a fix: none, fitted (the reported inputs special\n    # cased), sign, clamp, or both\n    if fix == \"fitted\":\n        for r in reported():\n            if r == v:\n                return truth(v)\n        return render(v, True, True)\n    return render(v, fix != \"sign\" and fix != \"both\", fix != \"clamp\" and fix != \"both\")\n\ndef findings():\n    # [name, period it arrives, harm each period it stays unfixed]\n    return [[\"f1\", 1, 1], [\"f2\", 1, 9], [\"f3\", 2, 2], [\"f4\", 2, 8], [\"f5\", 3, 1], [\"f6\", 3, 7], [\"f7\", 4, 3], [\"f8\", 4, 6], [\"f9\", 5, 1], [\"f10\", 5, 10]]\n\ndef work(policy, capacity, periods):\n    # [harm in all, fixed in order, still waiting]; each period the arrivals\n    # join, every waiting finding does its harm, then capacity are fixed\n    [] => waiting\n    [] => fixed\n    0 => harm\n    1 => p\n    while p <= periods:\n        for f in findings():\n            if f[1] == p:\n                waiting + [f] => waiting\n        for f in waiting:\n            harm + f[2] => harm\n        0 => k\n        while k < capacity and len(waiting) > 0:\n            0 => pick\n            if policy == \"harm\":\n                0 => i\n                for f in waiting:\n                    if f[2] > waiting[pick][2]:\n                        i => pick\n                    i + 1 => i\n            fixed + [waiting[pick][0]] => fixed\n            [] => rest\n            0 => i\n            for f in waiting:\n                if i != pick:\n                    rest + [f] => rest\n                i + 1 => i\n            rest => waiting\n            k + 1 => k\n        p + 1 => p\n    [] => names\n    for f in waiting:\n        names + [f[0]] => names\n    return [harm, fixed, names]\n",
      "python": "def days():\n    return [3, 10, 17, 24, 31]\n\ndef weekday(day, parser_bug):\n    if parser_bug:\n        return (day + 1) % 7\n    return day % 7\n\ndef report(day, parser_bug, patched):\n    w = weekday(day, parser_bug)\n    if patched:\n        return (w + 6) % 7\n    return w\n\ndef reminder(day, parser_bug, patched):\n    w = weekday(day, parser_bug)\n    if patched:\n        return (w + 6) % 7\n    return w\n\ndef audit(day, parser_bug):\n    return weekday(day, parser_bug)\n\ndef states():\n    return [[\"as shipped\", True, False], [\"patched where seen\", True, True], [\"parser fixed\", False, False], [\"parser fixed, patches left\", False, True]]\n\ndef right_days(screen, parser_bug, patched):\n    n = 0\n    for d in days():\n        if screen == \"report\":\n            v = report(d, parser_bug, patched)\n        elif screen == \"reminder\":\n            v = reminder(d, parser_bug, patched)\n        else:\n            v = audit(d, parser_bug)\n        if v == d % 7:\n            n = n + 1\n    return n\n\ndef truth(v):\n    if v < 0:\n        return \"-\" + str(0 - v)\n    return str(v)\n\ndef render(v, sign_bug, clamp_bug):\n    x = v\n    if sign_bug and x < 0:\n        x = 0 - x\n    if clamp_bug and x > 99:\n        x = 99\n    if x < 0:\n        return \"-\" + str(0 - x)\n    return str(x)\n\ndef reported():\n    return [0 - 4, 150, 0 - 7]\n\ndef inputs():\n    return [0 - 9, 0 - 4, 0, 3, 42, 99, 100, 150, 260, 0 - 7, 0 - 1, 77]\n\ndef shown(v, fix):\n    if fix == \"fitted\":\n        for r in reported():\n            if r == v:\n                return truth(v)\n        return render(v, True, True)\n    return render(v, fix != \"sign\" and fix != \"both\", fix != \"clamp\" and fix != \"both\")\n\ndef findings():\n    return [[\"f1\", 1, 1], [\"f2\", 1, 9], [\"f3\", 2, 2], [\"f4\", 2, 8], [\"f5\", 3, 1], [\"f6\", 3, 7], [\"f7\", 4, 3], [\"f8\", 4, 6], [\"f9\", 5, 1], [\"f10\", 5, 10]]\n\ndef work(policy, capacity, periods):\n    waiting = []\n    fixed = []\n    harm = 0\n    p = 1\n    while p <= periods:\n        for f in findings():\n            if f[1] == p:\n                waiting = waiting + [f]\n        for f in waiting:\n            harm = harm + f[2]\n        k = 0\n        while k < capacity and len(waiting) > 0:\n            pick = 0\n            if policy == \"harm\":\n                i = 0\n                for f in waiting:\n                    if f[2] > waiting[pick][2]:\n                        pick = i\n                    i = i + 1\n            fixed = fixed + [waiting[pick][0]]\n            rest = []\n            i = 0\n            for f in waiting:\n                if i != pick:\n                    rest = rest + [f]\n                i = i + 1\n            waiting = rest\n            k = k + 1\n        p = p + 1\n    names = []\n    for f in waiting:\n        names = names + [f[0]]\n    return [harm, fixed, names]\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n3\n\n3\n3\n3\nx\n2\n4\n",
      "screen": "== Bug triage ==\nTwo findings with one cause, one report with two, and a backlog that outruns its fixes.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 0\nPick a number from 1 to 4.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> x\nPick a number from 1 to 4.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 3\nfixes each period (1 or 2)> \nCancelled.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 3\nfixes each period (1 or 2)> 3\nType 1 or 2.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 3\nfixes each period (1 or 2)> x\nType 1 or 2.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 2\nOne report, three wrong balances:\n     -4 shows    4, should be -4\n    150 shows   99, should be 150\n     -7 shows    7, should be -7\nOver the 12 inputs -9, -4, 0, 3, 42, 99, 100, 150, 260, -7, -1, 77:\n  fix                   wrong\n  none                  7   -9, -4, 100, 150, 260, -7, -1\n  the reported inputs   4   -9, 100, 260, -1\n  keep the sign         3   100, 150, 260\n  no clamp at 99        4   -9, -4, -7, -1\n  both                  0   none\nFitted to the report, the report passes and 4 failures remain; each mechanism run alone accounts for its share:\n  the sign dropped:      -9, -1\n  past 99 clamped:       100, 260\nThe report could not show that two of its rows came from one cause and the third from another.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\n3\n1\n3\n2\n4\n",
      "screen": "== Bug triage ==\nTwo findings with one cause, one report with two, and a backlog that outruns its fixes.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 1\nTwo findings, filed a week apart: the weekly report starts a day late; reminders come a day late.\nEach candidate cause alone, and the screens it makes wrong on the days 3, 10, 17, 24 and 31:\n  the date parser:      report, reminder, audit\n  the report's code:    report\n  the reminder's code:  reminder\nOnly the parser explains both findings, and it predicts a third nobody filed: the audit log.\nDays right of 5, as the fixes go in:\n                              report  reminder  audit\n  as shipped                       0         0      0\n  patched where seen               5         5      0\n  parser fixed                     5         5      5\n  parser fixed, patches left       0         0      5\nPatched where seen, both findings close and the audit log stays wrong; fix the parser later and the two patches make their screens wrong again.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 2\nOne report, three wrong balances:\n     -4 shows    4, should be -4\n    150 shows   99, should be 150\n     -7 shows    7, should be -7\nOver the 12 inputs -9, -4, 0, 3, 42, 99, 100, 150, 260, -7, -1, 77:\n  fix                   wrong\n  none                  7   -9, -4, 100, 150, 260, -7, -1\n  the reported inputs   4   -9, 100, 260, -1\n  keep the sign         3   100, 150, 260\n  no clamp at 99        4   -9, -4, -7, -1\n  both                  0   none\nFitted to the report, the report passes and 4 failures remain; each mechanism run alone accounts for its share:\n  the sign dropped:      -9, -1\n  past 99 clamped:       100, 260\nThe report could not show that two of its rows came from one cause and the third from another.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 3\nfixes each period (1 or 2)> 1\nTwo findings arrive in each of periods 1 to 5; 1 fixed a period; the harm each does every period it waits is summed over 6 periods.\n  in arrival order:  harm 127; still open: f7, f8, f9, f10\n  worst first:       harm  71; still open: f1, f3, f5, f9\nThe same number fixed each period, and the order changes the harm by 56: once findings outrun fixes, the order is not a preference.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 3\nfixes each period (1 or 2)> 2\nTwo findings arrive in each of periods 1 to 5; 2 fixed a period; the harm each does every period it waits is summed over 6 periods.\n  in arrival order:  harm  48; still open: none\n  worst first:       harm  48; still open: none\nThe order changes nothing here.\nWith fixes keeping up, the queue empties either way.\n\n1) two findings  2) one report  3) the backlog  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "two-findings-one-defect",
      "caseId": "371-two-findings-one-defect",
      "title": "Two findings, one defect — 2 causes each, 1 in the intersection"
    },
    {
      "slug": "one-report-two-mechanisms",
      "caseId": "361-one-report-two-mechanisms",
      "title": "One report, two mechanisms — 3 items named, 7 wrong, 2 causes"
    },
    {
      "slug": "finding-outruns-fixing",
      "caseId": "360-finding-outruns-fixing",
      "title": "Finding outruns fixing — same capacity, same count fixed, 127 against 71"
    }
  ],
  "updated": "2026-10-18"
}
