{"abstract":"A file replaced by a same-named directory is reported as a type change, and entries around directories are misordered.","category":"Text diff and three-way merge","checks":9,"contract":"Compare two tree listings of [name, mode, hash]. Entries are ordered by name, with directories (mode 040000) compared as name + \"/\". Walk both in that order: entries only in the old tree are \"D\", only in the new tree \"A\". Entries matched by sort key report \"T\" when the mode type (first two digits) differs, else \"M\" when the hash or mode differs. Return [status, name] rows.","evaluation_group":"w2-text-diff-merge-tree-listing-diff","failed_approach":"Appending a slash to every name keeps files and directories with the same name equal.","family":"w2-text-diff-merge-tree-listing-diff-directory-sort-key","id":"FA-75766","implementations":{"attempt":{"sha256":"2211c7e7ea9ffb0d4a2d62a9f8ecd6e2034fdc8a55f5d10361745fe4e0fbb37a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(old, new):\n    def key(x):\n        return x[0] + '/'\n    A = sorted(old, key=key)\n    B = sorted(new, key=key)\n    i = j = 0\n    out = []\n    while i < len(A) or j < len(B):\n        if j >= len(B) or (i < len(A) and key(A[i]) < key(B[j])):\n            out.append(['D', A[i][0]])\n            i += 1\n        elif i >= len(A) or key(B[j]) < key(A[i]):\n            out.append(['A', B[j][0]])\n            j += 1\n        else:\n            a, b = A[i], B[j]\n            if a[1][:2] != b[1][:2]:\n                out.append(['T', a[0]])\n            elif a[2] != b[2] or a[1] != b[1]:\n                out.append(['M', a[0]])\n            i += 1\n            j += 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = {\n    1: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n']]], [['A', 'z0']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    2: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n']]], [['A', 'z0'], ['A', 'z1']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    3: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    4: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    5: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n'], ['z4', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3'], ['A', 'z4']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n}[N]\nfor label, args, expected in cases:\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":"f2eef743dc977794fa55b1dac50650055ef7d4333bbb90dc9d4f614b0808721f","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(old, new):\n    def key(x):\n        return x[0]\n    A = sorted(old, key=key)\n    B = sorted(new, key=key)\n    i = j = 0\n    out = []\n    while i < len(A) or j < len(B):\n        if j >= len(B) or (i < len(A) and key(A[i]) < key(B[j])):\n            out.append(['D', A[i][0]])\n            i += 1\n        elif i >= len(A) or key(B[j]) < key(A[i]):\n            out.append(['A', B[j][0]])\n            j += 1\n        else:\n            a, b = A[i], B[j]\n            if a[1][:2] != b[1][:2]:\n                out.append(['T', a[0]])\n            elif a[2] != b[2] or a[1] != b[1]:\n                out.append(['M', a[0]])\n            i += 1\n            j += 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = {\n    1: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n']]], [['A', 'z0']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    2: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n']]], [['A', 'z0'], ['A', 'z1']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    3: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    4: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    5: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n'], ['z4', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3'], ['A', 'z4']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n}[N]\nfor label, args, expected in cases:\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"},"fixed":{"sha256":"65a54a854bdf51e007e9d36898821d1d01b1febc67a2764e097b92defbe15097","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(old, new):\n    def key(x):\n        return x[0] + '/' if x[1] == '040000' else x[0]\n    A = sorted(old, key=key)\n    B = sorted(new, key=key)\n    i = j = 0\n    out = []\n    while i < len(A) or j < len(B):\n        if j >= len(B) or (i < len(A) and key(A[i]) < key(B[j])):\n            out.append(['D', A[i][0]])\n            i += 1\n        elif i >= len(A) or key(B[j]) < key(A[i]):\n            out.append(['A', B[j][0]])\n            j += 1\n        else:\n            a, b = A[i], B[j]\n            if a[1][:2] != b[1][:2]:\n                out.append(['T', a[0]])\n            elif a[2] != b[2] or a[1] != b[1]:\n                out.append(['M', a[0]])\n            i += 1\n            j += 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = {\n    1: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n']]], [['A', 'z0']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    2: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n']]], [['A', 'z0'], ['A', 'z1']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    3: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    4: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n    5: [('modified blob', [[['a.txt', '100644', 'h1']], [['a.txt', '100644', 'h2']]], [['M', 'a.txt']]), ('exec bit change is a modification', [[['run.sh', '100644', 'h']], [['run.sh', '100755', 'h']]], [['M', 'run.sh']]), ('file becomes a symlink', [[['lnk', '100644', 'h']], [['lnk', '120000', 'h']]], [['T', 'lnk']]), ('file replaced by a directory of the same name', [[['x', '100644', 'h']], [['x', '040000', 't']]], [['D', 'x'], ['A', 'x']]), ('directory sorts as name plus slash', [[['a.b', '100644', 'h'], ['a', '040000', 't1']], [['a.b', '100644', 'h'], ['a', '040000', 't2'], ['a-c', '100644', 'q']]], [['A', 'a-c'], ['M', 'a']]), ('trailing additions and deletions', [[['b', '100644', '1']], [['b', '100644', '1'], ['z0', '100644', 'n'], ['z1', '100644', 'n'], ['z2', '100644', 'n'], ['z3', '100644', 'n'], ['z4', '100644', 'n']]], [['A', 'z0'], ['A', 'z1'], ['A', 'z2'], ['A', 'z3'], ['A', 'z4']]), ('only deletions at the end', [[['m', '100644', '1'], ['y', '100644', '2']], [['m', '100644', '1']]], [['D', 'y']]), ('hashes sharing a long prefix', [[['k', '100644', 'abcdef0123']], [['k', '100644', 'abcdef0999']]], [['M', 'k']]), ('added then removed around a common entry', [[['a', '100644', '1'], ['c', '100644', '3']], [['b', '100644', '2'], ['c', '100644', '3']]], [['D', 'a'], ['A', 'b']])],\n}[N]\nfor label, args, expected in cases:\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 diff, patch or merge rule with stipulated conventions; it is not a production diff or version-control implementation and makes no claim of conformance to any specific tool. 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-text-diff-merge-tree-listing-diff-directory-sort-key","generated_at":"2026-09-29T14:49:09.822293+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Tree diffs drive status, rename detection and checkout; their ordering and type-change rules follow the object-store conventions.","repair":"Order directories as if their name ended in \"/\".","root_cause":"The sort key ignores the implicit trailing slash of directory names.","sha256":"433c85aa961526d2776baff31b70b0590684641ac7d2757703432274b29cb8fa","title":"Tree listing diff: directories are ordered by bare name · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":40.059,"exit_code":1,"observations":[{"actual":[["M","a.txt"]],"check":"modified blob","expected":[["M","a.txt"]],"passed":true},{"actual":[["M","run.sh"]],"check":"exec bit change is a modification","expected":[["M","run.sh"]],"passed":true},{"actual":[["T","lnk"]],"check":"file becomes a symlink","expected":[["T","lnk"]],"passed":true},{"actual":[["T","x"]],"check":"file replaced by a directory of the same name","expected":[["D","x"],["A","x"]],"passed":false},{"actual":[["A","a-c"],["M","a"]],"check":"directory sorts as name plus slash","expected":[["A","a-c"],["M","a"]],"passed":true},{"actual":[["A","z0"]],"check":"trailing additions and deletions","expected":[["A","z0"]],"passed":true},{"actual":[["D","y"]],"check":"only deletions at the end","expected":[["D","y"]],"passed":true},{"actual":[["M","k"]],"check":"hashes sharing a long prefix","expected":[["M","k"]],"passed":true},{"actual":[["D","a"],["A","b"]],"check":"added then removed around a common entry","expected":[["D","a"],["A","b"]],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"modified blob\", \"actual\": [[\"M\", \"a.txt\"]], \"expected\": [[\"M\", \"a.txt\"]], \"passed\": true}, {\"check\": \"exec bit change is a modification\", \"actual\": [[\"M\", \"run.sh\"]], \"expected\": [[\"M\", \"run.sh\"]], \"passed\": true}, {\"check\": \"file becomes a symlink\", \"actual\": [[\"T\", \"lnk\"]], \"expected\": [[\"T\", \"lnk\"]], \"passed\": true}, {\"check\": \"file replaced by a directory of the same name\", \"actual\": [[\"T\", \"x\"]], \"expected\": [[\"D\", \"x\"], [\"A\", \"x\"]], \"passed\": false}, {\"check\": \"directory sorts as name plus slash\", \"actual\": [[\"A\", \"a-c\"], [\"M\", \"a\"]], \"expected\": [[\"A\", \"a-c\"], [\"M\", \"a\"]], \"passed\": true}, {\"check\": \"trailing additions and deletions\", \"actual\": [[\"A\", \"z0\"]], \"expected\": [[\"A\", \"z0\"]], \"passed\": true}, {\"check\": \"only deletions at the end\", \"actual\": [[\"D\", \"y\"]], \"expected\": [[\"D\", \"y\"]], \"passed\": true}, {\"check\": \"hashes sharing a long prefix\", \"actual\": [[\"M\", \"k\"]], \"expected\": [[\"M\", \"k\"]], \"passed\": true}, {\"check\": \"added then removed around a common entry\", \"actual\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"expected\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.973,"exit_code":1,"observations":[{"actual":[["M","a.txt"]],"check":"modified blob","expected":[["M","a.txt"]],"passed":true},{"actual":[["M","run.sh"]],"check":"exec bit change is a modification","expected":[["M","run.sh"]],"passed":true},{"actual":[["T","lnk"]],"check":"file becomes a symlink","expected":[["T","lnk"]],"passed":true},{"actual":[["T","x"]],"check":"file replaced by a directory of the same name","expected":[["D","x"],["A","x"]],"passed":false},{"actual":[["M","a"],["A","a-c"]],"check":"directory sorts as name plus slash","expected":[["A","a-c"],["M","a"]],"passed":false},{"actual":[["A","z0"]],"check":"trailing additions and deletions","expected":[["A","z0"]],"passed":true},{"actual":[["D","y"]],"check":"only deletions at the end","expected":[["D","y"]],"passed":true},{"actual":[["M","k"]],"check":"hashes sharing a long prefix","expected":[["M","k"]],"passed":true},{"actual":[["D","a"],["A","b"]],"check":"added then removed around a common entry","expected":[["D","a"],["A","b"]],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"modified blob\", \"actual\": [[\"M\", \"a.txt\"]], \"expected\": [[\"M\", \"a.txt\"]], \"passed\": true}, {\"check\": \"exec bit change is a modification\", \"actual\": [[\"M\", \"run.sh\"]], \"expected\": [[\"M\", \"run.sh\"]], \"passed\": true}, {\"check\": \"file becomes a symlink\", \"actual\": [[\"T\", \"lnk\"]], \"expected\": [[\"T\", \"lnk\"]], \"passed\": true}, {\"check\": \"file replaced by a directory of the same name\", \"actual\": [[\"T\", \"x\"]], \"expected\": [[\"D\", \"x\"], [\"A\", \"x\"]], \"passed\": false}, {\"check\": \"directory sorts as name plus slash\", \"actual\": [[\"M\", \"a\"], [\"A\", \"a-c\"]], \"expected\": [[\"A\", \"a-c\"], [\"M\", \"a\"]], \"passed\": false}, {\"check\": \"trailing additions and deletions\", \"actual\": [[\"A\", \"z0\"]], \"expected\": [[\"A\", \"z0\"]], \"passed\": true}, {\"check\": \"only deletions at the end\", \"actual\": [[\"D\", \"y\"]], \"expected\": [[\"D\", \"y\"]], \"passed\": true}, {\"check\": \"hashes sharing a long prefix\", \"actual\": [[\"M\", \"k\"]], \"expected\": [[\"M\", \"k\"]], \"passed\": true}, {\"check\": \"added then removed around a common entry\", \"actual\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"expected\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.261,"exit_code":0,"observations":[{"actual":[["M","a.txt"]],"check":"modified blob","expected":[["M","a.txt"]],"passed":true},{"actual":[["M","run.sh"]],"check":"exec bit change is a modification","expected":[["M","run.sh"]],"passed":true},{"actual":[["T","lnk"]],"check":"file becomes a symlink","expected":[["T","lnk"]],"passed":true},{"actual":[["D","x"],["A","x"]],"check":"file replaced by a directory of the same name","expected":[["D","x"],["A","x"]],"passed":true},{"actual":[["A","a-c"],["M","a"]],"check":"directory sorts as name plus slash","expected":[["A","a-c"],["M","a"]],"passed":true},{"actual":[["A","z0"]],"check":"trailing additions and deletions","expected":[["A","z0"]],"passed":true},{"actual":[["D","y"]],"check":"only deletions at the end","expected":[["D","y"]],"passed":true},{"actual":[["M","k"]],"check":"hashes sharing a long prefix","expected":[["M","k"]],"passed":true},{"actual":[["D","a"],["A","b"]],"check":"added then removed around a common entry","expected":[["D","a"],["A","b"]],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"modified blob\", \"actual\": [[\"M\", \"a.txt\"]], \"expected\": [[\"M\", \"a.txt\"]], \"passed\": true}, {\"check\": \"exec bit change is a modification\", \"actual\": [[\"M\", \"run.sh\"]], \"expected\": [[\"M\", \"run.sh\"]], \"passed\": true}, {\"check\": \"file becomes a symlink\", \"actual\": [[\"T\", \"lnk\"]], \"expected\": [[\"T\", \"lnk\"]], \"passed\": true}, {\"check\": \"file replaced by a directory of the same name\", \"actual\": [[\"D\", \"x\"], [\"A\", \"x\"]], \"expected\": [[\"D\", \"x\"], [\"A\", \"x\"]], \"passed\": true}, {\"check\": \"directory sorts as name plus slash\", \"actual\": [[\"A\", \"a-c\"], [\"M\", \"a\"]], \"expected\": [[\"A\", \"a-c\"], [\"M\", \"a\"]], \"passed\": true}, {\"check\": \"trailing additions and deletions\", \"actual\": [[\"A\", \"z0\"]], \"expected\": [[\"A\", \"z0\"]], \"passed\": true}, {\"check\": \"only deletions at the end\", \"actual\": [[\"D\", \"y\"]], \"expected\": [[\"D\", \"y\"]], \"passed\": true}, {\"check\": \"hashes sharing a long prefix\", \"actual\": [[\"M\", \"k\"]], \"expected\": [[\"M\", \"k\"]], \"passed\": true}, {\"check\": \"added then removed around a common entry\", \"actual\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"expected\": [[\"D\", \"a\"], [\"A\", \"b\"]], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}