)]}'
{
  "log": [
    {
      "commit": "9b39aa66590f68f9039a8efc0c4e1917551016e6",
      "tree": "6ac5e639d348bf2b2a3017abbc147411b79cf9bf",
      "parents": [
        "333aa67a4c1639f49c7ba03edab4ace3c6439e2b"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon Jul 14 11:56:02 2025 -0700"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Mon Jul 14 11:56:24 2025 -0700"
      },
      "message": "sketch: exclude internal processes (headless-chrome) from port monitoring\n\nAdd SKETCH_IGNORE_PORTS environment variable to headless-shell browser processes\nand modify port monitoring to exclude processes with this variable.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: sff3b145df27ee3bek\n"
    },
    {
      "commit": "c7a98d8360cf03f977625a65e8dd637d6b2ab18b",
      "tree": "043d571f69c08cc1211dbd9d85821ca488160a38",
      "parents": [
        "553cc842a3fea3594158c8314a577c2b916bf45d"
      ],
      "author": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon Jul 07 19:12:53 2025 -0700"
      },
      "committer": {
        "name": "Josh Bleecher Snyder",
        "email": "josharian@gmail.com",
        "time": "Mon Jul 07 19:13:43 2025 -0700"
      },
      "message": "sketch/loop: fix concurrency handling in port monitor shutdown\n\nThe graceful shutdown code assumes it can take the pm.mu lock.\nMake the Stop code oblige.\n\nThis fixes the issue at hand, but the remaining code still gives\nme the heebie jeebies--for example, after calling Stop, there could\nstill be notifications that come in.\n\nSketch really shouldn\u0027t write concurrent code.\n\nThis will work well enough, I guess, until it doesn\u0027t,\nat which point we\u0027ll have to carefully fix up the rats nest.\n\n\nBefore:\n\n2m10s: 1157 runs so far, 36 failures (3.11%)\n\nAfter:\n\n16m45s: 12484 runs so far, 0 failures\n\n\nFixes boldsoftware/bold#446 enough for now\n"
    },
    {
      "commit": "e48f2bb05d937c1bcc51bca81a010173d905c0bb",
      "tree": "90d08fc8e4b0775ec25af38580b6b68182087f31",
      "parents": [
        "6dc90c03abff887c09ca0418d4d493d16cf1b0c8"
      ],
      "author": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri Jul 04 04:15:26 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Fri Jul 04 04:15:26 2025 +0000"
      },
      "message": "all: fix formatting\n"
    },
    {
      "commit": "5f26a3445601f6ab0299d9be20ea99b67eae4d51",
      "tree": "740ba6f60a055e4e6ad8ec92e75992ca9d2b0795",
      "parents": [
        "da623b50da804963768d2633cb2686a9d91d49b9"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri Jul 04 01:30:29 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu Jul 03 21:14:55 2025 -0700"
      },
      "message": "sketch/loop: add PortMonitor for TCP port monitoring with Agent integration\n\nAdd PortMonitor struct that uses Tailscale portlist library to monitor\nopen/listening TCP ports and send AgentMessage notifications to Agent\nwhen ports are opened or closed, with cached port list access method.\n\nWhen I asked Sketch to do this with the old implementation, it did\nok parsing /proc, but then it tried to conver it to ss format...\nusing a library seems to work ok!\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s8fc57de4b5583d34k\n"
    },
    {
      "commit": "da623b50da804963768d2633cb2686a9d91d49b9",
      "tree": "74b03bb5091e12162088e77ef4e32fba91412821",
      "parents": [
        "2153f8b8eeb9215ed4b79af3aef09de1af83decd"
      ],
      "author": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Fri Jul 04 01:12:38 2025 +0000"
      },
      "committer": {
        "name": "Philip Zeyliger",
        "email": "philip@bold.dev",
        "time": "Thu Jul 03 20:57:50 2025 -0700"
      },
      "message": "remove port monitoring and automatic tunneling features\n\nRemove port_monitor, TunnelManager, and /port-events handler to eliminate\nautomatic port tunneling functionality that bridges outtie to innie environments.\n\nSketch got confused when I asked it to change how this works; removing\nand re-adding was easier!\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s78f868b27a44cb2bk\n"
    },
    {
      "commit": "cff0ff8f582a970fa8bd688448964bef8d2b84ab",
      "tree": "be78da943008f817a8af3ba40c34f633ce855344",
      "parents": [
        "7e36a04e5b9eb206faad20f0a37fa111285ffdce"
      ],
      "author": {
        "name": "banksean",
        "email": "banksean@gmail.com",
        "time": "Wed Jun 25 16:43:47 2025 +0000"
      },
      "committer": {
        "name": "Autoformatter",
        "email": "bot@sketch.dev",
        "time": "Wed Jun 25 18:39:06 2025 +0000"
      },
      "message": "sketch: add /proc filesystem fallback for port monitoring when ss command unavailable\n\nImplements /proc/net/tcp* parsing as fallback when ss command fails to eliminate\ndependency on ss being installed in container environments.\n\nProblems Solved:\n\nss Command Dependency:\n- PortMonitor.updatePortState() relied on \u0027ss -lntu\u0027 command for port detection\n- Failed on systems where ss (iproute2 package) is not installed\n- No fallback mechanism when ss command execution failed\n- Port monitoring became non-functional in minimal container environments\n\nLimited Container Support:\n- Many minimal container images don\u0027t include ss command\n- Port monitoring silently failed without providing any functionality\n- No way to detect listening ports without external command dependencies\n\nSolution Architecture:\n\n/proc Filesystem Parsing:\n- Added getListeningPortsFromProc() method to read /proc/net/tcp* files\n- Parses /proc/net/tcp, /proc/net/tcp6, /proc/net/udp, /proc/net/udp6\n- Hex address decoding for both IPv4 and IPv6 addresses\n- Socket state filtering to identify listening sockets (state 0x0A for TCP, 0x07 for UDP)\n\nFallback Implementation:\n- updatePortState() tries ss command first, falls back to /proc on failure\n- parseAddress() handles little-endian hex encoding from /proc files\n- Generated output format matches ss command output for compatibility\n- Maintains existing parseSSPorts() functionality for ss output\n\nImplementation Details:\n\nAddress Parsing:\n- IPv4: 8-character hex string representing little-endian 32-bit address\n- IPv6: 32-character hex string with little-endian 32-bit chunks\n- Port numbers stored as big-endian hex values\n- Special address handling: 0.0.0.0 and :: converted to \u0027*\u0027\n\nSocket State Detection:\n- TCP listening sockets: state 0x0A (TCP_LISTEN)\n- UDP bound sockets: state 0x07 (TCP_CLOSE for UDP)\n- Filters out non-listening connections and states\n\nError Handling:\n- Graceful fallback when ss command fails\n- Logs debug messages for command failures\n- Continues with /proc parsing if available\n- Handles missing /proc files gracefully\n\nTesting:\n\nComprehensive Test Coverage:\n- TestParseAddress() verifies hex address decoding for IPv4/IPv6\n- TestParseProcData() validates /proc file parsing with mock data\n- TestGetListeningPortsFromProcFallback() tests complete fallback functionality\n- TestUpdatePortStateWithFallback() validates end-to-end behavior\n\nAddress Parsing Validation:\n- IPv4 localhost (0100007F:0050 -\u003e 127.0.0.1:80)\n- IPv4 wildcard (00000000:0016 -\u003e *:22)\n- IPv6 wildcard and specific addresses\n- Error handling for invalid formats and hex values\n\nFiles Modified:\n- sketch/loop/port_monitor.go: Added /proc parsing methods and fallback logic\n- sketch/loop/port_monitor_test.go: Added comprehensive tests for new functionality\n\nThe implementation ensures port monitoring works reliably in any Linux environment\nregardless of whether ss command is available, using native /proc filesystem access.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s72dd58a0b3f4304bk\n"
    },
    {
      "commit": "138ec2436631f136dd2e8b4891211f896587ff00",
      "tree": "80afc394ad900e6e7a0a7b524972a303ef90ef15",
      "parents": [
        "457dfd12f281dbe9b1af8d1a7429f2977e234a6f"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Jun 02 22:42:06 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Jun 02 17:52:38 2025 -0700"
      },
      "message": "loop: automatic host/container ssh port tunneling\n\nFix for #47\n\nAdd comprehensive port event monitoring and automatic SSH tunnel management\nsystem that enables real-time port forwarding for container services.\n\nContainer processes need automatic port forwarding when services start or stop\nlistening on ports during agent execution. Previously, users had to manually\ncreate SSH tunnels using commands like \u0027ssh -L8000:localhost:8888 container\u0027,\nwhich required manual intervention and knowledge of when ports become available.\n\n- Extended PortMonitor with thread-safe event storage using circular buffer\n- Added PortEvent struct with type (opened/closed), port info, and timestamps\n- Maintained backward compatibility with existing logging functionality\n- Events stored in 100-item circular buffer with efficient timestamp filtering\n\n- Added /port-events endpoint in loophttp.go for container-to-host communication\n- Supports optional \u0027since\u0027 query parameter for incremental event fetching\n- Returns JSON array of recent port events with proper error handling\n- Integrated with existing Agent interface via GetPortMonitor() method\n\n- Created TunnelManager component for host-side tunnel orchestration\n- Polls container /port-events endpoint every 10 seconds for new events\n- Automatically creates SSH tunnels when ports open using same port numbers\n- Properly cleans up tunnels when ports close or context cancels\n- Skips common system ports (SSH, HTTP, SMTP) to avoid conflicts\n\n- Integrated TunnelManager into dockerimg.LaunchContainer() workflow\n- Starts tunnel manager alongside existing container management goroutines\n- Only activates when SSH is available and configured properly\n- Uses existing SSH infrastructure and container naming conventions\n\n- Container PortMonitor detects port changes via ss -lntu command\n- Events stored with RFC3339 timestamps for precise filtering\n- Thread-safe access patterns with dedicated mutex protection\n- Circular buffer prevents unbounded memory growth\n\n- RESTful GET /port-events endpoint with time-based filtering\n- Proper JSON encoding/decoding with error handling\n- Integration with existing HTTP server infrastructure\n- Non-blocking polling pattern with configurable intervals\n\n- Uses existing SSH theater configuration and host keys\n- Creates tunnels with format: ssh -L hostPort:localhost:containerPort container\n- Background monitoring of tunnel processes with automatic cleanup\n- Proper context cancellation and resource management\n\n- Added comprehensive port event storage and filtering tests\n- HTTP endpoint testing with mock agents and proper status codes\n- Verified thread-safe access patterns and circular buffer behavior\n- All existing loop package tests continue to pass\n\n- Confirmed HTTP endpoint returns proper JSON responses\n- Validated tunnel manager integrates with container launch process\n- Verified SSH tunnel creation follows existing authentication patterns\n- Build verification confirms no regressions in existing functionality\n\n- Automatic port forwarding eliminates manual SSH tunnel management\n- Real-time port detection provides immediate service accessibility\n- Transparent integration with existing Sketch container workflow\n- Maintains all existing SSH functionality and manual override options\n\n- Clean separation between container monitoring and host tunnel management\n- Extensible event-based architecture for future port-related features\n- Minimal performance impact with efficient polling and filtering\n- Robust error handling and graceful degradation when SSH unavailable\n\nThis enhancement provides seamless port forwarding automation while maintaining\nthe reliability and security of the existing SSH infrastructure, significantly\nimproving the developer experience when working with containerized services.\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s6bc363ed64835e5dk\n"
    },
    {
      "commit": "364f741483c1bd2c18cb3ff2ad255c9042c5362d",
      "tree": "95ff4d67ab4707d41a0ddad1e801c55cf8bf33c7",
      "parents": [
        "6cad861fbb3dbb646d190b7a5efc2fe982ea3aa8"
      ],
      "author": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Mon Jun 02 00:55:44 2025 +0000"
      },
      "committer": {
        "name": "Sean McCullough",
        "email": "banksean@gmail.com",
        "time": "Sun Jun 01 18:29:15 2025 -0700"
      },
      "message": "loop: add periodic port monitoring to container processes\n\nPartial fix for issue #47\n\nImplement periodic port monitoring functionality that runs ss every 5 seconds\nto detect changes in container listening ports, providing visibility into port\nusage changes during sketch agent execution.\n\nProblem Analysis:\nContainer processes need visibility into port changes that occur during\nagent execution. Without monitoring, it\u0027s difficult to detect when services\nstart or stop listening on ports, which can be crucial for debugging\nand understanding application behavior.\n\nImplementation:\nAdded comprehensive port monitoring system to Agent struct:\n\n1. Port Monitoring Infrastructure:\n   - Added portMonitorMu mutex and lastPorts field to Agent struct\n   - Created startPortMonitoring() method that launches background goroutine\n   - Uses time.Ticker with 5-second intervals for periodic checks\n   - Only activates when running in container mode (IsInContainer() check)\n\n2. Port Detection Logic:\n   - updatePortState() executes ss -lntu to get listening ports\n   - Compares current port state with previous state for change detection\n   - Thread-safe port state updates using dedicated mutex\n\n3. Port Parsing and Comparison:\n   - isSSOutput() automatically detects command output format\n   - Extracts protocol and local address from port listings\n   - Returns map[string]bool for efficient port comparison\n\n4. Change Detection and Logging:\n   - logPortDifferences() identifies newly opened and closed ports\n   - Structured logging with slog for port changes\n   - Separate log entries for new ports and closed ports\n   - Non-critical operation - errors don\u0027t interrupt agent execution\n\nTechnical Details:\n- Background goroutine lifecycle tied to agent context cancellation\n- Handles IPv4/IPv6 address formats correctly\n- Only monitors LISTEN state ports, ignores other connection states\n- 5-second polling interval balances responsiveness with resource usage\n\nTesting:\n- Added comprehensive test coverage for port parsing functions\n- Verifies port difference detection logic\n- All existing loop package tests continue to pass\n- Integration test confirms no regressions in agent functionality\n\nIntegration:\n- Port monitoring starts automatically in Agent.Loop() method\n- Only enabled for container execution mode\n- Uses same context pattern as existing background tasks\n- Follows established logging and error handling patterns\n\nThis enhancement provides real-time visibility into container port\nchanges without affecting core agent functionality or performance.\n\nBenefits:\n- Real-time port change detection for debugging\n- Thread-safe implementation with proper resource cleanup\n- Comprehensive test coverage ensures reliability\n\nCo-Authored-By: sketch \u003chello@sketch.dev\u003e\nChange-ID: s9bd1b1bd0b518b2bk\n"
    }
  ]
}
