)]}'
{
  "log": [
    {
      "commit": "d203b7de7d49cc5da03440d5a00b2efd0f8bb2c8",
      "tree": "4c24f0d862338bd9814da00f73d08480b8d02bcb",
      "parents": [
        "b509a5ddb86a4881eb19030f321857b305901022"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:35:30 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 12:50:41 2025 -0700"
      },
      "message": "loop: encourage e2e testing"
    },
    {
      "commit": "b509a5ddb86a4881eb19030f321857b305901022",
      "tree": "84c8d40e7c0545c63e7a8ea56a71fa109e91f028",
      "parents": [
        "7fbc8e43ff52b6f5dc69fdd26ad7388bdac70435"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 15:49:42 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 12:50:41 2025 -0700"
      },
      "message": "loop: ensure proper blank line before git commit trailers\n\nThe prepare-commit-msg hook was incorrectly adding only a single newline\nbefore trailers in some cases, resulting in missing blank lines between\nthe commit message body and trailers like Co-Authored-By and Change-ID.\n\nThis was particularly noticeable after rebasing where commit messages\nwould have:\n- Subject line\n- Single newline (no blank line)\n- Trailers\n\nThe fix improves the logic to:\n- Check if file ends with newline using tail -c 1\n- If no trailing newline: add two newlines (complete line + blank line)\n- If trailing newline exists: check if last line is empty\n- If last line has content: add one newline for blank line\n- If last line is empty: add nothing (blank line already exists)\n\nThis ensures there\u0027s always exactly one blank line before trailers,\nfollowing proper git commit message formatting conventions.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s796b26b31c71b2e2k"
    },
    {
      "commit": "7fbc8e43ff52b6f5dc69fdd26ad7388bdac70435",
      "tree": "abc653d8bf0563f00d232ad91edbed38eb5d4abd",
      "parents": [
        "57893c274ca6d7936580b8bd97af9e5a4b4dcd51"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 19:42:25 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 12:50:41 2025 -0700"
      },
      "message": "browse: set default viewport to 1280x720 (16:9 widescreen)\n\nImprove browser screenshot quality by setting a modern default viewport\nsize during browser initialization. This replaces the previous system-\ndependent default with a consistent 1280x720 resolution that provides:\n\n- Better readability and content coverage in screenshots\n- Modern 16:9 aspect ratio matching typical displays\n- Consistent testing environment across all users\n\nImplementation:\n- Add EmulateViewport call during browser startup in browse.go\n- Set viewport immediately after browser initialization\n- Add comprehensive test (TestDefaultViewportSize) to verify functionality\n\nThe test confirms the viewport is correctly set to 1280x720 on browser\nstartup and validates the JavaScript window dimensions match expectations.\n\nThis addresses screenshot quality issues with small default viewport sizes\nand provides a better default experience for browser automation.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s98815cfd1eaca88dk\n"
    },
    {
      "commit": "57893c274ca6d7936580b8bd97af9e5a4b4dcd51",
      "tree": "bcb821ad46e0197c71979dbefbac597c33f0b9c1",
      "parents": [
        "4d90f34a3acf65e369cddd0f6838e2ec1d23dfcf"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 29 13:49:53 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 29 13:49:53 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "4d90f34a3acf65e369cddd0f6838e2ec1d23dfcf",
      "tree": "01a1b5df4228299a4fac2f95830bd72f9856336c",
      "parents": [
        "d9b1eb4d5342d6be3b4f975463a3831abb581f7f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 02:18:38 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 06:39:30 2025 -0700"
      },
      "message": "webui: add cmd+s keyboard shortcut to Monaco diff editor\n\nAdd Cmd+S (Ctrl+S on Windows/Linux) keyboard shortcut to trigger save\nin Monaco diff editor instead of browser save dialog.\n\nThis prevents people with cmd+s-in-editor habits from constantly\nhaving to dismiss browser save pop-up dialogs.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sd86641652ae6f54ak"
    },
    {
      "commit": "d9b1eb4d5342d6be3b4f975463a3831abb581f7f",
      "tree": "318125d6d8c1081d89f5f8a6a5cc6ed2a48cb633",
      "parents": [
        "9500617d20b037b9ad1f88eb7550068679832a4d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 21:59:54 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 29 06:39:30 2025 -0700"
      },
      "message": "dear_llm.md: more hints about how to take screenshots"
    },
    {
      "commit": "9500617d20b037b9ad1f88eb7550068679832a4d",
      "tree": "15593d668443d3df4f6d223bd753c216f5f0274a",
      "parents": [
        "e89b3080f934a4bc70a0cfa85ffff49ac78d6f2b"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 20:05:46 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed May 28 20:26:29 2025 -0700"
      },
      "message": "dockerimg: fix Chromium support with multi-stage Docker build\n\nOMG, people, OMG. So, an earlier commit moved us to Ubuntu, and it turns\nout that \"apt-get install chromium-browser\" or whatever just does\nnothing, and tells you to use the snap. Snap requires systemd, and if\nyou\u0027re using containers, you don\u0027t usually have systemd, and ... yeah,\nno screenshots. There are no great stories for where to get Chromium.\nThere\u0027s a dude who publishes the Mint Linux packages in a compatible way\nfor Ubuntu. I chose instead the headless-chrome from a Docker build\nrecommended by the Chromedp library that we use to control Chromium.\n\nI\u0027m a bit snappy about all of this.\n\n...\n\nReplace Ubuntu 24 snap-based Chromium installation with chromedp/headless-shell\nto resolve container compatibility issues where snaps don\u0027t work properly.\n\nChanges include:\n\n1. Multi-stage Dockerfile.base build:\n   - Stage 1: Extract headless-shell from docker.io/chromedp/headless-shell:stable\n   - Stage 2: Main Ubuntu 24.04 application image with required Chrome dependencies\n   - Remove chromium package from apt-get install (replaced with headless-shell)\n   - Add required libraries: libglib2.0-0, libnss3, libx11-6, libxcomposite1,\n     libxdamage1, libxext6, libxi6, libxrandr2, libgbm1, libgtk-3-0\n   - Add headless-shell to PATH so chromedp can find it automatically\n\n2. Updated documentation in browse/README.md:\n   - Document Docker multi-stage build approach\n   - Clarify requirements for Docker vs local development\n\nBenefits:\n- Resolves Ubuntu 24 snap incompatibility issues in containers\n- Provides self-contained Chrome installation without system dependencies\n- Maintains backward compatibility for local development\n- Uses proven chromedp/headless-shell for reliable browser automation\n- Eliminates need for manual Chrome/Chromium installation in containers\n- No code changes needed in browse.go - chromedp finds headless-shell via PATH\n\nThe headless-shell binary is automatically discovered by chromedp\u0027s default\nexecutable search since it\u0027s added to PATH in the Docker environment.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: se4808dca7afba802k\n"
    },
    {
      "commit": "e89b3080f934a4bc70a0cfa85ffff49ac78d6f2b",
      "tree": "f3bcf44b2907c5c18f555b31df923488bb5efdc7",
      "parents": [
        "7ad1c7a4b759f4ba110d092a0fbbed0b95fc80a9"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 29 03:16:06 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 29 03:20:15 2025 +0000"
      },
      "message": "webui: comprehensive diff view improvements\n\nImplement multiple enhancements to the diff view interface for better\nusability and visual consistency with file change statistics and\nimproved navigation controls.\n\nBackend Changes:\n1. Enhanced git diff endpoint with --numstat support:\n   - Modified GitRawDiff to execute both --raw and --numstat commands\n   - Added Additions/Deletions fields to DiffFile struct\n   - Parse numstat output to show line change statistics (+X, -Y)\n   - Handle binary files and edge cases properly\n\nFrontend UI Improvements:\n2. File picker enhancements:\n   - Display (+X, -Y) change indicators next to file names\n   - Move file position indicator (\"X of Y\") between navigation buttons\n   - Simplified file info to show only status (Modified/Added/Deleted)\n   - Better visual grouping of navigation-related information\n\n3. Commit range picker refresh functionality:\n   - Added refresh button with subtle styling (gray background)\n   - 🔄 icon with \"Refresh commit list\" tooltip\n   - Reloads git log to get updated branch and commit information\n   - Proper disabled state during loading operations\n\n4. Editable file indicator improvements:\n   - Moved \"Editable\" indicator to Monaco editor save indicator area\n   - Shows \"Editable\" when file is editable but unchanged\n   - Consistent styling with \"Modified\", \"Saving\", \"Saved\" states\n   - Added proper CSS styling with gray background for idle state\n\n5. Expand/collapse button redesign:\n   - Custom SVG icons replacing text buttons\n   - Expand All: dotted line with arrows pointing away (outward)\n   - Collapse: dotted line with arrows pointing inward (toward line)\n   - Intuitive visual metaphor for show/hide functionality\n   - Enhanced tooltips with full action descriptions\n   - Renamed \"Hide Unchanged\" to \"Collapse Expanded Lines\"\n\nTechnical Improvements:\n6. TypeScript compatibility fixes:\n   - Updated mock data service with new DiffFile fields\n   - Fixed MSW handler type compatibility with proper type assertion\n   - Maintained full TypeScript checking without exclusions\n   - Added realistic mock data for testing change indicators\n\nInterface Consistency:\n- All buttons use consistent styling and hover effects\n- Better separation between navigation controls and file information\n- Improved logical grouping of related UI elements\n- Enhanced accessibility with descriptive tooltips\n\nThese changes significantly improve the diff view experience by providing\nclear visual indicators of file changes, intuitive navigation controls,\nand better organization of interface elements according to their function.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nChange-ID: s738289d132773bc3k\n"
    },
    {
      "commit": "7ad1c7a4b759f4ba110d092a0fbbed0b95fc80a9",
      "tree": "a8d2543ec9c660b69289a2233442208d29ba29b2",
      "parents": [
        "444f7f00ff439e79b65cf3d2efd4ad66a698af2c"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 29 02:00:19 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 29 02:00:19 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "444f7f00ff439e79b65cf3d2efd4ad66a698af2c",
      "tree": "7271aaf5cbf3ba074b732c3d264bd47082fa9d2a",
      "parents": [
        "b34b8b307e8d804b6ea3f2596388708839f30e58"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 21:16:55 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:59:10 2025 -0700"
      },
      "message": "webui: expand Monaco comment selections to full lines for better context\n\nEnhances the Monaco diff editor comment functionality to automatically\nexpand any text selection to include complete lines, providing better\ncontext for LLM analysis and code review discussions.\n\nChanges include:\n\n1. Modified handleSelectionChange method in sketch-monaco-view.ts:\n   - Automatically expands selection start to column 1 (beginning of line)\n   - Expands selection end to the maximum column of the end line\n   - Updates both selectedText and selectionRange to reflect full lines\n   - Maintains existing line number calculation for comment headers\n\n2. Enhanced selection behavior:\n   - Partial line selections now include the entire line(s)\n   - Multi-line partial selections expand to include complete first and last lines\n   - Already full-line selections remain unchanged\n   - Preserves line number information for accurate comment context\n\nThe expansion logic uses Monaco\u0027s getLineMaxColumn() method to determine\nproper line boundaries and getValueInRange() to extract the complete\ntext. This ensures that comments always include meaningful, complete\ncode segments rather than partial fragments.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s7a8b9c2d3e4f5g6k\n"
    },
    {
      "commit": "b34b8b307e8d804b6ea3f2596388708839f30e58",
      "tree": "d11dfa24942aae9784b18cfa0a3e47758ffb57f5",
      "parents": [
        "efa8f436182a310f7c5eaaf0f9f4787ba4fd3693"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 21:00:56 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:58:56 2025 -0700"
      },
      "message": "webui: add line numbers to Monaco diff view comment auto-inserted text\n\nEnhances the Monaco diff editor comment functionality to include line\nnumbers in the auto-inserted context text when users add comments to\nselected code. The comments now show specific line information along\nwith the filename and editor type.\n\nChanges include:\n\n1. Modified sketch-monaco-view.ts submitComment method:\n   - Added line number calculation logic using this.selectionRange\n   - Single line selections show \u0027(line N)\u0027 format\n   - Multi-line selections show \u0027(lines N-M)\u0027 format\n   - No line info added when selectionRange is unavailable\n   - Line info is appended to the existing fileContext and editorLabel\n\n2. Enhanced comment format from:\n   \u0027filename [Modified]:\u0027\n   to:\n   \u0027filename [Modified] (line 42):\u0027\n   or:\n   \u0027filename [Modified] (lines 10-15):\u0027\n\n3. Line number extraction uses Monaco\u0027s selection tracking:\n   - Leverages existing selectionRange state from handleSelectionChange\n   - Works for both original and modified editors in diff view\n   - Maintains backwards compatibility when selectionRange is null\n\nThe auto-inserted comment text now provides precise line context,\nmaking comments more useful for code review and collaboration by\nclearly indicating which specific lines are being referenced.\nThis addresses the issue where comments lacked line number context,\nmaking it difficult to locate the referenced code.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s2b4c8f9a1e6d7e3k\n"
    },
    {
      "commit": "efa8f436182a310f7c5eaaf0f9f4787ba4fd3693",
      "tree": "9fb7306edcfb68ebe9af2519784040ce25e16665",
      "parents": [
        "90993a0d42e84be835ebf2096687a299d461cfeb"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:04:41 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:58:46 2025 -0700"
      },
      "message": "claudetool: strengthen the \"no trailers\" commit message guidance\n\nShould prevent duplicate trailers.\n"
    },
    {
      "commit": "90993a0d42e84be835ebf2096687a299d461cfeb",
      "tree": "97578882ad4cb95eec131fea74c4f37eeac36420",
      "parents": [
        "7027307b381e2b8421c95ebb2f872b8e3c567f3e"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:15:15 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:58:28 2025 -0700"
      },
      "message": "loop: install hooks relative to repo root, not working dir\n\nAn evergreen git bug.\n\nFixes missing hooks when started from a subdirectory.\n"
    },
    {
      "commit": "7027307b381e2b8421c95ebb2f872b8e3c567f3e",
      "tree": "7f9027f4ba1f57b305ebfba47d3b0d920093de95",
      "parents": [
        "837699bf55d27975e9e5b881b8794683bb1b10c8"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 18:26:14 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Wed May 28 22:47:10 2025 +0000"
      },
      "message": "webui: replace hardcoded Monaco language map with dynamic detection\n\nReplace the static language mapping in the Monaco diff editor with\nMonaco\u0027s built-in language registry for automatic language detection.\n\nChanges:\n1. Remove hardcoded langMap that only supported 8 languages (js, ts, py,\n   html, css, json, md, go)\n2. Implement dynamic language detection using monaco.languages.getLanguages()\n3. Cache language list for performance since it doesn\u0027t change at runtime\n4. Maintain exact extension matching including the dot prefix (.js, .ts, etc.)\n5. Preserve fallback to \u0027plaintext\u0027 for unknown extensions\n\nBenefits:\n- Automatically supports all languages Monaco knows about (40+ languages)\n- No maintenance burden when Monaco adds new language support\n- Removes duplication between Monaco\u0027s registry and our hardcoded map\n- Better future-proofing as Monaco language support evolves\n\nThe implementation uses Monaco\u0027s ILanguageExtensionPoint interface which\nprovides language.extensions arrays for each registered language. This\nis more reliable than maintaining our own mapping and ensures consistency\nwith Monaco\u0027s actual language support.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nChange-ID: sca31f0ae899ae54dk\n"
    },
    {
      "commit": "837699bf55d27975e9e5b881b8794683bb1b10c8",
      "tree": "3aa7377ad7d441e10bfd0cf5e5f73a82de198764",
      "parents": [
        "c5848f3cb9753e94feddc04b8910b4ff113a458c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:58:17 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 12:01:29 2025 -0700"
      },
      "message": "github: fix Discord notification to handle multiple commits in queue push\n\nPreviously, commit queue pushes only notified about the final commit\ninstead of all commits being pushed to main. We now properly detect and\nnotify about all commits in a queue push in chronological order.\n\nChanges include:\n\n1. Enhanced push step in queue-main.yml and queue-dev.yml:\n   - Capture range of commits being pushed using git log origin/main..COMMIT_TO_PUSH\n   - Use --reverse flag to get commits in chronological order (oldest first)\n   - Store commit list in GITHUB_OUTPUT for notification step\n\n2. Updated Discord notification steps:\n   - Iterate through all commits in the push (not just the final one)\n   - Checkout each commit individually before calling discord_notify.py\n   - Send separate notification for each commit in correct chronological order\n\n3. Proper edge case handling:\n   - Single commit pushes: Works correctly (sends one notification)\n   - Empty pushes: Skips notification when no commits to notify about\n   - Formatted commits: Includes both original and formatting commits\n\nThe fix ensures that when developers push multiple commits to a queue branch\n(e.g., queue-main-username), Discord notifications are sent for each commit\nthat gets pushed to main, not just the latest one. Notifications appear in\nchronological order matching the actual commit sequence.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nChange-ID: s6a336eb2f945539fk"
    },
    {
      "commit": "c5848f3cb9753e94feddc04b8910b4ff113a458c",
      "tree": "8b3eb330c645e4f020a9ef7f10e78491474ec8ab",
      "parents": [
        "6e4636006501be61b940388381cd75a8ad00e6b5"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:50:58 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 12:01:29 2025 -0700"
      },
      "message": "loop: use repo root instead of working directory for git diff support\n\nChange all git HTTP endpoints to use RepoRoot() instead of WorkingDir()\nto resolve failures when sketch is started from different directories than\nwhere the Docker container was created.\n\nThe issue occurred because:\n- WorkingDir() returns current working directory (could be /app/subdir)\n- Git tools need repository root directory (/app) for relative file paths\n- When Docker sets working directory to subdirectory, git operations fail\n\nChanges include:\n\n1. Added RepoRoot() method to Agent and CodingAgent interface:\n   - Returns a.repoRoot (the git repository root directory)\n   - Complements existing WorkingDir() method\n\n2. Updated all git HTTP endpoints to use RepoRoot():\n   - handleGitCat: fixes GitCat file access from subdirectories\n   - handleGitRawDiff: ensures diff operations work correctly\n   - handleGitShow: ensures show operations work correctly\n   - handleGitSave: ensures file saving works correctly\n   - handleGitRecentLog: ensures log operations work correctly\n\nThe fix ensures git ls-files and other git operations work reliably\nregardless of which directory sketch was started from, resolving the\nreported GitCat directory issue where files couldn\u0027t be found when\nstarting sketch from different locations.\n\nTesting confirmed GitCat now works correctly when repository root is\nused instead of working directory, and git operations succeed from\nany starting directory.\n\nFixes #119\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sb73dac311df0c78dk"
    },
    {
      "commit": "6e4636006501be61b940388381cd75a8ad00e6b5",
      "tree": "39363c1c47111cbaf66eecd6b6e0274edbfa7b5c",
      "parents": [
        "77bac8c26324bad3c4b903a5321a2b0a078881ba"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 18:10:59 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 11:33:56 2025 -0700"
      },
      "message": "github: add Discord notification to commit queue workflow\n\nThe Discord notification workflow was not triggering when commits were\npushed to main via the commit queue because GitHub Actions doesn\u0027t\ntrigger workflows when pushes are made using GITHUB_TOKEN (security\nfeature).\n\nThis fix adds Discord notification directly to the queue-main.yml\nworkflow after successful push to main, ensuring notifications are sent\nfor both direct pushes and commit queue pushes.\n\nChanges:\n- Add commit SHA capture in push step to track which commit was pushed\n- Add checkout step to ensure correct commit is available for git commands\n- Add Discord notification step using existing .github/scripts/discord_notify.py\n- Configure proper environment variables (DISCORD_WEBHOOK_FOR_COMMITS, GITHUB_SHA)\n\nThe existing discord-notify.yml workflow continues to work for direct\npushes to main, providing dual coverage for all scenarios.\n\nTested Discord notification script in test mode - generates proper embed\nwith commit message, author, and GitHub link.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nChange-ID: s94d86820e52726b5k\n"
    },
    {
      "commit": "77bac8c26324bad3c4b903a5321a2b0a078881ba",
      "tree": "56fae11aa90aa418eca2c72bee7d4b0510f6160f",
      "parents": [
        "d85e97d97d2e88415bf1a87557278afd14f6d202"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 11:04:09 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 11:33:56 2025 -0700"
      },
      "message": "webui: make diff loading error message more useful\n"
    },
    {
      "commit": "d85e97d97d2e88415bf1a87557278afd14f6d202",
      "tree": "88e36c41930314fc74901b9de9794ad8ac49c2ba",
      "parents": [
        "a442ce32ac95d7e8337fba0a82f94cbd60be1296"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 17:59:08 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 11:17:24 2025 -0700"
      },
      "message": "webui: remove unused language property from Monaco editor\n\nRemove dead code - the language property was never set when the component\nis used, so it always defaulted to \u0027javascript\u0027 and was never meaningful.\n\nThe getLanguageForFile method now uses a simpler fallback:\nlangMap[extension] || \u0027plaintext\u0027\n\nSince filenames always have extensions in practice, this removes an\nunnecessary intermediate fallback that was never actually used.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s16c137c6267b58a5k\n"
    },
    {
      "commit": "a442ce32ac95d7e8337fba0a82f94cbd60be1296",
      "tree": "03207a7855e0db3afe0baa13f8e13f9d693d0974",
      "parents": [
        "574eda8d743b07cb0e0e11540d4f1b7db7eeb68c"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 02:48:26 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Wed May 28 10:54:50 2025 -0700"
      },
      "message": "dockerimg: change base container image to ubuntu 24.04 with go 1.24.3\n\nChanges the base Docker image from golang:1.24-bookworm (Debian 12) to\nubuntu:24.04 (Noble Numbat - current LTS) and installs Go 1.24.3 manually.\n\nChanges include:\n\n1. Updated FROM ubuntu:24.04 to use current Ubuntu LTS instead of Debian\n2. Added ca-certificates and wget for Go downloads\n3. Manual Go 1.24.3 installation from official golang.org tarball\n4. Proper GOROOT, GOPATH, and PATH environment setup\n5. Created GOPATH directory structure\n\nThis provides a cleaner foundation based on the current Ubuntu LTS\nwhile maintaining full Go development capabilities. The manual Go\ninstallation gives more control over the exact Go version used and\neliminates dependency on the golang base image layers.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s0bc05e04441c24a6k\n"
    },
    {
      "commit": "574eda8d743b07cb0e0e11540d4f1b7db7eeb68c",
      "tree": "8bb3cfafc2bca4c11c4deca4ea5f92e1af16282a",
      "parents": [
        "fa306776f93d607b88d4472f06ea788f69507945"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 10:30:43 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 10:36:09 2025 -0700"
      },
      "message": "skabandclient: fix typos"
    },
    {
      "commit": "fa306776f93d607b88d4472f06ea788f69507945",
      "tree": "ab2cb9324ed5dda09b2d6276779bedf922e759cd",
      "parents": [
        "217e987e1c8d16907849e1f8ba7e5dd8ad4af052"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 09:37:04 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 10:36:09 2025 -0700"
      },
      "message": ".github/scripts: include commit body, cut pointless title, repo"
    },
    {
      "commit": "217e987e1c8d16907849e1f8ba7e5dd8ad4af052",
      "tree": "65e06a1dedfccabd81e28a9585adce6d210a38ea",
      "parents": [
        "f178755c781c74ef242762ceb2c707c9a4dd2676"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 09:26:05 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 28 10:36:09 2025 -0700"
      },
      "message": "Revert \"webui: fix diff view failing when added file doesn\u0027t exist in working directory\"\n\nThis reverts commit 4c7865b4763552f4294e7a3738b796ea918a7c3d.\n\nThe real problem appears to be a race of some kind.\nThis is not the fix.\n"
    },
    {
      "commit": "f178755c781c74ef242762ceb2c707c9a4dd2676",
      "tree": "5a4dae9bd281ae0ff138cfb72a6883633bac2b22",
      "parents": [
        "a9948c03ce510e5f7aa08c266c9a7b11f817b958"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 02:44:39 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 28 02:44:39 2025 +0000"
      },
      "message": "github: fix Discord webhook notification User-Agent rejection\n\nThe Discord webhook was failing with 403 Forbidden (error code 1010)\nwhen sending notifications because Discord was rejecting requests from\nPython\u0027s default urllib User-Agent header.\n\nThe issue was that urllib.request.Request was using Python\u0027s default\nUser-Agent which Discord treats as suspicious or automated traffic.\nWhile simple curl requests worked fine, the Python script consistently\nfailed with \u0027Webhook not found\u0027 errors.\n\nFix:\n- Add explicit User-Agent header \u0027sketch.dev developers\u0027 to HTTP request\n- This allows Discord to properly identify the request as a legitimate webhook client\n\nTesting confirmed the fix:\n- Before: 403 Forbidden with error code 1010\n- After: 204 No Content (successful webhook delivery)\n\nThe Discord embed payload structure was already correct - only the\nUser-Agent header was causing the rejection.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\n\nChange-ID: sc716013db28856a0k\n"
    },
    {
      "commit": "a9948c03ce510e5f7aa08c266c9a7b11f817b958",
      "tree": "1990e647ef8261d8d4cafa1f835db1f961d3fc39",
      "parents": [
        "a09d6389c9c1baf859ab4bcd03fe93aa7f52258d"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 19:29:47 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 19:29:47 2025 -0700"
      },
      "message": "Remove CI\u003d1 requirement for discord_notify.\n"
    },
    {
      "commit": "a09d6389c9c1baf859ab4bcd03fe93aa7f52258d",
      "tree": "e9057a65d258f624725691a28654282b2dae9748",
      "parents": [
        "9e3c867ad3ae20dd6d6261d4242b802c993939e3"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 19:28:29 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 19:28:29 2025 -0700"
      },
      "message": "empty commit for testing\n"
    },
    {
      "commit": "9e3c867ad3ae20dd6d6261d4242b802c993939e3",
      "tree": "e9057a65d258f624725691a28654282b2dae9748",
      "parents": [
        "3d2eff03a428424a31173b0f30f3d647a570b455"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 17:09:14 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 18:13:33 2025 -0700"
      },
      "message": "github: add Discord webhook notification for main branch commits\n\nCreates a GitHub Actions workflow that sends Discord notifications when\ncommits are pushed to the main branch. The implementation prioritizes\nclean separation between workflow orchestration and notification logic.\n\nArchitecture:\n- .github/workflows/discord-notify.yml: Minimal workflow with single\n  Python script execution\n- .github/scripts/discord_notify.py: Self-contained script handling all\n  commit extraction, JSON generation, and webhook delivery\n\nFeatures:\n- Triggers only on pushes to main branch\n- Extracts commit information using git subprocess calls\n- Generates Discord embed with commit message, author, SHA, and link\n- Safe JSON serialization handles quotes, newlines, and special characters\n- Robust environment validation (requires CI\u003d1 and GITHUB_SHA)\n- Proper HTTP error handling with status code checking\n\nThe webhook sends rich embeds to Discord with commit details including\nclickable commit links and properly formatted timestamps. All shell\nscripting is avoided in the YAML file - the workflow simply executes\nthe Python script which handles everything else.\n\nWebhook URL points to the provided Discord channel endpoint.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s82b63953ab6ceccbk\n"
    },
    {
      "commit": "3d2eff03a428424a31173b0f30f3d647a570b455",
      "tree": "ac703dc76e758d99604bc5cc9514bbf2daaf96cd",
      "parents": [
        "ab6a811066a89a1e499253a7f854e6dd0a777ce5"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 09:30:31 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 27 09:30:31 2025 -0700"
      },
      "message": "sketch: avoid using tty when termui is false.\n\nWhen using with -termui\u003dfalse -verbose, the terminal does weird shit,\nand there\u0027s a ladder effect. It\u0027s because a tty is being allocated\nsomehow. We don\u0027t need a tty unless we\u0027re using termui, so tightening up\nthe if/else on when we pass \"-t\" to Docker.\n\nThe logic here is detailed, so apologies if I got it wrong.\n"
    },
    {
      "commit": "ab6a811066a89a1e499253a7f854e6dd0a777ce5",
      "tree": "c7ad7a41b2cb9518b3460a1e9b4e8252b48942df",
      "parents": [
        "83b2d35b61eb68c0d633a10c2f5b7c0905e584df"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:22:00 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:28:01 2025 -0700"
      },
      "message": "all: update tests for claude 4"
    },
    {
      "commit": "83b2d35b61eb68c0d633a10c2f5b7c0905e584df",
      "tree": "b29314fe23190123cc4e24d2327a237de7ebf096",
      "parents": [
        "3b733a5e21229c1ff29389895bb587c0243d6ba7"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:39:50 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:07:43 2025 -0700"
      },
      "message": "claudetool/codereview: expand on when to commit vs revert"
    },
    {
      "commit": "3b733a5e21229c1ff29389895bb587c0243d6ba7",
      "tree": "b7b600054987919fe0194a5f8d09f47d65e617d1",
      "parents": [
        "586ecb184b4466435507d9935e4240630e80f482"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 12:32:38 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:07:43 2025 -0700"
      },
      "message": "loop: add some coding guidelines\n\nThis should help tamp down wild comments.\n"
    },
    {
      "commit": "586ecb184b4466435507d9935e4240630e80f482",
      "tree": "4e49af79c8fe7df45567507c642dd31fe015ae8b",
      "parents": [
        "0efb29db25ff141e6463b40675defc423a42379c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 22 21:04:33 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:06:12 2025 -0700"
      },
      "message": "claudetool: fix sha command formatting"
    },
    {
      "commit": "0efb29db25ff141e6463b40675defc423a42379c",
      "tree": "19472c6271558f22e3b2ebd339f9e0e587f55009",
      "parents": [
        "78e7cf986aa461b62a923f6f5175ab94a12e2536"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 22 21:05:04 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:06:12 2025 -0700"
      },
      "message": "llm/ant: switch default to Claude 4 sonnet"
    },
    {
      "commit": "78e7cf986aa461b62a923f6f5175ab94a12e2536",
      "tree": "e01e7b04262ec71ae290ca77eb883f69acf1b3af",
      "parents": [
        "dbfd36a4149c03a501be12aacfecdbe237c7b7bf"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 14:33:34 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Sat May 24 12:06:12 2025 -0700"
      },
      "message": "dear_llm.md: help prevent industrial accidents"
    },
    {
      "commit": "dbfd36a4149c03a501be12aacfecdbe237c7b7bf",
      "tree": "c8928ebe5568b7c5330f9211538ab8139832652f",
      "parents": [
        "afeafea91f20db4e5b99620df98baa1628bfeaf1"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 20:57:50 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 14:25:55 2025 -0700"
      },
      "message": "claudetool/bashkit: add validation to reject blind git add commands\n\nImplements new validation function to prevent bash commands that blindly\nadd all files to git commits, requiring agents to specify files explicitly.\n\nChanges include:\n\n1. New noBlindGitAdd validation function that rejects:\n   - git add -A (add all)\n   - git add --all (add all)\n   - git add . (add current directory)\n   - git add * (add all files via glob)\n\n2. Enhanced hasBlindGitAdd helper function:\n   - Parses git command structure using existing AST approach\n   - Finds \u0027add\u0027 subcommand and checks subsequent arguments\n   - Handles git flags before \u0027add\u0027 subcommand correctly\n   - Allows legitimate specific file additions like \u0027git add main.go\u0027\n\n3. Comprehensive test coverage for all blind add patterns:\n   - Tests rejection of all blind patterns including flags combinations\n   - Tests acceptance of specific file additions and valid use cases\n   - Tests multiline scripts and edge cases like filenames that look\n     like flags (e.g., \u0027file.A\u0027)\n\n4. Integration with existing validation framework:\n   - Added noBlindGitAdd to the checks slice alongside existing\n     noGitConfigUsernameEmailChanges validation\n   - Uses same error reporting pattern and AST parsing infrastructure\n\nThis prevents agents from accidentally committing unintended files or\nbuild artifacts by forcing explicit file specification in git add\ncommands. The validation maintains the existing pattern of being\nmistake-prevention rather than security-focused.\n\nError message provides clear guidance: \u0027blind git add commands (git add -A,\ngit add ., git add --all, git add *) are not allowed, specify files explicitly\u0027\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s4d8fe71ef5816b36k\n"
    },
    {
      "commit": "afeafea91f20db4e5b99620df98baa1628bfeaf1",
      "tree": "7ba3f14d663cbc73bf78f8986bb5d3afe332e7b2",
      "parents": [
        "4c7865b4763552f4294e7a3738b796ea918a7c3d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 20:27:39 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 14:25:55 2025 -0700"
      },
      "message": "webui: change Monaco editor comment submit button from Submit to Add\n\nUpdates the Monaco editor\u0027s comment submission button text from \u0027Submit\u0027\nto \u0027Add\u0027 for better consistency with the UI and more concise labeling.\n\nThe button functionality remains unchanged - it still submits comments\non selected code sections in the Monaco editor view.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: seca3827c274ff3cdk\n"
    },
    {
      "commit": "4c7865b4763552f4294e7a3738b796ea918a7c3d",
      "tree": "7e26038aaf5393a2df9d5b945a6840555e7a661d",
      "parents": [
        "ed17fdf0b3ea6c0b8a8f96125ccc785c5587bb9c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 17:26:34 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 13:51:38 2025 -0700"
      },
      "message": "webui: fix diff view failing when added file doesn\u0027t exist in working directory\n\nWhen viewing uncommitted changes in the diff view and there\u0027s a file that\nwas added in the latest commit but doesn\u0027t exist in the current working\ndirectory, the code was trying to fetch the working copy content and\nfailing with \u0027Failed to fetch working copy content\u0027.\n\nThis adds fallback logic for added files (status \u0027A\u0027) to use the\ncommitted content from git when the working copy cannot be retrieved,\nsimilar to how deleted files are already handled.\n\nThe fix changes the error handling in loadFileContent() to:\n- Check if file status is \u0027A\u0027 (added) and has a new_hash\n- Fall back to using gitService.getFileContent(file.new_hash) instead\n  of failing completely\n- Log a warning but continue gracefully\n\nThis ensures the diff view works correctly when showing ranges ending\nin \u0027uncommitted changes\u0027 even with files that were added but later\nremoved from the working directory.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s73a6d30e7af97e82k\n"
    },
    {
      "commit": "ed17fdf0b3ea6c0b8a8f96125ccc785c5587bb9c",
      "tree": "d6463e625085f73143798b50c9fb2eb30b9c04ab",
      "parents": [
        "160fb06bb7c8df956daecd4d3bdb3f94d8a93406"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 17:26:07 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:46:11 2025 -0700"
      },
      "message": "loop: fix data race in Agent.CurrentStateName()\n\nThe CurrentStateName() method was directly accessing the stateMachine\u0027s\ncurrentState field without proper synchronization, causing data races\nwith TransitionWithEvent() which writes to the same field while holding\na write lock.\n\nThe StateMachine struct already provides a thread-safe CurrentState()\nmethod that properly acquires a read lock before accessing currentState.\n\nThis fix changes CurrentStateName() from:\n  return a.stateMachine.currentState.String()\nto:\n  return a.stateMachine.CurrentState().String()\n\nThis eliminates the race condition between HTTP handler goroutines\nreading state for SSE streams and the agent loop goroutine writing\nstate during transitions.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sadf9961b9f084fa7\n"
    },
    {
      "commit": "160fb06bb7c8df956daecd4d3bdb3f94d8a93406",
      "tree": "9456f5a0df9eb51180d189d87f8d52016ccb5f40",
      "parents": [
        "0e8073a19a88ef5e7a03acc8b5f924bfda0afdd5"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 22 21:04:22 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:30:35 2025 -0700"
      },
      "message": "claudetool: improve error message when all search terms match too much"
    },
    {
      "commit": "0e8073a19a88ef5e7a03acc8b5f924bfda0afdd5",
      "tree": "e5511fc6781ee80ec5f8c257e6a9a16446b27ab9",
      "parents": [
        "3e6a4c4abe8714ebb04c0d4834bcc7230f4d4a03"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 22 21:04:51 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:30:33 2025 -0700"
      },
      "message": "llm/ant: add Claude 4 sonnet/opus\n\nNot set as default yet.\nThere\u0027s a bit of prompt engineering work\nto do before we flip the switch."
    },
    {
      "commit": "3e6a4c4abe8714ebb04c0d4834bcc7230f4d4a03",
      "tree": "cf5b7dc0ed2ac2c55a949962d19416bae8553809",
      "parents": [
        "f4f929a48d358acb206a6cbc91dfdee813c45aed"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 17:29:57 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:30:07 2025 -0700"
      },
      "message": "dockerimg: mount Go caches for faster Docker race builds\n\nWhen building sketch binary with race detector in Docker, the system\nwas downloading all modules and rebuilding from scratch every time,\nmaking repeated builds slow and inefficient.\n\nThis adds host Go cache mounting to buildLinuxSketchBinWithDocker by:\n- Getting host GOCACHE and GOMODCACHE directories using \u0027go env\u0027\n- Mounting them as volumes in the Docker container:\n  -v $GOCACHE:/root/.cache/go-build\n  -v $GOMODCACHE:/go/pkg/mod\n\nThe optimization ensures:\n- First race build: Downloads modules (same time as before)\n- Subsequent race builds: Reuses cached modules (much faster)\n- Build artifacts persist between Docker container runs\n\nAdds helper functions getHostGoCacheDir() and getHostGoModCacheDir()\nto retrieve cache paths from the host environment, with proper error\nhandling and path validation.\n\nIncludes unit test to verify cache directory detection works correctly\non all platforms where Go is installed.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sd279e56e1574e4e1k\n"
    },
    {
      "commit": "f4f929a48d358acb206a6cbc91dfdee813c45aed",
      "tree": "8f078c859c7f2b3bca003e39faf6cfeb46001147",
      "parents": [
        "3b5646ff27d0e644396524b8ca2c9a4c5891726c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 17:19:26 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 11:30:07 2025 -0700"
      },
      "message": "dockerimg: fix VCS stamping error when building with race detector\n\nWhen building the sketch binary with race detector enabled in Docker,\nGo\u0027s VCS stamping feature was failing with \u0027error obtaining VCS status:\nexit status 128\u0027 because it couldn\u0027t properly determine the Git status\nin the mounted repository (especially in detached HEAD states).\n\nThis adds -buildvcs\u003dfalse to the Docker build command to disable VCS\nstamping when building with the race detector, which avoids the error\nwhile still enabling race detection functionality.\n\nThe fix changes the Docker build command from:\n  go build -race -o /tmp/sketch-out/sketch sketch.dev/cmd/sketch\nto:\n  go build -buildvcs\u003dfalse -race -o /tmp/sketch-out/sketch sketch.dev/cmd/sketch\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sb8b2e8656c0802f6k\n"
    },
    {
      "commit": "3b5646ff27d0e644396524b8ca2c9a4c5891726c",
      "tree": "2fea328279fa22fedef6b570af10c4bb45aaaf7e",
      "parents": [
        "12989b0cf7cb542f1286d53c3dce86ae1d56773b"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 16:47:53 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 23 10:06:40 2025 -0700"
      },
      "message": "llm/ant: prevent httprr cache misses from being retried\n\nPackage ant treated httprr\u0027s \u0027cached HTTP response not found\u0027 errors as\nretryable network errors, causing 30+ second delays and test\ntimeouts when httprr couldn\u0027t find matching requests.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s81a2a9035286ab41k"
    },
    {
      "commit": "12989b0cf7cb542f1286d53c3dce86ae1d56773b",
      "tree": "70b7cde65a4378b532c498725099a8a6380d74e6",
      "parents": [
        "4acf00626f50c342dc35f8525732074cf10e4d1a"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Fri May 23 11:27:47 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Fri May 23 11:27:47 2025 +0100"
      },
      "message": "fix: read API key from environment in host mode when not using skaband\n\nWhen running sketch in the default container mode with -skaband-addr\u003d,\nthe system was failing with \u0027x-api-key header is required\u0027 because the\nrunInHostMode function wasn\u0027t reading the ANTHROPIC_API_KEY environment\nvariable when skaband wasn\u0027t being used.\n\nThis change adds the missing logic to read the API key from environment\nvariables (ANTHROPIC_API_KEY for claude, or GEMINI_API_KEY for gemini)\nwhen skabandAddr is empty, matching the behavior in runInUnsafeMode.\n\nThe fix ensures that commands like:\nenvdir /path/to/env go run ./cmd/sketch -skaband-addr\u003d -prompt \u0027task\u0027\nnow work correctly by passing the API key to the Docker container\u0027s\ndockerfile creation process.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s592f0c893cafc931k\n"
    },
    {
      "commit": "4acf00626f50c342dc35f8525732074cf10e4d1a",
      "tree": "4096c36933030c1c238098a7cb2214adc86421c4",
      "parents": [
        "9bca61ef623ea8cd72a906752be73af572af02a9"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 13:53:46 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 13:53:46 2025 -0700"
      },
      "message": "dockerimg: Add race detector support to sketch binary build\n\nRun this with:\n\n\tgo run -race ./cmd/sketch -C $(pwd) -verbose -termui\u003dfalse\n\n-race requires CGO which makes cross compilation miserable, so, we punt,\nand we use the container to do it.\n\nThe big TODO is that there\u0027s no go caching, so it\u0027s kinda slower than it\nneeds to be. This is probably fixable with a docker volume.\n\nWhen the host binary is built with the race detector enabled (-race flag),\nthe inner sketch binary that runs in Docker will also be built with the race\ndetector. This helps with debugging race conditions in the inner binary.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s822ae1a915dcc857k\n"
    },
    {
      "commit": "9bca61ef623ea8cd72a906752be73af572af02a9",
      "tree": "4d6488b6e6e8543c3f0b5e1682d11e0927c27d1b",
      "parents": [
        "75bd37d2a3067b6f431d56e891064b73dc2def2c"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 12:40:06 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 12:44:59 2025 -0700"
      },
      "message": "feat: enhance UI with commit pulsing animation and improved copy icon\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s80fdaac660ea645ek\n"
    },
    {
      "commit": "75bd37d2a3067b6f431d56e891064b73dc2def2c",
      "tree": "69580944c24bd99c5286ae0611cf2998a3b85035",
      "parents": [
        "8c3b53a97ae2a204842c0c86ca859947ce20b1dd"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 18:49:14 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 12:40:44 2025 -0700"
      },
      "message": "loop: auto-commit changes when saving in diff view\n\nWhat I\u0027ve done is create a git commit whenever the user edits things,\nand amend if possible. The existing detection logic pushes the commits\nto the host, BUT, I had to do some plumbing to make that happen. The\nagent state machine would be out of sorts if I did this (since we\u0027re\ndoing things outside of the loop), but, I didn\u0027t tell it, so... it\u0027s ok!\n\nIf the user has the agent running when editing, everyone can get\nconfused. There\u0027s no atomicity for the git operations, etc.\nI suspect in practice this will all be as fine as everything else is.\n\nI\u0027m not running the autoformatters. That\u0027s a weird editing experience.\n\nThe alternative was to do what the diff comments does, and let the agent\ndeal with the changes by sending it a message. I chose not to do that:\nfirst of all, I want the push to happen fast, since I don\u0027t like losing\nuser data. Second, the latency on an operation is distracting sometimes,\nand sometimes what I do next is just cherrypick my changes over, and I\u0027m\nnot interested in the pedantry of the agent and the code formatters and\nso forth. If they were faster, maybe.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sec50af415124810bk\n"
    },
    {
      "commit": "8c3b53a97ae2a204842c0c86ca859947ce20b1dd",
      "tree": "6532221877cdcb1bd572144fcc5926cfd4231ecb",
      "parents": [
        "456d5f9d4213deab28a1f528cb8edc3a1f8d5262"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 22 18:30:58 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 22 18:30:58 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "456d5f9d4213deab28a1f528cb8edc3a1f8d5262",
      "tree": "5529284acc56079240e1f2780c210f4431d9ea32",
      "parents": [
        "14fe75d6ece5116b3887b6fc027e564c4de518e6"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 11:29:50 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 11:29:50 2025 -0700"
      },
      "message": "Remove \"restart conversation\" backend functionality\n"
    },
    {
      "commit": "14fe75d6ece5116b3887b6fc027e564c4de518e6",
      "tree": "5a3e72a02da8d06818fcd3531147087f8741f81b",
      "parents": [
        "f28729932fdf9ecc67d3fabbfca297178a323a14"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 17:39:38 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 11:28:39 2025 -0700"
      },
      "message": "webui: Remove restart conversation button and modal component\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s0da284ec42d4da59k\n"
    },
    {
      "commit": "f28729932fdf9ecc67d3fabbfca297178a323a14",
      "tree": "5ae2eca28c1c139a95dde0648a17eeaba3e60bce",
      "parents": [
        "716bfee93847e19465723af2d7c553d23c9984df"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 10:35:28 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 22 11:28:35 2025 -0700"
      },
      "message": "Refactor agent git state into its own struct to tease apart its locking a bit.\n\nI want to invoke calling the git state when editing files, and that\nrequires separating it somewhat from the agent\u0027s messy and coarse\nlocking.\n"
    },
    {
      "commit": "716bfee93847e19465723af2d7c553d23c9984df",
      "tree": "6a14fd9aa287ec8fe7a1b50655a3a864151da43d",
      "parents": [
        "bc8c8dc5bc7abca6fa523c5ca45c9fd2c09384c2"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 18:32:31 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 18:32:31 2025 -0700"
      },
      "message": "Fix agent init of git repo from recent change.\n"
    },
    {
      "commit": "bc8c8dc5bc7abca6fa523c5ca45c9fd2c09384c2",
      "tree": "d59b7b3ef6965949376481cfa6108fee7312f6fd",
      "parents": [
        "1a648f34a53216a9ed88792d583fad50246f3d4b"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 13:19:13 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 13:40:03 2025 -0700"
      },
      "message": "sketch main: migrating things from /init into cmdline flags\n\nAs much as possible, I want NewAgent() to take as many arguments as it\ncan, and try to avoid doing different things with Init().\n\nYou can\u0027t quite do everything because the port that Docker has\nopen for forwarding starts as \"0\" and we call \"docker port\" to find it,\nbut besides that, almost everything is knowable up front.\n"
    },
    {
      "commit": "1a648f34a53216a9ed88792d583fad50246f3d4b",
      "tree": "43c0eb12a4b13b4d9351666e44024c43dbb71d63",
      "parents": [
        "38411997b3ce4a6721f2942ebf0fc67131d94b6e"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 17:15:04 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 12:56:49 2025 -0700"
      },
      "message": "llm/oai: add entry for Mistral Devstral model\n\nAdd the Mistral Devstral coding model (devstral-small-2505) to the llm/oai package.\nThis model is designed specifically for software engineering tasks and is available\nthrough the Mistral API at the same cost as Mistral Small 3.1.\n\nSee: https://mistral.ai/news/devstral\n\nHowever, we can\u0027t actually use it, because the Mistral API\ndoesn\u0027t parse out tool calls, and the model generates at least\nthree different tool calls formats. None of which contains a tool_call_id,\nwhich somehow the Mistral API requires on the way back in.\nI don\u0027t understand how this is supposed to work.\nBut fighting it now is an utter waste of time.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sf3b4fcfc4b26e3b4k\n"
    },
    {
      "commit": "38411997b3ce4a6721f2942ebf0fc67131d94b6e",
      "tree": "e6445a72773f2c6d7731f02ec62051502642d9fc",
      "parents": [
        "0f1a3f86041fd04c33a9c9e4774f9abdf1c01c5f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 17:51:03 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:37:49 2025 -0700"
      },
      "message": "llm/oai: retry more on failure\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s6b8e59e9e006f5bak\n"
    },
    {
      "commit": "0f1a3f86041fd04c33a9c9e4774f9abdf1c01c5f",
      "tree": "24fc7243f28c7fbabd43dd05b3c6d44e52f92cfc",
      "parents": [
        "ac761c9dd5ad664b09d8588261a09d4aecdace5d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 09:05:55 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:37:49 2025 -0700"
      },
      "message": "loop: strengthen guidance file wording a bit\n"
    },
    {
      "commit": "ac761c9dd5ad664b09d8588261a09d4aecdace5d",
      "tree": "343cae654689288c8ff6807b036150f7e22a08ae",
      "parents": [
        "e10f0e6c540ac0f6c038a4a6b729e9401dd39e52"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 18:58:45 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:37:49 2025 -0700"
      },
      "message": "cmd/sketch: add mount flag for container volumes\n\nAdd a mount flag that simplifies mounting host directories into the container.\nWhen specified with format /path/on/host:/path/in/container it\u0027s automatically\nconverted to a docker volume mount argument (-v) in the docker invocation.\nThis simplifies volume mounting compared to the more generic docker-args flag.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s67251d45fd28831ek\n"
    },
    {
      "commit": "e10f0e6c540ac0f6c038a4a6b729e9401dd39e52",
      "tree": "c3704ca3c01f833195fee4f16f5764b80e268544",
      "parents": [
        "564043144868f401515c8ed250d989f60ea2e1de"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 10:57:09 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:37:49 2025 -0700"
      },
      "message": "claudetool: ignore trailers in git commit style analysis\n\n"
    },
    {
      "commit": "564043144868f401515c8ed250d989f60ea2e1de",
      "tree": "960ddee651a508164343db8fc23d00c293d2326e",
      "parents": [
        "6f041f5ac59a17987efdfe63d1d05e487e23a89e"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 08:48:10 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:36:32 2025 -0700"
      },
      "message": "loop: attempt some sycophancy reduction"
    },
    {
      "commit": "6f041f5ac59a17987efdfe63d1d05e487e23a89e",
      "tree": "fe277e0b16bff201ef26fb586b85eb639859a223",
      "parents": [
        "6e35332ceac45166d6dd549d1e3d94937f683320"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 17:31:08 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:36:32 2025 -0700"
      },
      "message": "claudetool/onstart: support .github/copilot-instructions.md as inject file\n\nUpdate categorizeFile function to recognize .github/copilot-instructions.md\nas an injectable file for the agent prompt, allowing GitHub Copilot\nguidance to be included in the system prompt.\n\nFixes #105\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s211c42575972fdbek\n"
    },
    {
      "commit": "6e35332ceac45166d6dd549d1e3d94937f683320",
      "tree": "87b4eeea74b9f6d9786d99983a976c1cf0f7ff05",
      "parents": [
        "8d8b7ac6b00b1d0b3a2c6d3a4079e2c2fb76cc8a"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 18:21:24 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 21 11:36:32 2025 -0700"
      },
      "message": "all: remove testify\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s51244611964f2413k"
    },
    {
      "commit": "8d8b7ac6b00b1d0b3a2c6d3a4079e2c2fb76cc8a",
      "tree": "eb46d3770aa48f0a809594eef93e0a053075b0ee",
      "parents": [
        "35c72bcbf69cce28395bc34236df8ef9d615c0da"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 09:57:23 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 21 11:07:52 2025 -0700"
      },
      "message": "Add buildinfo to /debug on Sketch http\n"
    },
    {
      "commit": "35c72bcbf69cce28395bc34236df8ef9d615c0da",
      "tree": "c56e26f5ce42cacf9630f3187a98fd356a469a7b",
      "parents": [
        "7ce7b0294ba1efe6c7b3d462e905c1b2a7057a37"
      ],
      "author": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Tue May 20 11:17:10 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue May 20 20:58:51 2025 -0700"
      },
      "message": "loop: send modified over-budget message\n"
    },
    {
      "commit": "7ce7b0294ba1efe6c7b3d462e905c1b2a7057a37",
      "tree": "9b0b92fbcf2b27a2b971481716e4d1dc99d3ec6f",
      "parents": [
        "9daa5183df5270beaf5611c20e4d77cd7cfe21f7"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 11:35:51 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue May 20 20:49:05 2025 -0700"
      },
      "message": "claudetool: draw attention to commit message capitalization and punctuation"
    },
    {
      "commit": "9daa5183df5270beaf5611c20e4d77cd7cfe21f7",
      "tree": "84bd4bf7d7bfbc723925bfae2af828cd9e7ccd0b",
      "parents": [
        "55c87e3ababb0800b5710cbb11bec4dea8c13515"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Fri May 16 18:34:00 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Tue May 20 14:27:29 2025 -0700"
      },
      "message": "experiment: remove llm_review experiment and associated code\n\nIt creates confusion for the agent and doesn\u0027t provide much value.\nPerhaps with better prompt engineering, but I can\u0027t invest\nin that much right now.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s9f2a8c418876c498k"
    },
    {
      "commit": "55c87e3ababb0800b5710cbb11bec4dea8c13515",
      "tree": "13517efe8467be99714a65a24963873cbe18e137",
      "parents": [
        "9d7f0ccec1317b68c754b6b154f7c362395028c2"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Tue May 20 14:08:18 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Tue May 20 13:11:23 2025 +0000"
      },
      "message": "webui: Fix cursor jumping during image uploads\n\nWhen pasting an image and continuing to type while it\u0027s uploading,\nthe cursor position would jump when upload completed, disrupting typing.\n\nThis fix simply removes the explicit cursor positioning code after\nimage upload, allowing the browser to maintain the user\u0027s current cursor\nposition naturally. This provides a more intuitive experience, especially\nwhen typing while an image is uploading.\n\nThe approach is simpler and more robust than trying to track cursor\nposition changes and calculate offsets manually.\n"
    },
    {
      "commit": "9d7f0ccec1317b68c754b6b154f7c362395028c2",
      "tree": "baa47109cc854d5abc4326669e05e9ceb49a016c",
      "parents": [
        "da514fccdf1135cfa52a869b892855aac117ee05"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Tue May 20 11:43:26 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Tue May 20 10:51:10 2025 +0000"
      },
      "message": "loop/server: fix race condition in SSE stream iterators\n\nFix panic \u0027send on closed channel\u0027 when a client disconnects from SSE stream.\nThe issue occurred because iterators were created at the beginning of\nhandleSSEStream with defer iterator.Close(), but used in separate goroutines.\nWhen the client disconnected, the iterators were closed while goroutines\nwere still using them.\n\nMove iterator creation into the goroutines that use them to ensure their\nlifecycle matches the goroutines\u0027 lifecycle, preventing the race condition.\n\nFixes #108\n"
    },
    {
      "commit": "da514fccdf1135cfa52a869b892855aac117ee05",
      "tree": "7846b18cc33a04bc5c94098a6a135a513b18d2c7",
      "parents": [
        "9df94b5cf626971b7a84cd1b743ee49f5ae8e009"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Mon May 19 19:21:07 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Mon May 19 19:25:20 2025 -0700"
      },
      "message": "Update dockerfile tests.\n"
    },
    {
      "commit": "9df94b5cf626971b7a84cd1b743ee49f5ae8e009",
      "tree": "49a54416207ef2418b9684fb6289e54a35badfc0",
      "parents": [
        "fbe6478d2829fcc7e5e7cc0c1b87721927b18d57"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Sun May 18 03:43:14 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Mon May 19 19:25:20 2025 -0700"
      },
      "message": "dockerimg: Extract base Dockerfile to separate file\n\nExtract the dockerfileBase constant into a Dockerfile.base file and use Go embed\ndirectives to include it in the code. This improves maintainability by separating\nthe Docker configuration from the Go code while preserving the same functionality.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: se66b902985dca8a1k\n"
    },
    {
      "commit": "fbe6478d2829fcc7e5e7cc0c1b87721927b18d57",
      "tree": "7b8090ef32ba34fa29d0f3a4ebc4582f739a7270",
      "parents": [
        "d6d12d188814c114ed4b2acb1df2d201c1cf96b5"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Tue May 13 18:24:31 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip.zeyliger@gmail.com",
        "time": "Mon May 19 19:25:20 2025 -0700"
      },
      "message": "docker: Add lsof and ss to base docker image\n\nThese are tools that the agent seems to want. It doesn\u0027t\ndo a great job of installing them, but they\u0027re pretty useful.\n"
    },
    {
      "commit": "d6d12d188814c114ed4b2acb1df2d201c1cf96b5",
      "tree": "2e2bc28d9882efe47d95c992f66b1c8f0d705540",
      "parents": [
        "e9eaf6c556fe058ccc6f9aa60b7db0f4a3ec77d3"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 19:19:21 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 19:19:21 2025 -0700"
      },
      "message": "Fail clearly when repo has no commits. (#109, #84)\n"
    },
    {
      "commit": "e9eaf6c556fe058ccc6f9aa60b7db0f4a3ec77d3",
      "tree": "22527d450d724872458b9258b9ec92d323ba3ed4",
      "parents": [
        "cabfa5520708460e4537216df26be15262c855e6"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 16:14:39 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 16:14:39 2025 -0700"
      },
      "message": "Add skaband heartbeat support.\n\nWe want Sketch to re-connect if its connection to skaband is busted. To\ndo so, we expect a heartbeat from skaband, and, if we\u0027ve missed it, we\nshut down the connection and re-connect.\n"
    },
    {
      "commit": "cabfa5520708460e4537216df26be15262c855e6",
      "tree": "27785b2f11ce1b0c360a781c4a1b2a8e2c513049",
      "parents": [
        "397871d299216f63dc38a9cc6f2ca386d0f4bd75"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 16:14:28 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon May 19 16:14:28 2025 -0700"
      },
      "message": "Pass -verbose flag to innie to see logs.\n"
    },
    {
      "commit": "397871d299216f63dc38a9cc6f2ca386d0f4bd75",
      "tree": "ea1cec9278f37739f972a390b0ec564a1fe9219f",
      "parents": [
        "a8322202f36c35f677b8834cdce8f21ab3d8c6dc"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Mon May 19 15:02:45 2025 +0100"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Mon May 19 14:03:43 2025 +0000"
      },
      "message": "webui: Add End button to shutdown container\n\nThis change adds a new button to the sketch-app-shell UI alongside the\nexisting Restart and Stop buttons. When clicked, the End button shows a\nconfirmation dialog and then sends a request to a new /end endpoint.\n\nThe /end endpoint gracefully shuts down the inner sketch container.\n\nFixes #88\n"
    },
    {
      "commit": "a8322202f36c35f677b8834cdce8f21ab3d8c6dc",
      "tree": "449d31ca4023b97fa87b5831c5a071864406e516",
      "parents": [
        "87d29ef5b027120ea0857a9aa5661a3fab7b25b9"
      ],
      "author": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Sat May 17 06:54:34 2025 -0700"
      },
      "committer": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Sat May 17 06:54:37 2025 -0700"
      },
      "message": "loop: only do in-docker git init if connected to host git\n"
    },
    {
      "commit": "87d29ef5b027120ea0857a9aa5661a3fab7b25b9",
      "tree": "1e7a7555b3c2cf9e764c9a62fe02e31b6667f27e",
      "parents": [
        "8c4636270be67625cc27ce356f6da1a11e245069"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 20:25:28 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 20:26:06 2025 -0700"
      },
      "message": "docker: use consistent ephemeral port for SSH\n\nI sense that some versions of docker interpret -p 22 as 22:22\nand some as 0:22. We already use 0:80 for HTTP, so let\u0027s do the same\nfor SSH.\n\nThis is an optimistic fix for a user issue.\n"
    },
    {
      "commit": "8c4636270be67625cc27ce356f6da1a11e245069",
      "tree": "f6a4db58f1eb71033410150daa7290d4e41aca0a",
      "parents": [
        "5e3570280bf3bb0f84482ff9556739d34eb08093"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri May 16 21:54:17 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri May 16 21:54:17 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "5e3570280bf3bb0f84482ff9556739d34eb08093",
      "tree": "0721d16a93a8744466fb5206114d1f25b5b8cadb",
      "parents": [
        "272a90ee1a74bda5618d4866e03f4b7067947784"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 04:50:34 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 14:53:24 2025 -0700"
      },
      "message": "webui: Update status indicators\n\n- Remove green dot connection indicator\n- Add DISCONNECTED state with red styling when connection is lost\n- Update the status bar to show DISCONNECTED instead of IDLE/WORKING when disconnected\n- Create demo page to preview all three status states\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: skR3m0v3Gr3nD0tD1sc0nn3ct3dR3d\n\nChange-ID: sa2b3679b9cdcaf80k\n"
    },
    {
      "commit": "272a90ee1a74bda5618d4866e03f4b7067947784",
      "tree": "9baf4f84ce80b1c7073a95b6959f6dd11ab3b48b",
      "parents": [
        "d3ac112a45111abf0e57c327d55e2cc66a136abb"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 14:49:51 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 14:51:40 2025 -0700"
      },
      "message": "Add Monaco diff-view, the saga ...\n\nI set out to use Monaco to support the diff view. diff2html is lovely,\nbut there were a ton of usability improvements I wanted to make (line\nnumbers not making things double spaced, choosing which diff, editing\nthe right-hand side), and it seemed a dead end. Furthermore, Phabricator\nand Gerrit\u0027s experience is that diffs should be shown file by file,\nbecause you\u0027ll inevitably see a diff with a file that\u0027s too large, and\nthe GitHub PR view often breaks on big changes... so I wanted to show\nfiles diff-by-diff, with \"infinite\" context when unchanged sections are\nexpanded. So...\n\nUltimately, all of this was sketch-coded over maybe 30 Sketch sessions.\nI threw away a lot of branches. My git reflog is a superfund site.\n\nPrompting whole-hog didn\u0027t work. Or, rather, it made significant\nprogress, but something very serious wouldn\u0027t work, and I couldn\u0027t\nfigure out what, and nor could Sketch.\n\nInstead, I started by adding a new webcomponent that was just a\nplaceholder. Then, using https://rodydavis.com/posts/lit-monaco-editor,\nI nudged Sketch into adding Monaco to it. Sketch pulled out:\n\n   You\u0027re right, I should properly read the blog post before implementing the\n   solution. Let me check the referenced blog post.\n\nI worked heavily in the demo environment at first, but here I ran into\nthe issue that we have two different esbuild systems: one is vite and\none is esbuild.go, and they\u0027re configured differently enough.\n\nMonaco is unusable and confusingly so when its CSS isn\u0027t loaded. The right\nway to load it, I\u0027ve found, is via\n\n  @import url(\u0027./static/monaco/min/vs/editor/editor.main.css\u0027);\n\nI spent more time than I care to admit noticing that originally\nthis wasn\u0027t relative, and when we use a skaband setting, the\npaths need to be relative-aware.\n\nThe paths to the various workers need to be similarly correctly placed.\n\nGetting Sketch to build demo data but not put testing code into production\ncode was tricky. (I threw away a lot of efforts and factories and singletons...)\n\nWhen I set out to do the git commit selection, I wanted to do a bunch of\nbackend /git/* handlers. These were easy enough to code in sketch. I had\nto convince Sketch to put them in git_tools.go and not in the agent.\nIt doesn\u0027t really matter: these functions to parse git are pretty stateless,\nbut it\u0027s less work to have them separate. Sketch was mediocre at writing\ntests for them. Did you know that our container has an older version\nof git that doesn\u0027t have the same options to decorate ref names? Yeah, nor did\nI.\n\nHandling unstaged changes was fun. git diff --raw shows unstaged files\nas having identity 0000. Ideally we\u0027d be using jj and there\u0027d be\na synthetic commit, but instead uncommitted-possible files are read\nby content.\n\nA real big challenge was getting the Monaco view to use the right vertical and\nhorizontal space. I did this many, many times. I don\u0027t claim to understand flex\nand the virtual dom, and :host, and all the interactions. It would fix one\nthing and break another. The chat window would shrink. The terminal would\nshrink.\n\nScreenshot support was excellent. I eventually added paste support just so\nthat I could expedite my workflow, and Sketch coded that easily on the first\npass with minor feedback.\n\nI learned the hard way that Safari\u0027s support for WebComponents/shadow\ndom in its web inspector is rough. See https://fediverse.zachleat.com/@zachleat/114518629612122858\n\nI also learned the hard way that Chrome doesn\u0027t use fonts loaded in CSS\nin a shadow dom. That\u0027s why the codicon font had to be in the global\nstyle sheet.\n\nKudos to John Reese who kindly allowed me, a long time ago, to adapt a\nshell script he had at work to look over diffs into https://github.com/philz/git-vimdiff.\nThat\u0027s the inspiration for having the \"new code\" be editable when you\u0027re\nreviewing it; why shouldn\u0027t it be!?!\n\nThere are a handful of follow up tasks:\n\n* We lose state when we switch to the Chat view and back.\n* Need URL-based support for where we are.\n* Maybe need shortcut keys to move between diffs and changes.\n* Maybe need caching or look-ahead for downloading the next or previous\n  file.\n* We spend too much vertical real estate on all the diff selections;\n  could we scroll it out of the way, collapse it, tighten it, etc.\n* The workers sometimes throw errors into the console. I think they\u0027re\n  harmless and merely need to be caught and suppressed.\n* Needing to commit changes when things are saved is weird. Should we\n  commit automatically? Amend the previous commit? Have a button for\n  that? Show the git dirty state?\n* Our JS bundle is big. We could maybe delay loading the monaco bundle\n  to help.\n\nThanks for coming to my TED talk.\n"
    },
    {
      "commit": "d3ac112a45111abf0e57c327d55e2cc66a136abb",
      "tree": "7d2cab01515d7c482be1a39cc0492e9d9ac657e7",
      "parents": [
        "8bdf627180b64b0dc09018bf512f6ebf192ab674"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Wed May 14 02:54:18 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 14:51:40 2025 -0700"
      },
      "message": "git_tools: Implement git diff and show API\n\nAdded git_tools package providing structured access to git diff and show commands. Exposed these methods via HTTP endpoints in loophttp.\n\nThis is a stepping stone to a better diff view.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: se75f0a1b2c3d4e5k\n"
    },
    {
      "commit": "8bdf627180b64b0dc09018bf512f6ebf192ab674",
      "tree": "47d9b1e5348a33846fc11704f99c3cf7151ec3f1",
      "parents": [
        "0ead54d4591b9de1dedb897302f3ffaf36454c8e"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 13:36:21 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri May 16 14:51:40 2025 -0700"
      },
      "message": "Playwright: don\u0027t use junit inside Sketch.\n\nI\u0027ve found Sketch doesn\u0027t understand the JUnit failure nearly\nas well as the usual way.\n"
    },
    {
      "commit": "0ead54d4591b9de1dedb897302f3ffaf36454c8e",
      "tree": "aebc7418f3d60df3fcdafab155412f123454bb26",
      "parents": [
        "5eccd68ca894e5591bd6cc689bbb12b97a869464"
      ],
      "author": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Fri May 16 13:58:36 2025 -0700"
      },
      "committer": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Fri May 16 13:58:36 2025 -0700"
      },
      "message": "cmd/sketch: move NewSessionID function\n"
    },
    {
      "commit": "5eccd68ca894e5591bd6cc689bbb12b97a869464",
      "tree": "dde938683a329c38ecf657e585169b75479c8629",
      "parents": [
        "044a62e8e3d28a573c624d722f0fde38c30a19e2"
      ],
      "author": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Fri May 16 07:09:30 2025 -0700"
      },
      "committer": {
        "name": "David Crawshaw",
        "email": "david@zentus.com",
        "time": "Fri May 16 07:09:36 2025 -0700"
      },
      "message": "cmd/sketch: invert bool to fix open flag default behavior\n"
    },
    {
      "commit": "044a62e8e3d28a573c624d722f0fde38c30a19e2",
      "tree": "cfed4a459489b6f8c08c7aa98aa6ea416dc0f427",
      "parents": [
        "276f460cc7136e50a07cf544ee5ef6bf2a1c2630"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Fri May 16 10:40:59 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri May 16 10:47:11 2025 +0000"
      },
      "message": "webui: Prevent sending messages while uploads are in progress\n\nThis fixes an issue where users could press Enter immediately after pasting an image,\nwhich would submit the message with just the \u0027[Uploading image.png...]\u0027 placeholder text.\n\nNow the system:\n1. Tracks uploads in progress\n2. Prevents message submission while uploads are active\n3. Shows visual feedback to the user\n4. Disables the send button during uploads\n"
    },
    {
      "commit": "276f460cc7136e50a07cf544ee5ef6bf2a1c2630",
      "tree": "0e00d887c0bac515e49775041be83eadbc174074",
      "parents": [
        "a4500c98a8f7c2e5500d330d7f4e82037fb38239"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 17:57:51 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 22:00:19 2025 -0700"
      },
      "message": "all: read agent.md files too\n\ntoo many agent rules files!\n"
    },
    {
      "commit": "a4500c98a8f7c2e5500d330d7f4e82037fb38239",
      "tree": "32f069d493f4e76ef425acfc8a87800f06d01091",
      "parents": [
        "613c0f5288dd0e18dc9fee09254161d78fc7acb7"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 15:38:32 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 22:00:19 2025 -0700"
      },
      "message": "llm/ant: retry more on failure"
    },
    {
      "commit": "613c0f5288dd0e18dc9fee09254161d78fc7acb7",
      "tree": "e909ee44b0e1f0a6c14e7fab714450326a7e0b3f",
      "parents": [
        "bd7b625d4ca17b5cb5207b4917a6e61ea398f2d0"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 15 16:36:22 2025 -0700"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 15 23:42:04 2025 +0000"
      },
      "message": "logging: make -verbose -termui\u003dfalse log to stdout\n\nCommit d72563ac30bab6471121f561f3bb41991a3c91d1 made it so we never send\nlogs to stdout/stderr, but I prefer them on stderr when possible. So, if\ntermui isn\u0027t enabled, let\u0027s send them to stderr. --termui used to not be\npropogated; now it is.\n"
    },
    {
      "commit": "bd7b625d4ca17b5cb5207b4917a6e61ea398f2d0",
      "tree": "32c1588d9cd5854d1322615d0aa14cc35d33f3a9",
      "parents": [
        "e3c2f22ee87eb9830dad42ca0388b9743923ec59"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 15 16:21:36 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu May 15 15:14:37 2025 -0700"
      },
      "message": "webui: reposition working/idle banner over lightbulb/wrench icons\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sb695b8b61b1f5134k\n"
    },
    {
      "commit": "e3c2f22ee87eb9830dad42ca0388b9743923ec59",
      "tree": "6e6b8fe475c62eac64d6600fb8be82affec545ce",
      "parents": [
        "956626d63041ec76d3994bd3fda02448e49aab46"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 20:54:52 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 14:41:38 2025 -0700"
      },
      "message": "skabandclient: fix handling of empty skaband-addr\n\nThis had regressed considerably.\n\nFixes #96\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s4d698cae3417a4f9k"
    },
    {
      "commit": "956626d63041ec76d3994bd3fda02448e49aab46",
      "tree": "3723db8c989cbb1bc324aa2680bd60c2cce0b114",
      "parents": [
        "f163e9e785845bed2d7fba31ddf06a22a2e1e853"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 21:24:07 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 14:37:05 2025 -0700"
      },
      "message": "termui: add branch delete command\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s114722c8790c2a41k\n"
    },
    {
      "commit": "f163e9e785845bed2d7fba31ddf06a22a2e1e853",
      "tree": "c728e8da4f5c9a7a3d885f3130bc9bde13f28c3e",
      "parents": [
        "de5f74466b6db86c310762d627ea5f05b24cd08e"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 12:38:30 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 13:17:42 2025 -0700"
      },
      "message": "claudetool/codereview: stop checking string iteration patterns\n\nEven frontier LLMs get confused by these recent language improvements.\nI\u0027m sick of fighting them (i.e. watching them fight themselves).\nWe\u0027ll just have to wait for them to either get more capable,\nor to learn the new idioms. Sigh.\n"
    },
    {
      "commit": "de5f74466b6db86c310762d627ea5f05b24cd08e",
      "tree": "12196afbbb7362c93883cf63fe8d94d5e87b5387",
      "parents": [
        "fbbf83bba97e2e2fd5e5ea1693c96efce1fdc3b1"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 18:32:32 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 13:17:42 2025 -0700"
      },
      "message": "claudetool: ignore some gopls (/vet) checks\n\nFixes #95\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s934f225a42c1d576k\n"
    },
    {
      "commit": "fbbf83bba97e2e2fd5e5ea1693c96efce1fdc3b1",
      "tree": "968706f07817a92905dbbc28a5bcdd1125bf4467",
      "parents": [
        "a4092d26857aa5aeba70813e8942f321232e987c"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 10:55:55 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 13:17:42 2025 -0700"
      },
      "message": "webui: tweak done tool card emojis\n\nDear Sketch, please stop using big red angry failure emojis.\nAlso, gender neutral is fine thank you very much.\n"
    },
    {
      "commit": "a4092d26857aa5aeba70813e8942f321232e987c",
      "tree": "3d8caf262c8f0b103010a2450bfea896bb07417e",
      "parents": [
        "74d690e7b4794f2c164a9da30dd106a002b935d9"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 14 18:32:53 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 13:17:39 2025 -0700"
      },
      "message": "loop: make about_sketch not experimental\n\nseems to work ok enough to unleash it on everyone else..."
    },
    {
      "commit": "74d690e7b4794f2c164a9da30dd106a002b935d9",
      "tree": "412f1ad777e599ed61904c7f80c53859315babab",
      "parents": [
        "039fc34bd9c8f7cf3e9f3c9aeee2e9677ce28e00"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 14 18:16:03 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 12:40:29 2025 -0700"
      },
      "message": "claudetool: remove knowledge base, focus on about sketch\n\nWe should have a more general kb.\nMeanwhile, this is important and standalone.\nMake it all clearer and sharper.\n"
    },
    {
      "commit": "039fc34bd9c8f7cf3e9f3c9aeee2e9677ce28e00",
      "tree": "d04e1be0103e486d0e1905e4aa431b7cc1820640",
      "parents": [
        "6ada85d6c4401ca82e3809fbd3af0178de1b7b11"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 14 21:24:12 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 12:40:08 2025 -0700"
      },
      "message": "loop/agent: add git commit hooks when running inside container\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s8d03af4abcafd1dbk"
    },
    {
      "commit": "6ada85d6c4401ca82e3809fbd3af0178de1b7b11",
      "tree": "e95b40c49571b6777c386a85dcc500fcc4f487f1",
      "parents": [
        "f7bebdd0a51bfe6f4148d7717e833d8d3e4fe5a5"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 14 22:08:09 2025 +0000"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 12:24:07 2025 -0700"
      },
      "message": "ci: fix checkout reference in formatting workflow\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sb7ac2d84761d3e37k\n"
    },
    {
      "commit": "f7bebdd0a51bfe6f4148d7717e833d8d3e4fe5a5",
      "tree": "2e280111e0e016971322952860bc76e7402ab051",
      "parents": [
        "124c9421ab7650020428f5b26348a963b49f107f"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Wed May 14 15:22:24 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Thu May 15 12:24:07 2025 -0700"
      },
      "message": "loop: attempt to stop sketch from bouncing around between branches"
    },
    {
      "commit": "124c9421ab7650020428f5b26348a963b49f107f",
      "tree": "7e2143b85574f4a6fd1b64245ee49e13f3662379",
      "parents": [
        "339b56efb8d84aa0c445071b01c48637e4943192"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Thu May 15 19:07:50 2025 +0100"
      },
      "committer": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Thu May 15 19:07:50 2025 +0100"
      },
      "message": "Improve Discord badge\n"
    },
    {
      "commit": "339b56efb8d84aa0c445071b01c48637e4943192",
      "tree": "0afd52f0b7e2eee21cd4d1ae8c834bb706ca91ac",
      "parents": [
        "75f93a1e5f32366c138c1584fdeb4919e257719d"
      ],
      "author": {
        "name": "Pokey Rule",
        "email": "755842+pokey@users.noreply.github.com",
        "time": "Thu May 15 14:48:07 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Thu May 15 15:01:30 2025 +0000"
      },
      "message": "webui: Implement drag-and-drop file upload in chat window\n\nFixes https://github.com/boldsoftware/sketch/issues/93\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s1ff4cfd325e3822ck\n"
    }
  ],
  "next": "75f93a1e5f32366c138c1584fdeb4919e257719d"
}
