{
  "task": "Add a saved-filter control",
  "project": "Field Notes — fictional demo",
  "recordedAt": "2026-09-06T08:17:59.834Z",
  "author": "Codex",
  "review": "Source review by the same author; no independent reviewer execution is claimed.",
  "first": {
    "exitCode": 1,
    "output": "TAP version 13\n# Subtest: All work preserves every item\nok 1 - All work preserves every item\n  ---\n  duration_ms: 1.098103\n  type: 'test'\n  ...\n# Subtest: Ready for review selects exactly the ready items\nok 2 - Ready for review selects exactly the ready items\n  ---\n  duration_ms: 0.139812\n  type: 'test'\n  ...\n# Subtest: A saved filter with no matches returns an empty list\nnot ok 3 - A saved filter with no matches returns an empty list\n  ---\n  duration_ms: 1.556044\n  type: 'test'\n  location: '/home/david-hathiramani/david/devinterface-website/examples/saved-filter/filter.test.mjs:6:1'\n  failureType: 'testCodeFailure'\n  error: |-\n    Expected values to be strictly deep-equal:\n    + actual - expected\n    \n    + [\n    +   {\n    +     id: 1,\n    +     status: 'ready',\n    +     title: 'Keyboard navigation'\n    +   },\n    +   {\n    +     id: 2,\n    +     status: 'in-progress',\n    +     title: 'Saved filter control'\n    +   },\n    +   {\n    +     id: 3,\n    +     status: 'ready',\n    +     title: 'Empty-result message'\n    +   },\n    +   {\n    +     id: 4,\n    +     status: 'backlog',\n    +     title: 'Mobile spacing'\n    +   }\n    + ]\n    - []\n    \n  code: 'ERR_ASSERTION'\n  name: 'AssertionError'\n  expected:\n  actual:\n    0:\n      id: 1\n      title: 'Keyboard navigation'\n      status: 'ready'\n    1:\n      id: 2\n      title: 'Saved filter control'\n      status: 'in-progress'\n    2:\n      id: 3\n      title: 'Empty-result message'\n      status: 'ready'\n    3:\n      id: 4\n      title: 'Mobile spacing'\n      status: 'backlog'\n  operator: 'deepStrictEqual'\n  stack: |-\n    TestContext.<anonymous> (file:///home/david-hathiramani/david/devinterface-website/examples/saved-filter/filter.test.mjs:6:72)\n    Test.runInAsyncScope (node:async_hooks:214:14)\n    Test.run (node:internal/test_runner/test:1047:25)\n    Test.processPendingSubtests (node:internal/test_runner/test:744:18)\n    Test.postRun (node:internal/test_runner/test:1173:19)\n    Test.run (node:internal/test_runner/test:1101:12)\n    async Test.processPendingSubtests (node:internal/test_runner/test:744:7)\n  ...\n# Subtest: Search and a saved filter are combined\nok 4 - Search and a saved filter are combined\n  ---\n  duration_ms: 0.103821\n  type: 'test'\n  ...\n# Subtest: Search with no matches does not reset the selection\nnot ok 5 - Search with no matches does not reset the selection\n  ---\n  duration_ms: 0.378399\n  type: 'test'\n  location: '/home/david-hathiramani/david/devinterface-website/examples/saved-filter/filter.test.mjs:8:1'\n  failureType: 'testCodeFailure'\n  error: |-\n    Expected values to be strictly deep-equal:\n    + actual - expected\n    \n    + [\n    +   {\n    +     id: 1,\n    +     status: 'ready',\n    +     title: 'Keyboard navigation'\n    +   },\n    +   {\n    +     id: 2,\n    +     status: 'in-progress',\n    +     title: 'Saved filter control'\n    +   },\n    +   {\n    +     id: 3,\n    +     status: 'ready',\n    +     title: 'Empty-result message'\n    +   },\n    +   {\n    +     id: 4,\n    +     status: 'backlog',\n    +     title: 'Mobile spacing'\n    +   }\n    + ]\n    - []\n    \n  code: 'ERR_ASSERTION'\n  name: 'AssertionError'\n  expected:\n  actual:\n    0:\n      id: 1\n      title: 'Keyboard navigation'\n      status: 'ready'\n    1:\n      id: 2\n      title: 'Saved filter control'\n      status: 'in-progress'\n    2:\n      id: 3\n      title: 'Empty-result message'\n      status: 'ready'\n    3:\n      id: 4\n      title: 'Mobile spacing'\n      status: 'backlog'\n  operator: 'deepStrictEqual'\n  stack: |-\n    TestContext.<anonymous> (file:///home/david-hathiramani/david/devinterface-website/examples/saved-filter/filter.test.mjs:8:71)\n    Test.runInAsyncScope (node:async_hooks:214:14)\n    Test.run (node:internal/test_runner/test:1047:25)\n    Test.processPendingSubtests (node:internal/test_runner/test:744:18)\n    Test.postRun (node:internal/test_runner/test:1173:19)\n    Test.run (node:internal/test_runner/test:1101:12)\n    async Test.processPendingSubtests (node:internal/test_runner/test:744:7)\n  ...\n# Subtest: Filtering leaves source data unchanged\nok 6 - Filtering leaves source data unchanged\n  ---\n  duration_ms: 0.152566\n  type: 'test'\n  ...\n1..6\n# tests 6\n# suites 0\n# pass 4\n# fail 2\n# cancelled 0\n# skipped 0\n# todo 0\n# duration_ms 57.781529\n"
  },
  "final": {
    "exitCode": 0,
    "output": "TAP version 13\n# Subtest: All work preserves every item\nok 1 - All work preserves every item\n  ---\n  duration_ms: 1.163948\n  type: 'test'\n  ...\n# Subtest: Ready for review selects exactly the ready items\nok 2 - Ready for review selects exactly the ready items\n  ---\n  duration_ms: 0.130037\n  type: 'test'\n  ...\n# Subtest: A saved filter with no matches returns an empty list\nok 3 - A saved filter with no matches returns an empty list\n  ---\n  duration_ms: 0.071712\n  type: 'test'\n  ...\n# Subtest: Search and a saved filter are combined\nok 4 - Search and a saved filter are combined\n  ---\n  duration_ms: 0.075583\n  type: 'test'\n  ...\n# Subtest: Search with no matches does not reset the selection\nok 5 - Search with no matches does not reset the selection\n  ---\n  duration_ms: 0.157992\n  type: 'test'\n  ...\n# Subtest: Filtering leaves source data unchanged\nok 6 - Filtering leaves source data unchanged\n  ---\n  duration_ms: 0.132777\n  type: 'test'\n  ...\n1..6\n# tests 6\n# suites 0\n# pass 6\n# fail 0\n# cancelled 0\n# skipped 0\n# todo 0\n# duration_ms 56.773486\n"
  },
  "diff": "diff --git apublic/dark-lord/saved-filter/draft.mjs bpublic/dark-lord/saved-filter/filter.mjs\nindex abfb5e1..e36de75 100644\n--- apublic/dark-lord/saved-filter/draft.mjs\n+++ bpublic/dark-lord/saved-filter/filter.mjs\n@@ -11,6 +11,5 @@ export const FILTERS = [\n ];\n export function applyFilter(items, filter, query = \"\") {\n   const needle = query.trim().toLocaleLowerCase(\"en\");\n-  const matches = items.filter(item => (!filter.status || item.status === filter.status) && item.title.toLocaleLowerCase(\"en\").includes(needle));\n-  return matches.length ? matches : items;\n+  return items.filter(item => (!filter.status || item.status === filter.status) && item.title.toLocaleLowerCase(\"en\").includes(needle));\n }\n",
  "sourceHash": "119af4fc6d0e513663c595f03af2d2c606af26badcaeae311fb5f3594d990887",
  "proposedCommit": "Add saved filters with honest empty results"
}
