)]}'
{
  "commit": "f59c8948729debc6d57c4dfade5486176468edbf",
  "tree": "4090122073c645ab5c73cf58cb01075950a2f88f",
  "parents": [
    "11bdbc3eac085e4a946e25a8a614bcbf62e41fa2"
  ],
  "author": {
    "name": "hathach",
    "email": "thach@tinyusb.org",
    "time": "Tue Aug 18 15:28:58 2026 +0700"
  },
  "committer": {
    "name": "hathach",
    "email": "thach@tinyusb.org",
    "time": "Tue Aug 18 16:58:58 2026 +0700"
  },
  "message": "skill(read-doc): search the Calibre database instead of the filesystem\n\nFinding documents by walking the library tree misses anything the filename\ndoes not carry - Calibre stores only a truncated title and the author there, so\nthe tags, series, publisher and description that hold most part numbers and\nerrata IDs are invisible to it. A zero-result tree search then reads as \"the\ndocument does not exist\" rather than as a bad search; that happened here, and\nled to a confident claim that a fully populated 14,000-file library was empty.\n\nsearch.py queries metadata.db, ANDs its keywords across every metadata field\n(including the stored filename), and prints the best matches first with the\nexact path to read. Matching is NFKC + casefold, so a typed ASCII apostrophe or\nmu reaches the titles that store the typographic ones.\n\nEvery printed path is checked on disk. Calibre renames \u003cauthor\u003e/\u003ctitle\u003e (\u003cid\u003e)\nwhen metadata is edited and leaves the old directory behind, so a miss retries\nby the stable book id before reporting MISSING - which distinguishes \"the file\nis not here right now\" from \"no such document\". The gate tests for metadata.db\nrather than the directory, since an unmounted or half-synced mountpoint is\nstill a directory.\n\nConsumers that prescribed their own tree search - driver-reviewer, port-dev,\nthe driver-review workflow, and the calibre-library references in CLAUDE.md,\nusbtest, etm-trace and target-debug - now point at the skill, which owns the\nlibrary\u0027s location.\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "f45eca03ef035c95ba8c2bf34be32bc62ebf86c3",
      "old_mode": 33188,
      "old_path": ".claude/agents/driver-reviewer.md",
      "new_id": "9ce8b621f4728d92f777d23306eb81f7b691b0a3",
      "new_mode": 33188,
      "new_path": ".claude/agents/driver-reviewer.md"
    },
    {
      "type": "modify",
      "old_id": "76bafb39b18ad83fe72310026966d01b46df17ed",
      "old_mode": 33188,
      "old_path": ".claude/agents/port-dev.md",
      "new_id": "77a28bafa9420233830dc5db0f7cbffc67577f93",
      "new_mode": 33188,
      "new_path": ".claude/agents/port-dev.md"
    },
    {
      "type": "modify",
      "old_id": "99e89729c1884c0bc9e0c3e62d55f80279257668",
      "old_mode": 33188,
      "old_path": ".claude/skills/etm-trace/SKILL.md",
      "new_id": "43cf6a2a5e446547c1ae42b73cba0d095c89fb65",
      "new_mode": 33188,
      "new_path": ".claude/skills/etm-trace/SKILL.md"
    },
    {
      "type": "modify",
      "old_id": "4a5f297aecce0976af2c67127bec8f0fa44c06ae",
      "old_mode": 33188,
      "old_path": ".claude/skills/etm-trace/boards.md",
      "new_id": "044d4e0ee680149937e03d9e81e128c700a16c17",
      "new_mode": 33188,
      "new_path": ".claude/skills/etm-trace/boards.md"
    },
    {
      "type": "modify",
      "old_id": "df845e7b5b42e5badd2a95cee52caf9e10ede59a",
      "old_mode": 33188,
      "old_path": ".claude/skills/read-doc/SKILL.md",
      "new_id": "feaa914afaaf06165b38af52a49c105894de5eff",
      "new_mode": 33188,
      "new_path": ".claude/skills/read-doc/SKILL.md"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "c70d368056a3f3ea799a8ac6d4b4cb01b1ae5621",
      "new_mode": 33261,
      "new_path": ".claude/skills/read-doc/search.py"
    },
    {
      "type": "modify",
      "old_id": "9a61a86c70389f63c21cfdc49165176f8094161b",
      "old_mode": 33188,
      "old_path": ".claude/skills/target-debug/SKILL.md",
      "new_id": "050a697b933d51ed2992496d5d199ed0b8ba5374",
      "new_mode": 33188,
      "new_path": ".claude/skills/target-debug/SKILL.md"
    },
    {
      "type": "modify",
      "old_id": "6197ccd51d37c7a0babce163fe91398f973d688e",
      "old_mode": 33188,
      "old_path": ".claude/skills/usbtest/SKILL.md",
      "new_id": "32c2be913f10b4858ab1a4eea2b052a5da6665a9",
      "new_mode": 33188,
      "new_path": ".claude/skills/usbtest/SKILL.md"
    },
    {
      "type": "modify",
      "old_id": "3638aa1793490a8d8a612e506e9f7a042b477d87",
      "old_mode": 33188,
      "old_path": ".claude/workflows/driver-review.js",
      "new_id": "255b8ac74a0f82e67a1e8493610475ba3208f4e7",
      "new_mode": 33188,
      "new_path": ".claude/workflows/driver-review.js"
    },
    {
      "type": "modify",
      "old_id": "4198081fb4c7d6012d31d8afa35b402e75b8d52e",
      "old_mode": 33188,
      "old_path": "CLAUDE.md",
      "new_id": "7624737143e1189eee505815e9433e1b00a2a9fa",
      "new_mode": 33188,
      "new_path": "CLAUDE.md"
    }
  ]
}
