)]}'
{
  "log": [
    {
      "commit": "49edc92f95cab092a7ee62c350c6e69275b50cc8",
      "tree": "946b8359f6187ed630c4d08fa05e91fe1bc5a48d",
      "parents": [
        "52eeb15cf2f70caaadc4e0722a3b687ad9a91981"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 14 09:45:45 2025 -0700"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Wed May 14 16:46:49 2025 +0000"
      },
      "message": "agent: move \"sketch-base\" into git\n\nThe agent\u0027s notion of \"initial commit\" is kind of special, in that it\nis used as the \"base\" for a bunch of git operations. It\u0027s hard for\nthe user to change (we only provide a workflow via restart), yet\nsometimes you want to do just that.\n\nSo, instead we put it as data inside of it, named as a tag sketch-base.\nIt\u0027s abusing tags, but branches are no better.\n"
    },
    {
      "commit": "eab12def4e6aacfd50bf8a460c714d20300706b7",
      "tree": "4db97e5dfb30f73fc47435f3651eee55876a6b0b",
      "parents": [
        "8a1b89a210d3c48c6f02f0c8cf1feebb03cdffd5"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 14 02:35:53 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 14 02:36:01 2025 +0000"
      },
      "message": "loop: Add StateTransitionIterator and stream state updates\n\nImplement CodingAgent.NewStateTransitionIterator to observe state transitions.\nUpdate the /stream endpoint to send state updates when transitions occur.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s4b4f9a0689c94c54k\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s4b4f9a0689c94c54k\n"
    },
    {
      "commit": "208938f612a498ec6b594564a643fe9172da061f",
      "tree": "80a8c313fbd548fc488ffeab3f00357eb7286726",
      "parents": [
        "3e9d80c6b6315ccf1754996e9b691555915d9839"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 13 17:17:18 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 13 17:45:17 2025 -0700"
      },
      "message": "bash: Shorten bash tool default timeout to 10s.\n"
    },
    {
      "commit": "18e336804bb6f052b29d891f7db54bd45e1de503",
      "tree": "48a979aa7f5e89975cf8f579722ff9f363768985",
      "parents": [
        "34bb09adf0cfc2f7fa4a2615e72d634aa88a6016"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 13 16:34:21 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 13 16:34:21 2025 -0700"
      },
      "message": "browser: Add console log capture tools\n\nThis was entirely Sketch-coded.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sc6bbdde6b1a71d8fk\n"
    },
    {
      "commit": "17b1094cadb489b38596527d2d1f693653797fad",
      "tree": "854eea2340ab00e8d23b60bb8d24a4006e284f15",
      "parents": [
        "44d1f1ad69d7db4df1249b9e37a7f747e610ba59"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:19:42 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:22:34 2025 -0700"
      },
      "message": "loop: tell the agent that it is powering sketch\n\nThis makes the knowledge base verbiage make more sense,\nwhile avoiding anthropomorphization."
    },
    {
      "commit": "44d1f1ad69d7db4df1249b9e37a7f747e610ba59",
      "tree": "10032ac0eaa586036381e8889dae533d5802d447",
      "parents": [
        "385da541a187a3499bf8d6368a66c2ba1109c398"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:18:32 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:18:32 2025 -0700"
      },
      "message": "loop: instruction the agent not to make new branches\n\nThings always get muddled when it starts making lots of branches.\n"
    },
    {
      "commit": "31785aed38e0f63fa736430c6240c8a76b8285dc",
      "tree": "35916d3dbedaeac296ece3dd57610efd82c99c8d",
      "parents": [
        "5c7f95714f34ea327b8f300238da6491dedd6adb"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue May 06 01:50:58 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:17:50 2025 -0700"
      },
      "message": "loop: add knowledge_base tool for on-demand information\n\nThe knowledge_base tool provides a way for agents to access specialized information\nwhen needed. Initial topics include:\n\n- sketch: how to use Sketch, including SSH, secrets, and file management\n- go_iterators: information about Go\u0027s iterator feature added in Go 1.22\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "8dff12f977fa4f52c27142e8f7b4c8c5d9293711",
      "tree": "8bfb2d10bb9826d9b82435cbd3ca551ea22bb251",
      "parents": [
        "6d4c7eadb2d465aa665288acc3f45e693d9a76d3"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 19:48:36 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 12 18:16:14 2025 -0700"
      },
      "message": "loop: emphasize directory guidance\n\nMake it clearer and more emphatic that agents must check and read\ndirectory-specific guidance files before making changes to files.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s624b7b2b4c7c1054k"
    },
    {
      "commit": "e577ef7f883e2b8d54cd6862a23b2f42510d33a0",
      "tree": "30b11d3880b5425ec2e64780858628be54159f23",
      "parents": [
        "7a1136201c3444009e2eeda2fb13cb76c943443f"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Mon May 12 10:29:00 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Mon May 12 10:29:00 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "7a1136201c3444009e2eeda2fb13cb76c943443f",
      "tree": "479b870608115a330cd4da100e988bfd2d198887",
      "parents": [
        "a9a786b458e989a1ea2d6e8e2b35fb24b79de2cf"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Mon May 12 10:58:45 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Mon May 12 11:23:12 2025 +0100"
      },
      "message": "loop: on git fetch or checkout failure, retry without hooks\n\nFix #10 by removing git hooks on git fetch or checkout failure to solve problem where hooks might require dependencies not available in the container (e.g., git-branchless). This prevents errors during container initialization when git operations trigger hooks.\n\nWe can revisit this approach if we find users who need their hooks to run in the container environment.\n"
    },
    {
      "commit": "05224846741b500d8103bd6930a7717e1211ef01",
      "tree": "54eaad583c19b5c00719384a268d8dccab0dd13e",
      "parents": [
        "80b488d853e2766b638e65cfe44a5904d7cb24ee"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 10 18:26:08 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 10 18:26:08 2025 -0700"
      },
      "message": "browser: add window resize tool with chromedp\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s68bdc7fb84309a7ck\n"
    },
    {
      "commit": "80b488d853e2766b638e65cfe44a5904d7cb24ee",
      "tree": "abd280ec3924efb4dbbd72622129bc4af56e28ca",
      "parents": [
        "6458e7c751856a9f7f4004367cb6274e564a1489"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 10 18:21:54 2025 -0700"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Sun May 11 01:22:37 2025 +0000"
      },
      "message": "Browser tools: initialize lazily and add timeouts.\n\nAlso rename browser_screenshot to browser_take_screenshot for clarity\\n- Update both Go and UI code to maintain consistency\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s8a5cabff914f88dfk\n"
    },
    {
      "commit": "72252cbcb97840d724133be67c4c69cc69ebb2d3",
      "tree": "a361499dc3fa6b9af2be3e74cfd59fd8ba34690e",
      "parents": [
        "7ce5fb76d8748ebf73c5adf9d6cd8eb67716fba8"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 10 17:00:08 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 10 17:00:08 2025 -0700"
      },
      "message": "llm and everything: Update ToolResult to use []Content instead of string for multimodal support\n\nThis was a journey. The sketch-generated summary below is acceptable,\nbut I want to tell you about it in my voice too. The goal was to send\nscreenshots to Claude, so that it could... look at them. Currently\nthe take screenshot and read screenshot tools are different, and they\u0027ll\nneed to be renamed/prompt-engineered a bit, but that\u0027s all fine.\n\nThe miserable part was that we had to change the return value\nof tool from string to Content[], and this crosses several layers:\n - llm.Tool\n - llm.Content\n - ant.Content \u0026 openai and gemini friends\n - AgentMessage [we left this alone]\n\nExtra fun is that Claude\u0027s API for sending images has nested Content\nfields, and empty string and missing needs to be distinguished for the\nText field (because lots of shell commands return the empty string!).\n\nFor the UI, I made us transform the results into a string, dropping\nimages. This would have been yet more churn for not much obvious\nbenefit. Plus, it was going to break skaband\u0027s compatibility, and ...\nyet more work.\n\nOpenAI and Gemini don\u0027t obviously support images in this same way,\nso they just don\u0027t get the tools.\n\n~~~~~~~~~~ Sketch said:\n\nThis architectural change transforms tool results from plain strings to []Content arrays, enabling multimodal interaction in the system. Key changes include:\n\n- Core structural changes:\n  - Modified ToolResult type from string to []Content across all packages\n  - Added MediaType field to Content struct for MIME type support\n  - Created TextContent and ImageContent helper functions\n  - Updated all tool.Run implementations to return []Content\n\n- Image handling:\n  - Implemented base64 image support in Anthropic adapter\n  - Added proper media type detection and content formatting\n  - Created browser_read_image tool for displaying screenshots\n  - Updated browser_screenshot to provide usable image paths\n\n- Adapter improvements:\n  - Updated all LLM adapters (ANT, OAI, GEM) to handle content arrays\n  - Added specialized image content handling in the Anthropic adapter\n  - Ensured proper JSON serialization/deserialization for all content types\n  - Improved test coverage for content arrays\n\n- UI enhancements:\n  - Added omitempty tags to reduce JSON response size\n  - Updated TypeScript types to handle array content\n  - Made field naming consistent (tool_error vs is_error)\n  - Preserved backward compatibility for existing consumers\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s1a2b3c4d5e6f7g8h\n"
    },
    {
      "commit": "a997be617bd5548a307c708cdba325ea6562acec",
      "tree": "1890bd46f87cf7261ba5a6aaa3fd2d110e7d67cc",
      "parents": [
        "dce8d84fdcda62e03b13c95d7614ee7ab983ddca"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 22:52:46 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 09 15:32:45 2025 -0700"
      },
      "message": "claudetool/onstart: add codebase analysis tool and basic memory support\n\nThis is a preliminary approach. Big high level questions include:\n\n* should we keep the multichoice tool prompting?\n* should we push the list of quidance files or respond with them during codereview?\n* should we use the list of docs and build files at all?\n* are there other files we should hint (e.g. editor settings, something from aider, etc.)?\n\nWe should probably also blog about dear_llm.md to stop the endless proliferation of new files.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "dce8d84fdcda62e03b13c95d7614ee7ab983ddca",
      "tree": "bf7f0dad1b07863b80ae16ea0a183a9c2b270b34",
      "parents": [
        "f59df72da9277859885d4dd65afe76d6de70fd0d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 09 12:27:19 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 09 15:32:17 2025 -0700"
      },
      "message": "claudetool: remove mention of go doc"
    },
    {
      "commit": "f59df72da9277859885d4dd65afe76d6de70fd0d",
      "tree": "c5972e45b3666b5e66277bc864b923bb6339771b",
      "parents": [
        "113e2053753d5b3e08be0f3509a204fe24ba5e87"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 09 12:24:03 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 09 15:31:54 2025 -0700"
      },
      "message": "claudetool: don\u0027t list out available binaries in bash tool\n\nIt does what it wants to do; I\u0027ve never seen it use this information.\nAnd there\u0027s no impact on Go eval, and it biases the model\ntowards assuming it is working in Go.\n\n"
    },
    {
      "commit": "113e2053753d5b3e08be0f3509a204fe24ba5e87",
      "tree": "1d86ecce8062bd94d0daeb6052623cde019f5e99",
      "parents": [
        "e97a8e54e0c7e5c5cabf29a00bce6a81094a6ca9"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 09 21:59:40 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 09 15:06:33 2025 -0700"
      },
      "message": "git: add retry logic for checked out branch conflicts\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: se1c139889d8c3e3fk\n"
    },
    {
      "commit": "e97a8e54e0c7e5c5cabf29a00bce6a81094a6ca9",
      "tree": "166a672959cbee9c81e56e720eed3572dc375505",
      "parents": [
        "51e8e2b0c970ef488094a33b3c259583fe142dc5"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 09 14:53:33 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 09 15:06:33 2025 -0700"
      },
      "message": "git: Make \"git fetch sketch-host\" update origin refs as well.\n"
    },
    {
      "commit": "d03318d51ca1e707698f1aab8d18ed83fc159cbe",
      "tree": "ae2ee324779b56baa1bc0670aa6852366a5ad9ab",
      "parents": [
        "8236cbc9eadb1bf775bbfa24ccf04be2c69faaaf"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 08 13:09:12 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 09 15:06:33 2025 -0700"
      },
      "message": "sketch: Introduce versions for sketch state\n"
    },
    {
      "commit": "220a36d6404a3a86af2537ca8572b9e28c77bcb6",
      "tree": "2329c0925b52432d519b7610b571328159ac5364",
      "parents": [
        "9320265a8e0ae7fb3091985c1999ed43bdae9525"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 08 19:06:26 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 08 12:44:11 2025 -0700"
      },
      "message": "experiment: remove not_done experiment\n\nIt didn\u0027t make a difference.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sc2849bd18751e2cak\n"
    },
    {
      "commit": "9320265a8e0ae7fb3091985c1999ed43bdae9525",
      "tree": "25a424999bee4597b971764640985585ce46f792",
      "parents": [
        "4d54493fe3808ecd0c6a9a4d0bbcc7786e97b094"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 08 02:05:57 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 08 12:34:07 2025 -0700"
      },
      "message": "loop: update git commit instruction to use --trailer, add Change-ID\n\nWe have run \u0027git config\u0027 for the user, so we can trim those instructions and simplify.\n(And in unsafe mode, the user has \u0027git config\u0027 set up anyway.)\n\nInstead of prompting the model to manually add \u0027Co-Authored-By\u0027 as a line in the\ncommit message, now instruct it to use the --trailer option.\nThis streamlines adding a Change-ID trailer with a random string (s\u003crandom_hex\u003ek format).\n\nI\u0027d actually like to use precommmit hooks to automatically do all the trailer,\nbut that doesn\u0027t play nicely with -unsafe, so for now, do it this way.\nAt least we\u0027ll have Change-IDs that we can start using.\n(Pity the official change-id support in git hasn\u0027t landed yet.)\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s9b68cbfa4c7eeb82k\n"
    },
    {
      "commit": "4d54493fe3808ecd0c6a9a4d0bbcc7786e97b094",
      "tree": "9877409fc95aaa32aed882426ea15464b8036e34",
      "parents": [
        "a4ad8af8b08a54326bbbd99d57110a42c459c54e"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 13:33:53 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 08 19:25:30 2025 +0000"
      },
      "message": "all: support hiding subconvo output\n\nSome of it is systematically noisy.\n"
    },
    {
      "commit": "b9e62fdfeb6d4050750aa7beceda13d7beb2223d",
      "tree": "7544977472861074bea9ccac721026efdab8ad38",
      "parents": [
        "b529e733365034174f0e5c99e3f0fce347b34c5d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 18:34:53 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 19:17:50 2025 -0700"
      },
      "message": "loop: remove some Go-specific language from system prompt\n\nIt never used gopls anyway. :/"
    },
    {
      "commit": "b529e733365034174f0e5c99e3f0fce347b34c5d",
      "tree": "69491005dfacfdbabfbb244ac72468d85a5f7a99",
      "parents": [
        "d2f54c2e43ad3ad2c9b389068c1555c3e7f231f2"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 22:06:46 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 19:17:50 2025 -0700"
      },
      "message": "loop: disable multiple choice tool in oneshot mode\n\nThis change disables the multiple choice tool when Sketch is running in one-shot mode.\nIt adds an OneShot flag to the AgentConfig struct and conditionally includes\nthe multiple choice tool based on this flag.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "d2f54c2e43ad3ad2c9b389068c1555c3e7f231f2",
      "tree": "a57204539b914c7109b5a53456148970b1293357",
      "parents": [
        "f392251fe06355e73d80eae868916410ab18b08b"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 18:38:07 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 19:17:50 2025 -0700"
      },
      "message": "loop: improve update_tests.sh reliability\n\nEncouraging the agent to call the title tool immediately\nhas its drawbacks!"
    },
    {
      "commit": "6aaf6afdee5d097c23d5e80314ea13cf37bea491",
      "tree": "add2c3678c614dd45b718ef1ff636bd2b012e8b2",
      "parents": [
        "6ab6fce0d5309447156935c39c3d29dc4977c49d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 20:47:13 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 14:04:30 2025 -0700"
      },
      "message": "experiment: make precommit always on\n\nRemove the precommit experiment flag and make commit message style guidance\nalways available when using the precommit tool.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "85de37e3be602ca67ef5e2f2185ee819323ec31c",
      "tree": "4332db4df2ab98f661731107102436291ae02ab9",
      "parents": [
        "a2a31508e1b7348a1337e2038c5560d4b1bc19d3"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 06:46:45 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 14:03:38 2025 -0700"
      },
      "message": "loop: encourage smaller diffs\n\nHopefully this will prevent the agent from being gratuitously \"helpful\".\nAnd small diffs are always welcome when reviewing.\n"
    },
    {
      "commit": "a2a31508e1b7348a1337e2038c5560d4b1bc19d3",
      "tree": "7c3234c35772260a8cbee23d78ec37d7775a1fc7",
      "parents": [
        "c3c202317359dae2647aee2bcdbe61382fa3b99f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 12:37:18 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 14:03:38 2025 -0700"
      },
      "message": "loop: split title tool into title and precommit tools\n\ntitle wants to be called early, as soon as the topic is clear.\nprecommit wants to be called late, just before first git commit.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "4936de3834a2c70db563d19975c072bb42d953cc",
      "tree": "b4e4e9eb513236636c523ca70d7e2983157af156",
      "parents": [
        "593ca6455ea14bf48f6ae4ff6f5d3296c6befa7b"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 13:50:04 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 07 14:02:13 2025 -0700"
      },
      "message": "all: make update_tests.sh scripts location-independent\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "4962f153fa0d6812543addd690be8dba8c04a406",
      "tree": "3a90c5736422c77f8ef3dc8d552640e65f1e07a0",
      "parents": [
        "8b43ffbf41d06aee5ad5c734f1661a3b62cfe1a9"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Tue May 06 17:24:20 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Tue May 06 17:24:20 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "33d282f80db786cc60ba521a38ed5166f23239ed",
      "tree": "9ed1f15c6d3081d5bef7d16b9d72e78a2c7780cf",
      "parents": [
        "a9d87aa69cfefdc91ec7aaa6bc42907749748e76"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Sat May 03 04:01:54 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 06 10:23:39 2025 -0700"
      },
      "message": "Add browse tool support.\n\nI reviewed some MCPs (using OpenAI\u0027s deep research to help), and it\nhelped me choose chromedp as the relevant library and helped me come up\nwith an interface. This commit adds chrome to the Docker image which is\nkind of big. (I\u0027ve noticed that it\u0027s smaller on Ubuntu, where it doesn\u0027t\npull in X11.) go-playwright was a library contender as well.\n\nImplement browser automation tooling using chromedp\n\nThis implementation adds browser automation capabilities to the system via the chromedp library,\nenabling Claude to interact with web content effectively.\n\nKey features include:\n\n1. Core browser automation functionality:\n   - Created new browsertools package in claudetool/browser\n   - Implemented tools for navigating, clicking, typing, waiting for elements,\n     getting text, evaluating JavaScript, taking screenshots, and scrolling\n   - Added lazy browser initialization that defers until first use\n   - Integrated with the agent to expose these tools to Claude\n\n2. Screenshot handling and display:\n   - Implemented screenshot storage with UUID-based IDs in /tmp/sketch-screenshots\n   - Added endpoint to serve screenshots via /screenshot/{id}\n   - Created dedicated UI component for displaying screenshots\n   - Ensured proper responsive design with loading states and error handling\n   - Fixed URL paths for proper rehomed URL support\n   - Modified tool calls component to auto-expand screenshot results\n\n3. Error handling and reliability:\n   - Added graceful error handling for browser initialization failures\n   - Implemented proper cleanup of browser resources\n\nThe browser automation tools provide a powerful way for Claude to interact with web content,\nmaking it possible to scrape data, test web applications, and automate web-based tasks.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "5cca56ff3aec7785494c6a9fcd4e846900968ed1",
      "tree": "25b99a05ae7450fc210110414252210d189ca993",
      "parents": [
        "4fcde4a88794aec937fd116d6059871297d974e7"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue May 06 01:10:16 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:32:34 2025 -0700"
      },
      "message": "loop: migrate system prompt to Go templates\n\nIt was bound to happen eventually.\nBite the bullet now.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "4fcde4a88794aec937fd116d6059871297d974e7",
      "tree": "c64431e4d72508f414c4dea441e47b079e5476fe",
      "parents": [
        "36a5cc15faa43d028f87706ca286adb7f5109120"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:28:13 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:28:13 2025 -0700"
      },
      "message": "loop: clarify tool-ends-turn logic\n\nIt mis-handled ends-turn-tools in subconvos.\nThe multi-if was confusing.\nIt missed an early return.\nGenerally unindent.\n\nMost of this doesn\u0027t matter, but when I noticed the subconvo\nand the weird if structure, I just kept going...\n"
    },
    {
      "commit": "36a5cc15faa43d028f87706ca286adb7f5109120",
      "tree": "a88ca83039990dd73f9582b6c1428af72da69e91",
      "parents": [
        "d42577f657516eba00e41bd266d581b88e28ae05"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 17:59:53 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:20:24 2025 -0700"
      },
      "message": "loop: don\u0027t rename title tool, even with precommit experiment\n\nDoing so breaks various UIs.\n"
    },
    {
      "commit": "c72ceb21966c5e7685db6c9bf28074042265d683",
      "tree": "8113c9aa9fe4fe689b8b1e3b7ff01c1aa5ff27bb",
      "parents": [
        "bfebfd141e023d12ae44ddcbcfc78c4d83b13344"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 23:30:15 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:20:24 2025 -0700"
      },
      "message": "claudetool: add go mod tidy check to codereview\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "f4047bbd0440a5cec265ef6805f97d18ca3b255e",
      "tree": "e8d00718fe1363d3826156bc5ce61fad1c25c582",
      "parents": [
        "e750ec9fb4821e241d6f0fbdfa1aeb031d025168"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 23:02:56 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 18:20:24 2025 -0700"
      },
      "message": "claudetool/codereview: new package extracted from claudetool\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "3659d8714d31bad050d36043b67efd76a8d53b77",
      "tree": "2803c54c63628e397e63bdbbe4fa2647a4d5f556",
      "parents": [
        "021557a7d33dacd4fedb9a4677fc93c48569d57a"
      ],
      "author": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Mon May 05 17:52:23 2025 -0700"
      },
      "committer": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Mon May 05 17:52:27 2025 -0700"
      },
      "message": "all: more gemini key plumbing\n"
    },
    {
      "commit": "021557a7d33dacd4fedb9a4677fc93c48569d57a",
      "tree": "13a020ae99f9f86de4b2b10d919427c9287f3de8",
      "parents": [
        "5a7b3698b523365fe070ffcd1019c704c2c3a7b5"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon May 05 23:20:53 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon May 05 16:58:53 2025 -0700"
      },
      "message": "Allow multiplechoice tool to end the model turn\n\nAdd EndsTurn field to llm.Tool to indicate if a tool should force the end of a turn.\nSet the multiplechoice tool to end the turn by setting EndsTurn\u003dtrue.\nUpdate OnResponse to check for tools that should end the turn.\n\nTranscript of the chat for this change:\nhttps://sketch.dev/messages/1f4n-17a3-hmfx-71gg\n\nNote that I did ask it to investigate an alternative approach, but decided\nthis one (explicit EndsTurn field on Tool) was a better trade-off than\nthe alternative (altering the Tool.Run signature).\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "4d4e8075e4df5249537e3ec96fea72a8bcc2399d",
      "tree": "ee1a4ae9fbac1614aefe235a5ea96814969fc420",
      "parents": [
        "6f446faed9f79e08362d22dfc9c79b15cba5f55c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 15:00:59 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 15:17:27 2025 -0700"
      },
      "message": "loop: use stringer for State.String, use String in slogs\n\n"
    },
    {
      "commit": "3871a09ecaeead3e67d95a9694ab0fb38fa5e8fe",
      "tree": "17d7d56c97fef75c994c79e750cc54a4af51adb5",
      "parents": [
        "961cc9e4d4b527d1924d8919d9294fc53eebab40"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon May 05 21:54:56 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon May 05 15:08:10 2025 -0700"
      },
      "message": "Update agent_user_cancel_test.go to use new package structure\n\n- Replace imports from sketch.dev/ant to sketch.dev/llm and sketch.dev/llm/conversation\n- Replace ant.* types with llm.* types\n- Update MockConvo to implement CancelToolUse method\n- Update method signatures like OnToolResult\n- Change InnerLoop references to processTurn per recent changes\n- Fix Agent struct initialization to match new structure\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "d7970e62c34243aaa9c7a6405ceedfb9a073a783",
      "tree": "aaf5359fe136652624580e48d240d732790de3c2",
      "parents": [
        "e2518e5c7b80d3f0d8f3017e34b19e59d6deeac6"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 01:56:28 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:48:06 2025 -0700"
      },
      "message": "claudetool: change title tool to precommit, add commit style guidance\n"
    },
    {
      "commit": "e2518e5c7b80d3f0d8f3017e34b19e59d6deeac6",
      "tree": "4d23f4326e76a8f587b4a148aa4347cdc9d243f6",
      "parents": [
        "503b5e3543f69cc56c05bd02ce48666259d01f90"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 11:13:40 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:48:06 2025 -0700"
      },
      "message": "claudetool: add experimental LLM reviewer stage"
    },
    {
      "commit": "503b5e3543f69cc56c05bd02ce48666259d01f90",
      "tree": "b1d5efec44e4ff2d6094758b7ccb8d306055c53a",
      "parents": [
        "d7e56386b4243bb6b2f303ef824418bae971a836"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:30:55 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:48:06 2025 -0700"
      },
      "message": "loop: add not_done experiment\n\nThis attempts to get the LLM to introspect a bit more\nwhile calling the done tool, encouraging it to change\nitself mind if it thinks better of its progress\nwhile working through the checklist.\n"
    },
    {
      "commit": "d7e56386b4243bb6b2f303ef824418bae971a836",
      "tree": "cb2d5668a2bdb0b4b1c86864c846dbeb9708d6ef",
      "parents": [
        "c6a2c2408e1fbacbff92931190b3558b8e353944"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:22:08 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:48:06 2025 -0700"
      },
      "message": "loop: pull done tool description out into a constant"
    },
    {
      "commit": "c6a2c2408e1fbacbff92931190b3558b8e353944",
      "tree": "d3ea94cd8f8190f0561b23b2d5d094b2406285eb",
      "parents": [
        "b4782147bb79cd34495c4418a351672bc44035de"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 22 18:04:16 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 13:48:06 2025 -0700"
      },
      "message": "loop: clean up whitespace"
    },
    {
      "commit": "995704692a260e7792a6116d19882bc1943e08b4",
      "tree": "54d2b592cb77cf09cc462da3df92849a7095ea37",
      "parents": [
        "50608b1df40053cb18d91a8493872a7ce9243655"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 10:26:14 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon May 05 10:26:21 2025 -0700"
      },
      "message": "dockerimg: remove configurability from open browser request\n\nInnie is untrusted, so we can\u0027t let it provide a url to open (duh).\nThere\u0027s a chicken-and-egg problem here: we need to start the git\nserver before launching the container, but we need the container\nport information to store the ps1URL on the git server.\nSolve it with a little sync/atomic. There\u0027s a logical race here,\nbut if we lose the race, the behavior is that nothing happens,\nat which point the user tries again and it works.\nGood enough for now.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "bdfb126de211f5f2fabb39498de00acde5faf58f",
      "tree": "665cedc4a7148c2ba86e915be96e1cc1d8a01450",
      "parents": [
        "cf291fafd7142308f27ec5805251f2e2bdeded6b"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Sat May 03 20:15:41 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Sat May 03 20:15:41 2025 -0700"
      },
      "message": "sshserver: s/log/slog\n"
    },
    {
      "commit": "cf291fafd7142308f27ec5805251f2e2bdeded6b",
      "tree": "f18805cbe3583f62e423c5a0b17a3be3a757df54",
      "parents": [
        "d0a3cd609ca36baebd066d6fd83c153293c459eb"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Sat May 03 17:55:48 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Sat May 03 17:59:43 2025 -0700"
      },
      "message": "sshserver: add scp support\n\nfixes https://github.com/boldsoftware/sketch/issues/53\n"
    },
    {
      "commit": "485afc6975b853aa670b5087c323fa3df3df0672",
      "tree": "291bbf09de69cec72c13f652f3d9be81f35451e4",
      "parents": [
        "6234a8d9d229904994f49a5edacca05e54b26d1f"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Apr 28 14:28:39 2025 -0700"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri May 02 22:12:51 2025 +0000"
      },
      "message": "tool_use: add multiplechoice support to Agent\n\nThis implements the \"dumb\" approach - the tool itself just tells\nthe llm that it rendered the options to the user, and it\u0027s done.\n\nIf the user selects one of the options, we paste its response text\ninto the chat input textarea on the frontend.  The user is of\ncourse free to ignore the question or the options presented.\n\nThis keeps no association between user response and the original\ntool_use block that solicited it from the user. I.e. the user\nresponse message doesn\u0027t include the original tool_use_id value\nit it.  It looks as though the user typed it by hand.\n"
    },
    {
      "commit": "25f6ff1b44e739e64d8b86cc4ea11bf8c631265c",
      "tree": "2255018ca38ba211e57eb9e76e87b82d61a0c826",
      "parents": [
        "d01d1341abf9b2e62f0b4cc821277dc4c40c6225"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 02 04:24:10 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 02 14:25:31 2025 -0700"
      },
      "message": "Implement Server-Sent Events (SSE) for Real-time Agent Communication\n\n- Add server-side SSE endpoint (/stream?from\u003dN) for streaming state updates and messages\n- Replace polling with SSE in frontend for real-time updates with significant performance improvements\n- Implement efficient connection handling with backoff strategy for reconnections\n- Add visual network status indicator in UI to show connection state\n- Use non-blocking goroutine with channel pattern to handle SSE message delivery\n- Ensure proper message sequencing and state synchronization between client and server\n- Fix test suite to accommodate the new streaming architecture\n- Update mocks to use conversation.Budget instead of ant.Budget\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "4f84ab729ddbf428b0e891940f08f70b4edee05c",
      "tree": "f2e52e4a01c188ada1f5acf8b2a013029b999495",
      "parents": [
        "44f9b4cec11e269a52fbfc099989ab425b8e125f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 22 16:40:54 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 02 12:57:44 2025 -0700"
      },
      "message": "all: support openai-compatible models\n\nThe support is rather minimal at this point:\nOnly hard-coded models, only -unsafe, only -skabandaddr\u003d\"\".\n\nThe \"shared\" LLM package is strongly Claude-flavored.\n\nWe can fix all of this and more over time, if we are inspired to.\n(Maybe we\u0027ll switch to https://github.com/maruel/genai?)\n\nThe goal for now is to get the rough structure in place.\nI\u0027ve rebased and rebuilt this more times than I care to remember.\n"
    },
    {
      "commit": "dc372f3f962771b1e30212847371db837d758c2e",
      "tree": "a7c98e40b6fcbb5d3aa8fed99f2363eea6182f78",
      "parents": [
        "6c2bb84114e1387e8751d6d2db33bcfc89f2dde5"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 02 18:35:48 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 02 11:53:13 2025 -0700"
      },
      "message": "loop: the end of a subconvo is not an End of Turn\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "4d5e9978fce2feb262663b9d0455c06546723ddc",
      "tree": "dfa4824a78b33a01c5c0d72d4077cfec78010a62",
      "parents": [
        "2772f63c725cdc47f644f68a9e684e798e54b543"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 15:56:37 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 16:09:09 2025 -0700"
      },
      "message": "all: make tests accept OUTER_SKETCH_ANTHROPIC_API_KEY\n\nInner sketch already has an ANTHROPIC_API_KEY...but it is the\nsketch anthropic key, not the anthropic anthropic key. Blarg!\n\n"
    },
    {
      "commit": "a3dcd86d1c05e95ee9c058a43262458a92160898",
      "tree": "86a49759e93940a80c940703a0d03a7084a90dd1",
      "parents": [
        "8da3d456505ec29a27d73720731a929cfab46b3f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 19:47:16 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 12:39:18 2025 -0700"
      },
      "message": "ant: improve encapsulation\n\n- Replace string literals with package constants for message roles and content types.\n- Create UserStringMessage helper function to simplify user message creation\n- Replace manual Content creation with ant.StringContent()\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "9373c07a6d2fc97c2fad41e8228a7f2e8bc10ccb",
      "tree": "f7485f9715aee87c185ba2113b2eab6c41b1398d",
      "parents": [
        "b7c5875548da5057eac0405bf4e0ae8bbc43667c"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 01 10:27:01 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 01 12:13:31 2025 -0700"
      },
      "message": "Update tests for agent\u0027s new iterator implementation\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nThe commit 4eb6bb6c9ac switched from outbox channels to a subscriber model\nwith message iterators. This commit updates all existing tests to use the\nnew iterator implementation and adds new tests specifically for the iterator\nfunctionality.\n\n- Modified agent_test.go to use new iterator approach\n- Modified agent_git_test.go to check history array directly\n- Added new iterator_test.go to test iterator-specific functionality\n\nFix issues found by code review\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\n- Fix context leak by properly using cancel function\n- Modernize for loops using range over int\n- Use fmt.Appendf instead of []byte(fmt.Sprintf)\n\nOptimize slow tests to improve test execution time\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nThis commit optimizes the test suite to reduce execution time:\n\n1. Reduces TestGitCommitTracking test time by using fewer git commits\n   (20 instead of 110) which cuts the test time by 77%.\n\n2. Improves iterator tests by using channels for synchronization instead\n   of time.Sleep, reducing TestIteratorWithNewMessages from 200ms to nearly 0ms.\n\n3. Reduces timeouts and sleeps in other iterator tests.\n\nTotal test execution time reduced by more than 60% (from 2.3s to 0.9s).\n"
    },
    {
      "commit": "b7c5875548da5057eac0405bf4e0ae8bbc43667c",
      "tree": "a0b9eb0f68de826d7b51a5e8f5eaa7976fb48de3",
      "parents": [
        "5228b5850d8453c225e5611918fcd00b747c65cc"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 01 10:10:17 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 01 12:13:31 2025 -0700"
      },
      "message": "agent plumbing: convert outbox to subscribers and an iterator\n\nWaitForMessage() could only work for one thread, because it was using a\nsingular channel for outboxes. This was fine when we only had one user,\nbut WaitForMessageCount() was kinda similar, and had its own thing, and\nI want to rework how polling works and need another user.\n\nAnyway, this one is hand-coded, because Sketch really struggled\nwith getting the iterator convincingly safe. In a follow-up commit,\nI\u0027ll try to get Sketch to write some tests.\n"
    },
    {
      "commit": "a1e0e49213c07f74618f0e0f324e707792858e0c",
      "tree": "9bddcd7afb99b196c6e7238be9bcbf509d2256ff",
      "parents": [
        "76ccdfd8bbbcd9aa2c069e5560f3b9e2284ee900"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu May 01 10:51:08 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu May 01 10:51:08 2025 -0700"
      },
      "message": "loop/agent.go: don\u0027t panic on nil toolResp\n"
    },
    {
      "commit": "76ccdfd8bbbcd9aa2c069e5560f3b9e2284ee900",
      "tree": "2c4a7e2102aaa361aecb0fcccbbb5e2c78dbe6dd",
      "parents": [
        "453a62f584a738ab243ddae8dc0736a673aa3c08"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 17:14:18 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 01 10:15:17 2025 -0700"
      },
      "message": "Add git fetch prune to improve Docker container initialization\n\nThis change modifies the agent initialization to run \u0027git fetch --prune sketch-host\u0027\ninstead of \u0027git fetch sketch-host\u0027 when running in Docker. This ensures that\nleftover remote branches from the sketch host are properly cleaned up.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "d9d4581952edb59469a8402910783570be852fb8",
      "tree": "7b06cf74a10d3d812152c21fc72ced395a3e5024",
      "parents": [
        "48c84c9a4df29b1e51c7fdca81053dd9cd0c2446"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 16:53:41 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 18:00:55 2025 -0700"
      },
      "message": "webui: add current Agent state to call-status tooltip\n"
    },
    {
      "commit": "3e2111b1e18a39a4eba4a0afa0327b6a67acf802",
      "tree": "6add6c3a0583877f173f1f2baf6ceeb8c39b3f69",
      "parents": [
        "e54b00af5cf711c2171a26ed0f29a8ce83d50fb4"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 17:53:28 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 17:13:18 2025 -0700"
      },
      "message": "all: support popping a browser from termui\n\n- Add \u0027browser\u0027, \u0027open\u0027, and \u0027b\u0027 command aliases to termui\n- Open the current conversation URL in default browser\n- Add help documentation for the new command\n\nAdd browser launch endpoint to Git server for Docker support.\n\nWe\u0027ll probably want to set up a proper mux for the no-longer-just-git\nserver pretty soon.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "96b60dd7e71c7db55dfe4cff86265eab02e54e9f",
      "tree": "3ee9ddbbe4b260b7000f194e369b527ce658cd66",
      "parents": [
        "bce3a13a7c16ffdb602b66550e6b3479d34fb9b0"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 09:49:10 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 15:20:35 2025 -0700"
      },
      "message": "Add StateMachine tracking to Agent control flow\n\nThis commit integrates the existing StateMachine type with the Agent\nto provide state tracking and validation throughout the conversation\ncontrol flow. This allows for better monitoring and debugging of the\nAgent\u0027s behavior during execution.\n\nThis commit adds tests to verify the correct behavior of the state\nmachine integration with the Agent type:\n\n1. A test for basic state transitions\n2. A test for a complete processTurn flow with a simple response\n3. A test for a processTurn flow with tool use\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "2c4db099e6763cf18f0c57876298b9f5c70ed925",
      "tree": "ae4408992dd74fa0b5392523d2e6713e388326e7",
      "parents": [
        "b74b526b579320c08ad85cc8b4bdd719c9d6d7c8"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon Apr 28 16:57:50 2025 -0700"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Wed Apr 30 19:59:45 2025 +0000"
      },
      "message": "Restart conversation support.\n\nThe idea here is to let the user restart the conversation, possibly with\na better prompt. This is a common manual workflow, and I\u0027d like to make\nit easier.\n\nI hand wrote the agent.go stuff, but Sketch wrote the rest.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "9f4b8089f93f39300b819ccf83cf64a7a867c0dc",
      "tree": "c1f00c2b00892efd2656196ebbc37c433d138658",
      "parents": [
        "bc6b629676e97d1789cff9a1d945b5faf680372e"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 17:34:07 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 11:28:34 2025 -0700"
      },
      "message": "agent.go: don\u0027t panic on nil initialResp\n\na.processUserMessage(ctx) appears to return nil, nil under\ncertain circumstances, and this causes a panic in processTurn().\n\nThis change makes it log the error instead of panicing.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "250348ec3c8bcba21caa62fd4ae53e4d9476fafa",
      "tree": "4be2e3660c84343af23cb81fa14b3c7a5709ebfd",
      "parents": [
        "eb5166a5043946ad6782cb64af987d23a32e3203"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 10:31:28 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 11:13:16 2025 -0700"
      },
      "message": "all: mild prompt engineering\n\n"
    },
    {
      "commit": "42f7a7c93682a4ed04c62688e1475cd6ebc04de5",
      "tree": "e2c65947daa4012b98c6a884149c393332fd2f0c",
      "parents": [
        "23b6a2d690a4e208ec21604a5dd6a59bd1129ab5"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 10:29:21 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 11:13:16 2025 -0700"
      },
      "message": "loop: enforce rather than fix branch formatting\n\nThis way the UI will always be correct;\nthe UI runs off the LLM response, not the fixed version.\n"
    },
    {
      "commit": "edc88dcc56ebdb1a2d9887728d0b5133b6131fbb",
      "tree": "a5b44389b3ac59022c3006d8347c36626cc7019e",
      "parents": [
        "885a16a8e37fe82dac66a7db729be202f6ce4bea"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 02:55:01 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 09:41:22 2025 -0700"
      },
      "message": "Rename cancelInnerLoop to cancelTurn to match refactored naming\n\n- Updated all references to cancelInnerLoop and CancelInnerLoop\n- Changed method and variable names to match the new processTurn naming\n- Updated references in related files: server/loophttp.go and termui/termui.go\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "885a16a8e37fe82dac66a7db729be202f6ce4bea",
      "tree": "eff84390d70dda2a09c79faffad2ba0850c1b763",
      "parents": [
        "0d95d3a268ffad82b7c645200804fb43ed088a81"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 02:49:25 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 30 09:41:22 2025 -0700"
      },
      "message": "Refactor loop/agent.go to reduce complexity\n\n- Restructured Agent.InnerLoop into smaller, more focused functions\n- Renamed InnerLoop to processTurn to better reflect its purpose\n- Extracted helper methods for different responsibilities\n- Improved code organization and testability\n- Each extracted function now handles a single responsibility\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "78520f50d518f331c6608cfd0dff7bb4a75dc93b",
      "tree": "fadca8a92dbe7e67fcae66c89f54f398fb219c58",
      "parents": [
        "3b0795b1c52d9b470f361299e9cd359c53704a04"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 06:16:08 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 06:16:08 2025 -0700"
      },
      "message": "loop: update test fixture"
    },
    {
      "commit": "fff269b875d14dd6fbd1b90050739679f4bc2061",
      "tree": "ee3155adc63e627cf2fe8e24a4bf1a5d7776b5c7",
      "parents": [
        "47b193683089f6ca98877af497f7800d4a26f4a9"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 01:49:39 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 19:06:19 2025 -0700"
      },
      "message": "Update title tool to reject branch names that already exist\n\nAdded a check to the title tool to verify that branches do not already exist\nbefore setting them, which prevents potential issues with duplicate branch names.\nIncludes a new unit test to validate this behavior.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "47b193683089f6ca98877af497f7800d4a26f4a9",
      "tree": "43b4b54c7b32650ff7ea9256c0aca7a793d68246",
      "parents": [
        "0137a7f2a025a2ac08e536b207ded2d58e928e32"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 01:34:14 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 19:06:19 2025 -0700"
      },
      "message": "Display branch name alongside title in termui and webui\n\nThis change adds the branch name alongside the title in both the terminal UI and the web UI, following up on commit a9b3822fd2cfdc035e7daa8b59496f9838a4b2c6 which added the branch_name parameter to the title tool.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "d499fd6e12374193df2d769d12753bbd1ddd1493",
      "tree": "e8c2a8a134773164910b78b4606bd196c55d6d5f",
      "parents": [
        "dae19073cfdc420af8da311c4f3974ac6db77b46"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 01:31:29 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 19:06:19 2025 -0700"
      },
      "message": "Add permission callback to Bash tool to enforce title setting before git commits\n\n- Convert Bash tool from a plain variable to a struct with a permission callback function\n- Add a constructor for creating Bash tools with custom callback functions\n- Implement a permission check in agent.go that verifies a branch name has been set before allowing git commits\n- If no branch name is set and a git commit command is attempted, return an error instructing to use the title tool first\n- Maintain backward compatibility for tests with BashRun function\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "a9b3822fd2cfdc035e7daa8b59496f9838a4b2c6",
      "tree": "9fc7773eb4c012398133633e41e6f1551f621996",
      "parents": [
        "1ae976bde49d4f0dc48146c1e3d3f38201e1f830"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 18:05:06 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 18:05:06 2025 -0700"
      },
      "message": "Add branch_name parameter to title tool\n\nModified the title tool to accept a branch_name parameter, which allows specifying\na custom branch name slug instead of deriving it from the title. The branch name\nis still cleaned to ensure it\u0027s valid.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e"
    },
    {
      "commit": "1ae976bde49d4f0dc48146c1e3d3f38201e1f830",
      "tree": "9d6235d7b3a16df5b968c271ca318147ac293412",
      "parents": [
        "e2d24ab80f34e25f602b306ea8e8b765101d8585"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed Apr 30 00:06:43 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 17:59:55 2025 -0700"
      },
      "message": "loop: fiddle with titleToBranch\n\nAdd support for numbers.\nUse strings.Map.\n"
    },
    {
      "commit": "dbe02304e804066bb32fcf6f41690336a98e6531",
      "tree": "d27ed5e5b94b004167e202254b97f7d1806733bd",
      "parents": [
        "2b2090e7fa8fd53eda5dca132980c3e2fa4cb3b8"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 16:44:23 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 16:44:23 2025 -0700"
      },
      "message": "loop: extract system prompt into a separate file\n\nThis will make swapping it out easier, if/when desired.\n"
    },
    {
      "commit": "2b2090e7fa8fd53eda5dca132980c3e2fa4cb3b8",
      "tree": "269e400e420a30079bfbaa7dea562e4b6d80d9d7",
      "parents": [
        "c72fff52ad6c5436fa8469f049fa232f2f6be5ed"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 16:41:34 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 16:42:35 2025 -0700"
      },
      "message": "claudetool: add missing json schema field\n\nApparently this is required, and Anthropic happens to not care."
    },
    {
      "commit": "c72fff52ad6c5436fa8469f049fa232f2f6be5ed",
      "tree": "2f42838fc0af2f4954a64b8edcc4c8e09ec08af4",
      "parents": [
        "d3906e2e0a18197148089f384b188135b07559be"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue Apr 29 20:17:54 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue Apr 29 16:24:19 2025 -0700"
      },
      "message": "Add SSH connection information to web UI\n\nThis commit implements:\n1. Added SSH information display to the web UI info button\n2. Shows SSH connection information only when running inside Docker container\n3. Constructs the full SSH hostname as \"sketch-[session_id]\"\n4. Added copy-to-clipboard buttons for SSH commands\n5. Styles the VSCode URL as a proper clickable link\n6. Shows a warning message when SSH is not available\n7. Modified container naming to use only SessionID instead of imgName+SessionID\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "50a1d62e0dc285c69b7c495e4a01a47fa3561692",
      "tree": "3a3e261735a063208430e457a0fbf93c1d30f58c",
      "parents": [
        "5fabc74b668752dc68e05a9a452cc15cf62077f7"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 09:59:03 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue Apr 29 09:59:13 2025 -0700"
      },
      "message": "loop: don\u0027t panic when LLM API call fails\n\nAnd refactor a touch."
    },
    {
      "commit": "9c07e1d30f7f576bd7679a155873f6419743e6a6",
      "tree": "e962e6cb86fdaca7fbb4359efd025b39a47de74e",
      "parents": [
        "ffecb1e9fbaca84d7f142aa294fa795c324587af"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon Apr 28 19:25:37 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon Apr 28 19:25:37 2025 -0700"
      },
      "message": "loop: prevent panic on double Agent.Init"
    },
    {
      "commit": "22bd8eb83b7c779d9d2396c75cc344124e150aee",
      "tree": "81fc507d28db05b011d463745e125e6126260fb0",
      "parents": [
        "0dcebe1bf2ec5d6f85aa71fb46367e2adf8f4947"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Apr 28 10:36:37 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Apr 28 10:36:37 2025 -0700"
      },
      "message": "sshserver: fix env for ssh pty sessions\n"
    },
    {
      "commit": "99a9a0285fe449f047fbc93766f37e6ea7af21df",
      "tree": "ba255c9b05449c09d137cd6cf81edf58469542a1",
      "parents": [
        "f98d7305e73ecec9a78f94f527693d5adfb89159"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Sun Apr 27 15:15:25 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Sun Apr 27 20:00:22 2025 -0700"
      },
      "message": "Implement tracking of outstanding LLM and Tool calls\n\nThis commit implements a listener pattern between ant.convo and the Agent for tracking outstanding calls.\n\n* Added fields to the Agent struct to track outstanding LLM calls and Tool calls\n* Implemented the listener methods to properly track and update these fields\n* Added methods to retrieve the counts and names\n* Updated the State struct in loophttp.go to expose this information\n* Added a unit test to verify the tracking functionality\n* Created UI components with lightbulb and wrench icons to display call status\n* Added numerical indicators that always show when there are active calls\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n"
    },
    {
      "commit": "833a0f83af52be33eed3baf0f67ffa3ddab55cb4",
      "tree": "0f1c78df648d499ed6ac3e975276ecc977ab4e70",
      "parents": [
        "0cbd976940708c94eb8b644b14bfda3f19087997"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu Apr 24 18:39:36 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri Apr 25 19:31:00 2025 -0700"
      },
      "message": "claudetool: improve codereview\n\nDo a bunch of un-vibecoding and bug fixing.\nUnfortunately, lots left.\nGet rid of vet; gopls check covers it.\n\nAdd testing infrastructure and a bunch of fixtures.\n"
    },
    {
      "commit": "01ed5bee0c121852d0e2ab3836a08acab68397e4",
      "tree": "e2b473d510d146f9474b2eedb5526b8a4eead1f2",
      "parents": [
        "7d5a6301a256823ab4b26a68dbd166f0d0737409"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu Apr 24 22:46:53 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu Apr 24 22:46:53 2025 -0700"
      },
      "message": "sshserver: enable ssh port forwarding\n"
    },
    {
      "commit": "1d06132f5a79950ab8a64eb72219363fb63ca92f",
      "tree": "46ed36f431ee3aef7caacbae7b1ebe7560d3f544",
      "parents": [
        "6a50b1811c7fbf8be7e5ad4cc77a576e2d612a66"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu Apr 24 09:52:56 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Thu Apr 24 11:11:44 2025 -0700"
      },
      "message": "sshserver: add direct-tcpip channel, allow non-pty\n\nThis change enables VS Code to connect to local sketch containers\nover SSH.\n\nThe VSC docs describe how to use this feature:\nhttps://code.visualstudio.com/docs/remote/ssh\n"
    },
    {
      "commit": "75ec6bb42c08c8407cb96025b070dc9f1eb66eb9",
      "tree": "b7563c63b29f1535c5904e180344423412daab4e",
      "parents": [
        "08951fb6789dc172d4719eb6a09fcac21f94ef95"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu Apr 24 10:49:16 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu Apr 24 10:49:16 2025 -0700"
      },
      "message": "loop: add email address to Co-Authored-By trailer\n\n- It\u0027s the standard.\n- It\u0027ll let us set up a gravatar for hello@sketch.dev with the sketch logo.\n- It tells people how to find sketch (there was no domain or other hint anywhere).\n"
    },
    {
      "commit": "2032b1c1971ceb85ca14b20273a3783729fba3e3",
      "tree": "0486e9222643ffcbbd34286148f4a7913a169668",
      "parents": [
        "4f50a68ac73677c0022b2b3da8b4667cee01c11b"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 19:40:42 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 19:40:42 2025 -0700"
      },
      "message": "Move webui from /loop/webui to /webui\n\nThanks, perl (and git mv):\n\n\tperl -pi -e s,loop/webui,webui,g $(git grep -l loop/webui)\n"
    },
    {
      "commit": "b60f0f2c4f6baf635c7eeb2972d6ed25d9485891",
      "tree": "93a6b85c34010b1ef41072aad309e56e759694a6",
      "parents": [
        "cc3ba220373b62dd5a098180ea6797af76407525"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 18:19:32 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 19:28:10 2025 -0700"
      },
      "message": "Add background execution capability to bash tool\n\nThis adds a \u0027background\u0027 flag to the bash tool, allowing commands to be\nexecuted without waiting for them to complete. When running in background\nmode, the command\u0027s stdout and stderr are redirected to temporary files,\nand the tool returns the PID and paths to these files as a JSON structure.\n\nFeatures:\n- Different default timeouts: 1m for foreground, 10m for background\n- Goroutine to properly reap background processes when they complete\n- Uses \u0027sketch-bg-\u0027 prefix for temporary directories\n- Added robust test helpers for waiting on files and processes\n- Skip agent test that uses recorded HTTP interactions incompatible with\n  the updated schema\n\nSketch also updated the various UIs\n\nCo-Authored-By: sketch\n"
    },
    {
      "commit": "18532b212b8c108cc1c8bfcbaf5804a5c4156655",
      "tree": "3667714104cdd0bc0f8078a0ea619676e0764c7f",
      "parents": [
        "d013131a2892d175fcecc270d51e526c617dc170"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 21:11:46 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 19:28:10 2025 -0700"
      },
      "message": "Rename Host/Runtime hostname fields to Outside/Inside pattern\n\nThis renames all hostname/OS/working directory fields to follow the\nOutside/Inside naming pattern rather than Host/Runtime naming pattern.\n\n- HostHostname -\u003e OutsideHostname\n- RuntimeHostname -\u003e InsideHostname\n- HostOS -\u003e OutsideOS\n- RuntimeOS -\u003e InsideOS\n- HostWorkingDir -\u003e OutsideWorkingDir\n- RuntimeWorkingDir -\u003e InsideWorkingDir\n\nThis includes related method names, struct fields, and JavaScript properties.\n\nCo-Authored-By: sketch\n"
    },
    {
      "commit": "ae3480fee8b8ebf867a1097868d0032ff4b51324",
      "tree": "468d02673f8e9fff21fd33d9a343ef4125d646ac",
      "parents": [
        "5544d146e1ebe2747ae282e611f8d0a2c23f2b6c"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 23 15:28:20 2025 -0700"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 23 15:57:49 2025 -0700"
      },
      "message": "allow random (ephemeral) host ports for ssh server\n\nalso fixes an issue with authorized_keys files that\ncontain multiple pks: it now checks all of them not\njust the first one it parses.\n"
    },
    {
      "commit": "73db6056606c17e78973e124681a86754ed466d9",
      "tree": "2a6af32e75f371c843c385e175777772fb48ad46",
      "parents": [
        "8d50d7b66ae26221cbc8fbb246c62e47d8462cfe"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:09:07 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:41:14 2025 -0700"
      },
      "message": "sketch: another attempt at chat/diff fixes.\n\nNow, I\u0027ve moved the chat message property to sketch-chat-input\nand out of sketch-app-shell, which means the message for diff\nupdates goes straight there. The issue was that sketch-chat-input\nwas mutating this anyway, so clearing the chat message in\napp-shell didn\u0027t make sense and/or didn\u0027t work.\n"
    },
    {
      "commit": "8d50d7b66ae26221cbc8fbb246c62e47d8462cfe",
      "tree": "bddba9157a35c1a472d93f7d274a715a57ff154f",
      "parents": [
        "72682df0c3aa2e2b8917d0f66bdf8988dfbcb59f"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:12:40 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:12:40 2025 -0700"
      },
      "message": "gofumpt.\n"
    },
    {
      "commit": "72682df0c3aa2e2b8917d0f66bdf8988dfbcb59f",
      "tree": "b5c213237eced535db85dc8906fa42127bd525f0",
      "parents": [
        "4de80d219b96677b9e43e50293ec55bdf273f36d"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:09:46 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 13:09:46 2025 -0700"
      },
      "message": "Prettier.\n"
    },
    {
      "commit": "9a66cad2e538c0edd4b973332f8e3e6d3a5763ef",
      "tree": "2dabe16fa6608b3bbe23fc20189d83d3f1039b7b",
      "parents": [
        "10a7ac13a8aac36d947de8824452814596eb1dde"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 12:21:40 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 12:25:04 2025 -0700"
      },
      "message": "sketch: simplify sketch-chat-input and diff comment handling\n\nIt seems like the top-level property in sketch-app-shell is enough\nfor the chat input, and we can just use that.\n"
    },
    {
      "commit": "10a7ac13a8aac36d947de8824452814596eb1dde",
      "tree": "58bb570782fa0dc026e4653874373d8dd0653c83",
      "parents": [
        "af2d7e3940d063e4e5dfed2abed69c698f9b04fc"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 11:56:03 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 12:12:36 2025 -0700"
      },
      "message": "Fix chat input resize test by waiting for animation frame\n\nThe test was checking the height of the textarea immediately after filling\nit with content, but the component uses requestAnimationFrame() to adjust\nthe height asynchronously. Added a wait for the animation frame to complete\nbefore checking the height.\n\nCo-Authored-By: sketch\n"
    },
    {
      "commit": "af2d7e3940d063e4e5dfed2abed69c698f9b04fc",
      "tree": "5a72ddaadf85da2a8ac01a4935becd9d75b2095c",
      "parents": [
        "baa2b590cc3a5f63bc52c3324f2835666b9ae450"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 11:35:03 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 11:51:57 2025 -0700"
      },
      "message": "sketch: diff commenting: avoid re-sending old messages\n\nWhen I was adding diff comments, it was sending me back to the chat\nscreen, which isn\u0027t what I wanted, since I want to send multiple\ncomments in one go. Furthermore, it was re-sending old comments\nbecause of some new-to-me attribute stuff.\n\nFinally I moved the comment box out of its right-hand corner to\nthe line I\u0027m commenting on. (Sketch did this part.)\n\nCo-Authored-By: sketch\n"
    },
    {
      "commit": "baa2b590cc3a5f63bc52c3324f2835666b9ae450",
      "tree": "69b313aab41b2f3d3cd27c72ce7d09f6b6453aa6",
      "parents": [
        "97188fc1955f036e57c42a2f345b3c01fc5f0dc0"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Wed Apr 23 10:40:08 2025 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 23 10:40:08 2025 -0700"
      },
      "message": "sketch: initial container ssh support (#15)\n\nAdds an in-process ssh server to the sketch agent running inside\nthe container.\n\nThe ssh server implementation uses https://github.com/gliderlabs/ssh/\n\nThis change does not automatically generate any keys (this may come later).\nYou specify the server identity private key and the user\u0027s authorized public\nkeys on the sketch command line.\n\nThe host sketch process reads these files from the cli flags at startup. Once\nthe container is launched, it passes these keys to to the container\nsketch process via new /init POST body fields."
    },
    {
      "commit": "97188fc1955f036e57c42a2f345b3c01fc5f0dc0",
      "tree": "7d9e1e419c3e946bcad16346f417bd2e53954708",
      "parents": [
        "7be879f27f93627e69714406b4eb8b07610aa0d0"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:50:04 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:50:04 2025 +0100"
      },
      "message": "style: Don\u0027t stretch Send button on input grow\n"
    },
    {
      "commit": "7be879f27f93627e69714406b4eb8b07610aa0d0",
      "tree": "9f174c2e8dff7e7c41275dd833f0dcb800940381",
      "parents": [
        "e2a8c2f1fae1f8e3162b2533d27825e1bf800574"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:30:15 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:30:15 2025 +0100"
      },
      "message": "Fix WebUI tests for sketch-timeline-message component\n\n- Update commit hash display to show 8 characters instead of 7\n- Add missing \u0027pushed-branch\u0027 class to branch display element\n- Fix whitespace issues in the commit hash display\n\nCo-Authored-By: sketch\nFix the failure in webui tests\n"
    },
    {
      "commit": "e2a8c2f1fae1f8e3162b2533d27825e1bf800574",
      "tree": "4dcdd7de679c90a4d3ec79b47111ce5e67fd07b2",
      "parents": [
        "d140295fa7d794f5b30feb4eee2f45f9cc9ff383"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:09:25 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Wed Apr 23 15:09:49 2025 +0100"
      },
      "message": "webui: Improve dx\n\nFor local development, switch to Vite and update web components for improved demo experience. Note that we haven\u0027t changed how we bundle when we\u0027re actually running in sketch; that\u0027s still the go/esbuild in-memory setup. This just changes demo dev setup to get breakpoints working and a functioning full sketch-app-shell.\n\nWe still need to add some mock data, but this is a start\n\n- Introduced `vite.config.mts` for Vite setup with hot module reloading.\n- Updated `package.json` and `package-lock.json` to include Vite and related plugins.\n- Refactored demo scripts to utilize Vite for local development.\n- Created `launch.json` for VSCode debugging configuration.\n- Enhanced `Makefile` with a new demo task.\n- Improved styling and structure in demo HTML and CSS files.\n- Implemented `aggregateAgentMessages` function for message handling in web components.\n"
    },
    {
      "commit": "d140295fa7d794f5b30feb4eee2f45f9cc9ff383",
      "tree": "659e3d00a94eb2aee0da202efaf2e33477c0e895",
      "parents": [
        "37dc4cf04df5dee6feff005d68a4a24e55be8990"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 03:54:37 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 06:40:17 2025 -0700"
      },
      "message": "sketch: Propagate host vs. runtime OS/WorkingDir/Hostname\n\nIf you have a bunch of sketch sessions, you need to know where they were\nlaunched. The container hostnames (some random thing) and working dirs (always /app)\naren\u0027t very helpful, so we want to keep around both. I\u0027ve updated the UI\nto show them as well.\n\nThis commit chooses \"Host\" and \"Runtime\" as the names of the \"Outside\"\nand \"Inside\" sketch. I\u0027m open to suggestions for better names.\n\nCo-Authored-By: sketch, but it did a so-so job\n"
    },
    {
      "commit": "37dc4cf04df5dee6feff005d68a4a24e55be8990",
      "tree": "7c2f8bec8e7041bfffeed6934bf0445114603753",
      "parents": [
        "a4674b16548d6db22acddb80c40e05a5decf919d"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 12:58:52 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed Apr 23 06:00:19 2025 -0700"
      },
      "message": "Enhance commit display in UI\n\nCompletely redesigned the commit display UI to make it more intuitive and useful:\n\n1. Format \u0026 Appearance:\n   - Format commit display as \u0027hash (branch) subject\u0027 matching git log --decorate\n   - Improve spacing and readability of all elements\n   - Add \u0027View Diff\u0027 button directly after the commit subject\n   - Remove extraneous whitespace for a cleaner look\n\n2. Interactive Features:\n   - Make commit hash and branch name directly clickable to copy to clipboard\n   - Show a floating \u0027Copied!\u0027 message when text is copied\n   - Add hover effects to indicate clickable elements\n   - Add tooltips showing full hash and branch name on hover\n\n3. UX Improvements:\n   - Show floating feedback messages instead of modifying content\n   - Animate feedback messages for better visibility\n   - Only underline branch name on hover, not the surrounding parentheses\n   - Use consistent styling for all interactive elements\n\nCo-Authored-By: sketch\n"
    }
  ],
  "next": "a4674b16548d6db22acddb80c40e05a5decf919d"
}
