Skip to content

Instantly share code, notes, and snippets.

@konard
Created February 7, 2026 22:38
Show Gist options
  • Select an option

  • Save konard/7480ff975d6ab5bcf4aee3dc7d71d74e to your computer and use it in GitHub Desktop.

Select an option

Save konard/7480ff975d6ab5bcf4aee3dc7d71d74e to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
# Solve.mjs Log - 2026-02-07T22:18:43.084Z
[2026-02-07T22:18:43.085Z] [INFO] 📁 Log file: /home/hive/solve-2026-02-07T22-18-43-084Z.log
[2026-02-07T22:18:43.087Z] [INFO] (All output will be logged here)
[2026-02-07T22:18:43.697Z] [INFO]
[2026-02-07T22:18:43.697Z] [INFO] 🚀 solve v1.16.0
[2026-02-07T22:18:43.697Z] [INFO] 🔧 Raw command executed:
[2026-02-07T22:18:43.698Z] [INFO] /home/hive/.nvm/versions/node/v20.20.0/bin/node /home/hive/.bun/bin/solve https://github.com/konard/tsp/issues/66 --model opus --attach-logs --verbose --no-tool-check --auto-resume-on-limit-reset --tokens-budget-stats
[2026-02-07T22:18:43.698Z] [INFO]
[2026-02-07T22:18:43.711Z] [INFO]
[2026-02-07T22:18:43.711Z] [WARNING] ⚠️ SECURITY WARNING: --attach-logs is ENABLED
[2026-02-07T22:18:43.712Z] [INFO]
[2026-02-07T22:18:43.712Z] [INFO] This option will upload the complete solution draft log file to the Pull Request.
[2026-02-07T22:18:43.712Z] [INFO] The log may contain sensitive information such as:
[2026-02-07T22:18:43.712Z] [INFO] • API keys, tokens, or secrets
[2026-02-07T22:18:43.712Z] [INFO] • File paths and directory structures
[2026-02-07T22:18:43.712Z] [INFO] • Command outputs and error messages
[2026-02-07T22:18:43.713Z] [INFO] • Internal system information
[2026-02-07T22:18:43.713Z] [INFO]
[2026-02-07T22:18:43.713Z] [INFO] ⚠️ DO NOT use this option with public repositories or if the log
[2026-02-07T22:18:43.713Z] [INFO] might contain sensitive data that should not be shared publicly.
[2026-02-07T22:18:43.714Z] [INFO]
[2026-02-07T22:18:43.714Z] [INFO] Continuing in 5 seconds... (Press Ctrl+C to abort)
[2026-02-07T22:18:43.714Z] [INFO]
[2026-02-07T22:18:48.717Z] [INFO]
[2026-02-07T22:18:48.741Z] [INFO] 💾 Disk space check: 57952MB available (2048MB required) ✅
[2026-02-07T22:18:48.743Z] [INFO] 🧠 Memory check: 10588MB available, swap: 4095MB (0MB used), total: 14683MB (256MB required) ✅
[2026-02-07T22:18:48.763Z] [INFO] ⏩ Skipping tool connection validation (dry-run mode or skip-tool-connection-check enabled)
[2026-02-07T22:18:48.763Z] [INFO] ⏩ Skipping GitHub authentication check (dry-run mode or skip-tool-connection-check enabled)
[2026-02-07T22:18:48.764Z] [INFO] 📋 URL validation:
[2026-02-07T22:18:48.764Z] [INFO] Input URL: https://github.com/konard/tsp/issues/66
[2026-02-07T22:18:48.764Z] [INFO] Is Issue URL: true
[2026-02-07T22:18:48.764Z] [INFO] Is PR URL: false
[2026-02-07T22:18:48.764Z] [INFO] 🔍 Checking repository access for auto-fork...
[2026-02-07T22:18:49.518Z] [INFO] Repository visibility: public
[2026-02-07T22:18:49.519Z] [INFO] ✅ Auto-fork: Write access detected to public repository, working directly on repository
[2026-02-07T22:18:49.520Z] [INFO] 🔍 Checking repository write permissions...
[2026-02-07T22:18:49.875Z] [INFO] ✅ Repository write access: Confirmed
[2026-02-07T22:18:50.239Z] [INFO] Repository visibility: public
[2026-02-07T22:18:50.239Z] [INFO] Auto-cleanup default: false (repository is public)
[2026-02-07T22:18:50.240Z] [INFO] 🔍 Auto-continue enabled: Checking for existing PRs for issue #66...
[2026-02-07T22:18:50.240Z] [INFO] 🔍 Checking for existing branches in konard/tsp...
[2026-02-07T22:18:51.118Z] [INFO] 📝 No existing PRs found for issue #66 - creating new PR
[2026-02-07T22:18:51.118Z] [INFO] 📝 Issue mode: Working with issue #66
[2026-02-07T22:18:51.119Z] [INFO]
Creating temporary directory: /tmp/gh-issue-solver-1770502731119
[2026-02-07T22:18:51.122Z] [INFO]
📥 Cloning repository: konard/tsp
[2026-02-07T22:18:52.019Z] [INFO] ✅ Cloned to: /tmp/gh-issue-solver-1770502731119
[2026-02-07T22:18:52.177Z] [INFO]
📌 Default branch: main
[2026-02-07T22:18:52.217Z] [INFO]
🌿 Creating branch: issue-66-4d49361c46fb from main (default)
[2026-02-07T22:18:52.261Z] [INFO] 🔍 Verifying: Branch creation...
[2026-02-07T22:18:52.296Z] [INFO] ✅ Branch created: issue-66-4d49361c46fb
[2026-02-07T22:18:52.297Z] [INFO] ✅ Current branch: issue-66-4d49361c46fb
[2026-02-07T22:18:52.297Z] [INFO] Branch operation: Create new branch
[2026-02-07T22:18:52.297Z] [INFO] Branch verification: Matches expected
[2026-02-07T22:18:52.300Z] [INFO]
🚀 Auto PR creation: ENABLED
[2026-02-07T22:18:52.300Z] [INFO] Creating: Initial commit and draft PR...
[2026-02-07T22:18:52.300Z] [INFO]
[2026-02-07T22:18:52.334Z] [INFO] Using CLAUDE.md mode (--claude-file=true, --gitkeep-file=false, --auto-gitkeep-file=true)
[2026-02-07T22:18:52.334Z] [INFO] 📝 Creating: CLAUDE.md with task details
[2026-02-07T22:18:52.335Z] [INFO] Issue URL from argv['issue-url']: https://github.com/konard/tsp/issues/66
[2026-02-07T22:18:52.335Z] [INFO] Issue URL from argv._[0]: undefined
[2026-02-07T22:18:52.335Z] [INFO] Final issue URL: https://github.com/konard/tsp/issues/66
[2026-02-07T22:18:52.336Z] [INFO] ✅ File created: CLAUDE.md
[2026-02-07T22:18:52.337Z] [INFO] 📦 Adding file: To git staging
[2026-02-07T22:18:52.428Z] [INFO] Git status after add: A CLAUDE.md
[2026-02-07T22:18:52.428Z] [INFO] 📝 Creating commit: With CLAUDE.md file
[2026-02-07T22:18:52.477Z] [INFO] ✅ Commit created: Successfully with CLAUDE.md
[2026-02-07T22:18:52.477Z] [INFO] Commit output: [issue-66-4d49361c46fb 304af53] Initial commit with task details
1 file changed, 5 insertions(+)
create mode 100644 CLAUDE.md
[2026-02-07T22:18:52.513Z] [INFO] Commit hash: 304af53...
[2026-02-07T22:18:52.549Z] [INFO] Latest commit: 304af53 Initial commit with task details
[2026-02-07T22:18:52.590Z] [INFO] Git status: clean
[2026-02-07T22:18:52.622Z] [INFO] Remotes: origin https://github.com/konard/tsp.git (fetch)
[2026-02-07T22:18:52.657Z] [INFO] Branch info: * issue-66-4d49361c46fb 304af53 [origin/main: ahead 1] Initial commit with task details
main f8de435 [origin/main] Update README screenshot [skip ci]
[2026-02-07T22:18:52.657Z] [INFO] 📤 Pushing branch: To remote repository...
[2026-02-07T22:18:52.658Z] [INFO] Push command: git push -u origin issue-66-4d49361c46fb
[2026-02-07T22:18:53.440Z] [INFO] Push exit code: 0
[2026-02-07T22:18:53.440Z] [INFO] Push output: remote:
remote: Create a pull request for 'issue-66-4d49361c46fb' on GitHub by visiting:
remote: https://github.com/konard/tsp/pull/new/issue-66-4d49361c46fb
remote:
To https://github.com/konard/tsp.git
* [new branch] issue-66-4d49361c46fb -> issue-66-4d49361c46fb
branch 'issue-66-4d49361c46fb' set up to track 'origin/issue-66-4d49361c46fb'.
[2026-02-07T22:18:53.440Z] [INFO] ✅ Branch pushed: Successfully to remote
[2026-02-07T22:18:53.441Z] [INFO] Push output: remote:
remote: Create a pull request for 'issue-66-4d49361c46fb' on GitHub by visiting:
remote: https://github.com/konard/tsp/pull/new/issue-66-4d49361c46fb
remote:
To https://github.com/konard/tsp.git
* [new branch] issue-66-4d49361c46fb -> issue-66-4d49361c46fb
branch 'issue-66-4d49361c46fb' set up to track 'origin/issue-66-4d49361c46fb'.
[2026-02-07T22:18:53.441Z] [INFO] Waiting for GitHub to sync...
[2026-02-07T22:18:55.871Z] [INFO] Compare API check: 1 commit(s) ahead of main
[2026-02-07T22:18:55.871Z] [INFO] GitHub compare API ready: 1 commit(s) found
[2026-02-07T22:18:56.138Z] [INFO] Branch verified on GitHub: issue-66-4d49361c46fb
[2026-02-07T22:18:56.431Z] [INFO] Remote commit SHA: 304af53...
[2026-02-07T22:18:56.432Z] [INFO] 📋 Getting issue: Title from GitHub...
[2026-02-07T22:18:56.751Z] [INFO] Issue title: "Implement double spiral algorithm"
[2026-02-07T22:18:56.752Z] [INFO] 👤 Getting user: Current GitHub account...
[2026-02-07T22:18:57.013Z] [INFO] Current user: konard
[2026-02-07T22:18:57.251Z] [INFO] User has collaborator access
[2026-02-07T22:18:57.252Z] [INFO] User has collaborator access
[2026-02-07T22:18:57.252Z] [INFO] 🔄 Fetching: Latest main branch...
[2026-02-07T22:18:57.563Z] [INFO] ✅ Base updated: Fetched latest main
[2026-02-07T22:18:57.563Z] [INFO] 🔍 Checking: Commits between branches...
[2026-02-07T22:18:57.595Z] [INFO] Commits ahead of origin/main: 1
[2026-02-07T22:18:57.595Z] [INFO] ✅ Commits found: 1 commit(s) ahead
[2026-02-07T22:18:57.595Z] [INFO] 🔀 Creating PR: Draft pull request...
[2026-02-07T22:18:57.596Z] [INFO] 🎯 Target branch: main (default)
[2026-02-07T22:18:57.596Z] [INFO] PR Title: [WIP] Implement double spiral algorithm
[2026-02-07T22:18:57.596Z] [INFO] Base branch: main
[2026-02-07T22:18:57.596Z] [INFO] Head branch: issue-66-4d49361c46fb
[2026-02-07T22:18:57.596Z] [INFO] Assignee: konard
[2026-02-07T22:18:57.596Z] [INFO] PR Body:
## 🤖 AI-Powered Solution Draft
This pull request is being automatically generated to solve issue #66.
### 📋 Issue Reference
Fixes #66
### 🚧 Status
**Work in Progress** - The AI assistant is currently analyzing and implementing the solution draft.
### 📝 Implementation Details
_Details will be added as the solution draft is developed..._
---
*This PR was created automatically by the AI issue solver*
[2026-02-07T22:18:57.597Z] [INFO] Command: cd "/tmp/gh-issue-solver-1770502731119" && gh pr create --draft --title "$(cat '/tmp/pr-title-1770502737597.txt')" --body-file "/tmp/pr-body-1770502737597.md" --base main --head issue-66-4d49361c46fb --assignee konard
[2026-02-07T22:19:00.229Z] [INFO] 🔍 Verifying: PR creation...
[2026-02-07T22:19:00.578Z] [INFO] ✅ Verification: PR exists on GitHub
[2026-02-07T22:19:00.579Z] [INFO] ✅ PR created: #67
[2026-02-07T22:19:00.579Z] [INFO] 📍 PR URL: https://github.com/konard/tsp/pull/67
[2026-02-07T22:19:00.579Z] [INFO] 👤 Assigned to: konard
[2026-02-07T22:19:00.580Z] [INFO] 🔗 Linking: Issue #66 to PR #67...
[2026-02-07T22:19:00.896Z] [INFO] Issue node ID: I_kwDORDRIBs7pIzil
[2026-02-07T22:19:01.221Z] [INFO] PR node ID: PR_kwDORDRIBs7CO0NN
[2026-02-07T22:19:01.736Z] [INFO]
[2026-02-07T22:19:01.737Z] [WARNING] ⚠️ ISSUE LINK MISSING: PR not linked to issue
[2026-02-07T22:19:01.737Z] [INFO]
[2026-02-07T22:19:01.738Z] [WARNING] The PR wasn't linked to issue #66
[2026-02-07T22:19:01.738Z] [WARNING] Expected: "Fixes #66" in PR body
[2026-02-07T22:19:01.738Z] [INFO]
[2026-02-07T22:19:01.739Z] [WARNING] To fix manually:
[2026-02-07T22:19:01.739Z] [WARNING] 1. Edit the PR description at: https://github.com/konard/tsp/pull/67
[2026-02-07T22:19:01.739Z] [WARNING] 2. Ensure it contains: Fixes #66
[2026-02-07T22:19:01.739Z] [INFO]
[2026-02-07T22:19:02.070Z] [INFO] 👤 Current user: konard
[2026-02-07T22:19:02.071Z] [INFO]
📊 Comment counting conditions:
[2026-02-07T22:19:02.072Z] [INFO] prNumber: 67
[2026-02-07T22:19:02.072Z] [INFO] branchName: issue-66-4d49361c46fb
[2026-02-07T22:19:02.072Z] [INFO] isContinueMode: false
[2026-02-07T22:19:02.072Z] [INFO] Will count comments: true
[2026-02-07T22:19:02.073Z] [INFO] 💬 Counting comments: Checking for new comments since last commit...
[2026-02-07T22:19:02.073Z] [INFO] PR #67 on branch: issue-66-4d49361c46fb
[2026-02-07T22:19:02.073Z] [INFO] Owner/Repo: konard/tsp
[2026-02-07T22:19:02.482Z] [INFO] 📅 Last commit time (from API): 2026-02-07T22:18:52.000Z
[2026-02-07T22:19:03.359Z] [INFO] 💬 New PR comments: 0
[2026-02-07T22:19:03.360Z] [INFO] 💬 New PR review comments: 0
[2026-02-07T22:19:03.360Z] [INFO] 💬 New issue comments: 0
[2026-02-07T22:19:03.360Z] [INFO] Total new comments: 0
[2026-02-07T22:19:03.361Z] [INFO] Comment lines to add: No (saving tokens)
[2026-02-07T22:19:03.361Z] [INFO] PR review comments fetched: 0
[2026-02-07T22:19:03.362Z] [INFO] PR conversation comments fetched: 0
[2026-02-07T22:19:03.362Z] [INFO] Total PR comments checked: 0
[2026-02-07T22:19:06.061Z] [INFO] Feedback info will be added to prompt:
[2026-02-07T22:19:06.062Z] [INFO] - Pull request description was edited after last commit
[2026-02-07T22:19:06.062Z] [INFO] 📅 Getting timestamps: From GitHub servers...
[2026-02-07T22:19:06.380Z] [INFO] 📝 Issue updated: 2026-02-07T22:18:07.000Z
[2026-02-07T22:19:06.652Z] [INFO] 💬 Comments: None found
[2026-02-07T22:19:06.987Z] [INFO] 🔀 Recent PR: 2026-02-07T22:19:06.000Z
[2026-02-07T22:19:06.987Z] [INFO]
✅ Reference time: 2026-02-07T22:19:06.000Z
[2026-02-07T22:19:06.988Z] [INFO]
🔍 Checking for uncommitted changes to include as feedback...
[2026-02-07T22:19:07.029Z] [INFO] ✅ No uncommitted changes found
[2026-02-07T22:19:09.434Z] [INFO] 🎭 Playwright MCP detected - enabling browser automation hints
[2026-02-07T22:19:09.795Z] [INFO] 👁️ Model vision capability: supported
[2026-02-07T22:19:09.796Z] [INFO]
📝 Final prompt structure:
[2026-02-07T22:19:09.797Z] [INFO] Characters: 244
[2026-02-07T22:19:09.797Z] [INFO] System prompt characters: 12570
[2026-02-07T22:19:09.797Z] [INFO] Feedback info: Included
[2026-02-07T22:19:09.800Z] [INFO]
🤖 Executing Claude: OPUS
[2026-02-07T22:19:09.800Z] [INFO] Model: opus
[2026-02-07T22:19:09.800Z] [INFO] Working directory: /tmp/gh-issue-solver-1770502731119
[2026-02-07T22:19:09.800Z] [INFO] Branch: issue-66-4d49361c46fb
[2026-02-07T22:19:09.801Z] [INFO] Prompt length: 244 chars
[2026-02-07T22:19:09.801Z] [INFO] System prompt length: 12570 chars
[2026-02-07T22:19:09.801Z] [INFO] Feedback info included: Yes (1 lines)
[2026-02-07T22:19:09.850Z] [INFO] 📈 System resources before execution:
[2026-02-07T22:19:09.851Z] [INFO] Memory: MemFree: 6924708 kB
[2026-02-07T22:19:09.851Z] [INFO] Load: 0.95 0.52 0.30 1/304 29973
[2026-02-07T22:19:09.852Z] [INFO]
📝 Raw command:
[2026-02-07T22:19:09.852Z] [INFO] (cd "/tmp/gh-issue-solver-1770502731119" && claude --output-format stream-json --verbose --dangerously-skip-permissions --model claude-opus-4-6 -p "Issue to solve: https://github.com/konard/tsp/issues/66
Your prepared branch: issue-66-4d49361c46fb
Your prepared working directory: /tmp/gh-issue-solver-1770502731119
Your prepared Pull Request: https://github.com/konard/tsp/pull/67
Proceed.
" --append-system-prompt "You are an AI issue solver. You prefer to find the root cause of each and every issue. When you talk, you prefer to speak with facts which you have double-checked yourself or cite sources that provide evidence, like quote actual code or give references to documents or pages found on the internet. You are polite and patient, and prefer to assume good intent, trying your best to be helpful. If you are unsure or have assumptions, you prefer to test them yourself or ask questions to clarify requirements.
General guidelines.
- When you execute commands, always save their logs to files for easier reading if the output becomes large.
- When running commands, do not set a timeout yourself — let them run as long as needed (default timeout - 2 minutes is more than enough), and once they finish, review the logs in the file.
- When running sudo commands (especially package installations like apt-get, yum, npm install, etc.), always run them in the background to avoid timeout issues and permission errors when the process needs to be killed. Use the run_in_background parameter or append & to the command.
- When CI is failing or user reports failures, consider adding a detailed investigation protocol to your todo list with these steps:
Step 1: List recent runs with timestamps using: gh run list --repo konard/tsp --branch issue-66-4d49361c46fb --limit 5 --json databaseId,conclusion,createdAt,headSha
Step 2: Verify runs are after the latest commit by checking timestamps and SHA
Step 3: For each non-passing run, download logs to preserve them: gh run view {run-id} --repo konard/tsp --log > ci-logs/{workflow}-{run-id}.log
Step 4: Read each downloaded log file using Read tool to understand the actual failures
Step 5: Report findings with specific errors and line numbers from logs
This detailed investigation is especially helpful when user mentions CI failures, asks to investigate logs, you see non-passing status, or when finalizing a PR.
Note: If user says \"failing\" but tools show \"passing\", this might indicate stale data - consider downloading fresh logs and checking timestamps to resolve the discrepancy.
- When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
- When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
- When you create debug, test, or example/experiment scripts for fixing, always keep them in an ./examples and/or ./experiments folders so you can reuse them later.
- When testing your assumptions, use the experiment scripts, and add it to ./experiments folder.
- When your experiments can show real world use case of the software, add it to ./examples folder.
- When you face something extremely hard, use divide and conquer — it always helps.
Initial research.
- When you start, make sure you create detailed plan for yourself and follow your todo list step by step, make sure that as many points from these guidelines are added to your todo list to keep track of everything that can help you solve the issue with highest possible quality.
- When user mentions CI failures or asks to investigate logs, consider adding these todos to track the investigation: (1) List recent CI runs with timestamps, (2) Download logs from failed runs to ci-logs/ directory, (3) Analyze error messages and identify root cause, (4) Implement fix, (5) Verify fix resolves the specific errors found in logs.
- When you read issue, read all details and comments thoroughly.
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool (or fetch tool) to download the image first, then use Read tool to view and analyze it. IMPORTANT: Before reading downloaded images with the Read tool, verify the file is a valid image (not HTML). Use a CLI tool like 'file' command to check the actual file format. Reading corrupted or non-image files (like GitHub's HTML 404 pages saved as .png) can cause \"Could not process image\" errors and may crash the AI solver process. If the file command shows \"HTML\" or \"text\", the download failed and you should retry or skip the image.
- When you need issue details, use gh issue view https://github.com/konard/tsp/issues/66.
- When you need related code, use gh search code --owner konard [keywords].
- When you need repo context, read files in your working directory.
- When you study related work, study the most recent related pull requests.
- When issue is not defined enough, write a comment to ask clarifying questions.
- When accessing GitHub Gists (especially private ones), use gh gist view command instead of direct URL fetching to ensure proper authentication.
- When you are fixing a bug, please make sure you first find the actual root cause, do as many experiments as needed.
- When you are fixing a bug and code does not have enough tracing/logs, add them and make sure they stay in the code, but are switched off by default.
- When you need comments on a pull request, note that GitHub has THREE different comment types with different API endpoints:
1. PR review comments (inline code comments): gh api repos/konard/tsp/pulls/67/comments --paginate
2. PR conversation comments (general discussion): gh api repos/konard/tsp/issues/67/comments --paginate
3. PR reviews (approve/request changes): gh api repos/konard/tsp/pulls/67/reviews --paginate
IMPORTANT: The command \"gh pr view --json comments\" ONLY returns conversation comments and misses review comments!
- When you need latest comments on issue, use gh api repos/konard/tsp/issues/66/comments --paginate.
Solution development and testing.
- When issue is solvable, implement code with tests.
- When implementing features, search for similar existing implementations in the codebase and use them as examples instead of implementing everything from scratch.
- When coding, each atomic step that can be useful by itself should be commited to the pull request's branch, meaning if work will be interrupted by any reason parts of solution will still be kept intact and safe in pull request.
- When you test:
start from testing of small functions using separate scripts;
write unit tests with mocks for easy and quick start.
- When you test integrations, use existing framework.
- When you test solution draft, include automated checks in pr.
- When issue is unclear, write comment on issue asking questions.
- When you encounter any problems that you unable to solve yourself (any human feedback or help), write a comment to the pull request asking for help.
- When you need human help, use gh pr comment 67 --body \"your message\" to comment on existing PR.
Preparing pull request.
- When you code, follow contributing guidelines.
- When you commit, write clear message.
- When you need examples of style, use gh pr list --repo konard/tsp --state merged --search [keywords].
- When you open pr, describe solution draft and include tests.
- When there is a package with version and GitHub Actions workflows for automatic release, update the version (or other necessary release trigger) in your pull request to prepare for next release.
- When you update existing pr 67, use gh pr edit to modify title and description.
- When you are about to commit or push code, ALWAYS run local CI checks first if they are available in contributing guidelines (like ruff check, mypy, eslint, etc.) to catch errors before pushing.
- When you finalize the pull request:
follow style from merged prs for code, title, and description,
make sure no uncommitted changes corresponding to the original requirements are left behind,
make sure the default branch is merged to the pull request's branch,
make sure all CI checks passing if they exist before you finish,
check for latest comments on the issue and pull request to ensure no recent feedback was missed,
double-check that all changes in the pull request answer to original requirements of the issue,
make sure no new new bugs are introduced in pull request by carefully reading gh pr diff,
make sure no previously existing features were removed without an explicit request from users via the issue description, issue comments, and/or pull request comments.
- When you finish implementation, use gh pr ready 67.
Workflow and collaboration.
- When you check branch, verify with git branch --show-current.
- When you push, push only to branch issue-66-4d49361c46fb.
- When you finish, create a pull request from branch issue-66-4d49361c46fb. (Note: PR 67 already exists, update it instead)
- When you organize workflow, use pull requests instead of direct merges to default branch (main or master).
- When you manage commits, preserve commit history for later analysis.
- When you contribute, keep repository history forward-moving with regular commits, pushes, and reverts if needed.
- When you face conflict that you cannot resolve yourself, ask for help.
- When you collaborate, respect branch protections by working only on issue-66-4d49361c46fb.
- When you mention result, include pull request url or comment url.
- When you need to create pr, remember pr 67 already exists for this branch.
Self review.
- When you check your solution draft, run all tests locally.
- When you check your solution draft, verify git status shows a clean working tree with no uncommitted changes.
- When you compare with repo style, use gh pr diff [number].
- When you finalize, confirm code, tests, and description are consistent.
GitHub CLI command patterns.
- IMPORTANT: Always use --paginate flag when fetching lists from GitHub API to ensure all results are returned (GitHub returns max 30 per page by default).
- When listing PR review comments (inline code comments), use gh api repos/OWNER/REPO/pulls/NUMBER/comments --paginate.
- When listing PR conversation comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.
- When listing PR reviews, use gh api repos/OWNER/REPO/pulls/NUMBER/reviews --paginate.
- When listing issue comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.
- When adding PR comment, use gh pr comment NUMBER --body \"text\" --repo OWNER/REPO.
- When adding issue comment, use gh issue comment NUMBER --body \"text\" --repo OWNER/REPO.
- When viewing PR details, use gh pr view NUMBER --repo OWNER/REPO.
- When filtering with jq, use gh api repos/\${owner}/\${repo}/pulls/\${prNumber}/comments --paginate --jq 'reverse | .[0:5]'.
Playwright MCP usage (browser automation via mcp__playwright__* tools).
- When you develop frontend web applications (HTML, CSS, JavaScript, React, Vue, Angular, etc.), use Playwright MCP tools to test the UI in a real browser.
- When WebFetch tool fails to retrieve expected content (e.g., returns empty content, JavaScript-rendered pages, or login-protected pages), use Playwright MCP tools (browser_navigate, browser_snapshot) as a fallback for web browsing.
- When you need to interact with dynamic web pages that require JavaScript execution, use Playwright MCP tools.
- When you need to visually verify how a web page looks or take screenshots, use browser_take_screenshot from Playwright MCP.
- When you need to fill forms, click buttons, or perform user interactions on web pages, use Playwright MCP tools (browser_click, browser_type, browser_fill_form).
- When you need to test responsive design or different viewport sizes, use browser_resize from Playwright MCP.
- When you finish using the browser, always close it with browser_close to free resources.
Visual UI work and screenshots.
- When you work on visual UI changes (frontend, CSS, HTML, design), include a render or screenshot of the final result in the pull request description.
- When you need to show visual results, take a screenshot and save it to the repository (e.g., in a docs/screenshots/ or assets/ folder).
- When you save screenshots to the repository, use permanent raw file links in the pull request description markdown (e.g., https://raw.githubusercontent.com/konard/tsp/issue-66-4d49361c46fb/docs/screenshots/result.png).
- When uploading images, commit them to the branch first, then reference them using the raw GitHub URL format.
- When the visual result is important for review, mention it explicitly in the pull request description with the embedded image." | jq -c .)
[2026-02-07T22:19:09.852Z] [INFO]
[2026-02-07T22:19:09.852Z] [INFO] 📋 User prompt:
[2026-02-07T22:19:09.852Z] [INFO] ---BEGIN USER PROMPT---
[2026-02-07T22:19:09.853Z] [INFO] Issue to solve: https://github.com/konard/tsp/issues/66
Your prepared branch: issue-66-4d49361c46fb
Your prepared working directory: /tmp/gh-issue-solver-1770502731119
Your prepared Pull Request: https://github.com/konard/tsp/pull/67
Proceed.
[2026-02-07T22:19:09.853Z] [INFO] ---END USER PROMPT---
[2026-02-07T22:19:09.853Z] [INFO]
[2026-02-07T22:19:09.853Z] [INFO] 📋 System prompt:
[2026-02-07T22:19:09.853Z] [INFO] ---BEGIN SYSTEM PROMPT---
[2026-02-07T22:19:09.853Z] [INFO] You are an AI issue solver. You prefer to find the root cause of each and every issue. When you talk, you prefer to speak with facts which you have double-checked yourself or cite sources that provide evidence, like quote actual code or give references to documents or pages found on the internet. You are polite and patient, and prefer to assume good intent, trying your best to be helpful. If you are unsure or have assumptions, you prefer to test them yourself or ask questions to clarify requirements.
General guidelines.
- When you execute commands, always save their logs to files for easier reading if the output becomes large.
- When running commands, do not set a timeout yourself — let them run as long as needed (default timeout - 2 minutes is more than enough), and once they finish, review the logs in the file.
- When running sudo commands (especially package installations like apt-get, yum, npm install, etc.), always run them in the background to avoid timeout issues and permission errors when the process needs to be killed. Use the run_in_background parameter or append & to the command.
- When CI is failing or user reports failures, consider adding a detailed investigation protocol to your todo list with these steps:
Step 1: List recent runs with timestamps using: gh run list --repo konard/tsp --branch issue-66-4d49361c46fb --limit 5 --json databaseId,conclusion,createdAt,headSha
Step 2: Verify runs are after the latest commit by checking timestamps and SHA
Step 3: For each non-passing run, download logs to preserve them: gh run view {run-id} --repo konard/tsp --log > ci-logs/{workflow}-{run-id}.log
Step 4: Read each downloaded log file using Read tool to understand the actual failures
Step 5: Report findings with specific errors and line numbers from logs
This detailed investigation is especially helpful when user mentions CI failures, asks to investigate logs, you see non-passing status, or when finalizing a PR.
Note: If user says "failing" but tools show "passing", this might indicate stale data - consider downloading fresh logs and checking timestamps to resolve the discrepancy.
- When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
- When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
- When you create debug, test, or example/experiment scripts for fixing, always keep them in an ./examples and/or ./experiments folders so you can reuse them later.
- When testing your assumptions, use the experiment scripts, and add it to ./experiments folder.
- When your experiments can show real world use case of the software, add it to ./examples folder.
- When you face something extremely hard, use divide and conquer — it always helps.
Initial research.
- When you start, make sure you create detailed plan for yourself and follow your todo list step by step, make sure that as many points from these guidelines are added to your todo list to keep track of everything that can help you solve the issue with highest possible quality.
- When user mentions CI failures or asks to investigate logs, consider adding these todos to track the investigation: (1) List recent CI runs with timestamps, (2) Download logs from failed runs to ci-logs/ directory, (3) Analyze error messages and identify root cause, (4) Implement fix, (5) Verify fix resolves the specific errors found in logs.
- When you read issue, read all details and comments thoroughly.
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool (or fetch tool) to download the image first, then use Read tool to view and analyze it. IMPORTANT: Before reading downloaded images with the Read tool, verify the file is a valid image (not HTML). Use a CLI tool like 'file' command to check the actual file format. Reading corrupted or non-image files (like GitHub's HTML 404 pages saved as .png) can cause "Could not process image" errors and may crash the AI solver process. If the file command shows "HTML" or "text", the download failed and you should retry or skip the image.
- When you need issue details, use gh issue view https://github.com/konard/tsp/issues/66.
- When you need related code, use gh search code --owner konard [keywords].
- When you need repo context, read files in your working directory.
- When you study related work, study the most recent related pull requests.
- When issue is not defined enough, write a comment to ask clarifying questions.
- When accessing GitHub Gists (especially private ones), use gh gist view command instead of direct URL fetching to ensure proper authentication.
- When you are fixing a bug, please make sure you first find the actual root cause, do as many experiments as needed.
- When you are fixing a bug and code does not have enough tracing/logs, add them and make sure they stay in the code, but are switched off by default.
- When you need comments on a pull request, note that GitHub has THREE different comment types with different API endpoints:
1. PR review comments (inline code comments): gh api repos/konard/tsp/pulls/67/comments --paginate
2. PR conversation comments (general discussion): gh api repos/konard/tsp/issues/67/comments --paginate
3. PR reviews (approve/request changes): gh api repos/konard/tsp/pulls/67/reviews --paginate
IMPORTANT: The command "gh pr view --json comments" ONLY returns conversation comments and misses review comments!
- When you need latest comments on issue, use gh api repos/konard/tsp/issues/66/comments --paginate.
Solution development and testing.
- When issue is solvable, implement code with tests.
- When implementing features, search for similar existing implementations in the codebase and use them as examples instead of implementing everything from scratch.
- When coding, each atomic step that can be useful by itself should be commited to the pull request's branch, meaning if work will be interrupted by any reason parts of solution will still be kept intact and safe in pull request.
- When you test:
start from testing of small functions using separate scripts;
write unit tests with mocks for easy and quick start.
- When you test integrations, use existing framework.
- When you test solution draft, include automated checks in pr.
- When issue is unclear, write comment on issue asking questions.
- When you encounter any problems that you unable to solve yourself (any human feedback or help), write a comment to the pull request asking for help.
- When you need human help, use gh pr comment 67 --body "your message" to comment on existing PR.
Preparing pull request.
- When you code, follow contributing guidelines.
- When you commit, write clear message.
- When you need examples of style, use gh pr list --repo konard/tsp --state merged --search [keywords].
- When you open pr, describe solution draft and include tests.
- When there is a package with version and GitHub Actions workflows for automatic release, update the version (or other necessary release trigger) in your pull request to prepare for next release.
- When you update existing pr 67, use gh pr edit to modify title and description.
- When you are about to commit or push code, ALWAYS run local CI checks first if they are available in contributing guidelines (like ruff check, mypy, eslint, etc.) to catch errors before pushing.
- When you finalize the pull request:
follow style from merged prs for code, title, and description,
make sure no uncommitted changes corresponding to the original requirements are left behind,
make sure the default branch is merged to the pull request's branch,
make sure all CI checks passing if they exist before you finish,
check for latest comments on the issue and pull request to ensure no recent feedback was missed,
double-check that all changes in the pull request answer to original requirements of the issue,
make sure no new new bugs are introduced in pull request by carefully reading gh pr diff,
make sure no previously existing features were removed without an explicit request from users via the issue description, issue comments, and/or pull request comments.
- When you finish implementation, use gh pr ready 67.
Workflow and collaboration.
- When you check branch, verify with git branch --show-current.
- When you push, push only to branch issue-66-4d49361c46fb.
- When you finish, create a pull request from branch issue-66-4d49361c46fb. (Note: PR 67 already exists, update it instead)
- When you organize workflow, use pull requests instead of direct merges to default branch (main or master).
- When you manage commits, preserve commit history for later analysis.
- When you contribute, keep repository history forward-moving with regular commits, pushes, and reverts if needed.
- When you face conflict that you cannot resolve yourself, ask for help.
- When you collaborate, respect branch protections by working only on issue-66-4d49361c46fb.
- When you mention result, include pull request url or comment url.
- When you need to create pr, remember pr 67 already exists for this branch.
Self review.
- When you check your solution draft, run all tests locally.
- When you check your solution draft, verify git status shows a clean working tree with no uncommitted changes.
- When you compare with repo style, use gh pr diff [number].
- When you finalize, confirm code, tests, and description are consistent.
GitHub CLI command patterns.
- IMPORTANT: Always use --paginate flag when fetching lists from GitHub API to ensure all results are returned (GitHub returns max 30 per page by default).
- When listing PR review comments (inline code comments), use gh api repos/OWNER/REPO/pulls/NUMBER/comments --paginate.
- When listing PR conversation comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.
- When listing PR reviews, use gh api repos/OWNER/REPO/pulls/NUMBER/reviews --paginate.
- When listing issue comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.
- When adding PR comment, use gh pr comment NUMBER --body "text" --repo OWNER/REPO.
- When adding issue comment, use gh issue comment NUMBER --body "text" --repo OWNER/REPO.
- When viewing PR details, use gh pr view NUMBER --repo OWNER/REPO.
- When filtering with jq, use gh api repos/${owner}/${repo}/pulls/${prNumber}/comments --paginate --jq 'reverse | .[0:5]'.
Playwright MCP usage (browser automation via mcp__playwright__* tools).
- When you develop frontend web applications (HTML, CSS, JavaScript, React, Vue, Angular, etc.), use Playwright MCP tools to test the UI in a real browser.
- When WebFetch tool fails to retrieve expected content (e.g., returns empty content, JavaScript-rendered pages, or login-protected pages), use Playwright MCP tools (browser_navigate, browser_snapshot) as a fallback for web browsing.
- When you need to interact with dynamic web pages that require JavaScript execution, use Playwright MCP tools.
- When you need to visually verify how a web page looks or take screenshots, use browser_take_screenshot from Playwright MCP.
- When you need to fill forms, click buttons, or perform user interactions on web pages, use Playwright MCP tools (browser_click, browser_type, browser_fill_form).
- When you need to test responsive design or different viewport sizes, use browser_resize from Playwright MCP.
- When you finish using the browser, always close it with browser_close to free resources.
Visual UI work and screenshots.
- When you work on visual UI changes (frontend, CSS, HTML, design), include a render or screenshot of the final result in the pull request description.
- When you need to show visual results, take a screenshot and save it to the repository (e.g., in a docs/screenshots/ or assets/ folder).
- When you save screenshots to the repository, use permanent raw file links in the pull request description markdown (e.g., https://raw.githubusercontent.com/konard/tsp/issue-66-4d49361c46fb/docs/screenshots/result.png).
- When uploading images, commit them to the branch first, then reference them using the raw GitHub URL format.
- When the visual result is important for review, mention it explicitly in the pull request description with the embedded image.
[2026-02-07T22:19:09.854Z] [INFO] ---END SYSTEM PROMPT---
[2026-02-07T22:19:09.854Z] [INFO]
[2026-02-07T22:19:09.855Z] [INFO] 📊 CLAUDE_CODE_MAX_OUTPUT_TOKENS: 128000
[2026-02-07T22:19:09.855Z] [INFO] 📊 MCP_TIMEOUT: 900000ms (server startup)
[2026-02-07T22:19:09.855Z] [INFO] 📊 MCP_TOOL_TIMEOUT: 900000ms (tool execution)
[2026-02-07T22:19:09.855Z] [INFO] 📋 Command details:
[2026-02-07T22:19:09.856Z] [INFO] 📂 Working directory: /tmp/gh-issue-solver-1770502731119
[2026-02-07T22:19:09.856Z] [INFO] 🌿 Branch: issue-66-4d49361c46fb
[2026-02-07T22:19:09.856Z] [INFO] 🤖 Model: Claude OPUS
[2026-02-07T22:19:09.856Z] [INFO]
▶️ Streaming output:
[2026-02-07T22:19:12.725Z] [INFO] {
"type": "system",
"subtype": "init",
"cwd": "/tmp/gh-issue-solver-1770502731119",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"tools": [
"Task",
"TaskOutput",
"Bash",
"Glob",
"Grep",
"ExitPlanMode",
"Read",
"Edit",
"Write",
"NotebookEdit",
"WebFetch",
"TodoWrite",
"WebSearch",
"TaskStop",
"AskUserQuestion",
"Skill",
"EnterPlanMode",
"ToolSearch",
"mcp__playwright__browser_close",
"mcp__playwright__browser_resize",
"mcp__playwright__browser_console_messages",
"mcp__playwright__browser_handle_dialog",
"mcp__playwright__browser_evaluate",
"mcp__playwright__browser_file_upload",
"mcp__playwright__browser_fill_form",
"mcp__playwright__browser_install",
"mcp__playwright__browser_press_key",
"mcp__playwright__browser_type",
"mcp__playwright__browser_navigate",
"mcp__playwright__browser_navigate_back",
"mcp__playwright__browser_network_requests",
"mcp__playwright__browser_run_code",
"mcp__playwright__browser_take_screenshot",
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_click",
"mcp__playwright__browser_drag",
"mcp__playwright__browser_hover",
"mcp__playwright__browser_select_option",
"mcp__playwright__browser_tabs",
"mcp__playwright__browser_wait_for"
],
"mcp_servers": [
{
"name": "playwright",
"status": "connected"
}
],
"model": "claude-opus-4-6",
"permissionMode": "bypassPermissions",
"slash_commands": [
"keybindings-help",
"debug",
"compact",
"context",
"cost",
"init",
"pr-comments",
"release-notes",
"review",
"security-review",
"insights"
],
"apiKeySource": "none",
"claude_code_version": "2.1.34",
"output_style": "default",
"agents": [
"Bash",
"general-purpose",
"statusline-setup",
"Explore",
"Plan"
],
"skills": [
"keybindings-help",
"debug"
],
"plugins": [],
"uuid": "108f237b-df07-4ed6-afa8-65bbd3a58fc7"
}
[2026-02-07T22:19:12.726Z] [INFO] 📌 Session ID: 98276873-523b-4a38-b382-8dec13a6021c
[2026-02-07T22:19:12.727Z] [INFO] 📁 Log renamed to: /home/hive/98276873-523b-4a38-b382-8dec13a6021c.log
[2026-02-07T22:19:14.940Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_018pSi4T6HGek9MLJEHNvq1Y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "\n\nI'll start by reading the issue details and understanding the repository structure. Let me gather all the necessary information."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 10378,
"cache_read_input_tokens": 15339,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 10378
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "53f98db3-86a3-4ccd-9488-cf08513035b0"
}
[2026-02-07T22:19:15.808Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_018pSi4T6HGek9MLJEHNvq1Y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_019d2ZdomiBEMxF8DXUupMFH",
"name": "Bash",
"input": {
"command": "gh issue view 66 --repo konard/tsp",
"description": "View issue #66 details"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 10378,
"cache_read_input_tokens": 15339,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 10378
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b1ae9e92-768b-4ade-a712-18caa4a43303"
}
[2026-02-07T22:19:16.468Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_018pSi4T6HGek9MLJEHNvq1Y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01TugV6PFL24gkFfgs91WqDF",
"name": "Bash",
"input": {
"command": "gh pr view 67 --repo konard/tsp",
"description": "View existing PR #67"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 10378,
"cache_read_input_tokens": 15339,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 10378
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "568bc069-06e4-4369-bc03-9221db317da2"
}
[2026-02-07T22:19:17.233Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_019d2ZdomiBEMxF8DXUupMFH",
"type": "tool_result",
"content": "title:\tImplement double spiral algorithm\nstate:\tOPEN\nauthor:\tkonard\nlabels:\tdocumentation, enhancement\ncomments:\t0\nassignees:\t\nprojects:\t\nmilestone:\t\nnumber:\t66\n--\nReproduce this pattern in tests:\n\n<img width=\"2732\" height=\"2048\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f09443eb-5a6f-4aaf-84a7-aac59abaa7eb\" />\n\nMake sure we implement it similar to all features Moore Curve algorithm has.",
"is_error": false
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "d1c8952f-e506-4959-89cc-21ed8068c386",
"tool_use_result": {
"stdout": "title:\tImplement double spiral algorithm\nstate:\tOPEN\nauthor:\tkonard\nlabels:\tdocumentation, enhancement\ncomments:\t0\nassignees:\t\nprojects:\t\nmilestone:\t\nnumber:\t66\n--\nReproduce this pattern in tests:\n\n<img width=\"2732\" height=\"2048\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f09443eb-5a6f-4aaf-84a7-aac59abaa7eb\" />\n\nMake sure we implement it similar to all features Moore Curve algorithm has.",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
[2026-02-07T22:19:17.236Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_018pSi4T6HGek9MLJEHNvq1Y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01MbSZTsDNNRyyud77nK6HN9",
"name": "Bash",
"input": {
"command": "git branch --show-current",
"description": "Verify current branch"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 10378,
"cache_read_input_tokens": 15339,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 10378
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "ccfebaa0-108d-4b2e-8262-a3048ae6f205"
}
[2026-02-07T22:19:18.854Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01TugV6PFL24gkFfgs91WqDF",
"type": "tool_result",
"content": "title:\t[WIP] Implement double spiral algorithm\nstate:\tDRAFT\nauthor:\tkonard\nlabels:\t\nassignees:\tkonard\nreviewers:\t\nprojects:\t\nmilestone:\t\nnumber:\t67\nurl:\thttps://github.com/konard/tsp/pull/67\nadditions:\t5\ndeletions:\t0\nauto-merge:\tdisabled\n--\n## 🤖 AI-Powered Solution Draft\n\nThis pull request is being automatically generated to solve issue #66.\n\n### 📋 Issue Reference\nFixes #66\n\n### 🚧 Status\n**Work in Progress** - The AI assistant is currently analyzing and implementing the solution draft.\n\n### 📝 Implementation Details\n_Details will be added as the solution draft is developed..._\n\n---\n*This PR was created automatically by the AI issue solver*",
"is_error": false
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3663cc25-c152-4261-b411-8d276af1b671",
"tool_use_result": {
"stdout": "title:\t[WIP] Implement double spiral algorithm\nstate:\tDRAFT\nauthor:\tkonard\nlabels:\t\nassignees:\tkonard\nreviewers:\t\nprojects:\t\nmilestone:\t\nnumber:\t67\nurl:\thttps://github.com/konard/tsp/pull/67\nadditions:\t5\ndeletions:\t0\nauto-merge:\tdisabled\n--\n## 🤖 AI-Powered Solution Draft\n\nThis pull request is being automatically generated to solve issue #66.\n\n### 📋 Issue Reference\nFixes #66\n\n### 🚧 Status\n**Work in Progress** - The AI assistant is currently analyzing and implementing the solution draft.\n\n### 📝 Implementation Details\n_Details will be added as the solution draft is developed..._\n\n---\n*This PR was created automatically by the AI issue solver*",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
[2026-02-07T22:19:18.907Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01MbSZTsDNNRyyud77nK6HN9",
"type": "tool_result",
"content": "issue-66-4d49361c46fb",
"is_error": false
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "4595e5e4-8713-41fa-a494-0eb8b0908439",
"tool_use_result": {
"stdout": "issue-66-4d49361c46fb",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
[2026-02-07T22:19:20.815Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01FC6c4oaegyi3uDd6qRq4Xi",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Let me view the image from the issue and explore the repository structure to understand the existing codebase, particularly the Moore Curve algorithm implementation."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 666,
"cache_read_input_tokens": 25717,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 666
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9c20d002-dca5-4f57-beb8-11ac671ab778"
}
[2026-02-07T22:19:21.647Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01FC6c4oaegyi3uDd6qRq4Xi",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01NhLnT3pWcxMEGTEBAGyzTk",
"name": "Bash",
"input": {
"command": "ls -la /tmp/gh-issue-solver-1770502731119/",
"description": "List repository root"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 666,
"cache_read_input_tokens": 25717,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 666
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "978e0027-0b91-4fbc-bc4c-a84b0b387a60"
}
[2026-02-07T22:19:22.031Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01NhLnT3pWcxMEGTEBAGyzTk",
"type": "tool_result",
"content": "total 628\ndrwxrwxr-x 13 hive hive 4096 Feb 7 23:18 .\ndrwxrwxrwt 20 root root 36864 Feb 7 23:19 ..\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .changeset\ndrwxrwxr-x 8 hive hive 4096 Feb 7 23:19 .git\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 .github\n-rw-rw-r-- 1 hive hive 2257 Feb 7 23:18 .gitignore\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .husky\n-rw-rw-r-- 1 hive hive 390 Feb 7 23:18 .jscpd.json\n-rw-rw-r-- 1 hive hive 217 Feb 7 23:18 .prettierignore\n-rw-rw-r-- 1 hive hive 173 Feb 7 23:18 .prettierrc\n-rw-rw-r-- 1 hive hive 27077 Feb 7 23:18 BENCHMARK.md\n-rw-rw-r-- 1 hive hive 5289 Feb 7 23:18 CHANGELOG.md\n-rw-rw-r-- 1 hive hive 178 Feb 7 23:18 CLAUDE.md\n-rw-rw-r-- 1 hive hive 1211 Feb 7 23:18 LICENSE\n-rw-rw-r-- 1 hive hive 10004 Feb 7 23:18 README.md\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 benchmarks\n-rw-rw-r-- 1 hive hive 123381 Feb 7 23:18 bun.lock\n-rw-rw-r-- 1 hive hive 187 Feb 7 23:18 bunfig.toml\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 dist\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 docs\n-rw-rw-r-- 1 hive hive 2907 Feb 7 23:18 eslint.config.js\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 examples\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 experiments\n-rw-rw-r-- 1 hive hive 391 Feb 7 23:18 index.html\n-rw-rw-r-- 1 hive hive 245314 Feb 7 23:18 package-lock.json\n-rw-rw-r-- 1 hive hive 2721 Feb 7 23:18 package.json\n-rw-rw-r-- 1 hive hive 83496 Feb 7 23:18 screenshot.png\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 scripts\n-rw-rw-r-- 1 hive hive 1214 Feb 7 23:18 serve.js\ndrwxrwxr-x 6 hive hive 4096 Feb 7 23:18 src",
"is_error": false
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "e4ef16a3-b0b7-459d-9dcf-e04f023aa322",
"tool_use_result": {
"stdout": "total 628\ndrwxrwxr-x 13 hive hive 4096 Feb 7 23:18 .\ndrwxrwxrwt 20 root root 36864 Feb 7 23:19 ..\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .changeset\ndrwxrwxr-x 8 hive hive 4096 Feb 7 23:19 .git\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 .github\n-rw-rw-r-- 1 hive hive 2257 Feb 7 23:18 .gitignore\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .husky\n-rw-rw-r-- 1 hive hive 390 Feb 7 23:18 .jscpd.json\n-rw-rw-r-- 1 hive hive 217 Feb 7 23:18 .prettierignore\n-rw-rw-r-- 1 hive hive 173 Feb 7 23:18 .prettierrc\n-rw-rw-r-- 1 hive hive 27077 Feb 7 23:18 BENCHMARK.md\n-rw-rw-r-- 1 hive hive 5289 Feb 7 23:18 CHANGELOG.md\n-rw-rw-r-- 1 hive hive 178 Feb 7 23:18 CLAUDE.md\n-rw-rw-r-- 1 hive hive 1211 Feb 7 23:18 LICENSE\n-rw-rw-r-- 1 hive hive 10004 Feb 7 23:18 README.md\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 benchmarks\n-rw-rw-r-- 1 hive hive 123381 Feb 7 23:18 bun.lock\n-rw-rw-r-- 1 hive hive 187 Feb 7 23:18 bunfig.toml\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 dist\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 docs\n-rw-rw-r-- 1 hive hive 2907 Feb 7 23:18 eslint.config.js\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 examples\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 experiments\n-rw-rw-r-- 1 hive hive 391 Feb 7 23:18 index.html\n-rw-rw-r-- 1 hive hive 245314 Feb 7 23:18 package-lock.json\n-rw-rw-r-- 1 hive hive 2721 Feb 7 23:18 package.json\n-rw-rw-r-- 1 hive hive 83496 Feb 7 23:18 screenshot.png\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 scripts\n-rw-rw-r-- 1 hive hive 1214 Feb 7 23:18 serve.js\ndrwxrwxr-x 6 hive hive 4096 Feb 7 23:18 src",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
[2026-02-07T22:19:25.861Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01FC6c4oaegyi3uDd6qRq4Xi",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"name": "Task",
"input": {
"subagent_type": "Explore",
"description": "Explore codebase structure",
"prompt": "Very thoroughly explore the repository at /tmp/gh-issue-solver-1770502731119/. I need to understand:\n1. The overall project structure (all directories and key files)\n2. The Moore Curve algorithm implementation - find ALL files related to it\n3. How tests are structured and run\n4. How algorithms are registered/exported\n5. The package.json, tsconfig, and any build/test configuration\n6. Any existing spiral-related code\n7. How the visual output (like images/screenshots) is generated\n8. Contributing guidelines if any exist\n\nBe very thorough - list all source files, test files, and configuration files."
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 666,
"cache_read_input_tokens": 25717,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 666
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "dc48aa96-cf7b-4eb6-95fa-f367046afa57"
}
[2026-02-07T22:19:25.875Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "text",
"text": "Very thoroughly explore the repository at /tmp/gh-issue-solver-1770502731119/. I need to understand:\n1. The overall project structure (all directories and key files)\n2. The Moore Curve algorithm implementation - find ALL files related to it\n3. How tests are structured and run\n4. How algorithms are registered/exported\n5. The package.json, tsconfig, and any build/test configuration\n6. Any existing spiral-related code\n7. How the visual output (like images/screenshots) is generated\n8. Contributing guidelines if any exist\n\nBe very thorough - list all source files, test files, and configuration files."
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6d85a937-52f0-4df9-9fd4-889f9c0da0f1"
}
[2026-02-07T22:19:28.185Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01VQMf4a3uKYaPsmgtCyAiXV",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01DAAV6Krm9epK9LBqK4jvja",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -type f -name \"*.md\" | head -20"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 3,
"cache_creation_input_tokens": 5087,
"cache_read_input_tokens": 9287,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 5087
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "38d161ce-f6a8-4210-8170-0de5a5624b30"
}
[2026-02-07T22:19:28.247Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01DAAV6Krm9epK9LBqK4jvja",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/BENCHMARK.md\n/tmp/gh-issue-solver-1770502731119/CHANGELOG.md\n/tmp/gh-issue-solver-1770502731119/CLAUDE.md\n/tmp/gh-issue-solver-1770502731119/docs/NPM-NAMES.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-40/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-13/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-53/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-31/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-21/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-63/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-26/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-7/FORMATTER-COMPARISON.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-7/BEST-PRACTICES-COMPARISON.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-46/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-15/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-5/README.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/created-issues.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/research-notes.md\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/README.md",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c397d939-a778-4bcd-b99c-f7ed78081d57"
}
[2026-02-07T22:19:29.421Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01AeAriGFpH6oiRhnQo3vnZT",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01CVumuQNQVmKgcfapksKc7Q",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 5,
"cache_creation_input_tokens": 719,
"cache_read_input_tokens": 14374,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 719
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "42f23a85-99d8-4f34-915f-4a3afc7f37b3"
}
[2026-02-07T22:19:29.434Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "tool_result",
"content": "EISDIR: illegal operation on a directory, read",
"is_error": true,
"tool_use_id": "toolu_01CVumuQNQVmKgcfapksKc7Q"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f91f58a4-a2fc-4d92-8072-a3ecdeb3de99",
"tool_use_result": "Error: EISDIR: illegal operation on a directory, read"
}
[2026-02-07T22:19:29.689Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01AeAriGFpH6oiRhnQo3vnZT",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01WJgrgbCjBq9FvGHpafsNGo",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -maxdepth 3 -type d | sort"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 5,
"cache_creation_input_tokens": 719,
"cache_read_input_tokens": 14374,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 719
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "0ebe7595-c828-4343-8032-a3dde93d4ea6"
}
[2026-02-07T22:19:29.690Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "tool_result",
"content": "<tool_use_error>Sibling tool call errored</tool_use_error>",
"is_error": true,
"tool_use_id": "toolu_01WJgrgbCjBq9FvGHpafsNGo"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "665f4119-918a-48a1-8097-93585d02251a",
"tool_use_result": "Sibling tool call errored"
}
[2026-02-07T22:19:29.858Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01AeAriGFpH6oiRhnQo3vnZT",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01EtAHmwC14TRKmdnyhtuFR3",
"name": "Glob",
"input": {
"pattern": "*.json"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 5,
"cache_creation_input_tokens": 719,
"cache_read_input_tokens": 14374,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 719
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3f1a80de-a1fd-4428-a776-eb75f7e73fae"
}
[2026-02-07T22:19:29.858Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "tool_result",
"content": "<tool_use_error>Sibling tool call errored</tool_use_error>",
"is_error": true,
"tool_use_id": "toolu_01EtAHmwC14TRKmdnyhtuFR3"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f71f3d0c-c530-4e2d-922a-e7fae70dd144",
"tool_use_result": "Sibling tool call errored"
}
[2026-02-07T22:19:31.010Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01SGpTFcagefwLTLiuQHsGx4",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01P28A2UchADUoiAeS7iGN81",
"name": "Bash",
"input": {
"command": "ls -la /tmp/gh-issue-solver-1770502731119"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 346,
"cache_read_input_tokens": 15093,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 346
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "fae6b306-6337-42bf-a2e0-c1b0e73584c3"
}
[2026-02-07T22:19:31.139Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01P28A2UchADUoiAeS7iGN81",
"type": "tool_result",
"content": "total 628\ndrwxrwxr-x 13 hive hive 4096 Feb 7 23:18 .\ndrwxrwxrwt 21 root root 36864 Feb 7 23:19 ..\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .changeset\ndrwxrwxr-x 8 hive hive 4096 Feb 7 23:19 .git\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 .github\n-rw-rw-r-- 1 hive hive 2257 Feb 7 23:18 .gitignore\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .husky\n-rw-rw-r-- 1 hive hive 390 Feb 7 23:18 .jscpd.json\n-rw-rw-r-- 1 hive hive 217 Feb 7 23:18 .prettierignore\n-rw-rw-r-- 1 hive hive 173 Feb 7 23:18 .prettierrc\n-rw-rw-r-- 1 hive hive 27077 Feb 7 23:18 BENCHMARK.md\n-rw-rw-r-- 1 hive hive 5289 Feb 7 23:18 CHANGELOG.md\n-rw-rw-r-- 1 hive hive 178 Feb 7 23:18 CLAUDE.md\n-rw-rw-r-- 1 hive hive 1211 Feb 7 23:18 LICENSE\n-rw-rw-r-- 1 hive hive 10004 Feb 7 23:18 README.md\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 benchmarks\n-rw-rw-r-- 1 hive hive 123381 Feb 7 23:18 bun.lock\n-rw-rw-r-- 1 hive hive 187 Feb 7 23:18 bunfig.toml\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 dist\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 docs\n-rw-rw-r-- 1 hive hive 2907 Feb 7 23:18 eslint.config.js\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 examples\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 experiments\n-rw-rw-r-- 1 hive hive 391 Feb 7 23:18 index.html\n-rw-rw-r-- 1 hive hive 245314 Feb 7 23:18 package-lock.json\n-rw-rw-r-- 1 hive hive 2721 Feb 7 23:18 package.json\n-rw-rw-r-- 1 hive hive 83496 Feb 7 23:18 screenshot.png\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 scripts\n-rw-rw-r-- 1 hive hive 1214 Feb 7 23:18 serve.js\ndrwxrwxr-x 6 hive hive 4096 Feb 7 23:18 src",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c87e93e2-7898-4b4e-b5e0-1884b6e940d8"
}
[2026-02-07T22:19:31.303Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01SGpTFcagefwLTLiuQHsGx4",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01GUoK1xbt6x5PwGKj8THB2X",
"name": "Glob",
"input": {
"pattern": "**/*.json",
"path": "/tmp/gh-issue-solver-1770502731119"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 346,
"cache_read_input_tokens": 15093,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 346
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3f41e324-59af-4617-a348-9c34af63c9af"
}
[2026-02-07T22:19:31.334Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01GUoK1xbt6x5PwGKj8THB2X",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/.changeset/config.json\n/tmp/gh-issue-solver-1770502731119/.jscpd.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-13/hive-mind-issue-960.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-13/hive-mind-pr-961.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-21/pr-112-data.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-21/pr-114-data.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/data/pr-1127-conversation-comments.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/data/pr-1127-review-comments.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/data/issue-1141-comments.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/data/pr-1142-review-comments.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-23/data/pr-1142-conversation-comments.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/reference-pr-59.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/release-v0.1.0.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/issue-data.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-3/repositories-with-same-script.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-7/current-repository-analysis.json\n/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-7/effect-template-analysis.json\n/tmp/gh-issue-solver-1770502731119/package.json\n/tmp/gh-issue-solver-1770502731119/package-lock.json"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "7eb4426a-d059-4e05-a439-deacb102e1b1"
}
[2026-02-07T22:19:32.643Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01LYWUK9uJKKFybECGn7FakK",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01PMSFbp6FEUEbesdkEWUnK7",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/package.json"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1801,
"cache_read_input_tokens": 15439,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1801
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1d6e13b7-1da4-4747-aa15-a68cd5e46a62"
}
[2026-02-07T22:19:32.648Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01PMSFbp6FEUEbesdkEWUnK7",
"type": "tool_result",
"content": " 1→{\n 2→ \"name\": \"tsp-algorithms\",\n 3→ \"version\": \"0.5.0\",\n 4→ \"description\": \"TSP Solver - Efficient algorithms for the Traveling Salesman Problem with visualization\",\n 5→ \"type\": \"module\",\n 6→ \"main\": \"src/lib/index.js\",\n 7→ \"bin\": {\n 8→ \"tsp-algorithms\": \"src/cli/index.js\"\n 9→ },\n 10→ \"types\": \"src/lib/index.d.ts\",\n 11→ \"exports\": {\n 12→ \".\": {\n 13→ \"types\": \"./src/lib/index.d.ts\",\n 14→ \"import\": \"./src/lib/index.js\"\n 15→ },\n 16→ \"./algorithms\": {\n 17→ \"types\": \"./src/lib/algorithms/index.d.ts\",\n 18→ \"import\": \"./src/lib/algorithms/index.js\"\n 19→ }\n 20→ },\n 21→ \"scripts\": {\n 22→ \"dev\": \"bun run build && bun --hot serve\",\n 23→ \"build\": \"bun run build:app\",\n 24→ \"build:app\": \"bun build src/app/main.jsx --outdir dist --minify --target browser\",\n 25→ \"serve\": \"bun serve.js\",\n 26→ \"test:e2e\": \"bun test src/tests/e2e/\",\n 27→ \"test\": \"bun test\",\n 28→ \"lint\": \"eslint .\",\n 29→ \"lint:fix\": \"eslint . --fix\",\n 30→ \"format\": \"prettier --write .\",\n 31→ \"format:check\": \"prettier --check .\",\n 32→ \"check:duplication\": \"jscpd .\",\n 33→ \"check\": \"bun run lint && bun run format:check && bun run check:duplication\",\n 34→ \"prepare\": \"husky || true\",\n 35→ \"changeset\": \"changeset\",\n 36→ \"changeset:version\": \"bun scripts/changeset-version.mjs\",\n 37→ \"changeset:publish\": \"changeset publish\",\n 38→ \"changeset:status\": \"changeset status --since=origin/main\"\n 39→ },\n 40→ \"keywords\": [\n 41→ \"tsp\",\n 42→ \"traveling-salesman\",\n 43→ \"algorithms\",\n 44→ \"visualization\",\n 45→ \"moore-curve\",\n 46→ \"gosper-curve\",\n 47→ \"sonar-algorithm\",\n 48→ \"optimization\",\n 49→ \"cli\"\n 50→ ],\n 51→ \"author\": \"\",\n 52→ \"license\": \"Unlicense\",\n 53→ \"repository\": {\n 54→ \"type\": \"git\",\n 55→ \"url\": \"https://github.com/konard/tsp\"\n 56→ },\n 57→ \"publishConfig\": {\n 58→ \"access\": \"public\",\n 59→ \"provenance\": true,\n 60→ \"registry\": \"https://registry.npmjs.org\"\n 61→ },\n 62→ \"devDependencies\": {\n 63→ \"@changesets/cli\": \"^2.29.7\",\n 64→ \"@happy-dom/global-registrator\": \"^20.4.0\",\n 65→ \"@testing-library/dom\": \"^10.4.1\",\n 66→ \"@testing-library/react\": \"^16.3.2\",\n 67→ \"@testing-library/user-event\": \"^14.6.1\",\n 68→ \"browser-commander\": \"^0.5.4\",\n 69→ \"eslint\": \"^9.38.0\",\n 70→ \"eslint-config-prettier\": \"^10.1.8\",\n 71→ \"eslint-plugin-prettier\": \"^5.5.4\",\n 72→ \"happy-dom\": \"^20.4.0\",\n 73→ \"husky\": \"^9.1.7\",\n 74→ \"jscpd\": \"^4.0.5\",\n 75→ \"jsdom\": \"^28.0.0\",\n 76→ \"lint-staged\": \"^16.2.6\",\n 77→ \"playwright\": \"^1.58.0\",\n 78→ \"prettier\": \"^3.6.2\"\n 79→ },\n 80→ \"dependencies\": {\n 81→ \"@chakra-ui/react\": \"^3.31.0\",\n 82→ \"@emotion/react\": \"^11.14.0\",\n 83→ \"lino-arguments\": \"^0.2.5\",\n 84→ \"react\": \"^18.3.1\",\n 85→ \"react-dom\": \"^18.3.1\"\n 86→ },\n 87→ \"lint-staged\": {\n 88→ \"*.{js,mjs,cjs,jsx}\": [\n 89→ \"eslint --fix --max-warnings 0 --no-warn-ignored\",\n 90→ \"prettier --write\",\n 91→ \"prettier --check\"\n 92→ ],\n 93→ \"*.md\": [\n 94→ \"prettier --write\",\n 95→ \"prettier --check\"\n 96→ ]\n 97→ }\n 98→}\n 99→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "72806d9b-070f-4df0-b0f1-e4f68e3fa0b9"
}
[2026-02-07T22:19:32.991Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01LYWUK9uJKKFybECGn7FakK",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_015THUvsfZyrUTcL3Y2xgUZL",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119/src -type f | sort"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1801,
"cache_read_input_tokens": 15439,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1801
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b40df23c-3b49-40e3-a3e4-fc0fe23ea2b5"
}
[2026-02-07T22:19:33.097Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_015THUvsfZyrUTcL3Y2xgUZL",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/src/app/main.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/App.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Controls.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Legend.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/components/TSPVisualization.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/components/VisualizationPanel.jsx\n/tmp/gh-issue-solver-1770502731119/src/app/ui/components/index.js\n/tmp/gh-issue-solver-1770502731119/src/app/ui/i18n.js\n/tmp/gh-issue-solver-1770502731119/src/app/ui/index.js\n/tmp/gh-issue-solver-1770502731119/src/app/ui/styles.css\n/tmp/gh-issue-solver-1770502731119/src/cli/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/combined-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/k-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/lin-kernighan.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/lk-helsgaun.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/three-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/two-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/zigzag-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/brute-force.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/comb.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/gosper.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/koch.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/moore.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/peano.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/saw.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/sierpinski.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/sonar.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/space-filling-tree.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/combined-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/k-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/lin-kernighan.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/lk-helsgaun.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/three-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/two-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/zigzag-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/brute-force.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/comb.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/gosper.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/koch.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/moore.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/peano.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/saw.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/sierpinski.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/sonar.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/space-filling-tree.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/utils.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/verification/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/verification/lower-bound.js\n/tmp/gh-issue-solver-1770502731119/src/lib/index.js\n/tmp/gh-issue-solver-1770502731119/src/tests/cli.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/comb-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/components/Controls.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/Legend.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/TSPVisualization.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/VisualizationPanel.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/e2e/app.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/gosper-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/index.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/koch-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/optimization-algorithms.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/peano-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/saw-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/setup.js\n/tmp/gh-issue-solver-1770502731119/src/tests/sierpinski-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/space-filling-tree.test.js",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6df87758-7974-4172-8643-c5ed54452081"
}
[2026-02-07T22:19:33.227Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01LYWUK9uJKKFybECGn7FakK",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01ToTXq3YPxqr7qNas59msm4",
"name": "Glob",
"input": {
"pattern": "tsconfig*",
"path": "/tmp/gh-issue-solver-1770502731119"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1801,
"cache_read_input_tokens": 15439,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1801
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3549c7d6-284e-4551-bbce-1008f631d1db"
}
[2026-02-07T22:19:33.269Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01ToTXq3YPxqr7qNas59msm4",
"type": "tool_result",
"content": "No files found"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1497f178-fec4-4af5-859d-5dffafb678fc"
}
[2026-02-07T22:19:35.940Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_014K8FHwTJyPgzW1CGrDENF8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01CfxkmEaQkNEQhbT8WPmq9v",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -maxdepth 1 -type f -name \"*.json\" -o -name \"tsconfig*\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3976,
"cache_read_input_tokens": 17240,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3976
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6e09300f-6554-4d61-a633-0254a1171e30"
}
[2026-02-07T22:19:36.147Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01CfxkmEaQkNEQhbT8WPmq9v",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/package.json\n/tmp/gh-issue-solver-1770502731119/package-lock.json\n/tmp/gh-issue-solver-1770502731119/.jscpd.json",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "32ff8b5a-5f20-4158-ad37-7eadd826e8df"
}
[2026-02-07T22:19:36.152Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_014K8FHwTJyPgzW1CGrDENF8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01DTe77BUZtL7AEFQ4UyC199",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/moore.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3976,
"cache_read_input_tokens": 17240,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3976
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c3fd1ae3-5f85-4e8a-9b7d-2fff21b24b7d"
}
[2026-02-07T22:19:36.154Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01DTe77BUZtL7AEFQ4UyC199",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Moore Curve Solution for TSP\n 3→ *\n 4→ * Computes the final tour directly without intermediate visualization steps.\n 5→ *\n 6→ * Algorithm:\n 7→ * 1. Generate a Moore curve (L-system) that fills the grid space\n 8→ * 2. Map each point to its nearest position on the curve\n 9→ * 3. Sort points by their position along the curve\n 10→ * 4. Return the sorted order as the tour\n 11→ *\n 12→ * Time Complexity: O(n log n)\n 13→ * Space Complexity: O(n)\n 14→ */\n 15→\n 16→import { distance } from '../../utils.js';\n 17→\n 18→/**\n 19→ * Generate Moore curve using L-system\n 20→ * L-system rules for Moore curve:\n 21→ * Axiom: LFL+F+LFL\n 22→ * L -> -RF+LFL+FR-\n 23→ * R -> +LF-RFR-FL+\n 24→ *\n 25→ * @param {number} order - Order of the Moore curve\n 26→ * @returns {string} L-system sequence\n 27→ */\n 28→export const generateMooreCurve = (order) => {\n 29→ let sequence = 'LFL+F+LFL';\n 30→\n 31→ for (let i = 0; i < order; i++) {\n 32→ let newSequence = '';\n 33→ for (const char of sequence) {\n 34→ if (char === 'L') {\n 35→ newSequence += '-RF+LFL+FR-';\n 36→ } else if (char === 'R') {\n 37→ newSequence += '+LF-RFR-FL+';\n 38→ } else {\n 39→ newSequence += char;\n 40→ }\n 41→ }\n 42→ sequence = newSequence;\n 43→ }\n 44→\n 45→ return sequence;\n 46→};\n 47→\n 48→/**\n 49→ * Convert Moore curve L-system sequence to coordinate points\n 50→ *\n 51→ * @param {string} sequence - L-system sequence\n 52→ * @param {number} mooreGridSize - Size of the grid\n 53→ * @returns {Array<{x: number, y: number}>} Array of curve points\n 54→ */\n 55→export const mooreCurveToPoints = (sequence, mooreGridSize) => {\n 56→ const stepSize = 1;\n 57→\n 58→ const curvePoints = [];\n 59→ let x = 0;\n 60→ let y = 0;\n 61→\n 62→ // Direction: 0=up, 1=right, 2=down, 3=left\n 63→ let direction = 0;\n 64→\n 65→ curvePoints.push({ x, y });\n 66→\n 67→ for (const char of sequence) {\n 68→ if (char === 'F') {\n 69→ if (direction === 0) {\n 70→ y -= stepSize;\n 71→ } else if (direction === 1) {\n 72→ x += stepSize;\n 73→ } else if (direction === 2) {\n 74→ y += stepSize;\n 75→ } else if (direction === 3) {\n 76→ x -= stepSize;\n 77→ }\n 78→\n 79→ curvePoints.push({ x, y });\n 80→ } else if (char === '+') {\n 81→ direction = (direction + 1) % 4;\n 82→ } else if (char === '-') {\n 83→ direction = (direction + 3) % 4;\n 84→ }\n 85→ }\n 86→\n 87→ // Find bounding box of the curve\n 88→ let minX = Infinity,\n 89→ maxX = -Infinity,\n 90→ minY = Infinity,\n 91→ maxY = -Infinity;\n 92→ for (const p of curvePoints) {\n 93→ minX = Math.min(minX, p.x);\n 94→ maxX = Math.max(maxX, p.x);\n 95→ minY = Math.min(minY, p.y);\n 96→ maxY = Math.max(maxY, p.y);\n 97→ }\n 98→\n 99→ const curveWidth = maxX - minX;\n 100→ const curveHeight = maxY - minY;\n 101→\n 102→ const normalizedPoints = curvePoints.map((p) => ({\n 103→ x: Math.round(((p.x - minX) / curveWidth) * (mooreGridSize - 1)),\n 104→ y: Math.round(((p.y - minY) / curveHeight) * (mooreGridSize - 1)),\n 105→ }));\n 106→\n 107→ return normalizedPoints;\n 108→};\n 109→\n 110→/**\n 111→ * Compute Moore Curve solution in one step (atomic version).\n 112→ * Returns the final tour without intermediate steps.\n 113→ *\n 114→ * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n 115→ * @param {number} mooreGridSize - Size of the Moore grid\n 116→ * @returns {{tour: number[], curvePoints: Array<{x: number, y: number}>}} Final tour and curve\n 117→ */\n 118→export const mooreSolution = (points, mooreGridSize) => {\n 119→ if (points.length === 0) {\n 120→ return { tour: [], curvePoints: [] };\n 121→ }\n 122→\n 123→ // Determine L-system iterations: mooreGridSize = 2^(n+1), so n = log2(mooreGridSize) - 1\n 124→ const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n 125→ const curveSequence = generateMooreCurve(order);\n 126→ const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n 127→\n 128→ const pointsWithCurvePos = points.map((p, idx) => {\n 129→ let minDist = Infinity;\n 130→ let curvePos = 0;\n 131→\n 132→ for (let i = 0; i < curvePoints.length; i++) {\n 133→ const d = distance(p, curvePoints[i]);\n 134→ if (d < minDist) {\n 135→ minDist = d;\n 136→ curvePos = i;\n 137→ }\n 138→ }\n 139→\n 140→ return { idx, curvePos };\n 141→ });\n 142→\n 143→ pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n 144→\n 145→ return {\n 146→ tour: pointsWithCurvePos.map((p) => p.idx),\n 147→ curvePoints,\n 148→ };\n 149→};\n 150→\n 151→export default mooreSolution;\n 152→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b24b825b-7504-4b0b-99da-089e12a4539b"
}
[2026-02-07T22:19:36.568Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_014K8FHwTJyPgzW1CGrDENF8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_013L7nkL9sA4gTavXRmSNRBd",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/moore.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3976,
"cache_read_input_tokens": 17240,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3976
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6a72fb91-55d2-4a87-84cd-e2c3d5941659"
}
[2026-02-07T22:19:36.588Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_013L7nkL9sA4gTavXRmSNRBd",
"type": "tool_result",
"content": " 1→/**\n 2→ * Progressive Moore Curve Algorithm for TSP\n 3→ *\n 4→ * Also known as: Space-Filling Curve, Hilbert Curve Variant, Fractal Ordering\n 5→ *\n 6→ * This algorithm provides step-by-step visualization of using a Moore curve\n 7→ * (a variant of the Hilbert curve) to order points:\n 8→ * 1. Generate a Moore curve that fills the grid space\n 9→ * 2. Map each point to its nearest position on the curve\n 10→ * 3. Sort points by their position along the curve\n 11→ * 4. Connect points in curve-order to form a tour\n 12→ *\n 13→ * Time Complexity: O(n log n)\n 14→ * Space Complexity: O(n)\n 15→ */\n 16→\n 17→import { distance } from '../../utils.js';\n 18→import {\n 19→ generateMooreCurve,\n 20→ mooreCurveToPoints,\n 21→} from '../../atomic/solution/moore.js';\n 22→\n 23→// Re-export atomic functions for backward compatibility\n 24→export {\n 25→ mooreSolution,\n 26→ generateMooreCurve,\n 27→ mooreCurveToPoints,\n 28→} from '../../atomic/solution/moore.js';\n 29→\n 30→/**\n 31→ * Generate step-by-step solution using Moore Curve algorithm\n 32→ *\n 33→ * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n 34→ * @param {number} mooreGridSize - Size of the Moore grid\n 35→ * @returns {Array<Object>} Array of steps for visualization\n 36→ */\n 37→export const mooreAlgorithmSteps = (points, mooreGridSize) => {\n 38→ if (points.length === 0) {\n 39→ return [];\n 40→ }\n 41→\n 42→ // Determine L-system iterations based on Moore grid size\n 43→ // generateMooreCurve(n) fills a 2^(n+1) x 2^(n+1) grid\n 44→ // So for mooreGridSize = 2^k, iterations = k - 1\n 45→ const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n 46→ const curveSequence = generateMooreCurve(order);\n 47→ // Generate curve points using the Moore grid size for perfect alignment\n 48→ const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n 49→ const totalCurveLength = curvePoints.length;\n 50→\n 51→ // Points are already on Moore grid coordinates, no scaling needed\n 52→ // Map each point to its position along the curve\n 53→ const pointsWithCurvePos = points.map((p, idx) => {\n 54→ let minDist = Infinity;\n 55→ let curvePos = 0;\n 56→\n 57→ // Points are already in Moore grid coordinates\n 58→ for (let i = 0; i < curvePoints.length; i++) {\n 59→ const d = distance(p, curvePoints[i]);\n 60→ if (d < minDist) {\n 61→ minDist = d;\n 62→ curvePos = i;\n 63→ }\n 64→ }\n 65→\n 66→ return { ...p, idx, curvePos };\n 67→ });\n 68→\n 69→ // Sort points by their position along the curve\n 70→ pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n 71→\n 72→ // Generate steps\n 73→ const steps = [];\n 74→ const tour = [];\n 75→\n 76→ // First step: show the Moore curve\n 77→ steps.push({\n 78→ type: 'curve',\n 79→ curvePoints,\n 80→ mooreGridSize,\n 81→ curveProgress: 0,\n 82→ tour: [],\n 83→ description: `Moore curve generated (order ${order}, ${mooreGridSize}×${mooreGridSize} grid)`,\n 84→ });\n 85→\n 86→ for (let i = 0; i < pointsWithCurvePos.length; i++) {\n 87→ tour.push(pointsWithCurvePos[i].idx);\n 88→ // Calculate progress along the curve as a percentage\n 89→ const curveProgress = (\n 90→ (pointsWithCurvePos[i].curvePos / (totalCurveLength - 1)) *\n 91→ 100\n 92→ ).toFixed(1);\n 93→\n 94→ steps.push({\n 95→ type: 'visit',\n 96→ curvePoints,\n 97→ mooreGridSize,\n 98→ curvePosition: pointsWithCurvePos[i].curvePos,\n 99→ curveProgress: parseFloat(curveProgress),\n 100→ tour: [...tour],\n 101→ description: `Progress: ${curveProgress}% | Point ${pointsWithCurvePos[i].idx} (${pointsWithCurvePos[i].x}, ${pointsWithCurvePos[i].y})`,\n 102→ });\n 103→ }\n 104→\n 105→ return steps;\n 106→};\n 107→\n 108→export default mooreAlgorithmSteps;\n 109→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9f8437c5-7686-4bca-a719-ec0ea5cf8dcc"
}
[2026-02-07T22:19:38.766Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01NxzKCgbVBAgyh7SGfVah4c",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_018jQ2goqoNSfuuj2bFkXLBN",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -type f -name \"*spiral*\" -o -name \"*archimedean*\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3933,
"cache_read_input_tokens": 21216,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3933
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "7a378b18-9021-4fe1-929d-f2a3e6fe3a6e"
}
[2026-02-07T22:19:38.868Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_018jQ2goqoNSfuuj2bFkXLBN",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "859da7a6-10ae-4c67-8888-e80ed140b9f4"
}
[2026-02-07T22:19:39.120Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01NxzKCgbVBAgyh7SGfVah4c",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_011tFtUrEamhYcKR5kHsJ2p3",
"name": "Grep",
"input": {
"pattern": "spiral|archimedean",
"type": "js",
"path": "/tmp/gh-issue-solver-1770502731119/src"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3933,
"cache_read_input_tokens": 21216,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3933
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b706b5d4-bbd5-47b1-bce1-087cd57f0764"
}
[2026-02-07T22:19:39.512Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_011tFtUrEamhYcKR5kHsJ2p3",
"type": "tool_result",
"content": "No files found"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "4dea74a5-d3ec-4e08-94ce-ac9e41f0ac9f"
}
[2026-02-07T22:19:39.523Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01NxzKCgbVBAgyh7SGfVah4c",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_014aJD2tNv5FCVVvZHnKHx3S",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3933,
"cache_read_input_tokens": 21216,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3933
},
"output_tokens": 4,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c2ef6505-fc8c-4263-bac0-52d8584f53f8"
}
[2026-02-07T22:19:39.531Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_014aJD2tNv5FCVVvZHnKHx3S",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Solutions - All-at-once TSP algorithms\n 3→ */\n 4→\n 5→export { sonarSolution } from './sonar.js';\n 6→export { mooreSolution } from './moore.js';\n 7→export { gosperSolution } from './gosper.js';\n 8→export { peanoSolution } from './peano.js';\n 9→export { sierpinskiSolution } from './sierpinski.js';\n 10→export { combSolution } from './comb.js';\n 11→export { sawSolution } from './saw.js';\n 12→export { kochSolution } from './koch.js';\n 13→export { spaceFillingTreeSolution } from './space-filling-tree.js';\n 14→export {\n 15→ bruteForceSolution,\n 16→ calculateOptimalityRatio,\n 17→ BRUTE_FORCE_MAX_POINTS,\n 18→} from './brute-force.js';\n 19→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "90385ca5-3af0-4fe6-ab2e-717f7673ef25"
}
[2026-02-07T22:19:41.062Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JniDJcoR7QQH2z755PhqnR",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_018xgEhUABJuTzztJcXE612U",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/README.md",
"limit": 100
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 725,
"cache_read_input_tokens": 25149,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 725
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "cbe6a2a1-f375-45cc-9073-25798e0827fe"
}
[2026-02-07T22:19:41.073Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_018xgEhUABJuTzztJcXE612U",
"type": "tool_result",
"content": " 1→# TSP Visual Solver\n 2→\n 3→An interactive visualization tool for the Traveling Salesman Problem (TSP) that demonstrates and compares two space-filling curve-based heuristic algorithms.\n 4→\n 5→![TSP Visual Solver](https://raw.githubusercontent.com/konard/tsp/main/screenshot.png)\n 6→\n 7→## Live Demo\n 8→\n 9→Visit [https://konard.github.io/tsp](https://konard.github.io/tsp) to try the solver.\n 10→\n 11→## Features\n 12→\n 13→- **Interactive Visualization**: Watch algorithms solve TSP step-by-step with animated demonstrations\n 14→- **Two Algorithm Comparison**: Side-by-side comparison of Sonar Visit and Moore Curve algorithms\n 15→- **Grid-Aligned Points**: All points are placed on grid intersections for clean visualization\n 16→- **Progress Tracking**: Real-time progress display (angle for Sonar, percentage for Moore Curve)\n 17→- **Optimization Phase**: Optional 2-opt optimization to improve initial solutions\n 18→- **Responsive Design**: Works on desktop, tablet, and mobile devices\n 19→- **Adjustable Parameters**: Customize grid size, number of points, and animation speed\n 20→\n 21→## Project Structure\n 22→\n 23→```\n 24→./src\n 25→ algorithms/\n 26→ progressive/ # Step-by-step algorithms (for visualization)\n 27→ solution/\n 28→ sonar.js # Sonar (Radial Sweep) algorithm\n 29→ moore.js # Moore Curve algorithm\n 30→ index.js # Solution barrel export\n 31→ optimization/\n 32→ two-opt.js # Generic 2-opt segment reversal\n 33→ zigzag-opt.js # Generic zigzag adjacent swap\n 34→ index.js # Optimization barrel export\n 35→ index.js # Progressive module export\n 36→ atomic/ # All-at-once algorithms (direct computation)\n 37→ solution/\n 38→ sonar.js # Atomic Sonar solution\n 39→ moore.js # Atomic Moore solution\n 40→ index.js\n 41→ optimization/\n 42→ two-opt.js # Atomic 2-opt optimization\n 43→ zigzag-opt.js # Atomic zigzag optimization\n 44→ index.js\n 45→ index.js # Atomic module export\n 46→ verification/ # Optimal tour verification\n 47→ brute-force.js # Brute-force exact solver\n 48→ index.js # Verification barrel export\n 49→ utils.js # Shared utility functions\n 50→ index.js # Main algorithms barrel export\n 51→ ui/\n 52→ components/\n 53→ TSPVisualization.jsx # SVG-based visualization component\n 54→ Controls.jsx # Control panel component\n 55→ Legend.jsx # Color legend components\n 56→ VisualizationPanel.jsx # Complete visualization panel\n 57→ index.js # Components barrel export\n 58→ App.jsx # Main application component\n 59→ styles.css # All CSS styles\n 60→ index.js # UI module export\n 61→index.html # Main HTML entry point\n 62→README.md # This file\n 63→```\n 64→\n 65→## Algorithms\n 66→\n 67→### Sonar Visit Algorithm\n 68→\n 69→Also known as: Radial Sweep, Angular Sort, Polar Angle Sort, Centroid-based Ordering\n 70→\n 71→This algorithm works by:\n 72→\n 73→1. Computing the centroid (center of mass) of all points\n 74→2. Calculating the polar angle of each point relative to the centroid\n 75→3. Sorting points by their polar angle\n 76→4. Connecting points in angular order to form a tour\n 77→\n 78→The visualization shows a \"sweep line\" rotating around the centroid, visiting points as it passes them.\n 79→\n 80→### Moore Curve Algorithm\n 81→\n 82→Also known as: Space-Filling Curve, Hilbert Curve Variant, Fractal Ordering\n 83→\n 84→This algorithm uses a Moore curve (a variant of the Hilbert curve) to order points:\n 85→\n 86→1. Generate a Moore curve that fills the grid space\n 87→2. Map each point to its nearest position on the curve\n 88→3. Sort points by their position along the curve\n 89→4. Connect points in curve-order to form a tour\n 90→\n 91→The Moore curve is a space-filling curve that visits every cell in a grid exactly once while maintaining spatial locality, making it effective for TSP approximations.\n 92→\n 93→### Optimization\n 94→\n 95→Both algorithms support optional optimization phases. Three optimization methods are available:\n 96→\n 97→#### 2-opt (Segment Reversal)\n 98→\n 99→- Picks two non-adjacent edges, removes them, and reconnects by reversing the segment between them\n 100→- Searches all pairs of edges (O(n^2) per pass)\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "21167f23-832a-4af2-8346-1b5387b42b93"
}
[2026-02-07T22:19:41.282Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JniDJcoR7QQH2z755PhqnR",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01NcQ5o6zQTqik1pKDuw5F29",
"name": "Bash",
"input": {
"command": "git log --oneline -20"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 725,
"cache_read_input_tokens": 25149,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 725
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "e1a3aa52-7031-4c59-a4a7-cb5b4318554e"
}
[2026-02-07T22:19:41.428Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01NcQ5o6zQTqik1pKDuw5F29",
"type": "tool_result",
"content": "304af53 Initial commit with task details\nf8de435 Update README screenshot [skip ci]\n68dbad5 Merge pull request #64 from konard/issue-63-4f9887961e4d\nc18bec1 Remove CLAUDE.md instruction file\nc884fea Fix changeset package name to tsp-algorithms\n9f0930b Add changeset and format case study README\n990d8b7 Fix benchmark TDZ error: move MOORE_GRID_SIZE before PEANO_GRID_SIZE\nd7f486f Initial commit with task details\n2bd204f Update README screenshot [skip ci]\n597455e Merge pull request #58 from konard/issue-12-2af24724aba7\n5861c42 Merge main branch into Gosper implementation\n3c2b430 Update README screenshot [skip ci]\n1b3114c Merge pull request #59 from konard/issue-11-e0e05c25342c\n5ee940c Merge main into Peano branch, integrate all new algorithms\n400bcda Update README screenshot [skip ci]\n394b48f Merge pull request #57 from konard/issue-13-00351cce1b78\n8f199cb Fix French translation escaping and formatting in i18n.js\n559c927 Merge main into issue-13-00351cce1b78\n1260d44 Update README screenshot [skip ci]\n44de4be Merge pull request #55 from konard/issue-33-37394f3b1718",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "17689230-a4fa-4f47-ad30-f21ed56ee0f2"
}
[2026-02-07T22:19:41.488Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JniDJcoR7QQH2z755PhqnR",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_014uVH5mj37L9kQh9itCoMXG",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -type f -name \"*test*\" | grep -E \"(test|spec)\" | sort"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 725,
"cache_read_input_tokens": 25149,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 725
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "a290c1bb-eeba-46d6-8af8-75011886482e"
}
[2026-02-07T22:19:41.555Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_014uVH5mj37L9kQh9itCoMXG",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/experiments/gosper-curve-test.js\n/tmp/gh-issue-solver-1770502731119/experiments/peano-curve/test-peano.js\n/tmp/gh-issue-solver-1770502731119/experiments/quick-benchmark-test.js\n/tmp/gh-issue-solver-1770502731119/experiments/sierpinski-curve-test.js\n/tmp/gh-issue-solver-1770502731119/experiments/test-changeset-scripts.mjs\n/tmp/gh-issue-solver-1770502731119/experiments/test-failure-detection.mjs\n/tmp/gh-issue-solver-1770502731119/experiments/test-format-major-changes.mjs\n/tmp/gh-issue-solver-1770502731119/experiments/test-format-minor-changes.mjs\n/tmp/gh-issue-solver-1770502731119/experiments/test-format-no-hash.mjs\n/tmp/gh-issue-solver-1770502731119/experiments/test-format-patch-changes.mjs\n/tmp/gh-issue-solver-1770502731119/src/tests/cli.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/comb-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/components/Controls.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/Legend.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/TSPVisualization.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/components/VisualizationPanel.test.jsx\n/tmp/gh-issue-solver-1770502731119/src/tests/e2e/app.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/gosper-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/index.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/koch-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/optimization-algorithms.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/peano-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/saw-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/sierpinski-algorithm.test.js\n/tmp/gh-issue-solver-1770502731119/src/tests/space-filling-tree.test.js",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "187b5448-0c69-423a-9945-e72e8d93dd28"
}
[2026-02-07T22:19:42.948Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JeLpyYuE2PqDg5VJrZRMwD",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01FYrFYtrUQkQmfHpiSRV5ux",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2892,
"cache_read_input_tokens": 25874,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2892
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "cdd35671-ef10-4aff-8a8a-1bbf38f7fc0b"
}
[2026-02-07T22:19:42.950Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01FYrFYtrUQkQmfHpiSRV5ux",
"type": "tool_result",
"content": " 1→/**\n 2→ * TSP Algorithms Library\n 3→ *\n 4→ * This module provides two types of TSP algorithms:\n 5→ *\n 6→ * 1. Progressive (step-by-step) - Returns arrays of steps for visualization/animation\n 7→ * 2. Atomic (all-at-once) - Returns final result directly\n 8→ *\n 9→ * Each type includes:\n 10→ * - Solutions: Initial tour construction algorithms (Sonar, Moore, Gosper, Peano, Sierpiński, Comb, SAW, Koch, Space-Filling Tree, Brute-Force)\n 11→ * - Optimizations: Generic tour improvement algorithms (2-opt, 3-opt, k-opt, LK, LKH, Zigzag)\n 12→ *\n 13→ * Additionally, verification algorithms prove tour optimality:\n 14→ * - Lower bound (1-tree): Mathematical proof when upper bound = lower bound\n 15→ *\n 16→ * Available solution algorithms:\n 17→ * - Sonar (Radial Sweep): Sorts points by polar angle from centroid\n 18→ * - Moore Curve: Orders points along a Moore space-filling curve (2^n grid)\n 19→ * - Gosper Curve: Orders points along a hexagonal space-filling curve (60° turns)\n 20→ * - Peano Curve: Orders points along a Peano space-filling curve (3^n grid)\n 21→ * - Sierpiński Curve: Orders points along a Sierpiński space-filling curve\n 22→ * - Comb (Serpentine Scan): Visits points row by row in alternating directions\n 23→ * - Self-Avoiding Walk (SAW): Nearest-neighbor walk that never revisits a point\n 24→ * - Koch Snowflake: Orders points along a Koch snowflake fractal curve\n 25→ * - Space-Filling Tree: Orders points via DFS traversal of a recursive quadtree\n 26→ * - Brute-Force: Exhaustive search for the true optimal tour (small instances)\n 27→ *\n 28→ * Available optimizations (generic, work with any tour):\n 29→ * - 2-opt: Standard segment reversal optimization\n 30→ * - 3-opt: Three-edge exchange optimization\n 31→ * - k-opt: Generalized k-edge exchange (combines 2-opt and 3-opt)\n 32→ * - Lin-Kernighan: Variable-depth edge exchange heuristic\n 33→ * - Lin-Kernighan-Helsgaun: LK with perturbation for escaping local optima\n 34→ * - Zigzag: Adjacent pair swapping optimization\n 35→ * - Combined: Alternates zigzag and 2-opt until no improvement\n 36→ *\n 37→ * @example\n 38→ * // Progressive (for visualization)\n 39→ * import { sonarAlgorithmSteps, sawAlgorithmSteps, kochAlgorithmSteps, twoOptSteps, bruteForceAlgorithmSteps } from './algorithms';\n 40→ * const solutionSteps = sonarAlgorithmSteps(points);\n 41→ * const kochSteps = kochAlgorithmSteps(points, mooreGridSize);\n 42→ * const optSteps = twoOptSteps(points, tour);\n 43→ * const bruteSteps = bruteForceAlgorithmSteps(points);\n 44→ *\n 45→ * @example\n 46→ * // Atomic (for direct computation)\n 47→ * import { sonarSolution, sawSolution, bruteForceSolution } from './algorithms/atomic';\n 48→ * import { twoOpt } from './algorithms/atomic';\n 49→ * const { tour } = sonarSolution(points);\n 50→ * const optimal = bruteForceSolution(points);\n 51→ *\n 52→ * @example\n 53→ * // Verification (prove optimality)\n 54→ * import { verifyOptimality } from './algorithms/verification';\n 55→ * const result = verifyOptimality(tourDistance, points);\n 56→ * if (result.isOptimal) console.log('Tour is proven optimal!');\n 57→ */\n 58→\n 59→// Utility functions\n 60→export * from './utils.js';\n 61→\n 62→// Progressive algorithms (step-by-step)\n 63→export * as progressive from './progressive/index.js';\n 64→\n 65→// Atomic algorithms (all-at-once)\n 66→export * as atomic from './atomic/index.js';\n 67→\n 68→// Verification algorithms (optimality proofs)\n 69→export * as verification from './verification/index.js';\n 70→\n 71→// Export progressive functions at top level for convenience\n 72→export {\n 73→ // Solutions\n 74→ sonarAlgorithmSteps,\n 75→ mooreAlgorithmSteps,\n 76→ generateMooreCurve,\n 77→ mooreCurveToPoints,\n 78→ gosperAlgorithmSteps,\n 79→ generateGosperCurve,\n 80→ gosperCurveToPoints,\n 81→ calculateGosperOrder,\n 82→ peanoAlgorithmSteps,\n 83→ generatePeanoCurve,\n 84→ peanoCurveToPoints,\n 85→ sierpinskiAlgorithmSteps,\n 86→ generateSierpinskiCurve,\n 87→ sierpinskiCurveToPoints,\n 88→ combAlgorithmSteps,\n 89→ sawAlgorithmSteps,\n 90→ sawSolution,\n 91→ kochAlgorithmSteps,\n 92→ generateKochSnowflake,\n 93→ kochCurveToPoints,\n 94→ calculateKochOrder,\n 95→ spaceFillingTreeAlgorithmSteps,\n 96→ bruteForceAlgorithmSteps,\n 97→ bruteForceSolution,\n 98→ calculateOptimalityRatio,\n 99→ BRUTE_FORCE_MAX_POINTS,\n 100→ // Generic optimizations\n 101→ twoOptSteps,\n 102→ threeOptSteps,\n 103→ kOptSteps,\n 104→ zigzagOptSteps,\n 105→ combinedOptSteps,\n 106→ linKernighanSteps,\n 107→ lkHelsgaunSteps,\n 108→ // Legacy aliases for backward compatibility\n 109→ sonarOptimizationSteps,\n 110→ mooreOptimizationSteps,\n 111→} from './progressive/index.js';\n 112→\n 113→// Export verification functions at top level for convenience\n 114→export {\n 115→ oneTreeLowerBound,\n 116→ verifyOptimality,\n 117→ // Backward-compatible aliases\n 118→ bruteForceOptimalTour,\n 119→ bruteForceSteps,\n 120→} from './verification/index.js';\n 121→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "db08088e-c475-433e-b0e2-6c4bc0a639f6"
}
[2026-02-07T22:19:43.099Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JeLpyYuE2PqDg5VJrZRMwD",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01QLjEDAw3XXaoxPdAwvTXQX",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2892,
"cache_read_input_tokens": 25874,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2892
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "efd6387b-f406-4d58-9922-f2e96bd2f21a"
}
[2026-02-07T22:19:43.101Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01QLjEDAw3XXaoxPdAwvTXQX",
"type": "tool_result",
"content": " 1→/**\n 2→ * TSP Library - Reusable TSP algorithms\n 3→ *\n 4→ * This library provides TSP (Traveling Salesman Problem) algorithms\n 5→ * that can be used by any application.\n 6→ */\n 7→\n 8→// Re-export everything from algorithms\n 9→export * from './algorithms/index.js';\n 10→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "04eae77e-731d-41a8-98f5-d515fcf39eb3"
}
[2026-02-07T22:19:43.456Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01JeLpyYuE2PqDg5VJrZRMwD",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01LE5GeFnChhE1TSJ5RXUaMm",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2892,
"cache_read_input_tokens": 25874,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2892
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "8002bf14-adfb-417c-b392-5917db5b9318"
}
[2026-02-07T22:19:43.478Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01LE5GeFnChhE1TSJ5RXUaMm",
"type": "tool_result",
"content": " 1→/**\n 2→ * Progressive Solutions - Step-by-step TSP algorithms\n 3→ */\n 4→\n 5→export { sonarAlgorithmSteps, sonarSolution } from './sonar.js';\n 6→export {\n 7→ mooreAlgorithmSteps,\n 8→ mooreSolution,\n 9→ generateMooreCurve,\n 10→ mooreCurveToPoints,\n 11→} from './moore.js';\n 12→export { combAlgorithmSteps, combSolution } from './comb.js';\n 13→export { sawAlgorithmSteps, sawSolution } from './saw.js';\n 14→export {\n 15→ kochAlgorithmSteps,\n 16→ kochSolution,\n 17→ generateKochSnowflake,\n 18→ kochCurveToPoints,\n 19→ calculateKochOrder,\n 20→} from './koch.js';\n 21→export {\n 22→ spaceFillingTreeAlgorithmSteps,\n 23→ spaceFillingTreeSolution,\n 24→} from './space-filling-tree.js';\n 25→export {\n 26→ sierpinskiAlgorithmSteps,\n 27→ sierpinskiSolution,\n 28→ generateSierpinskiCurve,\n 29→ sierpinskiCurveToPoints,\n 30→} from './sierpinski.js';\n 31→export {\n 32→ peanoAlgorithmSteps,\n 33→ peanoSolution,\n 34→ generatePeanoCurve,\n 35→ peanoCurveToPoints,\n 36→} from './peano.js';\n 37→export {\n 38→ gosperAlgorithmSteps,\n 39→ gosperSolution,\n 40→ generateGosperCurve,\n 41→ gosperCurveToPoints,\n 42→ calculateGosperOrder,\n 43→} from './gosper.js';\n 44→export {\n 45→ bruteForceAlgorithmSteps,\n 46→ bruteForceSolution,\n 47→ calculateOptimalityRatio,\n 48→ BRUTE_FORCE_MAX_POINTS,\n 49→} from './brute-force.js';\n 50→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "94d29ca0-c118-4eb5-93f6-0f3787514225"
}
[2026-02-07T22:19:44.818Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01GRdfQhzrYpfJPPL5GsQB38",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01G3epdPNSUTic1Q7Fz4AoCP",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Controls.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3084,
"cache_read_input_tokens": 28766,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3084
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "ceac5bc0-0bf3-41e7-a6a9-97a865ff5dde"
}
[2026-02-07T22:19:44.821Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01G3epdPNSUTic1Q7Fz4AoCP",
"type": "tool_result",
"content": " 1→/**\n 2→ * Controls Component\n 3→ *\n 4→ * Control panel for TSP solver including:\n 5→ * - Algorithm selection dropdowns (left and right panels)\n 6→ * - Grid size selector (valid Moore curve sizes)\n 7→ * - Points count input\n 8→ * - Animation speed slider\n 9→ * - Action buttons (New Points, Start, Stop, 2-opt Optimize, Zigzag Optimize)\n 10→ */\n 11→\n 12→import { VALID_GRID_SIZES } from '../../../lib/algorithms/utils.js';\n 13→import { t } from '../i18n.js';\n 14→\n 15→/**\n 16→ * Available algorithms for selection.\n 17→ * Each entry maps an id to a display label.\n 18→ */\n 19→export const ALGORITHM_OPTIONS = [\n 20→ { id: 'sonar', label: 'Sonar Visit' },\n 21→ { id: 'moore', label: 'Moore Curve' },\n 22→ { id: 'gosper', label: 'Gosper Curve' },\n 23→ { id: 'peano', label: 'Peano Curve' },\n 24→ { id: 'sierpinski', label: 'Sierpiński Curve' },\n 25→ { id: 'comb', label: 'Comb Scan' },\n 26→ { id: 'saw', label: 'Self-Avoiding Walk' },\n 27→ { id: 'koch', label: 'Koch Snowflake' },\n 28→ { id: 'space-filling-tree', label: 'Space-Filling Tree' },\n 29→ { id: 'brute-force', label: 'Brute-Force' },\n 30→];\n 31→\n 32→/**\n 33→ * Controls - Control panel for TSP solver\n 34→ *\n 35→ * @param {Object} props\n 36→ * @param {number} props.gridSize - Current grid size (must be a valid Moore curve size)\n 37→ * @param {function} props.setGridSize - Grid size setter\n 38→ * @param {number} props.numPoints - Number of points\n 39→ * @param {function} props.setNumPoints - Points count setter\n 40→ * @param {number} props.speed - Animation speed in ms\n 41→ * @param {function} props.setSpeed - Speed setter\n 42→ * @param {number} props.mooreGridSize - Actual Moore grid size\n 43→ * @param {boolean} props.isRunning - Whether animation is running\n 44→ * @param {boolean} props.canOptimize - Whether optimization can start\n 45→ * @param {string|null} props.activeOptimization - Currently active optimization method\n 46→ * @param {function} props.onGeneratePoints - Generate new points handler\n 47→ * @param {function} props.onStart - Start algorithm handler\n 48→ * @param {function} props.onStop - Stop animation handler\n 49→ * @param {function} props.onOptimize - Start optimization handler (receives method name)\n 50→ * @param {number} props.pointsCount - Current points count (for Start button state)\n 51→ * @param {boolean} props.startDisabled - Whether Start button should be disabled\n 52→ * @param {string} props.startDisabledReason - Tooltip explaining why Start is disabled\n 53→ * @param {string} props.lang - Current language code\n 54→ */\n 55→const Controls = ({\n 56→ gridSize,\n 57→ setGridSize,\n 58→ numPoints,\n 59→ setNumPoints,\n 60→ speed,\n 61→ setSpeed,\n 62→ mooreGridSize,\n 63→ isRunning,\n 64→ canOptimize,\n 65→ activeOptimization,\n 66→ onGeneratePoints,\n 67→ onStart,\n 68→ onStop,\n 69→ onOptimize,\n 70→ pointsCount,\n 71→ startDisabled,\n 72→ startDisabledReason,\n 73→ lang = 'en',\n 74→}) => {\n 75→ const maxPoints = mooreGridSize * mooreGridSize;\n 76→ return (\n 77→ <div className=\"controls\">\n 78→ <div className=\"control-group\">\n 79→ <label>{t(lang, 'gridSize')}</label>\n 80→ <select\n 81→ value={gridSize}\n 82→ onChange={(e) => setGridSize(parseInt(e.target.value))}\n 83→ disabled={isRunning}\n 84→ >\n 85→ {VALID_GRID_SIZES.map((size) => (\n 86→ <option key={size} value={size}>\n 87→ {size}×{size}\n 88→ </option>\n 89→ ))}\n 90→ </select>\n 91→ </div>\n 92→\n 93→ <div className=\"control-group\">\n 94→ <label>\n 95→ {t(lang, 'points')} ({t(lang, 'max')} {maxPoints})\n 96→ </label>\n 97→ <input\n 98→ type=\"number\"\n 99→ min=\"1\"\n 100→ max={maxPoints}\n 101→ value={numPoints}\n 102→ onChange={(e) => {\n 103→ const val = parseInt(e.target.value);\n 104→ if (isNaN(val) || val < 1) {\n 105→ setNumPoints(e.target.value === '' ? '' : 1);\n 106→ return;\n 107→ }\n 108→ setNumPoints(Math.min(val, maxPoints));\n 109→ }}\n 110→ onBlur={() => {\n 111→ const val =\n 112→ typeof numPoints === 'number' ? numPoints : parseInt(numPoints);\n 113→ if (isNaN(val) || val < 3) {\n 114→ setNumPoints(3);\n 115→ } else if (val > maxPoints) {\n 116→ setNumPoints(maxPoints);\n 117→ }\n 118→ }}\n 119→ disabled={isRunning}\n 120→ />\n 121→ </div>\n 122→\n 123→ <div className=\"control-group\">\n 124→ <label>{t(lang, 'animationSpeed')}</label>\n 125→ <div className=\"speed-control\">\n 126→ <span>{t(lang, 'fast')}</span>\n 127→ <input\n 128→ type=\"range\"\n 129→ min=\"50\"\n 130→ max=\"1000\"\n 131→ value={speed}\n 132→ onChange={(e) => setSpeed(parseInt(e.target.value))}\n 133→ />\n 134→ <span>{t(lang, 'slow')}</span>\n 135→ </div>\n 136→ </div>\n 137→\n 138→ <div className=\"buttons\">\n 139→ <button\n 140→ className=\"btn-outline\"\n 141→ onClick={onGeneratePoints}\n 142→ disabled={isRunning}\n 143→ >\n 144→ {t(lang, 'newPoints')}\n 145→ </button>\n 146→\n 147→ {!isRunning ? (\n 148→ <>\n 149→ <span\n 150→ className={startDisabled ? 'tooltip-wrapper' : ''}\n 151→ data-tooltip={startDisabledReason || undefined}\n 152→ >\n 153→ <button\n 154→ className=\"btn-primary\"\n 155→ onClick={onStart}\n 156→ disabled={pointsCount === 0 || startDisabled}\n 157→ title={startDisabledReason || ''}\n 158→ >\n 159→ {t(lang, 'start')}\n 160→ </button>\n 161→ </span>\n 162→\n 163→ {canOptimize && (\n 164→ <>\n 165→ <button\n 166→ className={`btn-secondary${activeOptimization === '2-opt' ? ' btn-active' : ''}`}\n 167→ onClick={() => onOptimize('2-opt')}\n 168→ >\n 169→ 2-opt\n 170→ </button>\n 171→ <button\n 172→ className={`btn-secondary${activeOptimization === '3-opt' ? ' btn-active' : ''}`}\n 173→ onClick={() => onOptimize('3-opt')}\n 174→ >\n 175→ 3-opt\n 176→ </button>\n 177→ <button\n 178→ className={`btn-secondary${activeOptimization === 'k-opt' ? ' btn-active' : ''}`}\n 179→ onClick={() => onOptimize('k-opt')}\n 180→ >\n 181→ k-opt\n 182→ </button>\n 183→ <button\n 184→ className={`btn-secondary${activeOptimization === 'lin-kernighan' ? ' btn-active' : ''}`}\n 185→ onClick={() => onOptimize('lin-kernighan')}\n 186→ >\n 187→ LK\n 188→ </button>\n 189→ <button\n 190→ className={`btn-secondary${activeOptimization === 'lkh' ? ' btn-active' : ''}`}\n 191→ onClick={() => onOptimize('lkh')}\n 192→ >\n 193→ LKH\n 194→ </button>\n 195→ <button\n 196→ className={`btn-secondary${activeOptimization === 'zigzag' ? ' btn-active' : ''}`}\n 197→ onClick={() => onOptimize('zigzag')}\n 198→ >\n 199→ Zigzag\n 200→ </button>\n 201→ </>\n 202→ )}\n 203→ </>\n 204→ ) : (\n 205→ <button className=\"btn-secondary\" onClick={onStop}>\n 206→ {t(lang, 'stop')}\n 207→ </button>\n 208→ )}\n 209→ </div>\n 210→ </div>\n 211→ );\n 212→};\n 213→\n 214→export { Controls };\n 215→export default Controls;\n 216→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "cb22c90d-14cd-4eb9-bdec-657b95852a9e"
}
[2026-02-07T22:19:45.372Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01GRdfQhzrYpfJPPL5GsQB38",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01DNZQTMJL1Npfi2byv4iLkc",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/VisualizationPanel.jsx",
"limit": 80
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3084,
"cache_read_input_tokens": 28766,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3084
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "ede98a86-c199-49f5-955b-ba75d45ed6d0"
}
[2026-02-07T22:19:45.375Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01DNZQTMJL1Npfi2byv4iLkc",
"type": "tool_result",
"content": " 1→/**\n 2→ * VisualizationPanel Component\n 3→ *\n 4→ * A complete visualization panel including:\n 5→ * - Header with algorithm selector dropdown and distance\n 6→ * - Algorithm aliases/description\n 7→ * - TSP visualization canvas\n 8→ * - Step info display\n 9→ * - Color legend\n 10→ */\n 11→\n 12→/**\n 13→ * VisualizationPanel - Complete visualization panel for a single algorithm\n 14→ *\n 15→ * @param {Object} props\n 16→ * @param {string} props.selectedAlgorithm - Currently selected algorithm id\n 17→ * @param {function} props.onAlgorithmChange - Algorithm change handler\n 18→ * @param {Array} props.algorithmOptions - Available algorithm options (filtered)\n 19→ * @param {boolean} props.isRunning - Whether animation is running\n 20→ * @param {string} props.aliases - Alternative algorithm names\n 21→ * @param {string} props.distanceInfo - Formatted distance string with optional optimality info\n 22→ * @param {React.ReactNode} props.visualization - TSPVisualization component\n 23→ * @param {string} props.stepDescription - Current step description\n 24→ * @param {React.ReactNode} props.legend - Legend component\n 25→ */\n 26→const VisualizationPanel = ({\n 27→ selectedAlgorithm,\n 28→ onAlgorithmChange,\n 29→ algorithmOptions,\n 30→ isRunning,\n 31→ aliases,\n 32→ distanceInfo,\n 33→ visualization,\n 34→ stepDescription,\n 35→ defaultStepText,\n 36→ legend,\n 37→}) => {\n 38→ return (\n 39→ <div className=\"visualization\">\n 40→ <div className=\"visualization-header\">\n 41→ <select\n 42→ className=\"algorithm-select\"\n 43→ value={selectedAlgorithm}\n 44→ onChange={(e) => onAlgorithmChange(e.target.value)}\n 45→ disabled={isRunning}\n 46→ >\n 47→ {algorithmOptions.map((opt) => (\n 48→ <option key={opt.id} value={opt.id}>\n 49→ {opt.label}\n 50→ </option>\n 51→ ))}\n 52→ </select>\n 53→ <span className=\"visualization-stats\">{distanceInfo}</span>\n 54→ </div>\n 55→ <div className=\"algorithm-aliases\">{aliases}</div>\n 56→ <div className=\"canvas-wrapper\">{visualization}</div>\n 57→ <div className=\"step-info\">\n 58→ {stepDescription || defaultStepText || 'Click Start to begin'}\n 59→ </div>\n 60→ {legend}\n 61→ </div>\n 62→ );\n 63→};\n 64→\n 65→export { VisualizationPanel };\n 66→export default VisualizationPanel;\n 67→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "0e4a2bb4-15b8-45a3-992e-4e6940e76ad6"
}
[2026-02-07T22:19:45.489Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01GRdfQhzrYpfJPPL5GsQB38",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01ShEHSZwsZ5QKRMWwerJSXH",
"name": "Bash",
"input": {
"command": "ls -la /tmp/gh-issue-solver-1770502731119/.github/"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 3084,
"cache_read_input_tokens": 28766,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 3084
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3928d4cb-ea3e-4d45-ab9d-b4a52ed3c3f3"
}
[2026-02-07T22:19:45.554Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01ShEHSZwsZ5QKRMWwerJSXH",
"type": "tool_result",
"content": "total 12\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 .\ndrwxrwxr-x 13 hive hive 4096 Feb 7 23:18 ..\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 workflows",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "45ab611d-4eff-462a-a400-282651af3a69"
}
[2026-02-07T22:19:47.165Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01DvURzgDkFkNvEkGFADwp7h",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01VitpjYVWYKxesD9itmg2ds",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/tests/index.test.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 4114,
"cache_read_input_tokens": 31850,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4114
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f2fd73ee-8874-4412-9192-9e849ae99e37"
}
[2026-02-07T22:19:47.425Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01VitpjYVWYKxesD9itmg2ds",
"type": "tool_result",
"content": " 1→/**\n 2→ * Test file for TSP algorithms\n 3→ * Works with Bun test runner\n 4→ */\n 5→\n 6→import { describe, it, expect } from 'bun:test';\n 7→import {\n 8→ calculateMooreGridSize,\n 9→ generateRandomPoints,\n 10→ distance,\n 11→ calculateTotalDistance,\n 12→ VALID_GRID_SIZES,\n 13→} from '../lib/algorithms/utils.js';\n 14→import {\n 15→ sonarAlgorithmSteps,\n 16→ sonarSolution,\n 17→} from '../lib/algorithms/progressive/solution/sonar.js';\n 18→import {\n 19→ mooreAlgorithmSteps,\n 20→ mooreSolution,\n 21→ generateMooreCurve,\n 22→ mooreCurveToPoints,\n 23→} from '../lib/algorithms/progressive/solution/moore.js';\n 24→import {\n 25→ zigzagOptSteps,\n 26→ zigzagOpt,\n 27→ // Legacy aliases\n 28→ sonarOptimizationSteps,\n 29→ sonarOptimization,\n 30→} from '../lib/algorithms/progressive/optimization/zigzag-opt.js';\n 31→import {\n 32→ twoOptSteps,\n 33→ twoOpt,\n 34→ // Legacy aliases\n 35→ mooreOptimizationSteps,\n 36→ mooreOptimization,\n 37→} from '../lib/algorithms/progressive/optimization/two-opt.js';\n 38→import {\n 39→ combinedOptSteps,\n 40→ combinedOpt,\n 41→} from '../lib/algorithms/progressive/optimization/combined-opt.js';\n 42→import {\n 43→ bruteForceAlgorithmSteps,\n 44→ bruteForceSolution,\n 45→ calculateOptimalityRatio,\n 46→ BRUTE_FORCE_MAX_POINTS,\n 47→} from '../lib/algorithms/progressive/solution/brute-force.js';\n 48→import {\n 49→ oneTreeLowerBound,\n 50→ verifyOptimality,\n 51→} from '../lib/algorithms/verification/lower-bound.js';\n 52→\n 53→// Backward-compatible aliases\n 54→const bruteForceOptimalTour = bruteForceSolution;\n 55→const bruteForceSteps = bruteForceAlgorithmSteps;\n 56→\n 57→// ============================================================\n 58→// Utility Functions Tests\n 59→// ============================================================\n 60→\n 61→describe('VALID_GRID_SIZES', () => {\n 62→ it('should contain only powers of 2', () => {\n 63→ VALID_GRID_SIZES.forEach((size) => {\n 64→ expect(Math.log2(size) % 1).toBe(0);\n 65→ });\n 66→ });\n 67→\n 68→ it('should be sorted in ascending order', () => {\n 69→ for (let i = 1; i < VALID_GRID_SIZES.length; i++) {\n 70→ expect(VALID_GRID_SIZES[i]).toBeGreaterThan(VALID_GRID_SIZES[i - 1]);\n 71→ }\n 72→ });\n 73→\n 74→ it('should contain expected sizes', () => {\n 75→ expect(VALID_GRID_SIZES).toEqual([2, 4, 8, 16, 32, 64, 128]);\n 76→ });\n 77→});\n 78→\n 79→describe('calculateMooreGridSize', () => {\n 80→ it('should return smallest valid size >= input', () => {\n 81→ expect(calculateMooreGridSize(2)).toBe(2);\n 82→ expect(calculateMooreGridSize(3)).toBe(4);\n 83→ expect(calculateMooreGridSize(4)).toBe(4);\n 84→ expect(calculateMooreGridSize(5)).toBe(8);\n 85→ expect(calculateMooreGridSize(10)).toBe(16);\n 86→ expect(calculateMooreGridSize(16)).toBe(16);\n 87→ expect(calculateMooreGridSize(20)).toBe(32);\n 88→ expect(calculateMooreGridSize(32)).toBe(32);\n 89→ expect(calculateMooreGridSize(33)).toBe(64);\n 90→ expect(calculateMooreGridSize(64)).toBe(64);\n 91→ expect(calculateMooreGridSize(65)).toBe(128);\n 92→ expect(calculateMooreGridSize(128)).toBe(128);\n 93→ expect(calculateMooreGridSize(129)).toBe(128);\n 94→ });\n 95→\n 96→ it('should return largest valid size for very large input', () => {\n 97→ expect(calculateMooreGridSize(200)).toBe(128);\n 98→ });\n 99→\n 100→ it('should always return a valid Moore grid size', () => {\n 101→ for (let gs = 1; gs <= 100; gs++) {\n 102→ const result = calculateMooreGridSize(gs);\n 103→ expect(VALID_GRID_SIZES).toContain(result);\n 104→ }\n 105→ });\n 106→});\n 107→\n 108→describe('generateRandomPoints', () => {\n 109→ it('should generate the requested number of points', () => {\n 110→ const mooreGridSize = 16;\n 111→ const numPoints = 10;\n 112→ const points = generateRandomPoints(mooreGridSize, numPoints);\n 113→ expect(points.length).toBe(numPoints);\n 114→ });\n 115→\n 116→ it('should generate points within [0, mooreGridSize-1] range', () => {\n 117→ const mooreGridSize = 16;\n 118→ const points = generateRandomPoints(mooreGridSize, 5);\n 119→ points.forEach((point) => {\n 120→ expect(point.x).toBeGreaterThanOrEqual(0);\n 121→ expect(point.x).toBeLessThanOrEqual(mooreGridSize - 1);\n 122→ expect(point.y).toBeGreaterThanOrEqual(0);\n 123→ expect(point.y).toBeLessThanOrEqual(mooreGridSize - 1);\n 124→ });\n 125→ });\n 126→\n 127→ it('should generate unique points', () => {\n 128→ const mooreGridSize = 16;\n 129→ const points = generateRandomPoints(mooreGridSize, 10);\n 130→ const uniqueKeys = new Set(points.map((p) => `${p.x},${p.y}`));\n 131→ expect(uniqueKeys.size).toBe(points.length);\n 132→ });\n 133→\n 134→ it('should assign sequential IDs', () => {\n 135→ const points = generateRandomPoints(16, 5);\n 136→ points.forEach((point, idx) => {\n 137→ expect(point.id).toBe(idx);\n 138→ });\n 139→ });\n 140→});\n 141→\n 142→describe('distance', () => {\n 143→ it('should calculate distance between two points', () => {\n 144→ const p1 = { x: 0, y: 0 };\n 145→ const p2 = { x: 3, y: 4 };\n 146→ expect(distance(p1, p2)).toBe(5);\n 147→ });\n 148→\n 149→ it('should return 0 for same point', () => {\n 150→ const p = { x: 5, y: 5 };\n 151→ expect(distance(p, p)).toBe(0);\n 152→ });\n 153→\n 154→ it('should handle negative coordinates', () => {\n 155→ const p1 = { x: -3, y: -4 };\n 156→ const p2 = { x: 0, y: 0 };\n 157→ expect(distance(p1, p2)).toBe(5);\n 158→ });\n 159→});\n 160→\n 161→describe('calculateTotalDistance', () => {\n 162→ it('should return 0 for empty tour', () => {\n 163→ expect(calculateTotalDistance([], [])).toBe(0);\n 164→ });\n 165→\n 166→ it('should return 0 for single point', () => {\n 167→ const points = [{ x: 0, y: 0 }];\n 168→ expect(calculateTotalDistance([0], points)).toBe(0);\n 169→ });\n 170→\n 171→ it('should calculate correct closed loop distance', () => {\n 172→ const points = [\n 173→ { x: 0, y: 0 },\n 174→ { x: 3, y: 0 },\n 175→ { x: 3, y: 4 },\n 176→ ];\n 177→ const tour = [0, 1, 2];\n 178→ // 0->1: 3, 1->2: 4, 2->0: 5 = 12\n 179→ expect(calculateTotalDistance(tour, points)).toBe(12);\n 180→ });\n 181→});\n 182→\n 183→// ============================================================\n 184→// Sonar Algorithm Tests\n 185→// ============================================================\n 186→\n 187→describe('sonarAlgorithmSteps', () => {\n 188→ it('should return empty array for empty points', () => {\n 189→ expect(sonarAlgorithmSteps([])).toEqual([]);\n 190→ });\n 191→\n 192→ it('should generate steps for all points', () => {\n 193→ const points = [\n 194→ { x: 0, y: 0, id: 0 },\n 195→ { x: 10, y: 0, id: 1 },\n 196→ { x: 5, y: 10, id: 2 },\n 197→ ];\n 198→ const steps = sonarAlgorithmSteps(points);\n 199→ expect(steps.length).toBe(points.length);\n 200→ });\n 201→\n 202→ it('should include all points in final tour', () => {\n 203→ const points = [\n 204→ { x: 0, y: 0, id: 0 },\n 205→ { x: 10, y: 0, id: 1 },\n 206→ { x: 5, y: 10, id: 2 },\n 207→ ];\n 208→ const steps = sonarAlgorithmSteps(points);\n 209→ const finalTour = steps[steps.length - 1].tour;\n 210→ expect(finalTour.length).toBe(points.length);\n 211→ expect(new Set(finalTour).size).toBe(points.length);\n 212→ });\n 213→\n 214→ it('should have sweep type for all steps', () => {\n 215→ const points = [\n 216→ { x: 0, y: 0, id: 0 },\n 217→ { x: 10, y: 0, id: 1 },\n 218→ ];\n 219→ const steps = sonarAlgorithmSteps(points);\n 220→ steps.forEach((step) => {\n 221→ expect(step.type).toBe('sweep');\n 222→ });\n 223→ });\n 224→\n 225→ it('should include centroid in each step', () => {\n 226→ const points = [\n 227→ { x: 0, y: 0, id: 0 },\n 228→ { x: 6, y: 0, id: 1 },\n 229→ { x: 3, y: 6, id: 2 },\n 230→ ];\n 231→ const steps = sonarAlgorithmSteps(points);\n 232→ const expectedCentroid = { x: 3, y: 2 };\n 233→ steps.forEach((step) => {\n 234→ expect(step.centroid.x).toBe(expectedCentroid.x);\n 235→ expect(step.centroid.y).toBe(expectedCentroid.y);\n 236→ });\n 237→ });\n 238→});\n 239→\n 240→describe('sonarSolution', () => {\n 241→ it('should return empty tour for empty points', () => {\n 242→ const result = sonarSolution([]);\n 243→ expect(result.tour).toEqual([]);\n 244→ expect(result.centroid).toBe(null);\n 245→ });\n 246→\n 247→ it('should return tour with all point indices', () => {\n 248→ const points = [\n 249→ { x: 0, y: 0, id: 0 },\n 250→ { x: 10, y: 0, id: 1 },\n 251→ { x: 5, y: 10, id: 2 },\n 252→ ];\n 253→ const result = sonarSolution(points);\n 254→ expect(result.tour.length).toBe(points.length);\n 255→ expect(new Set(result.tour).size).toBe(points.length);\n 256→ });\n 257→});\n 258→\n 259→// ============================================================\n 260→// Moore Curve Algorithm Tests\n 261→// ============================================================\n 262→\n 263→describe('generateMooreCurve', () => {\n 264→ it('should generate valid L-system sequence', () => {\n 265→ const sequence = generateMooreCurve(1);\n 266→ expect(sequence).toContain('F');\n 267→ expect(typeof sequence).toBe('string');\n 268→ });\n 269→\n 270→ it('should expand sequence with higher order', () => {\n 271→ const order1 = generateMooreCurve(1);\n 272→ const order2 = generateMooreCurve(2);\n 273→ expect(order2.length).toBeGreaterThan(order1.length);\n 274→ });\n 275→});\n 276→\n 277→describe('mooreCurveToPoints', () => {\n 278→ it('should generate curve points', () => {\n 279→ const sequence = generateMooreCurve(1);\n 280→ const points = mooreCurveToPoints(sequence, 4);\n 281→ expect(points.length).toBeGreaterThan(0);\n 282→ });\n 283→\n 284→ it('should generate points within [0, gridSize-1] bounds', () => {\n 285→ const mooreGridSize = 16;\n 286→ // For mooreGridSize=16, iterations = log2(16) - 1 = 3\n 287→ const sequence = generateMooreCurve(3);\n 288→ const points = mooreCurveToPoints(sequence, mooreGridSize);\n 289→ points.forEach((p) => {\n 290→ expect(p.x).toBeGreaterThanOrEqual(0);\n 291→ expect(p.x).toBeLessThanOrEqual(mooreGridSize - 1);\n 292→ expect(p.y).toBeGreaterThanOrEqual(0);\n 293→ expect(p.y).toBeLessThanOrEqual(mooreGridSize - 1);\n 294→ });\n 295→ });\n 296→});\n 297→\n 298→describe('mooreAlgorithmSteps', () => {\n 299→ it('should return empty array for empty points', () => {\n 300→ expect(mooreAlgorithmSteps([], 16)).toEqual([]);\n 301→ });\n 302→\n 303→ it('should generate curve step first', () => {\n 304→ const points = [\n 305→ { x: 0, y: 0, id: 0 },\n 306→ { x: 10, y: 10, id: 1 },\n 307→ ];\n 308→ const steps = mooreAlgorithmSteps(points, 16);\n 309→ expect(steps[0].type).toBe('curve');\n 310→ });\n 311→\n 312→ it('should include all points in final tour', () => {\n 313→ const points = [\n 314→ { x: 0, y: 0, id: 0 },\n 315→ { x: 8, y: 8, id: 1 },\n 316→ { x: 4, y: 12, id: 2 },\n 317→ ];\n 318→ const steps = mooreAlgorithmSteps(points, 16);\n 319→ const finalTour = steps[steps.length - 1].tour;\n 320→ expect(finalTour.length).toBe(points.length);\n 321→ });\n 322→\n 323→ it('should include curve points in each step', () => {\n 324→ const points = [{ x: 5, y: 5, id: 0 }];\n 325→ const steps = mooreAlgorithmSteps(points, 16);\n 326→ steps.forEach((step) => {\n 327→ expect(step.curvePoints !== undefined).toBe(true);\n 328→ expect(step.curvePoints.length).toBeGreaterThan(0);\n 329→ });\n 330→ });\n 331→});\n 332→\n 333→describe('mooreSolution', () => {\n 334→ it('should return empty tour for empty points', () => {\n 335→ const result = mooreSolution([], 16);\n 336→ expect(result.tour).toEqual([]);\n 337→ expect(result.curvePoints).toEqual([]);\n 338→ });\n 339→\n 340→ it('should return tour with all point indices', () => {\n 341→ const points = [\n 342→ { x: 0, y: 0, id: 0 },\n 343→ { x: 10, y: 0, id: 1 },\n 344→ { x: 5, y: 10, id: 2 },\n 345→ ];\n 346→ const result = mooreSolution(points, 16);\n 347→ expect(result.tour.length).toBe(points.length);\n 348→ expect(new Set(result.tour).size).toBe(points.length);\n 349→ });\n 350→});\n 351→\n 352→// ============================================================\n 353→// Optimization Tests\n 354→// ============================================================\n 355→\n 356→describe('sonarOptimizationSteps', () => {\n 357→ it('should return empty array for tour with less than 4 points', () => {\n 358→ const points = [\n 359→ { x: 0, y: 0 },\n 360→ { x: 1, y: 1 },\n 361→ { x: 2, y: 2 },\n 362→ ];\n 363→ const tour = [0, 1, 2];\n 364→ expect(sonarOptimizationSteps(points, tour)).toEqual([]);\n 365→ });\n 366→\n 367→ it('should return optimization steps for valid tour', () => {\n 368→ const points = [\n 369→ { x: 0, y: 0 },\n 370→ { x: 10, y: 0 },\n 371→ { x: 10, y: 10 },\n 372→ { x: 0, y: 10 },\n 373→ ];\n 374→ // Create a non-optimal tour\n 375→ const tour = [0, 2, 1, 3];\n 376→ const steps = sonarOptimizationSteps(points, tour);\n 377→ // May or may not have improvements depending on tour\n 378→ expect(Array.isArray(steps)).toBe(true);\n 379→ });\n 380→\n 381→ it('should have optimize type for all steps', () => {\n 382→ const points = [\n 383→ { x: 0, y: 0 },\n 384→ { x: 10, y: 0 },\n 385→ { x: 10, y: 10 },\n 386→ { x: 0, y: 10 },\n 387→ { x: 5, y: 5 },\n 388→ ];\n 389→ const tour = [0, 2, 4, 1, 3];\n 390→ const steps = sonarOptimizationSteps(points, tour);\n 391→ steps.forEach((step) => {\n 392→ expect(step.type).toBe('optimize');\n 393→ });\n 394→ });\n 395→});\n 396→\n 397→describe('sonarOptimization', () => {\n 398→ it('should return original tour for small inputs', () => {\n 399→ const points = [\n 400→ { x: 0, y: 0 },\n 401→ { x: 1, y: 1 },\n 402→ ];\n 403→ const tour = [0, 1];\n 404→ const result = sonarOptimization(points, tour);\n 405→ expect(result.tour).toEqual(tour);\n 406→ expect(result.improvement).toBe(0);\n 407→ });\n 408→});\n 409→\n 410→describe('mooreOptimizationSteps', () => {\n 411→ it('should return empty array for tour with less than 4 points', () => {\n 412→ const points = [\n 413→ { x: 0, y: 0 },\n 414→ { x: 1, y: 1 },\n 415→ { x: 2, y: 2 },\n 416→ ];\n 417→ const tour = [0, 1, 2];\n 418→ expect(mooreOptimizationSteps(points, tour)).toEqual([]);\n 419→ });\n 420→\n 421→ it('should have optimize type for all steps', () => {\n 422→ const points = [\n 423→ { x: 0, y: 0 },\n 424→ { x: 10, y: 0 },\n 425→ { x: 10, y: 10 },\n 426→ { x: 0, y: 10 },\n 427→ { x: 5, y: 5 },\n 428→ ];\n 429→ const tour = [0, 2, 4, 1, 3];\n 430→ const steps = mooreOptimizationSteps(points, tour);\n 431→ steps.forEach((step) => {\n 432→ expect(step.type).toBe('optimize');\n 433→ });\n 434→ });\n 435→});\n 436→\n 437→describe('mooreOptimization', () => {\n 438→ it('should return original tour for small inputs', () => {\n 439→ const points = [\n 440→ { x: 0, y: 0 },\n 441→ { x: 1, y: 1 },\n 442→ ];\n 443→ const tour = [0, 1];\n 444→ const result = mooreOptimization(points, tour);\n 445→ expect(result.tour).toEqual(tour);\n 446→ expect(result.improvement).toBe(0);\n 447→ });\n 448→\n 449→ it('should not increase tour distance', () => {\n 450→ const points = [\n 451→ { x: 0, y: 0 },\n 452→ { x: 10, y: 0 },\n 453→ { x: 10, y: 10 },\n 454→ { x: 0, y: 10 },\n 455→ { x: 5, y: 5 },\n 456→ ];\n 457→ const tour = [0, 2, 4, 1, 3];\n 458→ const originalDistance = calculateTotalDistance(tour, points);\n 459→ const result = mooreOptimization(points, tour);\n 460→ const newDistance = calculateTotalDistance(result.tour, points);\n 461→ expect(newDistance).toBeLessThanOrEqual(originalDistance);\n 462→ });\n 463→});\n 464→\n 465→// ============================================================\n 466→// Generic Optimization Tests (new generic API)\n 467→// ============================================================\n 468→\n 469→describe('twoOptSteps (generic 2-opt)', () => {\n 470→ it('should return empty array for tour with less than 4 points', () => {\n 471→ const points = [\n 472→ { x: 0, y: 0 },\n 473→ { x: 1, y: 1 },\n 474→ { x: 2, y: 2 },\n 475→ ];\n 476→ const tour = [0, 1, 2];\n 477→ expect(twoOptSteps(points, tour)).toEqual([]);\n 478→ });\n 479→\n 480→ it('should work on any tour regardless of source algorithm', () => {\n 481→ const points = [\n 482→ { x: 0, y: 0 },\n 483→ { x: 10, y: 0 },\n 484→ { x: 10, y: 10 },\n 485→ { x: 0, y: 10 },\n 486→ { x: 5, y: 5 },\n 487→ ];\n 488→ // This is not from any specific algorithm\n 489→ const randomTour = [0, 2, 4, 1, 3];\n 490→ const steps = twoOptSteps(points, randomTour);\n 491→ expect(Array.isArray(steps)).toBe(true);\n 492→ });\n 493→\n 494→ it('should respect maxIterations option', () => {\n 495→ const points = [\n 496→ { x: 0, y: 0 },\n 497→ { x: 10, y: 0 },\n 498→ { x: 10, y: 10 },\n 499→ { x: 0, y: 10 },\n 500→ ];\n 501→ const tour = [0, 1, 2, 3];\n 502→ const steps = twoOptSteps(points, tour, { maxIterations: 1 });\n 503→ // Should still return valid array\n 504→ expect(Array.isArray(steps)).toBe(true);\n 505→ });\n 506→});\n 507→\n 508→describe('twoOpt (generic atomic 2-opt)', () => {\n 509→ it('should return original tour for small inputs', () => {\n 510→ const points = [\n 511→ { x: 0, y: 0 },\n 512→ { x: 1, y: 1 },\n 513→ ];\n 514→ const tour = [0, 1];\n 515→ const result = twoOpt(points, tour);\n 516→ expect(result.tour).toEqual(tour);\n 517→ expect(result.improvement).toBe(0);\n 518→ });\n 519→\n 520→ it('should never increase tour distance', () => {\n 521→ const points = [\n 522→ { x: 0, y: 0 },\n 523→ { x: 10, y: 0 },\n 524→ { x: 10, y: 10 },\n 525→ { x: 0, y: 10 },\n 526→ { x: 5, y: 5 },\n 527→ ];\n 528→ const tour = [0, 2, 4, 1, 3];\n 529→ const originalDistance = calculateTotalDistance(tour, points);\n 530→ const result = twoOpt(points, tour);\n 531→ const newDistance = calculateTotalDistance(result.tour, points);\n 532→ expect(newDistance).toBeLessThanOrEqual(originalDistance);\n 533→ });\n 534→});\n 535→\n 536→describe('zigzagOptSteps (generic zigzag)', () => {\n 537→ it('should return empty array for tour with less than 4 points', () => {\n 538→ const points = [\n 539→ { x: 0, y: 0 },\n 540→ { x: 1, y: 1 },\n 541→ { x: 2, y: 2 },\n 542→ ];\n 543→ const tour = [0, 1, 2];\n 544→ expect(zigzagOptSteps(points, tour)).toEqual([]);\n 545→ });\n 546→\n 547→ it('should work on any tour regardless of source algorithm', () => {\n 548→ const points = [\n 549→ { x: 0, y: 0 },\n 550→ { x: 10, y: 0 },\n 551→ { x: 10, y: 10 },\n 552→ { x: 0, y: 10 },\n 553→ { x: 5, y: 5 },\n 554→ ];\n 555→ // This is not from any specific algorithm\n 556→ const randomTour = [0, 2, 4, 1, 3];\n 557→ const steps = zigzagOptSteps(points, randomTour);\n 558→ expect(Array.isArray(steps)).toBe(true);\n 559→ });\n 560→});\n 561→\n 562→describe('zigzagOpt (generic atomic zigzag)', () => {\n 563→ it('should return original tour for small inputs', () => {\n 564→ const points = [\n 565→ { x: 0, y: 0 },\n 566→ { x: 1, y: 1 },\n 567→ ];\n 568→ const tour = [0, 1];\n 569→ const result = zigzagOpt(points, tour);\n 570→ expect(result.tour).toEqual(tour);\n 571→ expect(result.improvement).toBe(0);\n 572→ });\n 573→\n 574→ it('should never increase tour distance', () => {\n 575→ const points = [\n 576→ { x: 0, y: 0 },\n 577→ { x: 10, y: 0 },\n 578→ { x: 10, y: 10 },\n 579→ { x: 0, y: 10 },\n 580→ { x: 5, y: 5 },\n 581→ ];\n 582→ const tour = [0, 2, 4, 1, 3];\n 583→ const originalDistance = calculateTotalDistance(tour, points);\n 584→ const result = zigzagOpt(points, tour);\n 585→ const newDistance = calculateTotalDistance(result.tour, points);\n 586→ expect(newDistance).toBeLessThanOrEqual(originalDistance);\n 587→ });\n 588→});\n 589→\n 590→describe('combined optimization (zigzag + 2-opt)', () => {\n 591→ const fivePoints = [\n 592→ { x: 0, y: 0 },\n 593→ { x: 10, y: 0 },\n 594→ { x: 10, y: 10 },\n 595→ { x: 0, y: 10 },\n 596→ { x: 5, y: 5 },\n 597→ ];\n 598→\n 599→ it('steps: should return empty array for tour with less than 4 points', () => {\n 600→ const points = [\n 601→ { x: 0, y: 0 },\n 602→ { x: 1, y: 1 },\n 603→ { x: 2, y: 2 },\n 604→ ];\n 605→ expect(combinedOptSteps(points, [0, 1, 2])).toEqual([]);\n 606→ });\n 607→\n 608→ it('steps: should work on any tour and have optimize type', () => {\n 609→ const steps = combinedOptSteps(fivePoints, [0, 2, 4, 1, 3]);\n 610→ expect(Array.isArray(steps)).toBe(true);\n 611→ steps.forEach((step) => expect(step.type).toBe('optimize'));\n 612→ });\n 613→\n 614→ it('atomic: should return original tour for small inputs', () => {\n 615→ const result = combinedOpt(\n 616→ [\n 617→ { x: 0, y: 0 },\n 618→ { x: 1, y: 1 },\n 619→ ],\n 620→ [0, 1]\n 621→ );\n 622→ expect(result.tour).toEqual([0, 1]);\n 623→ expect(result.improvement).toBe(0);\n 624→ });\n 625→\n 626→ it('atomic: should never increase tour distance', () => {\n 627→ const tour = [0, 2, 4, 1, 3];\n 628→ const originalDistance = calculateTotalDistance(tour, fivePoints);\n 629→ const result = combinedOpt(fivePoints, tour);\n 630→ expect(calculateTotalDistance(result.tour, fivePoints)).toBeLessThanOrEqual(\n 631→ originalDistance\n 632→ );\n 633→ });\n 634→\n 635→ it('atomic: should return zero improvement for optimal square tour', () => {\n 636→ const square = [\n 637→ { x: 0, y: 0 },\n 638→ { x: 10, y: 0 },\n 639→ { x: 10, y: 10 },\n 640→ { x: 0, y: 10 },\n 641→ ];\n 642→ expect(combinedOpt(square, [0, 1, 2, 3]).improvement).toBe(0);\n 643→ });\n 644→});\n 645→\n 646→// ============================================================\n 647→// Already-Optimal Tour Tests (Issue #15)\n 648→// ============================================================\n 649→\n 650→describe('optimization with already-optimal tours (issue #15)', () => {\n 651→ // 3 points forming a triangle — already optimal, no improvements possible\n 652→ const trianglePoints = [\n 653→ { x: 0, y: 0 },\n 654→ { x: 5, y: 0 },\n 655→ { x: 2, y: 4 },\n 656→ ];\n 657→ const triangleTour = [0, 1, 2];\n 658→\n 659→ // 4 points forming a square in optimal order\n 660→ const squarePoints = [\n 661→ { x: 0, y: 0 },\n 662→ { x: 10, y: 0 },\n 663→ { x: 10, y: 10 },\n 664→ { x: 0, y: 10 },\n 665→ ];\n 666→ const squareOptimalTour = [0, 1, 2, 3];\n 667→\n 668→ describe('twoOptSteps with already-optimal tours', () => {\n 669→ it('should return empty array for 3-point triangle tour (< 4 points)', () => {\n 670→ const steps = twoOptSteps(trianglePoints, triangleTour);\n 671→ expect(steps).toEqual([]);\n 672→ });\n 673→\n 674→ it('should return empty array for optimal square tour', () => {\n 675→ const steps = twoOptSteps(squarePoints, squareOptimalTour);\n 676→ expect(steps).toEqual([]);\n 677→ });\n 678→\n 679→ it('should preserve tour distance when no improvement found', () => {\n 680→ const originalDistance = calculateTotalDistance(\n 681→ squareOptimalTour,\n 682→ squarePoints\n 683→ );\n 684→ const result = twoOpt(squarePoints, squareOptimalTour);\n 685→ const newDistance = calculateTotalDistance(result.tour, squarePoints);\n 686→ expect(newDistance).toBe(originalDistance);\n 687→ expect(result.improvement).toBe(0);\n 688→ });\n 689→ });\n 690→\n 691→ describe('zigzagOptSteps with already-optimal tours', () => {\n 692→ it('should return empty array for 3-point triangle tour (< 4 points)', () => {\n 693→ const steps = zigzagOptSteps(trianglePoints, triangleTour);\n 694→ expect(steps).toEqual([]);\n 695→ });\n 696→\n 697→ it('should return empty array for optimal square tour', () => {\n 698→ const steps = zigzagOptSteps(squarePoints, squareOptimalTour);\n 699→ expect(steps).toEqual([]);\n 700→ });\n 701→\n 702→ it('should preserve tour distance when no improvement found', () => {\n 703→ const originalDistance = calculateTotalDistance(\n 704→ squareOptimalTour,\n 705→ squarePoints\n 706→ );\n 707→ const result = zigzagOpt(squarePoints, squareOptimalTour);\n 708→ const newDistance = calculateTotalDistance(result.tour, squarePoints);\n 709→ expect(newDistance).toBe(originalDistance);\n 710→ expect(result.improvement).toBe(0);\n 711→ });\n 712→ });\n 713→\n 714→ describe('full pipeline: solution then optimization on 3-point tour', () => {\n 715→ const points = [\n 716→ { x: 0, y: 0, id: 0 },\n 717→ { x: 5, y: 0, id: 1 },\n 718→ { x: 2, y: 4, id: 2 },\n 719→ ];\n 720→\n 721→ it('should produce valid sonar solution then empty optimization', () => {\n 722→ const steps = sonarAlgorithmSteps(points);\n 723→ expect(steps.length).toBe(points.length);\n 724→ const finalTour = steps[steps.length - 1].tour;\n 725→ expect(finalTour.length).toBe(points.length);\n 726→\n 727→ const optSteps = zigzagOptSteps(points, finalTour);\n 728→ expect(optSteps).toEqual([]);\n 729→\n 730→ // Distance should still be computable from the solution tour\n 731→ const dist = calculateTotalDistance(finalTour, points);\n 732→ expect(dist).toBeGreaterThan(0);\n 733→ });\n 734→\n 735→ it('should produce valid moore solution then empty optimization', () => {\n 736→ const steps = mooreAlgorithmSteps(points, 16);\n 737→ expect(steps.length).toBeGreaterThan(0);\n 738→ const finalTour = steps[steps.length - 1].tour;\n 739→ expect(finalTour.length).toBe(points.length);\n 740→\n 741→ const optSteps = twoOptSteps(points, finalTour);\n 742→ expect(optSteps).toEqual([]);\n 743→\n 744→ // Distance should still be computable from the solution tour\n 745→ const dist = calculateTotalDistance(finalTour, points);\n 746→ expect(dist).toBeGreaterThan(0);\n 747→ });\n 748→ });\n 749→});\n 750→\n 751→// ============================================================\n 752→// Moore Curve Point-by-Point Verification Tests\n 753→// ============================================================\n 754→\n 755→/**\n 756→ * Helper: generate Moore curve points for a given grid size.\n 757→ * Grid size must be a power of 2 (2, 4, 8, 16, 32, 64).\n 758→ * Returns normalized points in [0, gridSize-1] range.\n 759→ */\n 760→function getMooreCurvePoints(gridSize) {\n 761→ const iterations = Math.round(Math.log2(gridSize)) - 1;\n 762→ const sequence = generateMooreCurve(iterations);\n 763→ return mooreCurveToPoints(sequence, gridSize);\n 764→}\n 765→\n 766→describe('Moore curve point-by-point verification (2x2)', () => {\n 767→ const gridSize = 2;\n 768→ const points = getMooreCurvePoints(gridSize);\n 769→\n 770→ it('should have exactly 4 vertices', () => {\n 771→ expect(points.length).toBe(4);\n 772→ });\n 773→\n 774→ it('should visit all 4 grid cells', () => {\n 775→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 776→ expect(unique.size).toBe(4);\n 777→ expect(unique.has('0,0')).toBe(true);\n 778→ expect(unique.has('0,1')).toBe(true);\n 779→ expect(unique.has('1,0')).toBe(true);\n 780→ expect(unique.has('1,1')).toBe(true);\n 781→ });\n 782→\n 783→ it('should follow the exact path: (0,1) -> (0,0) -> (1,0) -> (1,1)', () => {\n 784→ expect(points[0]).toEqual({ x: 0, y: 1 });\n 785→ expect(points[1]).toEqual({ x: 0, y: 0 });\n 786→ expect(points[2]).toEqual({ x: 1, y: 0 });\n 787→ expect(points[3]).toEqual({ x: 1, y: 1 });\n 788→ });\n 789→\n 790→ it('should have all consecutive points adjacent (distance 1)', () => {\n 791→ for (let i = 0; i < points.length - 1; i++) {\n 792→ const d = distance(points[i], points[i + 1]);\n 793→ expect(d).toBe(1);\n 794→ }\n 795→ });\n 796→\n 797→ it('should form a closed loop (first and last points are adjacent)', () => {\n 798→ const d = distance(points[0], points[points.length - 1]);\n 799→ expect(d).toBe(1);\n 800→ });\n 801→});\n 802→\n 803→describe('Moore curve point-by-point verification (4x4)', () => {\n 804→ const gridSize = 4;\n 805→ const points = getMooreCurvePoints(gridSize);\n 806→\n 807→ it('should have exactly 16 vertices', () => {\n 808→ expect(points.length).toBe(16);\n 809→ });\n 810→\n 811→ it('should visit all 16 grid cells', () => {\n 812→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 813→ expect(unique.size).toBe(16);\n 814→ for (let x = 0; x < 4; x++) {\n 815→ for (let y = 0; y < 4; y++) {\n 816→ expect(unique.has(`${x},${y}`)).toBe(true);\n 817→ }\n 818→ }\n 819→ });\n 820→\n 821→ it('should follow the exact 4x4 Moore curve path', () => {\n 822→ const expectedPath = [\n 823→ { x: 1, y: 3 },\n 824→ { x: 0, y: 3 },\n 825→ { x: 0, y: 2 },\n 826→ { x: 1, y: 2 },\n 827→ { x: 1, y: 1 },\n 828→ { x: 0, y: 1 },\n 829→ { x: 0, y: 0 },\n 830→ { x: 1, y: 0 },\n 831→ { x: 2, y: 0 },\n 832→ { x: 3, y: 0 },\n 833→ { x: 3, y: 1 },\n 834→ { x: 2, y: 1 },\n 835→ { x: 2, y: 2 },\n 836→ { x: 3, y: 2 },\n 837→ { x: 3, y: 3 },\n 838→ { x: 2, y: 3 },\n 839→ ];\n 840→ expect(points).toEqual(expectedPath);\n 841→ });\n 842→\n 843→ it('should have all consecutive points adjacent (distance 1)', () => {\n 844→ for (let i = 0; i < points.length - 1; i++) {\n 845→ const d = distance(points[i], points[i + 1]);\n 846→ expect(d).toBe(1);\n 847→ }\n 848→ });\n 849→\n 850→ it('should form a closed loop', () => {\n 851→ const d = distance(points[0], points[points.length - 1]);\n 852→ expect(d).toBe(1);\n 853→ });\n 854→});\n 855→\n 856→describe('Moore curve verification (8x8)', () => {\n 857→ const gridSize = 8;\n 858→ const points = getMooreCurvePoints(gridSize);\n 859→\n 860→ it('should have exactly 64 vertices', () => {\n 861→ expect(points.length).toBe(64);\n 862→ });\n 863→\n 864→ it('should visit all 64 grid cells', () => {\n 865→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 866→ expect(unique.size).toBe(64);\n 867→ for (let x = 0; x < 8; x++) {\n 868→ for (let y = 0; y < 8; y++) {\n 869→ expect(unique.has(`${x},${y}`)).toBe(true);\n 870→ }\n 871→ }\n 872→ });\n 873→\n 874→ it('should have all consecutive points adjacent (distance 1)', () => {\n 875→ for (let i = 0; i < points.length - 1; i++) {\n 876→ const d = distance(points[i], points[i + 1]);\n 877→ expect(d).toBe(1);\n 878→ }\n 879→ });\n 880→\n 881→ it('should form a closed loop', () => {\n 882→ const d = distance(points[0], points[points.length - 1]);\n 883→ expect(d).toBe(1);\n 884→ });\n 885→\n 886→ it('should have no cross-shaped gap (center row and column covered)', () => {\n 887→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 888→ // Center of 8x8 grid is at rows/columns 3 and 4\n 889→ for (let i = 0; i < 8; i++) {\n 890→ expect(unique.has(`${i},3`)).toBe(true);\n 891→ expect(unique.has(`${i},4`)).toBe(true);\n 892→ expect(unique.has(`3,${i}`)).toBe(true);\n 893→ expect(unique.has(`4,${i}`)).toBe(true);\n 894→ }\n 895→ });\n 896→\n 897→ it('should have all points within [0, 7] range', () => {\n 898→ points.forEach((p) => {\n 899→ expect(p.x).toBeGreaterThanOrEqual(0);\n 900→ expect(p.x).toBeLessThanOrEqual(7);\n 901→ expect(p.y).toBeGreaterThanOrEqual(0);\n 902→ expect(p.y).toBeLessThanOrEqual(7);\n 903→ });\n 904→ });\n 905→});\n 906→\n 907→describe('Moore curve verification (16x16)', () => {\n 908→ const gridSize = 16;\n 909→ const points = getMooreCurvePoints(gridSize);\n 910→\n 911→ it('should have exactly 256 vertices', () => {\n 912→ expect(points.length).toBe(256);\n 913→ });\n 914→\n 915→ it('should visit all 256 grid cells', () => {\n 916→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 917→ expect(unique.size).toBe(256);\n 918→ for (let x = 0; x < 16; x++) {\n 919→ for (let y = 0; y < 16; y++) {\n 920→ expect(unique.has(`${x},${y}`)).toBe(true);\n 921→ }\n 922→ }\n 923→ });\n 924→\n 925→ it('should have all consecutive points adjacent (distance 1)', () => {\n 926→ for (let i = 0; i < points.length - 1; i++) {\n 927→ const d = distance(points[i], points[i + 1]);\n 928→ expect(d).toBe(1);\n 929→ }\n 930→ });\n 931→\n 932→ it('should form a closed loop', () => {\n 933→ const d = distance(points[0], points[points.length - 1]);\n 934→ expect(d).toBe(1);\n 935→ });\n 936→\n 937→ it('should have no cross-shaped gap (center covered)', () => {\n 938→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 939→ for (let i = 0; i < 16; i++) {\n 940→ expect(unique.has(`${i},7`)).toBe(true);\n 941→ expect(unique.has(`${i},8`)).toBe(true);\n 942→ expect(unique.has(`7,${i}`)).toBe(true);\n 943→ expect(unique.has(`8,${i}`)).toBe(true);\n 944→ }\n 945→ });\n 946→});\n 947→\n 948→describe('Moore curve verification (32x32)', () => {\n 949→ const gridSize = 32;\n 950→ const points = getMooreCurvePoints(gridSize);\n 951→\n 952→ it('should have exactly 1024 vertices', () => {\n 953→ expect(points.length).toBe(1024);\n 954→ });\n 955→\n 956→ it('should visit all 1024 grid cells', () => {\n 957→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 958→ expect(unique.size).toBe(1024);\n 959→ for (let x = 0; x < 32; x++) {\n 960→ for (let y = 0; y < 32; y++) {\n 961→ expect(unique.has(`${x},${y}`)).toBe(true);\n 962→ }\n 963→ }\n 964→ });\n 965→\n 966→ it('should have all consecutive points adjacent (distance 1)', () => {\n 967→ for (let i = 0; i < points.length - 1; i++) {\n 968→ const d = distance(points[i], points[i + 1]);\n 969→ expect(d).toBe(1);\n 970→ }\n 971→ });\n 972→\n 973→ it('should form a closed loop', () => {\n 974→ const d = distance(points[0], points[points.length - 1]);\n 975→ expect(d).toBe(1);\n 976→ });\n 977→\n 978→ it('should have no cross-shaped gap (center covered)', () => {\n 979→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 980→ for (let i = 0; i < 32; i++) {\n 981→ expect(unique.has(`${i},15`)).toBe(true);\n 982→ expect(unique.has(`${i},16`)).toBe(true);\n 983→ expect(unique.has(`15,${i}`)).toBe(true);\n 984→ expect(unique.has(`16,${i}`)).toBe(true);\n 985→ }\n 986→ });\n 987→});\n 988→\n 989→// ============================================================\n 990→// Moore Curve Edge Verification Tests\n 991→// ============================================================\n 992→\n 993→describe('Moore curve edge verification (2x2)', () => {\n 994→ const points = getMooreCurvePoints(2);\n 995→\n 996→ it('should have correct edges', () => {\n 997→ // Path: (0,1) -> (0,0) -> (1,0) -> (1,1)\n 998→ const edges = [];\n 999→ for (let i = 0; i < points.length - 1; i++) {\n 1000→ edges.push(\n 1001→ `(${points[i].x},${points[i].y})->(${points[i + 1].x},${points[i + 1].y})`\n 1002→ );\n 1003→ }\n 1004→ expect(edges).toEqual(['(0,1)->(0,0)', '(0,0)->(1,0)', '(1,0)->(1,1)']);\n 1005→ });\n 1006→\n 1007→ it('should have closing edge back to start', () => {\n 1008→ const last = points[points.length - 1];\n 1009→ const first = points[0];\n 1010→ const d = distance(last, first);\n 1011→ expect(d).toBe(1);\n 1012→ // (1,1) -> (0,1) closing edge\n 1013→ expect(last).toEqual({ x: 1, y: 1 });\n 1014→ expect(first).toEqual({ x: 0, y: 1 });\n 1015→ });\n 1016→});\n 1017→\n 1018→describe('Moore curve edge verification (4x4)', () => {\n 1019→ const points = getMooreCurvePoints(4);\n 1020→\n 1021→ it('should have exactly 15 edges (16 vertices - 1)', () => {\n 1022→ const edges = [];\n 1023→ for (let i = 0; i < points.length - 1; i++) {\n 1024→ edges.push({\n 1025→ from: points[i],\n 1026→ to: points[i + 1],\n 1027→ });\n 1028→ }\n 1029→ expect(edges.length).toBe(15);\n 1030→ });\n 1031→\n 1032→ it('should have all edges with length 1 (horizontal or vertical)', () => {\n 1033→ for (let i = 0; i < points.length - 1; i++) {\n 1034→ const dx = Math.abs(points[i + 1].x - points[i].x);\n 1035→ const dy = Math.abs(points[i + 1].y - points[i].y);\n 1036→ // Each edge must be exactly 1 unit horizontal or vertical\n 1037→ expect((dx === 1 && dy === 0) || (dx === 0 && dy === 1)).toBe(true);\n 1038→ }\n 1039→ });\n 1040→\n 1041→ it('should have no self-intersecting edges', () => {\n 1042→ // All edges connect distinct vertices, and all vertices are unique\n 1043→ const visited = new Set();\n 1044→ for (const p of points) {\n 1045→ const key = `${p.x},${p.y}`;\n 1046→ expect(visited.has(key)).toBe(false);\n 1047→ visited.add(key);\n 1048→ }\n 1049→ });\n 1050→});\n 1051→\n 1052→// ============================================================\n 1053→// Moore Curve Properties Tests (all valid sizes)\n 1054→// ============================================================\n 1055→\n 1056→describe('Moore curve properties for all valid grid sizes', () => {\n 1057→ // Test for 2, 4, 8, 16, 32 (skip 64 to keep test fast)\n 1058→ const testSizes = [2, 4, 8, 16, 32];\n 1059→\n 1060→ testSizes.forEach((gridSize) => {\n 1061→ describe(`grid size ${gridSize}x${gridSize}`, () => {\n 1062→ const points = getMooreCurvePoints(gridSize);\n 1063→\n 1064→ it(`should have exactly ${gridSize * gridSize} vertices`, () => {\n 1065→ expect(points.length).toBe(gridSize * gridSize);\n 1066→ });\n 1067→\n 1068→ it('should visit every grid cell exactly once', () => {\n 1069→ const unique = new Set(points.map((p) => `${p.x},${p.y}`));\n 1070→ expect(unique.size).toBe(gridSize * gridSize);\n 1071→ });\n 1072→\n 1073→ it('should have all points within [0, gridSize-1]', () => {\n 1074→ points.forEach((p) => {\n 1075→ expect(p.x).toBeGreaterThanOrEqual(0);\n 1076→ expect(p.x).toBeLessThanOrEqual(gridSize - 1);\n 1077→ expect(p.y).toBeGreaterThanOrEqual(0);\n 1078→ expect(p.y).toBeLessThanOrEqual(gridSize - 1);\n 1079→ });\n 1080→ });\n 1081→\n 1082→ it('should have all consecutive points adjacent (distance 1)', () => {\n 1083→ for (let i = 0; i < points.length - 1; i++) {\n 1084→ const d = distance(points[i], points[i + 1]);\n 1085→ expect(d).toBe(1);\n 1086→ }\n 1087→ });\n 1088→\n 1089→ it('should form a closed loop', () => {\n 1090→ const d = distance(points[0], points[points.length - 1]);\n 1091→ expect(d).toBe(1);\n 1092→ });\n 1093→ });\n 1094→ });\n 1095→});\n 1096→\n 1097→// ============================================================\n 1098→// Brute-Force Verification Tests\n 1099→// ============================================================\n 1100→\n 1101→describe('BRUTE_FORCE_MAX_POINTS', () => {\n 1102→ it('should be a reasonable positive integer', () => {\n 1103→ expect(BRUTE_FORCE_MAX_POINTS).toBeGreaterThanOrEqual(8);\n 1104→ expect(BRUTE_FORCE_MAX_POINTS).toBeLessThanOrEqual(20);\n 1105→ });\n 1106→});\n 1107→\n 1108→describe('bruteForceOptimalTour', () => {\n 1109→ it('should return empty tour for empty points', () => {\n 1110→ const result = bruteForceOptimalTour([]);\n 1111→ expect(result.tour).toEqual([]);\n 1112→ expect(result.distance).toBe(0);\n 1113→ });\n 1114→\n 1115→ it('should return single-point tour', () => {\n 1116→ const result = bruteForceOptimalTour([{ x: 5, y: 5 }]);\n 1117→ expect(result.tour).toEqual([0]);\n 1118→ expect(result.distance).toBe(0);\n 1119→ });\n 1120→\n 1121→ it('should return correct tour for 2 points', () => {\n 1122→ const points = [\n 1123→ { x: 0, y: 0 },\n 1124→ { x: 3, y: 4 },\n 1125→ ];\n 1126→ const result = bruteForceOptimalTour(points);\n 1127→ expect(result.tour).toEqual([0, 1]);\n 1128→ expect(result.distance).toBe(10); // 2 * 5 = 10 (closed loop)\n 1129→ });\n 1130→\n 1131→ it('should return correct optimal tour for a square', () => {\n 1132→ const points = [\n 1133→ { x: 0, y: 0 },\n 1134→ { x: 10, y: 0 },\n 1135→ { x: 10, y: 10 },\n 1136→ { x: 0, y: 10 },\n 1137→ ];\n 1138→ const result = bruteForceOptimalTour(points);\n 1139→ // Optimal tour for a square has distance 40\n 1140→ expect(result.distance).toBe(40);\n 1141→ expect(result.tour.length).toBe(4);\n 1142→ expect(new Set(result.tour).size).toBe(4);\n 1143→ });\n 1144→\n 1145→ it('should return optimal tour for a triangle', () => {\n 1146→ const points = [\n 1147→ { x: 0, y: 0 },\n 1148→ { x: 3, y: 0 },\n 1149→ { x: 0, y: 4 },\n 1150→ ];\n 1151→ const result = bruteForceOptimalTour(points);\n 1152→ // Triangle: 3 + 4 + 5 = 12\n 1153→ expect(result.distance).toBe(12);\n 1154→ expect(result.tour.length).toBe(3);\n 1155→ });\n 1156→\n 1157→ it('should return null for too many points', () => {\n 1158→ const points = Array.from(\n 1159→ { length: BRUTE_FORCE_MAX_POINTS + 1 },\n 1160→ (_, i) => ({\n 1161→ x: i,\n 1162→ y: 0,\n 1163→ })\n 1164→ );\n 1165→ const result = bruteForceOptimalTour(points);\n 1166→ expect(result).toBeNull();\n 1167→ });\n 1168→\n 1169→ it('should find optimal tour shorter than or equal to sonar for 5 points', () => {\n 1170→ const points = [\n 1171→ { x: 0, y: 0, id: 0 },\n 1172→ { x: 10, y: 0, id: 1 },\n 1173→ { x: 10, y: 10, id: 2 },\n 1174→ { x: 0, y: 10, id: 3 },\n 1175→ { x: 5, y: 5, id: 4 },\n 1176→ ];\n 1177→ const optResult = bruteForceOptimalTour(points);\n 1178→ const sonarResult = sonarSolution(points);\n 1179→ const sonarDist = calculateTotalDistance(sonarResult.tour, points);\n 1180→ expect(optResult.distance).toBeLessThanOrEqual(sonarDist + 0.001);\n 1181→ });\n 1182→\n 1183→ it('should find optimal tour shorter than or equal to moore for 5 points', () => {\n 1184→ const points = [\n 1185→ { x: 0, y: 0, id: 0 },\n 1186→ { x: 8, y: 0, id: 1 },\n 1187→ { x: 8, y: 8, id: 2 },\n 1188→ { x: 0, y: 8, id: 3 },\n 1189→ { x: 4, y: 4, id: 4 },\n 1190→ ];\n 1191→ const optResult = bruteForceOptimalTour(points);\n 1192→ const mooreResult = mooreSolution(points, 16);\n 1193→ const mooreDist = calculateTotalDistance(mooreResult.tour, points);\n 1194→ expect(optResult.distance).toBeLessThanOrEqual(mooreDist + 0.001);\n 1195→ });\n 1196→\n 1197→ it('should handle collinear points correctly', () => {\n 1198→ const points = [\n 1199→ { x: 0, y: 0 },\n 1200→ { x: 1, y: 0 },\n 1201→ { x: 2, y: 0 },\n 1202→ { x: 3, y: 0 },\n 1203→ ];\n 1204→ const result = bruteForceOptimalTour(points);\n 1205→ // Optimal for collinear: 0->1->2->3->0 = 1+1+1+3 = 6\n 1206→ expect(result.distance).toBe(6);\n 1207→ });\n 1208→\n 1209→ it('should always start tour from point 0', () => {\n 1210→ const points = [\n 1211→ { x: 0, y: 0 },\n 1212→ { x: 5, y: 0 },\n 1213→ { x: 5, y: 5 },\n 1214→ { x: 0, y: 5 },\n 1215→ ];\n 1216→ const result = bruteForceOptimalTour(points);\n 1217→ expect(result.tour[0]).toBe(0);\n 1218→ });\n 1219→});\n 1220→\n 1221→describe('bruteForceAlgorithmSteps', () => {\n 1222→ it('should return steps for small point sets', () => {\n 1223→ const points = [\n 1224→ { x: 0, y: 0 },\n 1225→ { x: 3, y: 4 },\n 1226→ ];\n 1227→ const steps = bruteForceSteps(points);\n 1228→ expect(steps.length).toBeGreaterThanOrEqual(1);\n 1229→ expect(steps[0].type).toBe('solution');\n 1230→ expect(steps[steps.length - 1].tour.length).toBe(2);\n 1231→ });\n 1232→\n 1233→ it('should report infeasible for too many points', () => {\n 1234→ const points = Array.from(\n 1235→ { length: BRUTE_FORCE_MAX_POINTS + 1 },\n 1236→ (_, i) => ({\n 1237→ x: i,\n 1238→ y: 0,\n 1239→ })\n 1240→ );\n 1241→ const steps = bruteForceSteps(points);\n 1242→ expect(steps.length).toBe(1);\n 1243→ expect(steps[0].feasible).toBe(false);\n 1244→ expect(steps[0].description).toContain('Too many points');\n 1245→ });\n 1246→\n 1247→ it('should include distance in last step description', () => {\n 1248→ const points = [\n 1249→ { x: 0, y: 0 },\n 1250→ { x: 3, y: 4 },\n 1251→ ];\n 1252→ const steps = bruteForceSteps(points);\n 1253→ const lastStep = steps[steps.length - 1];\n 1254→ expect(lastStep.description).toContain('10.00');\n 1255→ });\n 1256→\n 1257→ it('should show progressive improvements for larger sets', () => {\n 1258→ const points = [\n 1259→ { x: 0, y: 0 },\n 1260→ { x: 3, y: 0 },\n 1261→ { x: 3, y: 4 },\n 1262→ { x: 0, y: 4 },\n 1263→ { x: 1, y: 2 },\n 1264→ ];\n 1265→ const steps = bruteForceSteps(points);\n 1266→ // Should have more than one step: initial + improvements + final\n 1267→ expect(steps.length).toBeGreaterThan(1);\n 1268→ // All steps should be type 'solution'\n 1269→ steps.forEach((step) => expect(step.type).toBe('solution'));\n 1270→ });\n 1271→\n 1272→ it('should return empty array for empty points', () => {\n 1273→ const steps = bruteForceSteps([]);\n 1274→ expect(steps).toEqual([]);\n 1275→ });\n 1276→\n 1277→ it('should return trivial tour for single point', () => {\n 1278→ const points = [{ x: 5, y: 3 }];\n 1279→ const steps = bruteForceSteps(points);\n 1280→ expect(steps.length).toBe(1);\n 1281→ expect(steps[0].type).toBe('solution');\n 1282→ expect(steps[0].tour).toEqual([0]);\n 1283→ expect(steps[0].description).toContain('trivial');\n 1284→ });\n 1285→});\n 1286→\n 1287→// ============================================================\n 1288→// Lower-Bound Verification Tests\n 1289→// ============================================================\n 1290→\n 1291→describe('oneTreeLowerBound', () => {\n 1292→ it('should return 0 for empty or single point', () => {\n 1293→ expect(oneTreeLowerBound([]).lowerBound).toBe(0);\n 1294→ expect(oneTreeLowerBound([{ x: 0, y: 0 }]).lowerBound).toBe(0);\n 1295→ });\n 1296→\n 1297→ it('should return exact distance for 2 points', () => {\n 1298→ const points = [\n 1299→ { x: 0, y: 0 },\n 1300→ { x: 3, y: 4 },\n 1301→ ];\n 1302→ const result = oneTreeLowerBound(points);\n 1303→ expect(result.lowerBound).toBe(10); // 2 * 5\n 1304→ expect(result.method).toBe('1-tree');\n 1305→ });\n 1306→\n 1307→ it('should provide a valid lower bound for a square', () => {\n 1308→ const points = [\n 1309→ { x: 0, y: 0 },\n 1310→ { x: 10, y: 0 },\n 1311→ { x: 10, y: 10 },\n 1312→ { x: 0, y: 10 },\n 1313→ ];\n 1314→ const result = oneTreeLowerBound(points);\n 1315→ // The optimal tour for a square is 40\n 1316→ // The lower bound should be <= 40\n 1317→ expect(result.lowerBound).toBeLessThanOrEqual(40 + 0.001);\n 1318→ expect(result.lowerBound).toBeGreaterThan(0);\n 1319→ });\n 1320→\n 1321→ it('should be less than or equal to brute-force optimal for small instances', () => {\n 1322→ const points = [\n 1323→ { x: 0, y: 0, id: 0 },\n 1324→ { x: 5, y: 0, id: 1 },\n 1325→ { x: 5, y: 5, id: 2 },\n 1326→ { x: 0, y: 5, id: 3 },\n 1327→ { x: 2, y: 3, id: 4 },\n 1328→ ];\n 1329→ const lbResult = oneTreeLowerBound(points);\n 1330→ const bfResult = bruteForceSolution(points);\n 1331→ expect(lbResult.lowerBound).toBeLessThanOrEqual(bfResult.distance + 0.001);\n 1332→ });\n 1333→});\n 1334→\n 1335→describe('verifyOptimality', () => {\n 1336→ it('should verify optimal tour for simple cases', () => {\n 1337→ const points = [\n 1338→ { x: 0, y: 0 },\n 1339→ { x: 3, y: 4 },\n 1340→ ];\n 1341→ // Optimal distance is 10\n 1342→ const result = verifyOptimality(10, points);\n 1343→ expect(result.isOptimal).toBe(true);\n 1344→ expect(result.gap).toBeCloseTo(0);\n 1345→ });\n 1346→\n 1347→ it('should detect suboptimal tour', () => {\n 1348→ const points = [\n 1349→ { x: 0, y: 0 },\n 1350→ { x: 10, y: 0 },\n 1351→ { x: 10, y: 10 },\n 1352→ { x: 0, y: 10 },\n 1353→ ];\n 1354→ // Tour distance much larger than optimal\n 1355→ const result = verifyOptimality(100, points);\n 1356→ expect(result.isOptimal).toBe(false);\n 1357→ expect(result.gapPercent).toBeGreaterThan(0);\n 1358→ });\n 1359→\n 1360→ it('should report method as 1-tree', () => {\n 1361→ const points = [\n 1362→ { x: 0, y: 0 },\n 1363→ { x: 1, y: 0 },\n 1364→ ];\n 1365→ const result = verifyOptimality(2, points);\n 1366→ expect(result.method).toBe('1-tree');\n 1367→ });\n 1368→});\n 1369→\n 1370→describe('calculateOptimalityRatio', () => {\n 1371→ it('should return 1.0 for optimal tour', () => {\n 1372→ expect(calculateOptimalityRatio(10, 10)).toBe(1.0);\n 1373→ });\n 1374→\n 1375→ it('should return correct ratio for suboptimal tour', () => {\n 1376→ expect(calculateOptimalityRatio(15, 10)).toBe(1.5);\n 1377→ });\n 1378→\n 1379→ it('should return 1.0 when both distances are 0', () => {\n 1380→ expect(calculateOptimalityRatio(0, 0)).toBe(1.0);\n 1381→ });\n 1382→\n 1383→ it('should return Infinity when optimal is 0 but tour is not', () => {\n 1384→ expect(calculateOptimalityRatio(5, 0)).toBe(Infinity);\n 1385→ });\n 1386→});\n 1387→\n 1388→// ============================================================\n 1389→// Integration: Verification with Algorithm Pipelines (Issue #31)\n 1390→// ============================================================\n 1391→\n 1392→describe('verification integration with algorithm pipelines', () => {\n 1393→ const points = [\n 1394→ { x: 0, y: 0, id: 0 },\n 1395→ { x: 5, y: 0, id: 1 },\n 1396→ { x: 5, y: 5, id: 2 },\n 1397→ { x: 0, y: 5, id: 3 },\n 1398→ ];\n 1399→\n 1400→ it('should verify sonar tour is not falsely claimed optimal', () => {\n 1401→ const sonarResult = sonarSolution(points);\n 1402→ const sonarDist = calculateTotalDistance(sonarResult.tour, points);\n 1403→ const optimal = bruteForceOptimalTour(points);\n 1404→\n 1405→ // The sonar tour may or may not be optimal, but we can verify the claim\n 1406→ if (Math.abs(sonarDist - optimal.distance) < 0.001) {\n 1407→ expect(calculateOptimalityRatio(sonarDist, optimal.distance)).toBeCloseTo(\n 1408→ 1.0\n 1409→ );\n 1410→ } else {\n 1411→ expect(sonarDist).toBeGreaterThan(optimal.distance);\n 1412→ }\n 1413→ });\n 1414→\n 1415→ it('should verify moore tour is not falsely claimed optimal', () => {\n 1416→ const mooreResult = mooreSolution(points, 16);\n 1417→ const mooreDist = calculateTotalDistance(mooreResult.tour, points);\n 1418→ const optimal = bruteForceOptimalTour(points);\n 1419→\n 1420→ if (Math.abs(mooreDist - optimal.distance) < 0.001) {\n 1421→ expect(calculateOptimalityRatio(mooreDist, optimal.distance)).toBeCloseTo(\n 1422→ 1.0\n 1423→ );\n 1424→ } else {\n 1425→ expect(mooreDist).toBeGreaterThan(optimal.distance);\n 1426→ }\n 1427→ });\n 1428→\n 1429→ it('should verify optimized tour is at least as good as unoptimized', () => {\n 1430→ const sonarResult = sonarSolution(points);\n 1431→ const sonarDist = calculateTotalDistance(sonarResult.tour, points);\n 1432→ const optimized = twoOpt(points, sonarResult.tour);\n 1433→ const optDist = calculateTotalDistance(optimized.tour, points);\n 1434→ const optimal = bruteForceOptimalTour(points);\n 1435→\n 1436→ expect(optDist).toBeLessThanOrEqual(sonarDist + 0.001);\n 1437→ expect(optimal.distance).toBeLessThanOrEqual(optDist + 0.001);\n 1438→ });\n 1439→\n 1440→ it('should compute meaningful optimality ratio for heuristic results', () => {\n 1441→ const points8 = [\n 1442→ { x: 0, y: 0, id: 0 },\n 1443→ { x: 4, y: 0, id: 1 },\n 1444→ { x: 8, y: 0, id: 2 },\n 1445→ { x: 8, y: 4, id: 3 },\n 1446→ { x: 8, y: 8, id: 4 },\n 1447→ { x: 4, y: 8, id: 5 },\n 1448→ { x: 0, y: 8, id: 6 },\n 1449→ { x: 0, y: 4, id: 7 },\n 1450→ ];\n 1451→ const optimal = bruteForceOptimalTour(points8);\n 1452→ const sonarResult = sonarSolution(points8);\n 1453→ const sonarDist = calculateTotalDistance(sonarResult.tour, points8);\n 1454→ const ratio = calculateOptimalityRatio(sonarDist, optimal.distance);\n 1455→\n 1456→ // Ratio should be >= 1.0 (optimal or worse)\n 1457→ expect(ratio).toBeGreaterThanOrEqual(1.0);\n 1458→ // And for these simple cases, not too far from optimal\n 1459→ expect(ratio).toBeLessThanOrEqual(2.0);\n 1460→ });\n 1461→});\n 1462→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "568b1f8c-e8e4-4409-be6f-0a87b3a43d4a"
}
[2026-02-07T22:19:47.429Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01DvURzgDkFkNvEkGFADwp7h",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01EdADt3UCz42DoTWJVykzuV",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/cli/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 4114,
"cache_read_input_tokens": 31850,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4114
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f034057d-f03c-4ce2-ae45-9b5291fcfce0"
}
[2026-02-07T22:19:47.430Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01EdADt3UCz42DoTWJVykzuV",
"type": "tool_result",
"content": " 1→#!/usr/bin/env node\n 2→\n 3→/* global performance */\n 4→\n 5→/**\n 6→ * TSP Algorithms CLI\n 7→ *\n 8→ * A globally installable command-line interface for running TSP algorithms.\n 9→ * Uses atomic algorithms (all-at-once computation) for benchmark-like performance.\n 10→ *\n 11→ * Supports:\n 12→ * - Algorithm selection: sonar, moore, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force\n 13→ * - Optimization: 2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined, none\n 14→ * - Random point generation with configurable grid size and point count\n 15→ * - Manual point input via links notation (coordinate pairs as links)\n 16→ * - Verification via lower-bound (1-tree) analysis\n 17→ *\n 18→ * @example\n 19→ * # Random points with sonar algorithm\n 20→ * tsp-algorithms --algorithm sonar --num-points 20 --grid-size 32\n 21→ *\n 22→ * # Moore curve with 2-opt optimization\n 23→ * tsp-algorithms --algorithm moore --optimization 2-opt --num-points 50\n 24→ *\n 25→ * # Lin-Kernighan-Helsgaun optimization\n 26→ * tsp-algorithms --algorithm moore --optimization lkh --num-points 50\n 27→ *\n 28→ * # Manual points via links notation\n 29→ * tsp-algorithms --algorithm sonar --points \"0 0 5 5 10 2 3 8 7 7\"\n 30→ *\n 31→ * # Brute-force with verification\n 32→ * tsp-algorithms --algorithm brute-force --num-points 8 --verify\n 33→ */\n 34→\n 35→import { makeConfig } from 'lino-arguments';\n 36→import {\n 37→ atomic,\n 38→ verification,\n 39→ calculateTotalDistance,\n 40→ generateRandomPoints,\n 41→ calculateMooreGridSize,\n 42→ calculatePeanoGridSize,\n 43→ VALID_GRID_SIZES,\n 44→ VALID_PEANO_GRID_SIZES,\n 45→} from '../lib/index.js';\n 46→\n 47→const {\n 48→ sonarSolution,\n 49→ mooreSolution,\n 50→ gosperSolution,\n 51→ peanoSolution,\n 52→ sierpinskiSolution,\n 53→ combSolution,\n 54→ sawSolution,\n 55→ kochSolution,\n 56→ spaceFillingTreeSolution,\n 57→ bruteForceSolution,\n 58→ twoOpt,\n 59→ threeOpt,\n 60→ kOpt,\n 61→ zigzagOpt,\n 62→ combinedOpt,\n 63→ linKernighan,\n 64→ lkHelsgaun,\n 65→ BRUTE_FORCE_MAX_POINTS,\n 66→} = atomic;\n 67→\n 68→const { verifyOptimality } = verification;\n 69→\n 70→/**\n 71→ * Parse points from a flat coordinate string.\n 72→ * Coordinates are provided as space-separated pairs: \"x1 y1 x2 y2 ...\"\n 73→ *\n 74→ * @param {string} pointsStr - Space-separated coordinate pairs\n 75→ * @returns {Array<{x: number, y: number, id: number}>} Array of point objects\n 76→ */\n 77→const parsePoints = (pointsStr) => {\n 78→ const values = pointsStr.trim().split(/\\s+/).map(Number);\n 79→\n 80→ if (values.length < 4 || values.length % 2 !== 0) {\n 81→ throw new Error(\n 82→ 'Points must be space-separated coordinate pairs (at least 2 points): \"x1 y1 x2 y2 ...\"'\n 83→ );\n 84→ }\n 85→\n 86→ if (values.some((v) => isNaN(v))) {\n 87→ throw new Error('All coordinates must be valid numbers');\n 88→ }\n 89→\n 90→ const points = [];\n 91→ for (let i = 0; i < values.length; i += 2) {\n 92→ points.push({ x: values[i], y: values[i + 1], id: points.length });\n 93→ }\n 94→ return points;\n 95→};\n 96→\n 97→/**\n 98→ * Format a tour for display.\n 99→ *\n 100→ * @param {number[]} tour - Array of point indices\n 101→ * @param {Array<{x: number, y: number}>} points - Array of point coordinates\n 102→ * @returns {string} Formatted tour string\n 103→ */\n 104→const formatTour = (tour, points) => {\n 105→ const coordStr = tour\n 106→ .map((idx) => `(${points[idx].x}, ${points[idx].y})`)\n 107→ .join(' → ');\n 108→ return `${tour.join(' → ')}\\n Coordinates: ${coordStr}`;\n 109→};\n 110→\n 111→/**\n 112→ * Run the selected algorithm on the given points.\n 113→ *\n 114→ * @param {string} algorithm - Algorithm name\n 115→ * @param {Array<{x: number, y: number, id: number}>} points - Points\n 116→ * @param {number} gridSize - Grid size (for Moore algorithm)\n 117→ * @returns {{tour: number[], label: string}} Result\n 118→ */\n 119→const runAlgorithm = (algorithm, points, gridSize) => {\n 120→ switch (algorithm) {\n 121→ case 'sonar': {\n 122→ const result = sonarSolution(points);\n 123→ return { tour: result.tour, label: 'Sonar (Radial Sweep)' };\n 124→ }\n 125→ case 'moore': {\n 126→ const mooreGrid = calculateMooreGridSize(gridSize);\n 127→ const result = mooreSolution(points, mooreGrid);\n 128→ return { tour: result.tour, label: `Moore Curve (grid: ${mooreGrid})` };\n 129→ }\n 130→ case 'gosper': {\n 131→ const gosperGrid = calculateMooreGridSize(gridSize);\n 132→ const result = gosperSolution(points, gosperGrid);\n 133→ return {\n 134→ tour: result.tour,\n 135→ label: `Gosper Curve (grid: ${gosperGrid})`,\n 136→ };\n 137→ }\n 138→ case 'peano': {\n 139→ const peanoGrid = calculatePeanoGridSize(gridSize);\n 140→ const result = peanoSolution(points, peanoGrid);\n 141→ return {\n 142→ tour: result.tour,\n 143→ label: `Peano Curve (grid: ${peanoGrid})`,\n 144→ };\n 145→ }\n 146→ case 'sierpinski': {\n 147→ const sierpinskiGrid = calculateMooreGridSize(gridSize);\n 148→ const result = sierpinskiSolution(points, sierpinskiGrid);\n 149→ return {\n 150→ tour: result.tour,\n 151→ label: `Sierpiński Curve (grid: ${sierpinskiGrid})`,\n 152→ };\n 153→ }\n 154→ case 'comb': {\n 155→ const result = combSolution(points);\n 156→ return { tour: result.tour, label: 'Comb (Serpentine Scan)' };\n 157→ }\n 158→ case 'saw': {\n 159→ const result = sawSolution(points);\n 160→ return {\n 161→ tour: result.tour,\n 162→ label: 'Self-Avoiding Walk (Nearest Neighbor)',\n 163→ };\n 164→ }\n 165→ case 'koch': {\n 166→ const mooreGrid = calculateMooreGridSize(gridSize);\n 167→ const result = kochSolution(points, mooreGrid);\n 168→ return {\n 169→ tour: result.tour,\n 170→ label: `Koch Snowflake (grid: ${mooreGrid})`,\n 171→ };\n 172→ }\n 173→ case 'space-filling-tree': {\n 174→ const result = spaceFillingTreeSolution(points);\n 175→ return { tour: result.tour, label: 'Space-Filling Tree (Quadtree DFS)' };\n 176→ }\n 177→ case 'brute-force': {\n 178→ if (points.length > BRUTE_FORCE_MAX_POINTS) {\n 179→ throw new Error(\n 180→ `Brute-force is limited to ${BRUTE_FORCE_MAX_POINTS} points (got ${points.length})`\n 181→ );\n 182→ }\n 183→ const result = bruteForceSolution(points);\n 184→ return {\n 185→ tour: result.tour,\n 186→ label: `Brute-Force (optimal distance: ${result.distance.toFixed(2)})`,\n 187→ };\n 188→ }\n 189→ default:\n 190→ throw new Error(\n 191→ `Unknown algorithm: ${algorithm}. Choose from: sonar, moore, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force`\n 192→ );\n 193→ }\n 194→};\n 195→\n 196→/**\n 197→ * Apply the selected optimization to a tour.\n 198→ *\n 199→ * @param {string} optimization - Optimization name\n 200→ * @param {Array<{x: number, y: number}>} points - Points\n 201→ * @param {number[]} tour - Initial tour\n 202→ * @returns {{tour: number[], improvement: number, label: string}} Optimized result\n 203→ */\n 204→const runOptimization = (optimization, points, tour) => {\n 205→ switch (optimization) {\n 206→ case 'none':\n 207→ return { tour, improvement: 0, label: 'None' };\n 208→ case '2-opt': {\n 209→ const result = twoOpt(points, tour);\n 210→ return { ...result, label: '2-opt' };\n 211→ }\n 212→ case '3-opt': {\n 213→ const result = threeOpt(points, tour);\n 214→ return { ...result, label: '3-opt' };\n 215→ }\n 216→ case 'k-opt': {\n 217→ const result = kOpt(points, tour);\n 218→ return { ...result, label: 'k-opt' };\n 219→ }\n 220→ case 'zigzag': {\n 221→ const result = zigzagOpt(points, tour);\n 222→ return { ...result, label: 'Zigzag' };\n 223→ }\n 224→ case 'combined': {\n 225→ const result = combinedOpt(points, tour);\n 226→ return { ...result, label: 'Combined (zigzag + 2-opt)' };\n 227→ }\n 228→ case 'lin-kernighan': {\n 229→ const result = linKernighan(points, tour);\n 230→ return { ...result, label: 'Lin-Kernighan' };\n 231→ }\n 232→ case 'lkh': {\n 233→ const result = lkHelsgaun(points, tour);\n 234→ return { ...result, label: 'Lin-Kernighan-Helsgaun' };\n 235→ }\n 236→ default:\n 237→ throw new Error(\n 238→ `Unknown optimization: ${optimization}. Choose from: none, 2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined`\n 239→ );\n 240→ }\n 241→};\n 242→\n 243→/**\n 244→ * Main CLI entry point.\n 245→ * Parses arguments, runs the algorithm, and prints results.\n 246→ */\n 247→// eslint-disable-next-line max-lines-per-function\n 248→export const main = () => {\n 249→ const config = makeConfig({\n 250→ yargs: ({ yargs, getenv }) =>\n 251→ yargs\n 252→ .usage('Usage: $0 [options]')\n 253→ .option('algorithm', {\n 254→ alias: 'a',\n 255→ type: 'string',\n 256→ describe: 'TSP algorithm to use',\n 257→ choices: [\n 258→ 'sonar',\n 259→ 'moore',\n 260→ 'gosper',\n 261→ 'peano',\n 262→ 'sierpinski',\n 263→ 'comb',\n 264→ 'saw',\n 265→ 'koch',\n 266→ 'space-filling-tree',\n 267→ 'brute-force',\n 268→ ],\n 269→ default: getenv('TSP_ALGORITHM', 'sonar'),\n 270→ })\n 271→ .option('optimization', {\n 272→ alias: 'o',\n 273→ type: 'string',\n 274→ describe: 'Optimization to apply after initial solution',\n 275→ choices: [\n 276→ 'none',\n 277→ '2-opt',\n 278→ '3-opt',\n 279→ 'k-opt',\n 280→ 'lin-kernighan',\n 281→ 'lkh',\n 282→ 'zigzag',\n 283→ 'combined',\n 284→ ],\n 285→ default: getenv('TSP_OPTIMIZATION', 'none'),\n 286→ })\n 287→ .option('num-points', {\n 288→ alias: 'n',\n 289→ type: 'number',\n 290→ describe: 'Number of random points to generate',\n 291→ default: getenv('TSP_NUM_POINTS', 10),\n 292→ })\n 293→ .option('grid-size', {\n 294→ alias: 'g',\n 295→ type: 'number',\n 296→ describe: `Grid size for point generation (Moore: ${VALID_GRID_SIZES.join(', ')}; Peano: ${VALID_PEANO_GRID_SIZES.join(', ')})`,\n 297→ default: getenv('TSP_GRID_SIZE', 16),\n 298→ })\n 299→ .option('points', {\n 300→ alias: 'p',\n 301→ type: 'string',\n 302→ describe:\n 303→ 'Manual points as space-separated coordinate pairs: \"x1 y1 x2 y2 ...\"',\n 304→ })\n 305→ .option('verify', {\n 306→ alias: 'v',\n 307→ type: 'boolean',\n 308→ describe: 'Run lower-bound verification on the result',\n 309→ default: false,\n 310→ })\n 311→ .option('json', {\n 312→ alias: 'j',\n 313→ type: 'boolean',\n 314→ describe: 'Output results as JSON',\n 315→ default: false,\n 316→ })\n 317→ .example(\n 318→ '$0 --algorithm sonar --num-points 20',\n 319→ 'Sonar with 20 random points'\n 320→ )\n 321→ .example(\n 322→ '$0 -a moore -o 2-opt -n 50 -g 32',\n 323→ 'Moore + 2-opt, 50 points on 32x32 grid'\n 324→ )\n 325→ .example(\n 326→ '$0 -a moore -o lkh -n 50',\n 327→ 'Moore + LKH optimization, 50 points'\n 328→ )\n 329→ .example(\n 330→ '$0 -a peano -o 2-opt -n 50 -g 27',\n 331→ 'Peano + 2-opt, 50 points on 27x27 grid'\n 332→ )\n 333→ .example(\n 334→ '$0 -a brute-force --points \"0 0 5 5 10 2 3 8\"',\n 335→ 'Brute-force with manual points'\n 336→ )\n 337→ .example(\n 338→ '$0 -a sonar -o combined -n 100 --verify',\n 339→ 'Sonar + combined + verify'\n 340→ )\n 341→ .epilog(\n 342→ 'TSP Algorithms CLI — https://github.com/konard/tsp\\n' +\n 343→ 'Runs atomic (all-at-once) algorithms for benchmark-like performance.'\n 344→ ),\n 345→ });\n 346→\n 347→ const {\n 348→ algorithm,\n 349→ optimization,\n 350→ numPoints,\n 351→ gridSize,\n 352→ points: pointsStr,\n 353→ verify,\n 354→ json: jsonOutput,\n 355→ } = config;\n 356→\n 357→ try {\n 358→ // Generate or parse points\n 359→ let points;\n 360→ if (pointsStr) {\n 361→ points = parsePoints(pointsStr);\n 362→ } else {\n 363→ const mooreGrid = calculateMooreGridSize(gridSize);\n 364→ points = generateRandomPoints(mooreGrid, numPoints);\n 365→ }\n 366→\n 367→ // Measure total execution time\n 368→ const startTime = performance.now();\n 369→\n 370→ // Run algorithm\n 371→ const algoResult = runAlgorithm(algorithm, points, gridSize);\n 372→\n 373→ // Run optimization\n 374→ const optResult = runOptimization(optimization, points, algoResult.tour);\n 375→\n 376→ // Calculate distances\n 377→ const initialDistance = calculateTotalDistance(algoResult.tour, points);\n 378→ const finalDistance = calculateTotalDistance(optResult.tour, points);\n 379→\n 380→ const endTime = performance.now();\n 381→ const timeMs = endTime - startTime;\n 382→\n 383→ // Verification\n 384→ let verificationResult = null;\n 385→ if (verify) {\n 386→ verificationResult = verifyOptimality(finalDistance, points);\n 387→ }\n 388→\n 389→ if (jsonOutput) {\n 390→ const output = {\n 391→ algorithm: algoResult.label,\n 392→ optimization: optResult.label,\n 393→ points: points.length,\n 394→ gridSize,\n 395→ tour: optResult.tour,\n 396→ initialDistance,\n 397→ finalDistance,\n 398→ improvement: optResult.improvement,\n 399→ timeMs: Math.round(timeMs * 100) / 100,\n 400→ };\n 401→ if (verificationResult) {\n 402→ output.verification = verificationResult;\n 403→ }\n 404→ console.log(JSON.stringify(output, null, 2));\n 405→ } else {\n 406→ console.log('TSP Algorithms CLI');\n 407→ console.log('==================\\n');\n 408→ console.log(`Algorithm: ${algoResult.label}`);\n 409→ console.log(`Optimization: ${optResult.label}`);\n 410→ console.log(`Points: ${points.length}`);\n 411→ console.log(`Grid size: ${gridSize}\\n`);\n 412→\n 413→ console.log(`Tour: ${formatTour(optResult.tour, points)}\\n`);\n 414→\n 415→ console.log(`Initial distance: ${initialDistance.toFixed(2)}`);\n 416→ if (optimization !== 'none') {\n 417→ console.log(`Final distance: ${finalDistance.toFixed(2)}`);\n 418→ console.log(`Improvement: ${optResult.improvement.toFixed(2)}`);\n 419→ }\n 420→ console.log(`Time: ${timeMs.toFixed(2)}ms`);\n 421→\n 422→ if (verificationResult) {\n 423→ console.log('\\nVerification (1-tree lower bound):');\n 424→ console.log(\n 425→ ` Lower bound: ${verificationResult.lowerBound.toFixed(2)}`\n 426→ );\n 427→ console.log(\n 428→ ` Gap: ${verificationResult.gapPercent.toFixed(2)}%`\n 429→ );\n 430→ console.log(\n 431→ ` Optimal: ${verificationResult.isOptimal ? 'YES ✓' : 'Not proven'}`\n 432→ );\n 433→ }\n 434→ }\n 435→ } catch (error) {\n 436→ if (jsonOutput) {\n 437→ console.error(JSON.stringify({ error: error.message }));\n 438→ } else {\n 439→ console.error(`Error: ${error.message}`);\n 440→ }\n 441→ process.exitCode = 1;\n 442→ }\n 443→};\n 444→\n 445→main();\n 446→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "2d3883ba-a99b-4b9e-ac2b-7a46d3574119"
}
[2026-02-07T22:19:47.859Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01DvURzgDkFkNvEkGFADwp7h",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01GRbjw42VHSZxkaSTHP9c6P",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -maxdepth 2 -type f -name \"*CONTRIB*\" -o -name \"*DEVELOP*\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 4114,
"cache_read_input_tokens": 31850,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4114
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "13c2bfc3-0f43-4a69-ad92-2ea286802a00"
}
[2026-02-07T22:19:47.923Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01GRbjw42VHSZxkaSTHP9c6P",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6cc0503c-6e9f-41ac-bcf7-00ade8fe49f0"
}
[2026-02-07T22:19:50.101Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01889xc8UVkVetCmCqffamdx",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01VQabwaoWc4EZdprtc1EhFj",
"name": "Bash",
"input": {
"command": "git log --all --grep=\"#66\" --oneline | head -5"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 27544,
"cache_read_input_tokens": 35964,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 27544
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f565bd8e-f6d6-4a9c-bf5b-7e230bb12072"
}
[2026-02-07T22:19:50.357Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01VQabwaoWc4EZdprtc1EhFj",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3fb61183-8326-4f47-86d2-7e01d1a635df"
}
[2026-02-07T22:19:50.382Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01889xc8UVkVetCmCqffamdx",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01HE68w5H5nxPThzAu4wVphr",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/utils.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 27544,
"cache_read_input_tokens": 35964,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 27544
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f2218b3e-63f4-48f3-9b02-e00b7ad79df9"
}
[2026-02-07T22:19:50.386Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01HE68w5H5nxPThzAu4wVphr",
"type": "tool_result",
"content": " 1→/**\n 2→ * Utility functions for TSP algorithms\n 3→ */\n 4→\n 5→/**\n 6→ * Valid grid sizes for Moore curve algorithm.\n 7→ * A Moore curve of order n fills a 2^n x 2^n grid.\n 8→ * These correspond to L-system iteration counts 0..7 (effective orders 1..8).\n 9→ */\n 10→export const VALID_GRID_SIZES = [2, 4, 8, 16, 32, 64, 128];\n 11→\n 12→/**\n 13→ * Valid grid sizes for Peano curve algorithm.\n 14→ * A Peano curve of order n fills a 3^n x 3^n grid.\n 15→ * These correspond to L-system iteration counts 1..4 (orders 1..4).\n 16→ */\n 17→export const VALID_PEANO_GRID_SIZES = [3, 9, 27, 81];\n 18→\n 19→/**\n 20→ * Calculate the Moore grid size based on user-specified grid size\n 21→ * Moore curve fills a grid of size 2^n x 2^n.\n 22→ * Returns the smallest valid Moore grid size >= gridSize.\n 23→ * @param {number} gridSize - User-specified grid size\n 24→ * @returns {number} Moore grid size (power of 2)\n 25→ */\n 26→export const calculateMooreGridSize = (gridSize) => {\n 27→ // Find smallest valid grid size >= gridSize\n 28→ for (const size of VALID_GRID_SIZES) {\n 29→ if (size >= gridSize) {\n 30→ return size;\n 31→ }\n 32→ }\n 33→ return VALID_GRID_SIZES[VALID_GRID_SIZES.length - 1];\n 34→};\n 35→\n 36→/**\n 37→ * Calculate the Peano grid size based on user-specified grid size\n 38→ * Peano curve fills a grid of size 3^n x 3^n.\n 39→ * Returns the smallest valid Peano grid size >= gridSize.\n 40→ * @param {number} gridSize - User-specified grid size\n 41→ * @returns {number} Peano grid size (power of 3)\n 42→ */\n 43→export const calculatePeanoGridSize = (gridSize) => {\n 44→ // Find smallest valid Peano grid size >= gridSize\n 45→ for (const size of VALID_PEANO_GRID_SIZES) {\n 46→ if (size >= gridSize) {\n 47→ return size;\n 48→ }\n 49→ }\n 50→ return VALID_PEANO_GRID_SIZES[VALID_PEANO_GRID_SIZES.length - 1];\n 51→};\n 52→\n 53→/**\n 54→ * Generate random points on the Moore grid\n 55→ * @param {number} mooreGridSize - Size of the Moore grid\n 56→ * @param {number} numPoints - Number of points to generate\n 57→ * @returns {Array<{x: number, y: number, id: number}>} Array of point objects\n 58→ */\n 59→export const generateRandomPoints = (mooreGridSize, numPoints) => {\n 60→ const points = [];\n 61→ const usedPositions = new Set();\n 62→ // Points are placed at grid intersections (0 to mooreGridSize-1 inclusive)\n 63→ const maxPoints = Math.min(numPoints, mooreGridSize * mooreGridSize);\n 64→\n 65→ while (points.length < maxPoints) {\n 66→ // Generate integer coordinates aligned to Moore grid vertices [0, mooreGridSize-1]\n 67→ const x = Math.floor(Math.random() * mooreGridSize);\n 68→ const y = Math.floor(Math.random() * mooreGridSize);\n 69→ const key = `${x},${y}`;\n 70→\n 71→ if (!usedPositions.has(key)) {\n 72→ usedPositions.add(key);\n 73→ points.push({ x, y, id: points.length });\n 74→ }\n 75→ }\n 76→ return points;\n 77→};\n 78→\n 79→/**\n 80→ * Calculate Euclidean distance between two points\n 81→ * @param {{x: number, y: number}} p1 - First point\n 82→ * @param {{x: number, y: number}} p2 - Second point\n 83→ * @returns {number} Euclidean distance\n 84→ */\n 85→export const distance = (p1, p2) => Math.hypot(p2.x - p1.x, p2.y - p1.y);\n 86→\n 87→/**\n 88→ * Calculate total tour distance (closed loop)\n 89→ * @param {number[]} tour - Array of point indices forming the tour\n 90→ * @param {Array<{x: number, y: number}>} points - Array of point coordinates\n 91→ * @returns {number} Total distance of the tour\n 92→ */\n 93→export const calculateTotalDistance = (tour, points) => {\n 94→ if (tour.length < 2) {\n 95→ return 0;\n 96→ }\n 97→ let total = 0;\n 98→ for (let i = 0; i < tour.length - 1; i++) {\n 99→ total += distance(points[tour[i]], points[tour[i + 1]]);\n 100→ }\n 101→ // Close the loop\n 102→ total += distance(points[tour[tour.length - 1]], points[tour[0]]);\n 103→ return total;\n 104→};\n 105→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9031526c-38e1-428f-a83c-f5fe67321dc4"
}
[2026-02-07T22:19:50.859Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01889xc8UVkVetCmCqffamdx",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01UK6ivbRjzeRrXQ4fxsuNeB",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/gosper.js",
"limit": 50
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 27544,
"cache_read_input_tokens": 35964,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 27544
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "0f76116d-839b-4247-b503-8277a87890e8"
}
[2026-02-07T22:19:50.912Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01UK6ivbRjzeRrXQ4fxsuNeB",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Gosper Curve Solution for TSP\n 3→ *\n 4→ * Computes the final tour directly without intermediate visualization steps.\n 5→ *\n 6→ * Algorithm:\n 7→ * 1. Generate a Gosper curve (L-system) that fills a hexagonal region\n 8→ * 2. Map each point to its nearest position on the curve\n 9→ * 3. Sort points by their position along the curve\n 10→ * 4. Return the sorted order as the tour\n 11→ *\n 12→ * The Gosper curve (also known as the Peano-Gosper curve or flowsnake) is a\n 13→ * space-filling fractal curve that uses 60-degree turns on a hexagonal grid.\n 14→ *\n 15→ * L-system rules:\n 16→ * - Angle: 60 degrees\n 17→ * - Axiom: A\n 18→ * - A -> A-B--B+A++AA+B-\n 19→ * - B -> +A-BB--B-A++A+B\n 20→ * Where A and B both mean \"move forward\", + means turn left 60°, - means turn right 60°.\n 21→ *\n 22→ * Time Complexity: O(n log n)\n 23→ * Space Complexity: O(n)\n 24→ */\n 25→\n 26→import { distance } from '../../utils.js';\n 27→\n 28→/**\n 29→ * Generate Gosper curve using L-system\n 30→ *\n 31→ * L-system rules for Gosper curve:\n 32→ * Axiom: A\n 33→ * A -> A-B--B+A++AA+B-\n 34→ * B -> +A-BB--B-A++A+B\n 35→ *\n 36→ * @param {number} order - Order of the Gosper curve (number of iterations)\n 37→ * @returns {string} L-system sequence\n 38→ */\n 39→export const generateGosperCurve = (order) => {\n 40→ let sequence = 'A';\n 41→\n 42→ for (let i = 0; i < order; i++) {\n 43→ let newSequence = '';\n 44→ for (const char of sequence) {\n 45→ if (char === 'A') {\n 46→ newSequence += 'A-B--B+A++AA+B-';\n 47→ } else if (char === 'B') {\n 48→ newSequence += '+A-BB--B-A++A+B';\n 49→ } else {\n 50→ newSequence += char;\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "0d9786f0-6315-4ce3-99bb-c2d34897b619"
}
[2026-02-07T22:19:52.908Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EPAtwwwYG64uVSSqe1chis",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01KsU1TpVxMnvwe4x8Svun5J",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119/src/lib/algorithms -type f -name \"*.js\" | sort"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2715,
"cache_read_input_tokens": 63508,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2715
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "ef50f08b-bb87-41d7-84d9-053ef35a5680"
}
[2026-02-07T22:19:53.126Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01KsU1TpVxMnvwe4x8Svun5J",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/combined-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/k-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/lin-kernighan.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/lk-helsgaun.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/three-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/two-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/optimization/zigzag-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/brute-force.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/comb.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/gosper.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/koch.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/moore.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/peano.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/saw.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/sierpinski.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/sonar.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/space-filling-tree.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/combined-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/k-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/lin-kernighan.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/lk-helsgaun.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/three-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/two-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/optimization/zigzag-opt.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/brute-force.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/comb.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/gosper.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/koch.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/moore.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/peano.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/saw.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/sierpinski.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/sonar.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/space-filling-tree.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/utils.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/verification/index.js\n/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/verification/lower-bound.js",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "dc8a8682-f4bf-437c-841e-c63409646d5f"
}
[2026-02-07T22:19:53.135Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EPAtwwwYG64uVSSqe1chis",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01AQ1QoFStW3mh6pid4xsbvr",
"name": "Bash",
"input": {
"command": "cat /tmp/gh-issue-solver-1770502731119/CLAUDE.md"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2715,
"cache_read_input_tokens": 63508,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2715
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "288bf771-cbc8-4ff5-8fe9-b4068ed2b3dc"
}
[2026-02-07T22:19:53.371Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01AQ1QoFStW3mh6pid4xsbvr",
"type": "tool_result",
"content": "Issue to solve: https://github.com/konard/tsp/issues/66\nYour prepared branch: issue-66-4d49361c46fb\nYour prepared working directory: /tmp/gh-issue-solver-1770502731119\n\nProceed.",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1329e879-93bd-47e4-9cc8-63c488aff42d"
}
[2026-02-07T22:19:53.454Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EPAtwwwYG64uVSSqe1chis",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_011dv1vNcjwBUdCxg7ojQkCj",
"name": "Bash",
"input": {
"command": "ls -la /tmp/gh-issue-solver-1770502731119/docs/case-studies/"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2715,
"cache_read_input_tokens": 63508,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2715
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f29d223c-e3b4-483d-938e-e7ccdd44db27"
}
[2026-02-07T22:19:53.524Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_011dv1vNcjwBUdCxg7ojQkCj",
"type": "tool_result",
"content": "total 60\ndrwxrwxr-x 15 hive hive 4096 Feb 7 23:18 .\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 ..\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-13\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-15\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 issue-21\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 issue-23\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 issue-26\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-3\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-31\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-40\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-46\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-5\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-53\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 issue-63\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 issue-7",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "352225e7-1fed-4647-9390-73cbcea8601f"
}
[2026-02-07T22:19:55.704Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EfrgvErR31Qx1vBjt4VS5y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_018h7osAB8NWbDM4GTgdvJoY",
"name": "Bash",
"input": {
"command": "find /tmp/gh-issue-solver-1770502731119 -type d -name \"*66*\" -o -type f -name \"*66*\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2198,
"cache_read_input_tokens": 66223,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2198
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f7f3cc84-16c5-4b42-958e-458429a9a1dc"
}
[2026-02-07T22:19:55.953Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_018h7osAB8NWbDM4GTgdvJoY",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/docs/case-studies/issue-63/ci-logs/update-benchmarks-62466903562.txt\n/tmp/gh-issue-solver-1770502731119/.git/refs/heads/issue-66-4d49361c46fb\n/tmp/gh-issue-solver-1770502731119/.git/refs/remotes/origin/issue-66-4d49361c46fb\n/tmp/gh-issue-solver-1770502731119/.git/logs/refs/heads/issue-66-4d49361c46fb\n/tmp/gh-issue-solver-1770502731119/.git/logs/refs/remotes/origin/issue-66-4d49361c46fb\n/tmp/gh-issue-solver-1770502731119/.git/objects/pack/pack-47ce603fc034a64d6d9aa668f39b6352ec1438c1.rev\n/tmp/gh-issue-solver-1770502731119/.git/objects/pack/pack-47ce603fc034a64d6d9aa668f39b6352ec1438c1.pack\n/tmp/gh-issue-solver-1770502731119/.git/objects/pack/pack-47ce603fc034a64d6d9aa668f39b6352ec1438c1.idx",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "a9205403-bc95-4da4-9a10-df1ff83e606a"
}
[2026-02-07T22:19:55.970Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EfrgvErR31Qx1vBjt4VS5y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_017wDvSBEVM4oCNSkD97jii6",
"name": "Bash",
"input": {
"command": "git log --all --oneline | grep -i spiral | head -10"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2198,
"cache_read_input_tokens": 66223,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2198
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "94fa8717-2fe7-444d-a6e2-13e4686cb67c"
}
[2026-02-07T22:19:56.354Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_017wDvSBEVM4oCNSkD97jii6",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "29478e02-ea99-4851-9f70-641850f636c2"
}
[2026-02-07T22:19:56.378Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01EfrgvErR31Qx1vBjt4VS5y",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01CxQptfxyDJfw1sjKvGZpk7",
"name": "Bash",
"input": {
"command": "git show HEAD:CLAUDE.md 2>/dev/null || echo \"No CLAUDE.md in HEAD\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 2198,
"cache_read_input_tokens": 66223,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2198
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9235380a-729f-4dcb-b854-370b48114a93"
}
[2026-02-07T22:19:56.455Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01CxQptfxyDJfw1sjKvGZpk7",
"type": "tool_result",
"content": "Issue to solve: https://github.com/konard/tsp/issues/66\nYour prepared branch: issue-66-4d49361c46fb\nYour prepared working directory: /tmp/gh-issue-solver-1770502731119\n\nProceed.",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "814bcf88-5d7b-4eab-a7cc-bb5d9225ec11"
}
[2026-02-07T22:19:57.833Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01Dr1fqoxiSGtjoUS3qR2fZv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_017u2kd2LtZyx2pHBCiaW621",
"name": "WebFetch",
"input": {
"url": "https://github.com/konard/tsp/issues/66",
"prompt": "What is the issue about? What needs to be implemented?"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 831,
"cache_read_input_tokens": 68421,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 831
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "cdc10aa0-7b2a-403a-ac28-3be81c538995"
}
[2026-02-07T22:19:58.113Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01Dr1fqoxiSGtjoUS3qR2fZv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01XmWmHZUcPC5FruSxphuCr6",
"name": "Bash",
"input": {
"command": "grep -r \"spiral\" /tmp/gh-issue-solver-1770502731119/src --include=\"*.js\" --include=\"*.jsx\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 831,
"cache_read_input_tokens": 68421,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 831
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "3a62d0a2-d330-4ad6-b25e-dc993124265d"
}
[2026-02-07T22:19:58.401Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01XmWmHZUcPC5FruSxphuCr6",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "edc40968-eafa-4c99-bb82-3ba6a2509653"
}
[2026-02-07T22:19:58.451Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01Dr1fqoxiSGtjoUS3qR2fZv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_018AY9Qxh43ZgYBDbYByFBjf",
"name": "Bash",
"input": {
"command": "grep -r \"archimedean\" /tmp/gh-issue-solver-1770502731119 --include=\"*.js\" --include=\"*.jsx\""
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 831,
"cache_read_input_tokens": 68421,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 831
},
"output_tokens": 3,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1e9c997c-84e4-4829-9cd1-ccbc9c832e8a"
}
[2026-02-07T22:19:58.516Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_018AY9Qxh43ZgYBDbYByFBjf",
"type": "tool_result",
"content": "",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "28ba747c-b6dc-4c13-8087-fc8965825272"
}
[2026-02-07T22:20:02.006Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_017u2kd2LtZyx2pHBCiaW621",
"type": "tool_result",
"content": "# Issue Summary\n\nThis GitHub issue (#66) requests the implementation of a **double spiral algorithm** for a TSP (Traveling Salesman Problem) project.\n\n## Key Requirements\n\nThe issue specifies that developers should:\n\n1. **Reproduce a specific visual pattern** - The issue includes an image showing a double spiral geometric pattern that needs to be generated by the algorithm\n\n2. **Match Moore Curve features** - The implementation should include all the same capabilities and features that the existing Moore Curve algorithm has in the codebase\n\n## Context\n\n- The issue is labeled as both \"documentation\" and \"enhancement\"\n- An open pull request (#67) exists for this feature, currently in draft status\n- The repository is a JavaScript project focused on path generation algorithms\n\nThe task essentially involves creating a new space-filling curve algorithm (double spiral) with feature parity to the Moore Curve implementation already in the project."
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b55d4fb7-645a-4ec0-b3e5-cbedeea0e380"
}
[2026-02-07T22:20:03.855Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01T5HjD1Bx8Xstm6EoGMLRTv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_018aQAC24LAfzbUcBKFxhnF7",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/sonar.js",
"limit": 50
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 66,
"cache_creation_input_tokens": 510,
"cache_read_input_tokens": 69252,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 510
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "a5cde510-b372-47b7-8b9b-b799d08bb1ee"
}
[2026-02-07T22:20:03.858Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_018aQAC24LAfzbUcBKFxhnF7",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Sonar Solution (Radial Sweep) for TSP\n 3→ *\n 4→ * Computes the final tour directly without intermediate visualization steps.\n 5→ *\n 6→ * Algorithm:\n 7→ * 1. Compute the centroid (center of mass) of all points\n 8→ * 2. Calculate the polar angle of each point relative to the centroid\n 9→ * 3. Sort points by their polar angle (starting from bottom, sweeping clockwise)\n 10→ * 4. Return the sorted order as the tour\n 11→ *\n 12→ * Time Complexity: O(n log n)\n 13→ * Space Complexity: O(n)\n 14→ */\n 15→\n 16→/**\n 17→ * Compute Sonar solution in one step (atomic version).\n 18→ * Returns the final tour without intermediate steps.\n 19→ *\n 20→ * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n 21→ * @returns {{tour: number[], centroid: {x: number, y: number}}} Final tour and centroid\n 22→ */\n 23→export const sonarSolution = (points) => {\n 24→ if (points.length === 0) {\n 25→ return { tour: [], centroid: null };\n 26→ }\n 27→\n 28→ // Find centroid\n 29→ const cx = points.reduce((sum, p) => sum + p.x, 0) / points.length;\n 30→ const cy = points.reduce((sum, p) => sum + p.y, 0) / points.length;\n 31→\n 32→ const startAngle = Math.PI / 2;\n 33→\n 34→ const pointsWithAngles = points.map((p, idx) => {\n 35→ const rawAngle = Math.atan2(p.y - cy, p.x - cx);\n 36→ let normalizedAngle = rawAngle - startAngle;\n 37→ if (normalizedAngle < 0) {\n 38→ normalizedAngle += 2 * Math.PI;\n 39→ }\n 40→ return { idx, sortAngle: normalizedAngle };\n 41→ });\n 42→\n 43→ pointsWithAngles.sort((a, b) => a.sortAngle - b.sortAngle);\n 44→\n 45→ return {\n 46→ tour: pointsWithAngles.map((p) => p.idx),\n 47→ centroid: { x: cx, y: cy },\n 48→ };\n 49→};\n 50→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6a416e32-52df-4c3d-9180-3c4321ba1b64"
}
[2026-02-07T22:20:04.122Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01T5HjD1Bx8Xstm6EoGMLRTv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_019qANUj5pZAYQJKudsSvjri",
"name": "Bash",
"input": {
"command": "ls -la /tmp/gh-issue-solver-1770502731119/src/app/ui/components/"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 66,
"cache_creation_input_tokens": 510,
"cache_read_input_tokens": 69252,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 510
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "dec0c9c8-a696-4ea9-b276-e0b894615c34"
}
[2026-02-07T22:20:04.346Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_019qANUj5pZAYQJKudsSvjri",
"type": "tool_result",
"content": "total 44\ndrwxrwxr-x 2 hive hive 4096 Feb 7 23:18 .\ndrwxrwxr-x 3 hive hive 4096 Feb 7 23:18 ..\n-rw-rw-r-- 1 hive hive 6970 Feb 7 23:18 Controls.jsx\n-rw-rw-r-- 1 hive hive 6769 Feb 7 23:18 Legend.jsx\n-rw-rw-r-- 1 hive hive 10601 Feb 7 23:18 TSPVisualization.jsx\n-rw-rw-r-- 1 hive hive 2107 Feb 7 23:18 VisualizationPanel.jsx\n-rw-rw-r-- 1 hive hive 301 Feb 7 23:18 index.js",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f560d7ac-bd50-4ddb-8fb3-d7760a1d909e"
}
[2026-02-07T22:20:04.381Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_01T5HjD1Bx8Xstm6EoGMLRTv",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01Cog5RYkq8YRpyA9cSmMwxF",
"name": "Bash",
"input": {
"command": "cat /tmp/gh-issue-solver-1770502731119/.prettierrc"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 66,
"cache_creation_input_tokens": 510,
"cache_read_input_tokens": 69252,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 510
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "e6427ab2-e993-4c73-8b72-355f83e915b5"
}
[2026-02-07T22:20:04.453Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01Cog5RYkq8YRpyA9cSmMwxF",
"type": "tool_result",
"content": "{\n \"semi\": true,\n \"trailingComma\": \"es5\",\n \"singleQuote\": true,\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"arrowParens\": \"always\",\n \"endOfLine\": \"lf\"\n}",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "bf1b7bb7-a897-45bb-bf2f-0ca042162600"
}
[2026-02-07T22:20:06.156Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_016MkdePtUreWEzkQXpPs58Q",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_014GZwAAAs52MQX5EN9VihHM",
"name": "Bash",
"input": {
"command": "head -50 /tmp/gh-issue-solver-1770502731119/src/app/ui/components/TSPVisualization.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1495,
"cache_read_input_tokens": 69762,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1495
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "755b4461-ab3d-4c83-9ded-98647f0fca60"
}
[2026-02-07T22:20:06.503Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_014GZwAAAs52MQX5EN9VihHM",
"type": "tool_result",
"content": "/**\n * TSPVisualization Component\n *\n * SVG-based visualization for TSP algorithms.\n * Displays points, tour paths, and algorithm-specific elements\n * (sweep line for Sonar, curve for Moore).\n */\n\nimport { useState, useEffect, useRef } from 'react';\n\n/**\n * Convert point coordinates to SVG space\n * @param {{x: number, y: number}} p - Point in grid coordinates\n * @param {number} padding - SVG padding\n * @param {number} scale - Coordinate scale factor\n * @returns {{x: number, y: number}} Point in SVG coordinates\n */\nconst toSvgCoords = (p, padding, scale) => ({\n x: padding + p.x * scale,\n y: padding + p.y * scale,\n});\n\n/**\n * TSPVisualization - SVG renderer for TSP algorithms\n *\n * @param {Object} props\n * @param {Array<{x: number, y: number, id: number}>} props.points - Array of points\n * @param {Array<Object>} props.steps - Array of algorithm steps\n * @param {number} props.currentStep - Current step index\n * @param {string} props.algorithm - Algorithm type ('sonar', 'moore', 'peano', 'sierpinski', 'comb', 'saw', 'koch', 'space-filling-tree', or 'brute-force')\n * @param {number} props.mooreGridSize - Size of the grid\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n */\nconst TSPVisualization = ({\n points,\n steps,\n currentStep,\n algorithm,\n mooreGridSize,\n showOptimization,\n}) => {\n const containerRef = useRef(null);\n const [svgSize, setSvgSize] = useState(400);\n const padding = 20;\n\n // Responsive SVG sizing\n useEffect(() => {\n const updateSize = () => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "dfae343a-7919-4755-aa11-851a7ac2aa91"
}
[2026-02-07T22:20:06.511Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_016MkdePtUreWEzkQXpPs58Q",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_014Xa1tH8iXyhKChPErADh75",
"name": "Bash",
"input": {
"command": "wc -l /tmp/gh-issue-solver-1770502731119/src/lib/algorithms/**/*.js 2>/dev/null | tail -1"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1495,
"cache_read_input_tokens": 69762,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1495
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "925d2762-0ff1-4aa2-86d6-927681f84580"
}
[2026-02-07T22:20:06.723Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-haiku-4-5-20251001",
"id": "msg_016MkdePtUreWEzkQXpPs58Q",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_012PznnYhEH4c7mi2SQgfVAQ",
"name": "Bash",
"input": {
"command": "du -sh /tmp/gh-issue-solver-1770502731119/src"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 1495,
"cache_read_input_tokens": 69762,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 1495
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "53d9971f-0222-43d9-a34e-2c441eeff325"
}
[2026-02-07T22:20:07.272Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_014Xa1tH8iXyhKChPErADh75",
"type": "tool_result",
"content": " 190 total",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "6693b832-baff-4792-a593-03652b0e799b"
}
[2026-02-07T22:20:07.333Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_012PznnYhEH4c7mi2SQgfVAQ",
"type": "tool_result",
"content": "656K\t/tmp/gh-issue-solver-1770502731119/src",
"is_error": false
}
]
},
"parent_tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c3e889e9-2760-430a-bf5a-721160539f6d"
}
[2026-02-07T22:20:59.726Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_012DFHxQqjMPGMHNL7rC7TSy",
"type": "tool_result",
"content": [
{
"type": "text",
"text": "Excellent! Now I have all the information I need. Let me create a comprehensive report.\n\n## Comprehensive Repository Exploration Report\n\nI've completed a thorough exploration of the TSP (Traveling Salesman Problem) repository. Here's everything you need to know:\n\n---\n\n## 1. OVERALL PROJECT STRUCTURE\n\n**Project**: TSP Visual Solver / tsp-algorithms \n**Package Name**: tsp-algorithms v0.5.0 \n**Type**: ES Module (Node.js + Browser) \n**License**: Unlicense \n**Repository**: https://github.com/konard/tsp \n\n### Root Files and Directories:\n```\n/tmp/gh-issue-solver-1770502731119/\n├── src/ # Source code (656 KB)\n├── dist/ # Compiled browser bundle\n├── docs/ # Case studies and documentation\n├── examples/ # Example scripts\n├── experiments/ # Experimental test files\n├── benchmarks/ # Benchmark data\n├── scripts/ # Build and automation scripts\n├── .github/workflows/ # GitHub Actions CI/CD\n├── .husky/ # Git hooks\n├── .changeset/ # Changeset version management\n├── package.json # NPM configuration\n├── package-lock.json # Dependency lock file\n├── bun.lock # Bun package manager lock\n├── tsconfig.json (missing) # No TypeScript config found\n├── eslint.config.js # ESLint configuration\n├── .prettierrc # Prettier formatting config\n├── .gitignore # Git ignore rules\n├── serve.js # Local development server\n├── index.html # Main HTML entry\n├── BENCHMARK.md # Performance benchmarks\n├── CHANGELOG.md # Version history\n├── README.md # Main documentation\n├── screenshot.png # UI screenshot\n└── CLAUDE.md # Task instructions (Issue #66)\n```\n\n**Task**: Issue #66 - Implement Double Spiral algorithm with Moore Curve feature parity\n\n---\n\n## 2. ISSUE #66 DETAILS\n\n**Issue**: Implement a Double Spiral algorithm \n**Requirements**:\n- Reproduce a specific visual pattern (double spiral geometry)\n- Match all Moore Curve algorithm features\n- Include progressive (step-by-step) and atomic (all-at-once) implementations\n- Integrate with UI visualization system\n- Match testing patterns and verification system\n\n**Related PR**: #67 (Draft status)\n\n---\n\n## 3. SOURCE CODE STRUCTURE\n\n### /src Directory Layout:\n\n```\nsrc/\n├── lib/ # Core algorithm library\n│ ├── algorithms/ # All TSP algorithms\n│ │ ├── atomic/ # Direct computation algorithms\n│ │ │ ├── solution/ # Solution algorithms (one-shot)\n│ │ │ │ ├── moore.js # Moore Curve (ATOMIC)\n│ │ │ │ ├── sonar.js # Sonar/Radial Sweep (ATOMIC)\n│ │ │ │ ├── gosper.js # Gosper Curve (ATOMIC)\n│ │ │ │ ├── peano.js # Peano Curve (ATOMIC)\n│ │ │ │ ├── sierpinski.js # Sierpinski Curve (ATOMIC)\n│ │ │ │ ├── comb.js # Comb/Serpentine (ATOMIC)\n│ │ │ │ ├── saw.js # Self-Avoiding Walk (ATOMIC)\n│ │ │ │ ├── koch.js # Koch Snowflake (ATOMIC)\n│ │ │ │ ├── space-filling-tree.js # Quadtree DFS (ATOMIC)\n│ │ │ │ ├── brute-force.js # Brute-force optimal (ATOMIC)\n│ │ │ │ └── index.js # Atomic exports barrel\n│ │ │ ├── optimization/ # Tour improvement (generic, work on any tour)\n│ │ │ │ ├── two-opt.js # 2-opt segment reversal\n│ │ │ │ ├── three-opt.js # 3-opt edge exchange\n│ │ │ │ ├── k-opt.js # k-opt generalized\n│ │ │ │ ├── lin-kernighan.js # LK heuristic\n│ │ │ │ ├── lk-helsgaun.js # LKH with perturbation\n│ │ │ │ ├── zigzag-opt.js # Adjacent swaps\n│ │ │ │ ├── combined-opt.js # Zigzag + 2-opt alternating\n│ │ │ │ └── index.js # Atomic optimization exports\n│ │ │ └── index.js # Atomic module export\n│ │ ├── progressive/ # Step-by-step visualization algorithms\n│ │ │ ├── solution/ # Progressive solution algorithms\n│ │ │ │ ├── moore.js # Moore Curve (PROGRESSIVE)\n│ │ │ │ ├── sonar.js # Sonar (PROGRESSIVE)\n│ │ │ │ ├── gosper.js # Gosper (PROGRESSIVE)\n│ │ │ │ ├── peano.js # Peano (PROGRESSIVE)\n│ │ │ │ ├── sierpinski.js # Sierpinski (PROGRESSIVE)\n│ │ │ │ ├── comb.js # Comb (PROGRESSIVE)\n│ │ │ │ ├── saw.js # SAW (PROGRESSIVE)\n│ │ │ │ ├── koch.js # Koch (PROGRESSIVE)\n│ │ │ │ ├── space-filling-tree.js # Space-Filling Tree (PROGRESSIVE)\n│ │ │ │ ├── brute-force.js # Brute-force (PROGRESSIVE)\n│ │ │ │ └── index.js # Progressive solution exports\n│ │ │ ├── optimization/ # Progressive optimization (step-by-step)\n│ │ │ │ ├── two-opt.js # 2-opt steps\n│ │ │ │ ├── three-opt.js # 3-opt steps\n│ │ │ │ ├── k-opt.js # k-opt steps\n│ │ │ │ ├── lin-kernighan.js # LK steps\n│ │ │ │ ├── lk-helsgaun.js # LKH steps\n│ │ │ │ ├── zigzag-opt.js # Zigzag steps\n│ │ │ │ ├── combined-opt.js # Combined steps\n│ │ │ │ └── index.js # Progressive optimization exports\n│ │ │ └── index.js # Progressive module export\n│ │ ├── verification/ # Optimality proof algorithms\n│ │ │ ├── lower-bound.js # 1-tree lower bound\n│ │ │ └── index.js # Verification exports\n│ │ ├── utils.js # Shared utilities (distance, grid sizes, etc.)\n│ │ └── index.js # Main algorithms export\n│ ├── index.js # Library entry point\n│ └── (no TypeScript .d.ts files) # Only JavaScript, no TypeScript\n├── app/ # React web application\n│ ├── main.jsx # React entry point\n│ ├── ui/\n│ │ ├── App.jsx # Main app component\n│ │ ├── components/\n│ │ │ ├── Controls.jsx # Algorithm/parameter controls\n│ │ │ ├── Legend.jsx # Visual legend component\n│ │ │ ├── TSPVisualization.jsx # SVG visualization renderer\n│ │ │ ├── VisualizationPanel.jsx # Wrapper component\n│ │ │ └── index.js # Component exports\n│ │ ├── i18n.js # Internationalization (en, fr, de, etc.)\n│ │ ├── styles.css # All styling\n│ │ └── index.js # UI module export\n├── cli/\n│ └── index.js # Command-line interface\n└── tests/\n ├── index.test.js # Main algorithm tests (1460+ lines)\n ├── cli.test.js # CLI tests\n ├── comb-algorithm.test.js # Comb algorithm tests\n ├── gosper-algorithm.test.js # Gosper tests\n ├── koch-algorithm.test.js # Koch tests\n ├── optimization-algorithms.test.js # Optimization tests\n ├── peano-algorithm.test.js # Peano tests\n ├── saw-algorithm.test.js # SAW tests\n ├── sierpinski-algorithm.test.js # Sierpinski tests\n ├── space-filling-tree.test.js # Space-Filling Tree tests\n ├── setup.js # Test configuration\n ├── components/ # React component tests\n │ ├── Controls.test.jsx\n │ ├── Legend.test.jsx\n │ ├── TSPVisualization.test.jsx\n │ └── VisualizationPanel.test.jsx\n └── e2e/\n └── app.test.js # End-to-end browser tests\n```\n\n---\n\n## 4. MOORE CURVE ALGORITHM IMPLEMENTATION (Reference)\n\n### Atomic Version (`/src/lib/algorithms/atomic/solution/moore.js`):\n\n**Key Components**:\n- `generateMooreCurve(order)`: L-system generation using rules:\n - Axiom: `LFL+F+LFL`\n - L → `-RF+LFL+FR-`\n - R → `+LF-RFR-FL+`\n - Returns expanded string sequence\n\n- `mooreCurveToPoints(sequence, mooreGridSize)`: Converts L-system to grid coordinates\n - Parses F (forward), + (turn left 90°), - (turn right 90°)\n - Normalizes to [0, gridSize-1] range\n - Returns array of {x, y} points\n\n- `mooreSolution(points, mooreGridSize)`: Main atomic function\n - Generates curve for given grid size\n - Maps each point to nearest curve position\n - Sorts points by curve position\n - Returns `{tour: number[], curvePoints: [{x, y}]}`\n\n**Time**: O(n log n), **Space**: O(n)\n\n### Progressive Version (`/src/lib/algorithms/progressive/solution/moore.js`):\n\n**Key Function**:\n- `mooreAlgorithmSteps(points, mooreGridSize)`: Returns visualization steps\n - First step: curve generation (`type: 'curve'`)\n - Subsequent steps: point visits (`type: 'visit'`)\n - Each step includes:\n - `tour`: cumulative tour\n - `curvePoints`: curve geometry\n - `curveProgress`: percentage along curve\n - `description`: human-readable text\n\n---\n\n## 5. ALGORITHM REGISTRATION & EXPORT SYSTEM\n\n### Main Export (`/src/lib/algorithms/index.js`):\n\n**Exported at top level** (for convenience):\n```javascript\n// Solutions (progressive)\nexport { sonarAlgorithmSteps, mooreAlgorithmSteps, gosperAlgorithmSteps, ... }\nexport { generateMooreCurve, mooreCurveToPoints, ... }\n\n// Optimizations (progressive)\nexport { twoOptSteps, zigzagOptSteps, ... }\n\n// Verification\nexport { oneTreeLowerBound, verifyOptimality, ... }\n\n// Namespaced access\nexport * as progressive from './progressive/index.js'\nexport * as atomic from './atomic/index.js'\nexport * as verification from './verification/index.js'\n\n// Utilities\nexport * from './utils.js'\n```\n\n### Controls Algorithm List (`/src/app/ui/components/Controls.jsx`):\n\n```javascript\nexport const ALGORITHM_OPTIONS = [\n { id: 'sonar', label: 'Sonar Visit' },\n { id: 'moore', label: 'Moore Curve' },\n { id: 'gosper', label: 'Gosper Curve' },\n { id: 'peano', label: 'Peano Curve' },\n { id: 'sierpinski', label: 'Sierpiński Curve' },\n { id: 'comb', label: 'Comb Scan' },\n { id: 'saw', label: 'Self-Avoiding Walk' },\n { id: 'koch', label: 'Koch Snowflake' },\n { id: 'space-filling-tree', label: 'Space-Filling Tree' },\n { id: 'brute-force', label: 'Brute-Force' },\n];\n```\n\n---\n\n## 6. TEST STRUCTURE\n\n### Test Files Location: `/src/tests/`\n\n**Main Test File** (`index.test.js` - 1460 lines):\n- Utility function tests (VALID_GRID_SIZES, calculateMooreGridSize, etc.)\n- Sonar algorithm tests\n- Moore Curve algorithm tests:\n - `generateMooreCurve` tests\n - `mooreCurveToPoints` tests\n - `mooreAlgorithmSteps` tests\n - `mooreSolution` tests\n- Optimization tests (2-opt, 3-opt, zigzag, combined)\n- Verification tests (brute-force, lower-bound)\n- Integration tests\n\n**Test Pattern Examples**:\n```javascript\ndescribe('mooreCurveToPoints', () => {\n it('should generate curve points', () => {\n const sequence = generateMooreCurve(1);\n const points = mooreCurveToPoints(sequence, 4);\n expect(points.length).toBeGreaterThan(0);\n });\n\n it('should generate points within [0, gridSize-1] bounds', () => {\n const mooreGridSize = 16;\n const sequence = generateMooreCurve(3);\n const points = mooreCurveToPoints(sequence, mooreGridSize);\n points.forEach((p) => {\n expect(p.x).toBeGreaterThanOrEqual(0);\n expect(p.x).toBeLessThanOrEqual(mooreGridSize - 1);\n });\n });\n});\n```\n\n**Test Runner**: Bun test framework \n**Commands**:\n- `npm test` - Run all tests\n- `npm run test:e2e` - Run browser E2E tests\n\n---\n\n## 7. UI VISUALIZATION SYSTEM\n\n### Controls Component (`Controls.jsx`):\n- Algorithm selector dropdown (left and right panels)\n- Grid size selector (valid Moore curve sizes: 2, 4, 8, 16, 32, 64, 128)\n- Points count input\n- Animation speed slider (50-1000 ms)\n- Action buttons: New Points, Start, Stop, 2-opt, 3-opt, k-opt, LK, LKH, Zigzag\n\n### VisualizationPanel Component (`VisualizationPanel.jsx`):\n- Algorithm selector dropdown\n- Distance display\n- Algorithm aliases/description\n- SVG visualization canvas\n- Step information text\n- Color legend\n\n### TSPVisualization Component (`TSPVisualization.jsx`):\n- SVG-based rendering (NOT Canvas)\n- Responsive sizing with resize observer\n- Coordinate transformation (grid → SVG space)\n- Algorithm-specific rendering:\n - **Moore**: Draws curve as connected line\n - **Sonar**: Draws centroid and sweep angle\n - **Other curves**: Draw respective curve geometry\n- Tour visualization with lines/edges\n- Point rendering (circles)\n- Current step highlighting\n\n### Legend Component (`Legend.jsx`):\n- Color-coded element descriptions\n- Algorithm-specific legend items\n\n---\n\n## 8. PACKAGE CONFIGURATION\n\n### `package.json` Details:\n\n**Scripts**:\n```\ndev - Build app + serve with hot reload\nbuild:app - Bun build browser bundle\ntest - Run all tests\ntest:e2e - Run E2E browser tests\nlint - Run ESLint\nlint:fix - Fix linting issues\nformat - Prettier format\nformat:check - Check formatting\ncheck - Lint + format + duplication check\nchangeset - Manage versioning\n```\n\n**Entry Points**:\n- `main`: `src/lib/index.js` (library)\n- `bin`: `src/cli/index.js` (CLI executable)\n- `types`: `src/lib/index.d.ts` (TypeScript types - MISSING)\n- `exports`:\n - `.`: Main export (library)\n - `./algorithms`: Algorithm-specific export\n\n**Dependencies**:\n- React 18.3.1\n- Chakra UI 3.31.0\n- lino-arguments (CLI parsing)\n\n**Dev Dependencies**:\n- Bun (test runner, bundler)\n- ESLint 9.38.0\n- Prettier 3.6.2\n- Playwright 1.58.0 (E2E tests)\n- Testing Library\n- Husky (git hooks)\n\n**Config Files**:\n- `.prettierrc` - Prettier config (80 char width, 2-space tabs, trailing commas, semicolons)\n- `eslint.config.js` - ESLint with prettier plugin\n- `.jscpd.json` - Copy-paste detection config\n- `bunfig.toml` - Bun configuration\n\n---\n\n## 9. CLI INTERFACE\n\n**Location**: `/src/cli/index.js`\n\n**Available Algorithms** (via `--algorithm` or `-a`):\n- sonar, moore, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force\n\n**Available Optimizations** (via `--optimization` or `-o`):\n- none, 2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined\n\n**Options**:\n```\n--algorithm/-a Algorithm name\n--optimization/-o Optimization method\n--num-points/-n Number of random points (default: 10)\n--grid-size/-g Grid size (default: 16)\n--points/-p Manual points as \"x1 y1 x2 y2 ...\"\n--verify/-v Run lower-bound verification\n--json/-j Output as JSON\n```\n\n**Example Commands**:\n```bash\ntsp-algorithms --algorithm sonar --num-points 20\ntsp-algorithms -a moore -o 2-opt -n 50 -g 32\ntsp-algorithms -a brute-force --points \"0 0 5 5 10 2 3 8\"\n```\n\n---\n\n## 10. GRID SIZE CONFIGURATION\n\n**Utility Functions** (`utils.js`):\n\n```javascript\nexport const VALID_GRID_SIZES = [2, 4, 8, 16, 32, 64, 128];\nexport const VALID_PEANO_GRID_SIZES = [3, 9, 27, 81];\n\ncalculateMooreGridSize(gridSize) // Returns nearest valid Moore size\ncalculatePeanoGridSize(gridSize) // Returns nearest valid Peano size\ngenerateRandomPoints(gridSize, numPoints) // Generate random points on grid\n```\n\n**Why**: Moore curve of order n fills a 2^n × 2^n grid. Peano fills 3^n × 3^n.\n\n---\n\n## 11. EXISTING SPIRAL-RELATED CODE\n\n**Result**: NO spiral or Archimedean spiral implementation found in codebase.\n\n- No `spiral.js` files\n- No references to \"spiral\" in code\n- No \"archimedean\" references\n- This is a NEW feature to be implemented (Issue #66)\n\n---\n\n## 12. BUILD & VISUALIZATION OUTPUT\n\n### Browser Build:\n- **Tool**: Bun\n- **Command**: `bun build src/app/main.jsx --outdir dist --minify --target browser`\n- **Output**: `/dist/` directory (minified bundle)\n- **Entry**: `/index.html` → loads React app\n\n### Visual Output:\n- SVG-based interactive visualization\n- Screenshot captured at `/screenshot.png`\n- No image generation to files mentioned (SVG in-browser only)\n\n### Development Server:\n- `serve.js` - Custom local server\n- Hot reload via `bun --hot`\n- Development URL: localhost (port undefined in code, likely 3000+)\n\n---\n\n## 13. CONTRIBUTING & GUIDELINES\n\n**No CONTRIBUTING.md found**, but patterns evident from codebase:\n\n**Code Style**:\n- ESLint + Prettier (80 char width, semicolons, trailing commas)\n- Husky git hooks for pre-commit checks\n- lint-staged for staged files only\n- jscpd for duplicate code detection\n\n**Testing**:\n- Bun test framework (no Jest, Vitest, etc.)\n- Tests for new algorithms required\n- Test file patterns: `{algorithm-name}.test.js` or `{feature}.test.js`\n- Must test both atomic and progressive versions\n\n**File Naming**:\n- Kebab-case files: `space-filling-tree.js`\n- Pascal-case exports: `spaceFillingTreeSolution`\n- camelCase functions: `mooreCurveToPoints`\n\n**Documentation**:\n- JSDoc comments on all functions\n- Algorithm names in comments\n- Time/space complexity documented\n- Axiom/L-system rules included for fractal curves\n\n**Versioning**:\n- Changeset-based versioning\n- `changeset` command for PRs\n- `changeset:version` to update versions\n- `changeset:publish` for npm release\n\n---\n\n## 14. KEY ALGORITHM PATTERNS\n\nAll space-filling curves follow this pattern:\n\n### Atomic Pattern:\n```javascript\nexport const {algorithm}Solution = (points, gridSize) => {\n // 1. Generate curve\n const curvePoints = generate{Algorithm}Curve(...);\n \n // 2. Map points to curve positions\n const pointsWithPositions = points.map((p) => ({\n idx: p.id,\n position: findNearestPositionOnCurve(p, curvePoints)\n }));\n \n // 3. Sort by position\n pointsWithPositions.sort((a, b) => a.position - b.position);\n \n // 4. Return tour\n return {\n tour: pointsWithPositions.map(p => p.idx),\n curvePoints: curvePoints\n };\n};\n```\n\n### Progressive Pattern:\n```javascript\nexport const {algorithm}AlgorithmSteps = (points, gridSize) => {\n const steps = [];\n \n // Step 1: Show curve generation\n steps.push({\n type: 'curve',\n curvePoints: curvePoints,\n tour: [],\n description: 'Curve generated...'\n });\n \n // Steps 2+: Show point visits\n for (let i = 0; i < sortedPoints.length; i++) {\n steps.push({\n type: 'visit',\n curvePoints: curvePoints,\n curveProgress: percentage,\n tour: [...tour, sortedPoints[i].idx],\n description: 'Point visited...'\n });\n }\n \n return steps;\n};\n```\n\n---\n\n## 15. FULL FILE LISTING\n\n### Source Files (46 files):\n**Algorithms** (44 files):\n- `/src/lib/algorithms/atomic/solution/` - 10 files (moore, sonar, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force, index)\n- `/src/lib/algorithms/atomic/optimization/` - 9 files (2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined, index)\n- `/src/lib/algorithms/progressive/solution/` - 10 files (same as atomic)\n- `/src/lib/algorithms/progressive/optimization/` - 9 files (same as atomic)\n- `/src/lib/algorithms/verification/` - 2 files (lower-bound, index)\n- `/src/lib/algorithms/` - utils.js, index.js\n\n**UI** (5 files):\n- `/src/app/ui/components/` - Controls.jsx, Legend.jsx, TSPVisualization.jsx, VisualizationPanel.jsx, index.js\n- `/src/app/ui/` - App.jsx, i18n.js, styles.css, index.js\n- `/src/app/` - main.jsx\n\n**CLI** (1 file):\n- `/src/cli/index.js`\n\n**Tests** (25 files):\n- Core tests: index.test.js, cli.test.js, setup.js\n- Algorithm tests: comb-, gosper-, koch-, optimization-, peano-, saw-, sierpinski-, space-filling-tree-algorithm.test.js\n- Component tests: 4 React component test files\n- E2E: app.test.js\n\n---\n\n## 16. TOTAL PROJECT STATISTICS\n\n- **Total source files**: ~70 files\n- **Algorithm implementations**: 10 different curves (+ optimizations)\n- **Test coverage**: 25+ test files, 1460+ lines in main test\n- **UI components**: 4 main components\n- **Code size**: 656 KB /src directory\n- **No TypeScript**: Pure JavaScript ES6+ modules\n\n---\n\n## KEY TAKEAWAYS FOR ISSUE #66 (Double Spiral)\n\nTo implement the Double Spiral algorithm:\n\n1. **Create two new files**:\n - `/src/lib/algorithms/atomic/solution/spiral.js`\n - `/src/lib/algorithms/progressive/solution/spiral.js`\n\n2. **Include these functions** (following Moore Curve pattern):\n - `generateDoubleSpiral(radius, density)` - Core spiral generation\n - `spiralToPoints(spiralSequence, gridSize)` - Convert to coordinates\n - `spiralSolution(points, gridSize)` - Atomic version\n - `spiralAlgorithmSteps(points, gridSize)` - Progressive visualization\n\n3. **Export in index files**:\n - Add to `/src/lib/algorithms/atomic/solution/index.js`\n - Add to `/src/lib/algorithms/progressive/solution/index.js`\n - Add to `/src/lib/algorithms/index.js` (main export)\n\n4. **Register in UI**:\n - Add to `ALGORITHM_OPTIONS` in `/src/app/ui/components/Controls.jsx`\n - Ensure TSPVisualization handles 'spiral' algorithm type\n\n5. **Add tests**:\n - Create `/src/tests/spiral-algorithm.test.js`\n - Test both atomic and progressive versions\n - Verify grid bounds and point mapping\n\n6. **Update documentation**:\n - README.md algorithm section\n - JSDoc comments in code\n - CLI help text in `/src/cli/index.js`\n\n---\n\n**Files are located in absolute paths:**\n- Algorithms: `/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/`\n- UI: `/tmp/gh-issue-solver-1770502731119/src/app/ui/`\n- Tests: `/tmp/gh-issue-solver-1770502731119/src/tests/`\n- Config: `/tmp/gh-issue-solver-1770502731119/package.json`"
},
{
"type": "text",
"text": "agentId: a5d0dba (for resuming to continue this agent's work if needed)\n<usage>total_tokens: 79157\ntool_uses: 45\nduration_ms: 93859</usage>"
}
]
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1c41ed63-6d33-436b-9894-4085be0eca28",
"tool_use_result": {
"status": "completed",
"prompt": "Very thoroughly explore the repository at /tmp/gh-issue-solver-1770502731119/. I need to understand:\n1. The overall project structure (all directories and key files)\n2. The Moore Curve algorithm implementation - find ALL files related to it\n3. How tests are structured and run\n4. How algorithms are registered/exported\n5. The package.json, tsconfig, and any build/test configuration\n6. Any existing spiral-related code\n7. How the visual output (like images/screenshots) is generated\n8. Contributing guidelines if any exist\n\nBe very thorough - list all source files, test files, and configuration files.",
"agentId": "a5d0dba",
"content": [
{
"type": "text",
"text": "Excellent! Now I have all the information I need. Let me create a comprehensive report.\n\n## Comprehensive Repository Exploration Report\n\nI've completed a thorough exploration of the TSP (Traveling Salesman Problem) repository. Here's everything you need to know:\n\n---\n\n## 1. OVERALL PROJECT STRUCTURE\n\n**Project**: TSP Visual Solver / tsp-algorithms \n**Package Name**: tsp-algorithms v0.5.0 \n**Type**: ES Module (Node.js + Browser) \n**License**: Unlicense \n**Repository**: https://github.com/konard/tsp \n\n### Root Files and Directories:\n```\n/tmp/gh-issue-solver-1770502731119/\n├── src/ # Source code (656 KB)\n├── dist/ # Compiled browser bundle\n├── docs/ # Case studies and documentation\n├── examples/ # Example scripts\n├── experiments/ # Experimental test files\n├── benchmarks/ # Benchmark data\n├── scripts/ # Build and automation scripts\n├── .github/workflows/ # GitHub Actions CI/CD\n├── .husky/ # Git hooks\n├── .changeset/ # Changeset version management\n├── package.json # NPM configuration\n├── package-lock.json # Dependency lock file\n├── bun.lock # Bun package manager lock\n├── tsconfig.json (missing) # No TypeScript config found\n├── eslint.config.js # ESLint configuration\n├── .prettierrc # Prettier formatting config\n├── .gitignore # Git ignore rules\n├── serve.js # Local development server\n├── index.html # Main HTML entry\n├── BENCHMARK.md # Performance benchmarks\n├── CHANGELOG.md # Version history\n├── README.md # Main documentation\n├── screenshot.png # UI screenshot\n└── CLAUDE.md # Task instructions (Issue #66)\n```\n\n**Task**: Issue #66 - Implement Double Spiral algorithm with Moore Curve feature parity\n\n---\n\n## 2. ISSUE #66 DETAILS\n\n**Issue**: Implement a Double Spiral algorithm \n**Requirements**:\n- Reproduce a specific visual pattern (double spiral geometry)\n- Match all Moore Curve algorithm features\n- Include progressive (step-by-step) and atomic (all-at-once) implementations\n- Integrate with UI visualization system\n- Match testing patterns and verification system\n\n**Related PR**: #67 (Draft status)\n\n---\n\n## 3. SOURCE CODE STRUCTURE\n\n### /src Directory Layout:\n\n```\nsrc/\n├── lib/ # Core algorithm library\n│ ├── algorithms/ # All TSP algorithms\n│ │ ├── atomic/ # Direct computation algorithms\n│ │ │ ├── solution/ # Solution algorithms (one-shot)\n│ │ │ │ ├── moore.js # Moore Curve (ATOMIC)\n│ │ │ │ ├── sonar.js # Sonar/Radial Sweep (ATOMIC)\n│ │ │ │ ├── gosper.js # Gosper Curve (ATOMIC)\n│ │ │ │ ├── peano.js # Peano Curve (ATOMIC)\n│ │ │ │ ├── sierpinski.js # Sierpinski Curve (ATOMIC)\n│ │ │ │ ├── comb.js # Comb/Serpentine (ATOMIC)\n│ │ │ │ ├── saw.js # Self-Avoiding Walk (ATOMIC)\n│ │ │ │ ├── koch.js # Koch Snowflake (ATOMIC)\n│ │ │ │ ├── space-filling-tree.js # Quadtree DFS (ATOMIC)\n│ │ │ │ ├── brute-force.js # Brute-force optimal (ATOMIC)\n│ │ │ │ └── index.js # Atomic exports barrel\n│ │ │ ├── optimization/ # Tour improvement (generic, work on any tour)\n│ │ │ │ ├── two-opt.js # 2-opt segment reversal\n│ │ │ │ ├── three-opt.js # 3-opt edge exchange\n│ │ │ │ ├── k-opt.js # k-opt generalized\n│ │ │ │ ├── lin-kernighan.js # LK heuristic\n│ │ │ │ ├── lk-helsgaun.js # LKH with perturbation\n│ │ │ │ ├── zigzag-opt.js # Adjacent swaps\n│ │ │ │ ├── combined-opt.js # Zigzag + 2-opt alternating\n│ │ │ │ └── index.js # Atomic optimization exports\n│ │ │ └── index.js # Atomic module export\n│ │ ├── progressive/ # Step-by-step visualization algorithms\n│ │ │ ├── solution/ # Progressive solution algorithms\n│ │ │ │ ├── moore.js # Moore Curve (PROGRESSIVE)\n│ │ │ │ ├── sonar.js # Sonar (PROGRESSIVE)\n│ │ │ │ ├── gosper.js # Gosper (PROGRESSIVE)\n│ │ │ │ ├── peano.js # Peano (PROGRESSIVE)\n│ │ │ │ ├── sierpinski.js # Sierpinski (PROGRESSIVE)\n│ │ │ │ ├── comb.js # Comb (PROGRESSIVE)\n│ │ │ │ ├── saw.js # SAW (PROGRESSIVE)\n│ │ │ │ ├── koch.js # Koch (PROGRESSIVE)\n│ │ │ │ ├── space-filling-tree.js # Space-Filling Tree (PROGRESSIVE)\n│ │ │ │ ├── brute-force.js # Brute-force (PROGRESSIVE)\n│ │ │ │ └── index.js # Progressive solution exports\n│ │ │ ├── optimization/ # Progressive optimization (step-by-step)\n│ │ │ │ ├── two-opt.js # 2-opt steps\n│ │ │ │ ├── three-opt.js # 3-opt steps\n│ │ │ │ ├── k-opt.js # k-opt steps\n│ │ │ │ ├── lin-kernighan.js # LK steps\n│ │ │ │ ├── lk-helsgaun.js # LKH steps\n│ │ │ │ ├── zigzag-opt.js # Zigzag steps\n│ │ │ │ ├── combined-opt.js # Combined steps\n│ │ │ │ └── index.js # Progressive optimization exports\n│ │ │ └── index.js # Progressive module export\n│ │ ├── verification/ # Optimality proof algorithms\n│ │ │ ├── lower-bound.js # 1-tree lower bound\n│ │ │ └── index.js # Verification exports\n│ │ ├── utils.js # Shared utilities (distance, grid sizes, etc.)\n│ │ └── index.js # Main algorithms export\n│ ├── index.js # Library entry point\n│ └── (no TypeScript .d.ts files) # Only JavaScript, no TypeScript\n├── app/ # React web application\n│ ├── main.jsx # React entry point\n│ ├── ui/\n│ │ ├── App.jsx # Main app component\n│ │ ├── components/\n│ │ │ ├── Controls.jsx # Algorithm/parameter controls\n│ │ │ ├── Legend.jsx # Visual legend component\n│ │ │ ├── TSPVisualization.jsx # SVG visualization renderer\n│ │ │ ├── VisualizationPanel.jsx # Wrapper component\n│ │ │ └── index.js # Component exports\n│ │ ├── i18n.js # Internationalization (en, fr, de, etc.)\n│ │ ├── styles.css # All styling\n│ │ └── index.js # UI module export\n├── cli/\n│ └── index.js # Command-line interface\n└── tests/\n ├── index.test.js # Main algorithm tests (1460+ lines)\n ├── cli.test.js # CLI tests\n ├── comb-algorithm.test.js # Comb algorithm tests\n ├── gosper-algorithm.test.js # Gosper tests\n ├── koch-algorithm.test.js # Koch tests\n ├── optimization-algorithms.test.js # Optimization tests\n ├── peano-algorithm.test.js # Peano tests\n ├── saw-algorithm.test.js # SAW tests\n ├── sierpinski-algorithm.test.js # Sierpinski tests\n ├── space-filling-tree.test.js # Space-Filling Tree tests\n ├── setup.js # Test configuration\n ├── components/ # React component tests\n │ ├── Controls.test.jsx\n │ ├── Legend.test.jsx\n │ ├── TSPVisualization.test.jsx\n │ └── VisualizationPanel.test.jsx\n └── e2e/\n └── app.test.js # End-to-end browser tests\n```\n\n---\n\n## 4. MOORE CURVE ALGORITHM IMPLEMENTATION (Reference)\n\n### Atomic Version (`/src/lib/algorithms/atomic/solution/moore.js`):\n\n**Key Components**:\n- `generateMooreCurve(order)`: L-system generation using rules:\n - Axiom: `LFL+F+LFL`\n - L → `-RF+LFL+FR-`\n - R → `+LF-RFR-FL+`\n - Returns expanded string sequence\n\n- `mooreCurveToPoints(sequence, mooreGridSize)`: Converts L-system to grid coordinates\n - Parses F (forward), + (turn left 90°), - (turn right 90°)\n - Normalizes to [0, gridSize-1] range\n - Returns array of {x, y} points\n\n- `mooreSolution(points, mooreGridSize)`: Main atomic function\n - Generates curve for given grid size\n - Maps each point to nearest curve position\n - Sorts points by curve position\n - Returns `{tour: number[], curvePoints: [{x, y}]}`\n\n**Time**: O(n log n), **Space**: O(n)\n\n### Progressive Version (`/src/lib/algorithms/progressive/solution/moore.js`):\n\n**Key Function**:\n- `mooreAlgorithmSteps(points, mooreGridSize)`: Returns visualization steps\n - First step: curve generation (`type: 'curve'`)\n - Subsequent steps: point visits (`type: 'visit'`)\n - Each step includes:\n - `tour`: cumulative tour\n - `curvePoints`: curve geometry\n - `curveProgress`: percentage along curve\n - `description`: human-readable text\n\n---\n\n## 5. ALGORITHM REGISTRATION & EXPORT SYSTEM\n\n### Main Export (`/src/lib/algorithms/index.js`):\n\n**Exported at top level** (for convenience):\n```javascript\n// Solutions (progressive)\nexport { sonarAlgorithmSteps, mooreAlgorithmSteps, gosperAlgorithmSteps, ... }\nexport { generateMooreCurve, mooreCurveToPoints, ... }\n\n// Optimizations (progressive)\nexport { twoOptSteps, zigzagOptSteps, ... }\n\n// Verification\nexport { oneTreeLowerBound, verifyOptimality, ... }\n\n// Namespaced access\nexport * as progressive from './progressive/index.js'\nexport * as atomic from './atomic/index.js'\nexport * as verification from './verification/index.js'\n\n// Utilities\nexport * from './utils.js'\n```\n\n### Controls Algorithm List (`/src/app/ui/components/Controls.jsx`):\n\n```javascript\nexport const ALGORITHM_OPTIONS = [\n { id: 'sonar', label: 'Sonar Visit' },\n { id: 'moore', label: 'Moore Curve' },\n { id: 'gosper', label: 'Gosper Curve' },\n { id: 'peano', label: 'Peano Curve' },\n { id: 'sierpinski', label: 'Sierpiński Curve' },\n { id: 'comb', label: 'Comb Scan' },\n { id: 'saw', label: 'Self-Avoiding Walk' },\n { id: 'koch', label: 'Koch Snowflake' },\n { id: 'space-filling-tree', label: 'Space-Filling Tree' },\n { id: 'brute-force', label: 'Brute-Force' },\n];\n```\n\n---\n\n## 6. TEST STRUCTURE\n\n### Test Files Location: `/src/tests/`\n\n**Main Test File** (`index.test.js` - 1460 lines):\n- Utility function tests (VALID_GRID_SIZES, calculateMooreGridSize, etc.)\n- Sonar algorithm tests\n- Moore Curve algorithm tests:\n - `generateMooreCurve` tests\n - `mooreCurveToPoints` tests\n - `mooreAlgorithmSteps` tests\n - `mooreSolution` tests\n- Optimization tests (2-opt, 3-opt, zigzag, combined)\n- Verification tests (brute-force, lower-bound)\n- Integration tests\n\n**Test Pattern Examples**:\n```javascript\ndescribe('mooreCurveToPoints', () => {\n it('should generate curve points', () => {\n const sequence = generateMooreCurve(1);\n const points = mooreCurveToPoints(sequence, 4);\n expect(points.length).toBeGreaterThan(0);\n });\n\n it('should generate points within [0, gridSize-1] bounds', () => {\n const mooreGridSize = 16;\n const sequence = generateMooreCurve(3);\n const points = mooreCurveToPoints(sequence, mooreGridSize);\n points.forEach((p) => {\n expect(p.x).toBeGreaterThanOrEqual(0);\n expect(p.x).toBeLessThanOrEqual(mooreGridSize - 1);\n });\n });\n});\n```\n\n**Test Runner**: Bun test framework \n**Commands**:\n- `npm test` - Run all tests\n- `npm run test:e2e` - Run browser E2E tests\n\n---\n\n## 7. UI VISUALIZATION SYSTEM\n\n### Controls Component (`Controls.jsx`):\n- Algorithm selector dropdown (left and right panels)\n- Grid size selector (valid Moore curve sizes: 2, 4, 8, 16, 32, 64, 128)\n- Points count input\n- Animation speed slider (50-1000 ms)\n- Action buttons: New Points, Start, Stop, 2-opt, 3-opt, k-opt, LK, LKH, Zigzag\n\n### VisualizationPanel Component (`VisualizationPanel.jsx`):\n- Algorithm selector dropdown\n- Distance display\n- Algorithm aliases/description\n- SVG visualization canvas\n- Step information text\n- Color legend\n\n### TSPVisualization Component (`TSPVisualization.jsx`):\n- SVG-based rendering (NOT Canvas)\n- Responsive sizing with resize observer\n- Coordinate transformation (grid → SVG space)\n- Algorithm-specific rendering:\n - **Moore**: Draws curve as connected line\n - **Sonar**: Draws centroid and sweep angle\n - **Other curves**: Draw respective curve geometry\n- Tour visualization with lines/edges\n- Point rendering (circles)\n- Current step highlighting\n\n### Legend Component (`Legend.jsx`):\n- Color-coded element descriptions\n- Algorithm-specific legend items\n\n---\n\n## 8. PACKAGE CONFIGURATION\n\n### `package.json` Details:\n\n**Scripts**:\n```\ndev - Build app + serve with hot reload\nbuild:app - Bun build browser bundle\ntest - Run all tests\ntest:e2e - Run E2E browser tests\nlint - Run ESLint\nlint:fix - Fix linting issues\nformat - Prettier format\nformat:check - Check formatting\ncheck - Lint + format + duplication check\nchangeset - Manage versioning\n```\n\n**Entry Points**:\n- `main`: `src/lib/index.js` (library)\n- `bin`: `src/cli/index.js` (CLI executable)\n- `types`: `src/lib/index.d.ts` (TypeScript types - MISSING)\n- `exports`:\n - `.`: Main export (library)\n - `./algorithms`: Algorithm-specific export\n\n**Dependencies**:\n- React 18.3.1\n- Chakra UI 3.31.0\n- lino-arguments (CLI parsing)\n\n**Dev Dependencies**:\n- Bun (test runner, bundler)\n- ESLint 9.38.0\n- Prettier 3.6.2\n- Playwright 1.58.0 (E2E tests)\n- Testing Library\n- Husky (git hooks)\n\n**Config Files**:\n- `.prettierrc` - Prettier config (80 char width, 2-space tabs, trailing commas, semicolons)\n- `eslint.config.js` - ESLint with prettier plugin\n- `.jscpd.json` - Copy-paste detection config\n- `bunfig.toml` - Bun configuration\n\n---\n\n## 9. CLI INTERFACE\n\n**Location**: `/src/cli/index.js`\n\n**Available Algorithms** (via `--algorithm` or `-a`):\n- sonar, moore, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force\n\n**Available Optimizations** (via `--optimization` or `-o`):\n- none, 2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined\n\n**Options**:\n```\n--algorithm/-a Algorithm name\n--optimization/-o Optimization method\n--num-points/-n Number of random points (default: 10)\n--grid-size/-g Grid size (default: 16)\n--points/-p Manual points as \"x1 y1 x2 y2 ...\"\n--verify/-v Run lower-bound verification\n--json/-j Output as JSON\n```\n\n**Example Commands**:\n```bash\ntsp-algorithms --algorithm sonar --num-points 20\ntsp-algorithms -a moore -o 2-opt -n 50 -g 32\ntsp-algorithms -a brute-force --points \"0 0 5 5 10 2 3 8\"\n```\n\n---\n\n## 10. GRID SIZE CONFIGURATION\n\n**Utility Functions** (`utils.js`):\n\n```javascript\nexport const VALID_GRID_SIZES = [2, 4, 8, 16, 32, 64, 128];\nexport const VALID_PEANO_GRID_SIZES = [3, 9, 27, 81];\n\ncalculateMooreGridSize(gridSize) // Returns nearest valid Moore size\ncalculatePeanoGridSize(gridSize) // Returns nearest valid Peano size\ngenerateRandomPoints(gridSize, numPoints) // Generate random points on grid\n```\n\n**Why**: Moore curve of order n fills a 2^n × 2^n grid. Peano fills 3^n × 3^n.\n\n---\n\n## 11. EXISTING SPIRAL-RELATED CODE\n\n**Result**: NO spiral or Archimedean spiral implementation found in codebase.\n\n- No `spiral.js` files\n- No references to \"spiral\" in code\n- No \"archimedean\" references\n- This is a NEW feature to be implemented (Issue #66)\n\n---\n\n## 12. BUILD & VISUALIZATION OUTPUT\n\n### Browser Build:\n- **Tool**: Bun\n- **Command**: `bun build src/app/main.jsx --outdir dist --minify --target browser`\n- **Output**: `/dist/` directory (minified bundle)\n- **Entry**: `/index.html` → loads React app\n\n### Visual Output:\n- SVG-based interactive visualization\n- Screenshot captured at `/screenshot.png`\n- No image generation to files mentioned (SVG in-browser only)\n\n### Development Server:\n- `serve.js` - Custom local server\n- Hot reload via `bun --hot`\n- Development URL: localhost (port undefined in code, likely 3000+)\n\n---\n\n## 13. CONTRIBUTING & GUIDELINES\n\n**No CONTRIBUTING.md found**, but patterns evident from codebase:\n\n**Code Style**:\n- ESLint + Prettier (80 char width, semicolons, trailing commas)\n- Husky git hooks for pre-commit checks\n- lint-staged for staged files only\n- jscpd for duplicate code detection\n\n**Testing**:\n- Bun test framework (no Jest, Vitest, etc.)\n- Tests for new algorithms required\n- Test file patterns: `{algorithm-name}.test.js` or `{feature}.test.js`\n- Must test both atomic and progressive versions\n\n**File Naming**:\n- Kebab-case files: `space-filling-tree.js`\n- Pascal-case exports: `spaceFillingTreeSolution`\n- camelCase functions: `mooreCurveToPoints`\n\n**Documentation**:\n- JSDoc comments on all functions\n- Algorithm names in comments\n- Time/space complexity documented\n- Axiom/L-system rules included for fractal curves\n\n**Versioning**:\n- Changeset-based versioning\n- `changeset` command for PRs\n- `changeset:version` to update versions\n- `changeset:publish` for npm release\n\n---\n\n## 14. KEY ALGORITHM PATTERNS\n\nAll space-filling curves follow this pattern:\n\n### Atomic Pattern:\n```javascript\nexport const {algorithm}Solution = (points, gridSize) => {\n // 1. Generate curve\n const curvePoints = generate{Algorithm}Curve(...);\n \n // 2. Map points to curve positions\n const pointsWithPositions = points.map((p) => ({\n idx: p.id,\n position: findNearestPositionOnCurve(p, curvePoints)\n }));\n \n // 3. Sort by position\n pointsWithPositions.sort((a, b) => a.position - b.position);\n \n // 4. Return tour\n return {\n tour: pointsWithPositions.map(p => p.idx),\n curvePoints: curvePoints\n };\n};\n```\n\n### Progressive Pattern:\n```javascript\nexport const {algorithm}AlgorithmSteps = (points, gridSize) => {\n const steps = [];\n \n // Step 1: Show curve generation\n steps.push({\n type: 'curve',\n curvePoints: curvePoints,\n tour: [],\n description: 'Curve generated...'\n });\n \n // Steps 2+: Show point visits\n for (let i = 0; i < sortedPoints.length; i++) {\n steps.push({\n type: 'visit',\n curvePoints: curvePoints,\n curveProgress: percentage,\n tour: [...tour, sortedPoints[i].idx],\n description: 'Point visited...'\n });\n }\n \n return steps;\n};\n```\n\n---\n\n## 15. FULL FILE LISTING\n\n### Source Files (46 files):\n**Algorithms** (44 files):\n- `/src/lib/algorithms/atomic/solution/` - 10 files (moore, sonar, gosper, peano, sierpinski, comb, saw, koch, space-filling-tree, brute-force, index)\n- `/src/lib/algorithms/atomic/optimization/` - 9 files (2-opt, 3-opt, k-opt, lin-kernighan, lkh, zigzag, combined, index)\n- `/src/lib/algorithms/progressive/solution/` - 10 files (same as atomic)\n- `/src/lib/algorithms/progressive/optimization/` - 9 files (same as atomic)\n- `/src/lib/algorithms/verification/` - 2 files (lower-bound, index)\n- `/src/lib/algorithms/` - utils.js, index.js\n\n**UI** (5 files):\n- `/src/app/ui/components/` - Controls.jsx, Legend.jsx, TSPVisualization.jsx, VisualizationPanel.jsx, index.js\n- `/src/app/ui/` - App.jsx, i18n.js, styles.css, index.js\n- `/src/app/` - main.jsx\n\n**CLI** (1 file):\n- `/src/cli/index.js`\n\n**Tests** (25 files):\n- Core tests: index.test.js, cli.test.js, setup.js\n- Algorithm tests: comb-, gosper-, koch-, optimization-, peano-, saw-, sierpinski-, space-filling-tree-algorithm.test.js\n- Component tests: 4 React component test files\n- E2E: app.test.js\n\n---\n\n## 16. TOTAL PROJECT STATISTICS\n\n- **Total source files**: ~70 files\n- **Algorithm implementations**: 10 different curves (+ optimizations)\n- **Test coverage**: 25+ test files, 1460+ lines in main test\n- **UI components**: 4 main components\n- **Code size**: 656 KB /src directory\n- **No TypeScript**: Pure JavaScript ES6+ modules\n\n---\n\n## KEY TAKEAWAYS FOR ISSUE #66 (Double Spiral)\n\nTo implement the Double Spiral algorithm:\n\n1. **Create two new files**:\n - `/src/lib/algorithms/atomic/solution/spiral.js`\n - `/src/lib/algorithms/progressive/solution/spiral.js`\n\n2. **Include these functions** (following Moore Curve pattern):\n - `generateDoubleSpiral(radius, density)` - Core spiral generation\n - `spiralToPoints(spiralSequence, gridSize)` - Convert to coordinates\n - `spiralSolution(points, gridSize)` - Atomic version\n - `spiralAlgorithmSteps(points, gridSize)` - Progressive visualization\n\n3. **Export in index files**:\n - Add to `/src/lib/algorithms/atomic/solution/index.js`\n - Add to `/src/lib/algorithms/progressive/solution/index.js`\n - Add to `/src/lib/algorithms/index.js` (main export)\n\n4. **Register in UI**:\n - Add to `ALGORITHM_OPTIONS` in `/src/app/ui/components/Controls.jsx`\n - Ensure TSPVisualization handles 'spiral' algorithm type\n\n5. **Add tests**:\n - Create `/src/tests/spiral-algorithm.test.js`\n - Test both atomic and progressive versions\n - Verify grid bounds and point mapping\n\n6. **Update documentation**:\n - README.md algorithm section\n - JSDoc comments in code\n - CLI help text in `/src/cli/index.js`\n\n---\n\n**Files are located in absolute paths:**\n- Algorithms: `/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/`\n- UI: `/tmp/gh-issue-solver-1770502731119/src/app/ui/`\n- Tests: `/tmp/gh-issue-solver-1770502731119/src/tests/`\n- Config: `/tmp/gh-issue-solver-1770502731119/package.json`"
}
],
"totalDurationMs": 93859,
"totalTokens": 79157,
"totalToolUseCount": 45,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 999,
"cache_read_input_tokens": 71257,
"output_tokens": 6895,
"server_tool_use": {
"web_search_requests": 0,
"web_fetch_requests": 0
},
"service_tier": "standard",
"cache_creation": {
"ephemeral_1h_input_tokens": 999,
"ephemeral_5m_input_tokens": 0
}
}
}
}
[2026-02-07T22:21:02.267Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01NPos2qwnBFR4YB6Vwo982M",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Now let me download and view the image from the issue, and read the key reference files (Moore curve implementations) to understand the exact pattern."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 8300,
"cache_read_input_tokens": 26383,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 8300
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f6c0d051-a8dc-45cb-99cb-ee4ea5be3908"
}
[2026-02-07T22:21:04.667Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01NPos2qwnBFR4YB6Vwo982M",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_016pM2dspyJn1mMD9FVGiDnk",
"name": "Bash",
"input": {
"command": "curl -sL -o /tmp/gh-issue-solver-1770502731119/spiral-reference.png \"https://github.com/user-attachments/assets/f09443eb-5a6f-4aaf-84a7-aac59abaa7eb\" && file /tmp/gh-issue-solver-1770502731119/spiral-reference.png",
"description": "Download the reference image from issue"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 8300,
"cache_read_input_tokens": 26383,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 8300
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f7f9c8eb-8cc8-4445-b9e3-424f46f4fed5"
}
[2026-02-07T22:21:05.390Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01NPos2qwnBFR4YB6Vwo982M",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01475MXQaE8dzDah3VBB5FPu",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/moore.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 8300,
"cache_read_input_tokens": 26383,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 8300
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "aa8ec30a-a500-4d75-b713-ba1977d6f8ba"
}
[2026-02-07T22:21:05.782Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01NPos2qwnBFR4YB6Vwo982M",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01EhnrPx1gUEVXyRQFor3Azv",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/moore.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 8300,
"cache_read_input_tokens": 26383,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 8300
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "eb93d5af-8697-46d6-b369-222ff7ce70ab"
}
[2026-02-07T22:21:06.600Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_016pM2dspyJn1mMD9FVGiDnk",
"type": "tool_result",
"content": "/tmp/gh-issue-solver-1770502731119/spiral-reference.png: PNG image data, 2732 x 2048, 16-bit/color RGBA, non-interlaced",
"is_error": false
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "d151e24a-77f3-4e95-b1c0-b905da868886",
"tool_use_result": {
"stdout": "/tmp/gh-issue-solver-1770502731119/spiral-reference.png: PNG image data, 2732 x 2048, 16-bit/color RGBA, non-interlaced",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
[2026-02-07T22:21:06.601Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01475MXQaE8dzDah3VBB5FPu",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Moore Curve Solution for TSP\n 3→ *\n 4→ * Computes the final tour directly without intermediate visualization steps.\n 5→ *\n 6→ * Algorithm:\n 7→ * 1. Generate a Moore curve (L-system) that fills the grid space\n 8→ * 2. Map each point to its nearest position on the curve\n 9→ * 3. Sort points by their position along the curve\n 10→ * 4. Return the sorted order as the tour\n 11→ *\n 12→ * Time Complexity: O(n log n)\n 13→ * Space Complexity: O(n)\n 14→ */\n 15→\n 16→import { distance } from '../../utils.js';\n 17→\n 18→/**\n 19→ * Generate Moore curve using L-system\n 20→ * L-system rules for Moore curve:\n 21→ * Axiom: LFL+F+LFL\n 22→ * L -> -RF+LFL+FR-\n 23→ * R -> +LF-RFR-FL+\n 24→ *\n 25→ * @param {number} order - Order of the Moore curve\n 26→ * @returns {string} L-system sequence\n 27→ */\n 28→export const generateMooreCurve = (order) => {\n 29→ let sequence = 'LFL+F+LFL';\n 30→\n 31→ for (let i = 0; i < order; i++) {\n 32→ let newSequence = '';\n 33→ for (const char of sequence) {\n 34→ if (char === 'L') {\n 35→ newSequence += '-RF+LFL+FR-';\n 36→ } else if (char === 'R') {\n 37→ newSequence += '+LF-RFR-FL+';\n 38→ } else {\n 39→ newSequence += char;\n 40→ }\n 41→ }\n 42→ sequence = newSequence;\n 43→ }\n 44→\n 45→ return sequence;\n 46→};\n 47→\n 48→/**\n 49→ * Convert Moore curve L-system sequence to coordinate points\n 50→ *\n 51→ * @param {string} sequence - L-system sequence\n 52→ * @param {number} mooreGridSize - Size of the grid\n 53→ * @returns {Array<{x: number, y: number}>} Array of curve points\n 54→ */\n 55→export const mooreCurveToPoints = (sequence, mooreGridSize) => {\n 56→ const stepSize = 1;\n 57→\n 58→ const curvePoints = [];\n 59→ let x = 0;\n 60→ let y = 0;\n 61→\n 62→ // Direction: 0=up, 1=right, 2=down, 3=left\n 63→ let direction = 0;\n 64→\n 65→ curvePoints.push({ x, y });\n 66→\n 67→ for (const char of sequence) {\n 68→ if (char === 'F') {\n 69→ if (direction === 0) {\n 70→ y -= stepSize;\n 71→ } else if (direction === 1) {\n 72→ x += stepSize;\n 73→ } else if (direction === 2) {\n 74→ y += stepSize;\n 75→ } else if (direction === 3) {\n 76→ x -= stepSize;\n 77→ }\n 78→\n 79→ curvePoints.push({ x, y });\n 80→ } else if (char === '+') {\n 81→ direction = (direction + 1) % 4;\n 82→ } else if (char === '-') {\n 83→ direction = (direction + 3) % 4;\n 84→ }\n 85→ }\n 86→\n 87→ // Find bounding box of the curve\n 88→ let minX = Infinity,\n 89→ maxX = -Infinity,\n 90→ minY = Infinity,\n 91→ maxY = -Infinity;\n 92→ for (const p of curvePoints) {\n 93→ minX = Math.min(minX, p.x);\n 94→ maxX = Math.max(maxX, p.x);\n 95→ minY = Math.min(minY, p.y);\n 96→ maxY = Math.max(maxY, p.y);\n 97→ }\n 98→\n 99→ const curveWidth = maxX - minX;\n 100→ const curveHeight = maxY - minY;\n 101→\n 102→ const normalizedPoints = curvePoints.map((p) => ({\n 103→ x: Math.round(((p.x - minX) / curveWidth) * (mooreGridSize - 1)),\n 104→ y: Math.round(((p.y - minY) / curveHeight) * (mooreGridSize - 1)),\n 105→ }));\n 106→\n 107→ return normalizedPoints;\n 108→};\n 109→\n 110→/**\n 111→ * Compute Moore Curve solution in one step (atomic version).\n 112→ * Returns the final tour without intermediate steps.\n 113→ *\n 114→ * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n 115→ * @param {number} mooreGridSize - Size of the Moore grid\n 116→ * @returns {{tour: number[], curvePoints: Array<{x: number, y: number}>}} Final tour and curve\n 117→ */\n 118→export const mooreSolution = (points, mooreGridSize) => {\n 119→ if (points.length === 0) {\n 120→ return { tour: [], curvePoints: [] };\n 121→ }\n 122→\n 123→ // Determine L-system iterations: mooreGridSize = 2^(n+1), so n = log2(mooreGridSize) - 1\n 124→ const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n 125→ const curveSequence = generateMooreCurve(order);\n 126→ const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n 127→\n 128→ const pointsWithCurvePos = points.map((p, idx) => {\n 129→ let minDist = Infinity;\n 130→ let curvePos = 0;\n 131→\n 132→ for (let i = 0; i < curvePoints.length; i++) {\n 133→ const d = distance(p, curvePoints[i]);\n 134→ if (d < minDist) {\n 135→ minDist = d;\n 136→ curvePos = i;\n 137→ }\n 138→ }\n 139→\n 140→ return { idx, curvePos };\n 141→ });\n 142→\n 143→ pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n 144→\n 145→ return {\n 146→ tour: pointsWithCurvePos.map((p) => p.idx),\n 147→ curvePoints,\n 148→ };\n 149→};\n 150→\n 151→export default mooreSolution;\n 152→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c7e76f92-0c13-4c0c-b716-7078bf0a7bff",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/moore.js",
"content": "/**\n * Atomic Moore Curve Solution for TSP\n *\n * Computes the final tour directly without intermediate visualization steps.\n *\n * Algorithm:\n * 1. Generate a Moore curve (L-system) that fills the grid space\n * 2. Map each point to its nearest position on the curve\n * 3. Sort points by their position along the curve\n * 4. Return the sorted order as the tour\n *\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n */\n\nimport { distance } from '../../utils.js';\n\n/**\n * Generate Moore curve using L-system\n * L-system rules for Moore curve:\n * Axiom: LFL+F+LFL\n * L -> -RF+LFL+FR-\n * R -> +LF-RFR-FL+\n *\n * @param {number} order - Order of the Moore curve\n * @returns {string} L-system sequence\n */\nexport const generateMooreCurve = (order) => {\n let sequence = 'LFL+F+LFL';\n\n for (let i = 0; i < order; i++) {\n let newSequence = '';\n for (const char of sequence) {\n if (char === 'L') {\n newSequence += '-RF+LFL+FR-';\n } else if (char === 'R') {\n newSequence += '+LF-RFR-FL+';\n } else {\n newSequence += char;\n }\n }\n sequence = newSequence;\n }\n\n return sequence;\n};\n\n/**\n * Convert Moore curve L-system sequence to coordinate points\n *\n * @param {string} sequence - L-system sequence\n * @param {number} mooreGridSize - Size of the grid\n * @returns {Array<{x: number, y: number}>} Array of curve points\n */\nexport const mooreCurveToPoints = (sequence, mooreGridSize) => {\n const stepSize = 1;\n\n const curvePoints = [];\n let x = 0;\n let y = 0;\n\n // Direction: 0=up, 1=right, 2=down, 3=left\n let direction = 0;\n\n curvePoints.push({ x, y });\n\n for (const char of sequence) {\n if (char === 'F') {\n if (direction === 0) {\n y -= stepSize;\n } else if (direction === 1) {\n x += stepSize;\n } else if (direction === 2) {\n y += stepSize;\n } else if (direction === 3) {\n x -= stepSize;\n }\n\n curvePoints.push({ x, y });\n } else if (char === '+') {\n direction = (direction + 1) % 4;\n } else if (char === '-') {\n direction = (direction + 3) % 4;\n }\n }\n\n // Find bounding box of the curve\n let minX = Infinity,\n maxX = -Infinity,\n minY = Infinity,\n maxY = -Infinity;\n for (const p of curvePoints) {\n minX = Math.min(minX, p.x);\n maxX = Math.max(maxX, p.x);\n minY = Math.min(minY, p.y);\n maxY = Math.max(maxY, p.y);\n }\n\n const curveWidth = maxX - minX;\n const curveHeight = maxY - minY;\n\n const normalizedPoints = curvePoints.map((p) => ({\n x: Math.round(((p.x - minX) / curveWidth) * (mooreGridSize - 1)),\n y: Math.round(((p.y - minY) / curveHeight) * (mooreGridSize - 1)),\n }));\n\n return normalizedPoints;\n};\n\n/**\n * Compute Moore Curve solution in one step (atomic version).\n * Returns the final tour without intermediate steps.\n *\n * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n * @param {number} mooreGridSize - Size of the Moore grid\n * @returns {{tour: number[], curvePoints: Array<{x: number, y: number}>}} Final tour and curve\n */\nexport const mooreSolution = (points, mooreGridSize) => {\n if (points.length === 0) {\n return { tour: [], curvePoints: [] };\n }\n\n // Determine L-system iterations: mooreGridSize = 2^(n+1), so n = log2(mooreGridSize) - 1\n const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n const curveSequence = generateMooreCurve(order);\n const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n\n const pointsWithCurvePos = points.map((p, idx) => {\n let minDist = Infinity;\n let curvePos = 0;\n\n for (let i = 0; i < curvePoints.length; i++) {\n const d = distance(p, curvePoints[i]);\n if (d < minDist) {\n minDist = d;\n curvePos = i;\n }\n }\n\n return { idx, curvePos };\n });\n\n pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n\n return {\n tour: pointsWithCurvePos.map((p) => p.idx),\n curvePoints,\n };\n};\n\nexport default mooreSolution;\n",
"numLines": 152,
"startLine": 1,
"totalLines": 152
}
}
}
[2026-02-07T22:21:06.601Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01EhnrPx1gUEVXyRQFor3Azv",
"type": "tool_result",
"content": " 1→/**\n 2→ * Progressive Moore Curve Algorithm for TSP\n 3→ *\n 4→ * Also known as: Space-Filling Curve, Hilbert Curve Variant, Fractal Ordering\n 5→ *\n 6→ * This algorithm provides step-by-step visualization of using a Moore curve\n 7→ * (a variant of the Hilbert curve) to order points:\n 8→ * 1. Generate a Moore curve that fills the grid space\n 9→ * 2. Map each point to its nearest position on the curve\n 10→ * 3. Sort points by their position along the curve\n 11→ * 4. Connect points in curve-order to form a tour\n 12→ *\n 13→ * Time Complexity: O(n log n)\n 14→ * Space Complexity: O(n)\n 15→ */\n 16→\n 17→import { distance } from '../../utils.js';\n 18→import {\n 19→ generateMooreCurve,\n 20→ mooreCurveToPoints,\n 21→} from '../../atomic/solution/moore.js';\n 22→\n 23→// Re-export atomic functions for backward compatibility\n 24→export {\n 25→ mooreSolution,\n 26→ generateMooreCurve,\n 27→ mooreCurveToPoints,\n 28→} from '../../atomic/solution/moore.js';\n 29→\n 30→/**\n 31→ * Generate step-by-step solution using Moore Curve algorithm\n 32→ *\n 33→ * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n 34→ * @param {number} mooreGridSize - Size of the Moore grid\n 35→ * @returns {Array<Object>} Array of steps for visualization\n 36→ */\n 37→export const mooreAlgorithmSteps = (points, mooreGridSize) => {\n 38→ if (points.length === 0) {\n 39→ return [];\n 40→ }\n 41→\n 42→ // Determine L-system iterations based on Moore grid size\n 43→ // generateMooreCurve(n) fills a 2^(n+1) x 2^(n+1) grid\n 44→ // So for mooreGridSize = 2^k, iterations = k - 1\n 45→ const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n 46→ const curveSequence = generateMooreCurve(order);\n 47→ // Generate curve points using the Moore grid size for perfect alignment\n 48→ const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n 49→ const totalCurveLength = curvePoints.length;\n 50→\n 51→ // Points are already on Moore grid coordinates, no scaling needed\n 52→ // Map each point to its position along the curve\n 53→ const pointsWithCurvePos = points.map((p, idx) => {\n 54→ let minDist = Infinity;\n 55→ let curvePos = 0;\n 56→\n 57→ // Points are already in Moore grid coordinates\n 58→ for (let i = 0; i < curvePoints.length; i++) {\n 59→ const d = distance(p, curvePoints[i]);\n 60→ if (d < minDist) {\n 61→ minDist = d;\n 62→ curvePos = i;\n 63→ }\n 64→ }\n 65→\n 66→ return { ...p, idx, curvePos };\n 67→ });\n 68→\n 69→ // Sort points by their position along the curve\n 70→ pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n 71→\n 72→ // Generate steps\n 73→ const steps = [];\n 74→ const tour = [];\n 75→\n 76→ // First step: show the Moore curve\n 77→ steps.push({\n 78→ type: 'curve',\n 79→ curvePoints,\n 80→ mooreGridSize,\n 81→ curveProgress: 0,\n 82→ tour: [],\n 83→ description: `Moore curve generated (order ${order}, ${mooreGridSize}×${mooreGridSize} grid)`,\n 84→ });\n 85→\n 86→ for (let i = 0; i < pointsWithCurvePos.length; i++) {\n 87→ tour.push(pointsWithCurvePos[i].idx);\n 88→ // Calculate progress along the curve as a percentage\n 89→ const curveProgress = (\n 90→ (pointsWithCurvePos[i].curvePos / (totalCurveLength - 1)) *\n 91→ 100\n 92→ ).toFixed(1);\n 93→\n 94→ steps.push({\n 95→ type: 'visit',\n 96→ curvePoints,\n 97→ mooreGridSize,\n 98→ curvePosition: pointsWithCurvePos[i].curvePos,\n 99→ curveProgress: parseFloat(curveProgress),\n 100→ tour: [...tour],\n 101→ description: `Progress: ${curveProgress}% | Point ${pointsWithCurvePos[i].idx} (${pointsWithCurvePos[i].x}, ${pointsWithCurvePos[i].y})`,\n 102→ });\n 103→ }\n 104→\n 105→ return steps;\n 106→};\n 107→\n 108→export default mooreAlgorithmSteps;\n 109→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "b2eb1357-c1e1-48ab-a84a-68e6b9336932",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/moore.js",
"content": "/**\n * Progressive Moore Curve Algorithm for TSP\n *\n * Also known as: Space-Filling Curve, Hilbert Curve Variant, Fractal Ordering\n *\n * This algorithm provides step-by-step visualization of using a Moore curve\n * (a variant of the Hilbert curve) to order points:\n * 1. Generate a Moore curve that fills the grid space\n * 2. Map each point to its nearest position on the curve\n * 3. Sort points by their position along the curve\n * 4. Connect points in curve-order to form a tour\n *\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n */\n\nimport { distance } from '../../utils.js';\nimport {\n generateMooreCurve,\n mooreCurveToPoints,\n} from '../../atomic/solution/moore.js';\n\n// Re-export atomic functions for backward compatibility\nexport {\n mooreSolution,\n generateMooreCurve,\n mooreCurveToPoints,\n} from '../../atomic/solution/moore.js';\n\n/**\n * Generate step-by-step solution using Moore Curve algorithm\n *\n * @param {Array<{x: number, y: number, id: number}>} points - Array of points\n * @param {number} mooreGridSize - Size of the Moore grid\n * @returns {Array<Object>} Array of steps for visualization\n */\nexport const mooreAlgorithmSteps = (points, mooreGridSize) => {\n if (points.length === 0) {\n return [];\n }\n\n // Determine L-system iterations based on Moore grid size\n // generateMooreCurve(n) fills a 2^(n+1) x 2^(n+1) grid\n // So for mooreGridSize = 2^k, iterations = k - 1\n const order = Math.max(0, Math.round(Math.log2(mooreGridSize)) - 1);\n const curveSequence = generateMooreCurve(order);\n // Generate curve points using the Moore grid size for perfect alignment\n const curvePoints = mooreCurveToPoints(curveSequence, mooreGridSize);\n const totalCurveLength = curvePoints.length;\n\n // Points are already on Moore grid coordinates, no scaling needed\n // Map each point to its position along the curve\n const pointsWithCurvePos = points.map((p, idx) => {\n let minDist = Infinity;\n let curvePos = 0;\n\n // Points are already in Moore grid coordinates\n for (let i = 0; i < curvePoints.length; i++) {\n const d = distance(p, curvePoints[i]);\n if (d < minDist) {\n minDist = d;\n curvePos = i;\n }\n }\n\n return { ...p, idx, curvePos };\n });\n\n // Sort points by their position along the curve\n pointsWithCurvePos.sort((a, b) => a.curvePos - b.curvePos);\n\n // Generate steps\n const steps = [];\n const tour = [];\n\n // First step: show the Moore curve\n steps.push({\n type: 'curve',\n curvePoints,\n mooreGridSize,\n curveProgress: 0,\n tour: [],\n description: `Moore curve generated (order ${order}, ${mooreGridSize}×${mooreGridSize} grid)`,\n });\n\n for (let i = 0; i < pointsWithCurvePos.length; i++) {\n tour.push(pointsWithCurvePos[i].idx);\n // Calculate progress along the curve as a percentage\n const curveProgress = (\n (pointsWithCurvePos[i].curvePos / (totalCurveLength - 1)) *\n 100\n ).toFixed(1);\n\n steps.push({\n type: 'visit',\n curvePoints,\n mooreGridSize,\n curvePosition: pointsWithCurvePos[i].curvePos,\n curveProgress: parseFloat(curveProgress),\n tour: [...tour],\n description: `Progress: ${curveProgress}% | Point ${pointsWithCurvePos[i].idx} (${pointsWithCurvePos[i].x}, ${pointsWithCurvePos[i].y})`,\n });\n }\n\n return steps;\n};\n\nexport default mooreAlgorithmSteps;\n",
"numLines": 109,
"startLine": 1,
"totalLines": 109
}
}
}
[2026-02-07T22:21:08.590Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Now let me view the reference image and read additional key files to understand the full pattern."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "408501ef-633a-4cfa-9518-831e29088e10"
}
[2026-02-07T22:21:09.717Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01AUwmwhmnfYzW6ftTmbQN4p",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/spiral-reference.png"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9cdc419d-42bf-4d96-be58-01ae6c6b089f"
}
[2026-02-07T22:21:10.531Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01AUwmwhmnfYzW6ftTmbQN4p",
"type": "tool_result",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"data": "iVBORw0KGgoAAAANSUhEUgAAB9AAAAXbCAYAAABnYCWTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAgAElEQVR4nOydB5QURdeG/f4vmUXC7rKJnHPOOSsSJUgQEAUBQXLOOYs5R0QFzAqKYBYJklFBzKJizhE/uf95b0319MzOzM7GCfv2Oc+Z2Z7u6urq6t6uem84LTU1TQghhJAU+5kS76S6PgsIyamSHIiUIOsJIYQQQgghhBASEIyz7Wc8kRxwfVqBItJzc4QQQtKihtMiXQFCCCGRJdAgoeCI6AVHSLdiuR3o+w/8CSGEEEIIIYQQEphIj+nzn2BzKPFHsLkxQgghaQUaCuiEEEKCDhj818cnBU9Md0T1QJMArnWRnqAghBBCCCGEEELyGhu1zYneltm4Oa5xz40UDNE80DwYIYSQtAIPBXRCCCEhifSgJnKCuv/AsWCjHuwuT3ZnosH1d9BQ8YQQQgghhBBCSD7gM0bFeDaz34kLfyeD+CfSc26EEELSohYK6IQQQjIQyAK3YOE/eOTg2h//CQcrrgf73X+9D/R2J4QQQgghhBDih//YMpzf3GPUUGPYgkboc4/0HAwFdEIIIWlRBwV0QgghAQk0kCiYInp2B6AkOwN6JdA6ergTQgghhBBCSEziHtsFGudlNkYM+nsAoZxkRlrBIsRcVqTn3QghhKRFNRTQCSGEBMQ9oPAfYER8ABRxIj3gjW8CTYAEFdVdhgyhvNltGdme9KGXPCGEEEIIISQSZDLWiQRu4+ZgY7Fwx3kUwHOZDG3vnsOI9FxK5HHPeUV63o0QQmKT9AiSv+dKAZ0QQkjY+A86Ij3wyV/8B5z+A1EScYKEjM+wzv1bJlEEfCaEXBNF9ng+k0N20shv+8zKt9vrtiEmpoKuCzGRlite+1mYqHO3VU7Lzmrdc3qusVz3vLymmW2bl/0x4Pbsj1Ff90j2x3xvlwLSH/P0mma17nktHhWQaxrLdc/La8r/eZG5prFc9ywTxrm6xwQ+9fMbP2RnPONTdiCxOxtl+2wf6fEgCUCgeY20gkWAuSw7nxXpOTZCCIklUvS5aYTs4sVTJDGpuCQm5g9JSclah7S09Hx9fuezgJ6uJ5iWViJMi4GcWBVk1TIhry0Z0l3nHzmLieDnm5PzT5f09JJKzs8p8lYlhBBf/AcZwX4vmKQGGIRGeoBM4gVHWA+1jf8EWCYeHO4yszrh5p4gC7l9chbrnpzNumelXTKpu9uIwWcSMQvtkpyF+uTlNc2Lutt+kuf9MRevqU9/DLdd/Ce486ru4ZZdQPtjWNcpxvpjnl/T/OiP8fCMYX/Mn/4Y5c+YWOiPgc4zt//n+RANz5gC1B99BOxMrish2cd/fiKtQBPO3BYhhFg9CjpXiRKglAu3/pWezxphVrWycPW18MtM8YjneIeBmF22bHmpXLmqVK1aXalWLW9A2VWqVJMKFSppHYyQnn8ier4J6BDN0bgJCUlSrFiiWg2YzlLC52TthcB6WDEUL57srMtqR7T7JyenZLq9Nn7xZN0H9cwt4RblWoMB1AXnD+yF9j//vMecq2mbjKBeWTt/U17hwkXlvPPOz8a18r3mODb6BtoI7WXX51/7EEKyQ6QHQ9GBe2Aa6cEyIYQQQgghhBBC4h/3nESgeYpIz5VEAVEwb0YIiV6gP6WlQ5tKkcTEJDn//CJy7rmF5Oyzz3XA31gP7QoaFsT0cHUrPIescA4NzmiEifrdiulmm0B4RWtsb8sKfjxTHrY3Gmwgr21f/TRcEb948RQpVaqMdOnSVcaOHS9z586TRYsWy+LFSxwWLlwkCxYszDXmz1+gx5k0aYr069dfBfX8FNHzXEDHSeACoVPgpFq0aCkXXdRFatasrRfQdBIjIgN0PHwWLZogpUuXlXLlKviIzKa8EpKeXiLk8dCp7P6lS5fJ9OJjP1hNgJIlS+VK49u62hADqE/Llq2lVas2UqZMOacT56eIbtsY54k6oMP7ULqMcw3CuWlsO8+ZM1fuvPMuLcMYLGTNcgWfMKzAd9wEDRs21nJNGyXle2gGQkjm2Oe2+zuxBBvMumCIO0KIQ4BnBCERg/2REJKX8BlDogn2RxK9ZC1CQaTnQCJPZnNVkZ5DI4REJ/Auh0YHB9FSpUpL06bNVLh95JFH5fnnX5AdO3bKtm3b5OGHH5HZs+eobgX9ENtDu8L+oZ4x5jdoW8a5GNs3a9ZCWrVqrVoatC+rp/k/y6z+Br0OOif0vMy1xHTV2SpWqiyVKlVxHGd9yzfllixZWsqXr+gcK1SZKSmpWvdLLx0ks2bNlp49e0m1ajWkTJmyqr/iXMqWLSfVq9eUWrXqSI0ataRmzZxSW2rVqi1169aXDh06yqRJk+Xqq8eqRzra3njxx7iAjguKC9a+fUfZt2+/uJfbbrtdG9icbAlnW3QkNMann34qv//+u1x4YWcV1K0nNzp0sWIJGS4qLjQuIjyhR44cJd9//738+uuv8uijj7n+WXr3wd/mmAly55136rF++OEHvREKFSrsCcmQvfO2ZaOuCC9w7733aV3s8ueff8ratWu1k1mB2HbGjJ01ULiFjKHOvWEfgl8LtGP37j3kxIkT8vPPP2s9Tp48qfz2229at2XLlqk1jW9IioxhJawlS8WKlWX/fnNtccPBakWvVSb18d58JvQCrtmxY8ecNkKdNmzYoDdIft0QhJCsE2xwQgLhHtx6PgMI6ZmF/yOEEEJItBPqPSCc7bNafqTPlxBCCCE5IWvzAO7//5Ge54gegs1VEUKIG/NsMJGPoQNCaJ48eYocPXpU/vjjD/nf//4ngZa//vpLfz906LAKueXLV/DR0QI/c8x6aJ7QHaFZ2gXfIdbbVDBuLQ0OxNBK69VrIG+99bZql0ePviPNm7dQjS+Qg7F1ZF6yZKmWDX3tvvvW6rb2nFHXIkWKqub63XffydSp09QYILQ3fbrqc61btzFGBI0aS5EixdQIoHfvPh76SufOF6k+izbB9qgLtM+cYfOgJ6nOCt34kkv66/+//EgBnacCOhodjQQB9JNPjmunuP322/UkX3ttu/597733OgI6LCEgKD/++BP6299//62f3bp11wuCi4vGQqdp27a9JCWZEATeTlVSjwerhA8//Eg7NJYXXnjR9U/TNCi+42LiBhk0aLBuawXuZcuWqwifEwHdhmOAVchzz23Vcnfv3q2dF+zatUvXvfTSy7qNvUFsKAb/G8y7Pt0nbAN+Q9vZDoltzM2THkRALya9evWWU6dOyZdffilPP/20bNq0SXnyySe1PsOGXalGBdZgwV2+O/S+DdtQoUJFeeONN/R80ImtZz06ta1fsIeHFfVHjx6j+3/99deydOkyfWA99dTTuu7gwYNqYZObofUJIbmPvc/dg5RID55ig8gP1AkhhBCSm5Pf5v87xkXuUHsg0OQ43pns+M6bUistRNkmJZfd3vweuGxCCCGExAv+cwiRnsuIHvznnyI9P0YIiXaM5gahF06dhw8fluws+/btk0GDhqjGGMy5FeshhM+bN1/32bt3n4rQ+PuTTz7RdYjujG2s5mb2MwL6Qw895DjkfvvttypiW63UfRxo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eaYA3SPcAQAAABgKAToAAAzbSSvQAQAAAGD5AH1qckqADgAAA3LyjCvQz+//XIAOAAAAQPOsQAcAgGE7KUAHAAAAgKUB+q654NwKdAAAGJKTZ3yEuwAdAAAAgMGuQBegAwDAkJw84wp070AHAAAAYKgB+pQAHQAAhuSkAB0AAAAAZnkHOgAADNtJ70AHAAAAgFkCdAAAGLaTZwjQz/cOdAAAAACGovUA/YUXXui3cWZmRimllFJKKTVzav3whz/sr53/5E/+ZIUA3SPcAQAAABjsO9DbCtABAIDVrUD/+Mc/bgX6OMQXe+LEifmGyC4Gj8ePH0+1w5xOuSO7BXGHebRN/GylbcqkRnZxvETbtDL5EsdM9GstaK2Pju1oqY+OttFH16mlPrq0jT663vNna310K1o6f7Y2xnH+rFecO1vqo2PFRtbzZ4sr0KNNyrH/H//xH9073/nO7n3ve1/37ne/WymllFJKKfXuxfV7v/d7fUj+c//9v/djgBKeT0xM9H/9gQ98YP46O4s0AXoM8u+///7uhhtu6G655Zbu6NGjXWbPPfdcd+DAge7666/v7r777tSTMrHDP/zww92+ffu6m266qTty5EiXWUwq3XHHHd11113X/8w+KfP444/37RLt88gjj6TqoJaK4ySOlzhu4vg5duxYl9lTTz3V3XzzzX2/Fv1b5snMmAw7fPhw3za33npr9/TTT3eZPfvss93+/fv77bnnnntSTfYt9cKLL3QPPvhgv5/F/vbEE090mcXk8sGDB/u2OXToUPrg+dFHH+375xtvvLF77LHHuszifBltEufPaKPy6Kas4liJdolj56GHHuoyi2A2+rI4bqJviz4uszjHxHggtifOPZmvbeLcf9999/XbEtsU1waZxbVZOX/GNVvm82eIMU70Aa2McW6//fb5MU7282eMceL8Ge0T59LsfXQ5f952220pz5/zAfqutlagx+eN9vjzP//zRdujlFJKKaWU2raqKivQ42bUkGkOZ1umibK9e/d2l112WV8RnmUbfC0UE0oxiIy66qqr+mAz80RZTF6UtomAJvMNAQ888EB3+eWX921zxRVX9H+feaIsJmOjXWJ7YjIz44RMEeFStElsS7TRvffem6rDXTpRFv1YaZvo3zJPmsdNTVdfffV8PxATtFnbJj73nXfeOd82sV2ZJ82feeaZfkK2tE3c4JD5/BlhWWmbK6+8sg83sor+OALasj1xLs0caERblGub6KMjFMwqrmMWnj/jGCqhc8a+LW4GiOMltiW2KYKarOL7X3j+vOaaa1LfWBtjnNiG0kdHeJZxHyvuuuuu7tJLL50f42S+MSjGOHHtXPa16K8znz9jTFO2Ja6nM98YFOfKMv4sY5zMT6SI46ScO2ObYoyTfwX6VPoAPfapuG6OdvnQhz7Ub8fLXvayfpuUUkoppZRSk8vWjrnAPOrVr35197rXva57xSte0X34wx/ur7MzzXmkCdAjWIrJpZiQiYqVDZkfcxiTS2WiLCY0swfoced/aZuYXMocAMRK4NI2MViOv88qBv1xQ0O0S2xPBADx9INsHVURq0vKxFJUrKbLuB0h+q/ox0rbLAwAMm7Tk08+2U+Ux7bENsXq04zbEeJzx8qs0jaxXbHKKXOAHjdolO2JPiHT5OVSMalctiV7ABD9cQQAZXviXJr5qSfRFiXMiIqbHTIH6AvPn3EMZQ7Q4yagcv6MbYqbhDKv2I6QubRN3OQU56CsbRMBemzDwjFOZnFzxve///35kDZ7gB7XzmVfi/468/kzxjSlbaLi6TRZxVizjD/LGCdzgB5jnHLjSbRRjHGy9WlLA/SpxCvQyzzTv/3bv3WvfvWruv/2s/+te+1rXzv2lTtKKaWUUkplqR0Ts+8//4u/+IvuG9/4Rvfd7363e/SxfE8O25bt8cAxgRkBbfZH0JbHA1977bX9JGbmwDkG9jEBExMXMZGReaJs4eOBo21aeARttEe0S7RPhBuZHxMex0kcL9E2sRog+yNoY8I/+rPo16J/y9w25fHA0TYROmVeTV8CjdiO2J644SnzDVvlFSixn8Xkf+bV9CV0jvAs2ib7I2jLK1Cif47Vc5lvplv4eOC4ISjaqNywlVUcK3H+jGMnVm5mCjKWuyEggs04bmJlfdxYk1mcY+L8GdsT557M58/47HFjUGxLbFPm1fQhrs1iHytjnMznzzLGiT6glTFO9M3RR8cYJ/MNWyHaI86fUZmfRlP66HL+jDFOxvPnKQF64negl37rH//xH2e3ZWp2Nf3Civc4KqWUUkoppSaWrdFo1F83f+UrX+nHa1nHn2kC9DLBFJOzmSfLlw7MYiIjwyByNRNMcRBkPRBWetdZ5km/5dom8+T/wn4g2ibzawIWiv4s+rV4T3V2rbVNbEdsT+Zgpohj3/mzTs6fOfpo588626aVPtoYp/7zZ2t9dAttE6JdMq88b+n82WKAvmfPnv6zn3POOWNfwaOUUkoppVSmmpiY6H9++9vfnr/Gzjh/kypABwAAAKDid6A38Aj3PUtWoO/YMfsYyl/8xV/qX4sSTw+Kp23EUyqUUkoppZRSe+crnhQWr6vL/DrEIEAHAAAA4OwC9F0lQJ9q7hHuZRXNO9/5rmaeGAIAAKxMgA4AAADAxqxAb+ER7isE6Oedd1537NixRY+iVEoppZRSSr2wqOLaP+vK80KADgAAAMC6tBig/+NpAvR4X33IPiEIAACsTIAOAAAAwLoMKUCfnp4WoAMAwAAI0AEAAABYlyEF6FagAwDAMAjQAQAAANiQAH2q4QDdCnQAABgGAToAAAAA6zKkFejT5wnQAQBgCAToAAAAAKzLkFage4Q7AAAMgwAdAAAAgA1agT4bOgvQAQCArAToAAAAAKyLAB0AAGiNAB0AAACAswzQdzUUoO/xDnQAABgwAToAAAAAG7QCPf870PfsWSFAnxagAwDAEAjQAQAAANiQAH1qKn+A7hHuAAAwbAJ0AAAAANalxRXoKwXo0wJ0AAAYBAE6AAAAAOsypEe4W4EOAADDIEAHAAAA4OwC9F1zAXrTj3D3DnQAABgCAToAAAAAG/MOdCvQAQCA5AToAAAAAGzMI9wbXoE+PS1ABwCAIRCgAwAAALAuLa5AX/kR7gJ0AAAYAgE6AAAAABu0An2q4QDdO9ABAGAIBOgAAAAArMuQ3oE+LUAHAIBBEKADAAAAsDEr0BsI0D3CHQAAhk2ADgAAAMDGrECfEqADAAC5CdABAAAAOLsAfdcQ3oEuQAcAgCEQoAMAAACwIQH6VNMBunegAwDAEAjQAQAAAFgX70AHAABaI0AHAAAAYF2GFKBPW4EOAACDIEAHAAAAYF2GFKBbgQ4AAMMgQAcAAABgXYYUoE9PW4EOAABDIEAHAAAAYF0GFaB7hDsAAAyCAB0AAACAdRlWgO4R7gAAMAQCdAAAAAA2KECfajZA9w50AAAYBgE6AAAAAOsypBXoAnQAABgGAToAAAAAZxmg77ICHQAAaIIAHQAAAIB1aXMF+p7l34E+PS1ABwCAARCgAwAAALAxAfpc6Jw7QLcCHQAAhkyADgAAAMC6tLkCXYAOAABDJkAHAAAAYF1aDND37Fn+Ee4CdAAAGAYBOgAAAADr0mKAbgU6AAAMmwAdAAAAgA0J0KeaCNBXWoE+LUAHAIABEKADAAAAsC5DWoE+PW0FOgAADIEAHQAAAICzC9B3zQXoU+0G6B7hDgAAwyBAB4ABiAm+mZkZpZRSSqlmSoBZ6Qr0udC5zQA9/yPcX3jhhbEfu0oppZRSqv16Men1ctoAPb7w7F96i9vS6va0osW2aWV7WtqW1ranpW0JLW0LAEBr1zeZrz1PeQd6wyvQp5MH6Bk/MwAAeb2Y+PozXYAOAKz9IuXZZ5/tvvjFL3Zf/vKXlVJKKaVS19///Zf765q4vll4vcN4DOkd6Jkf4R4rz8O+ffu6iy++uLvkkkvGfiwrpZRSSqn26pJLLuk+//nPdw8//HDK6+aUAXoMUh588MHuscceSzHwOp3YYZ588snugQce6J555pkuuxMnTvQHwyOPPNI/miG7p556qm+b+JldtEe0y0MPPdS3U3YxSRZtE8dP1o63iH4s+rPo18okTGbPPfdc3zaPP/74/ORMVvH5jxw50m/PsWPHuqziGIkJzegHrrzyyn7Sb/v27f1PpZRSSqmsVa5nrrrqqv6aOvvjAWNO4P777+/HOBkNaQV61gA9xjcxrok2+LM/+7NF26aUUkoppdRG1sTctfPXv/717vjx430ulenaOV2AHl/w/v37u8svv7wfJN93330pv/AiQrNrr722H0jeeOONqUP0mKy44447+raJgObuu+9OHZ7FpMX111/ft811112XdhIjxOA42uOKK67oK9op8w0OcZzE3fLRNnH8RFCbVRwjMUkWx0wcO7fddlvqGxxiEunmm2/u2+bqq6/ubwrILG46ie2I7bnp5pv6mwMyKufJOHa+853v9Bcu55wz6qZGU/2E2apq7t8dTY1O+bPRaf/9Nfw/Vvj3T/lna/ncZ/HZ1/K7V72t6/7sU1v62c/6d6+1Tdf52XPvj1vbpmf69+v57KM17Y+b1qa17I9NtOkmffapAe2P62rTYZzzRrcJiDgAACAASURBVKNz+uuab3/726nH0uUG4Rh3xnXnNddcMz/GyTTfceo70AXoNYoFAnGT8Mc//vF+W37sx35s0/sY57yz/Oyn+d3OefbHtXx247w1fHbXYJv+2Qe9Pzbapnk+eyXnvAHsjy9/+cv7682vfvWr/Tx71sWDaQL0CDFLmHHZZZd1t9xyS9ogMAZZEWTGdkRwFsFm5rDp6aefnh/wxzZF+Jw5CLz33nu7Sy+9tG+bqPj7bAPjIkK/EjiXCZmymjbjNsUq+tiOaJf4eejQobQ3a0T/FYFz6Qeif3viiSfStk1MxJSbAWKb4oanDBNky4l96sCBA/NtE9sVJ/qM4g6/T33qU91HPvKR7vd///fHfvehUkoppdRG1h/90R91n/zkJ/vHUWcN0mOME+PPmBeInzHGyWY+QN/1h4tC5zYD9FzvQC/j5Ztuuqm78MJd3UUXXdT90i/9Ur8tO3bsGPsxrJRSSiml2n1i2G/91m91H/7wh7s//dM/7Y4cyZd9bMsUBMZK7RJo3HX3Xam+6OUGyRHKxAB579693dGjR7usYrAcYVm0TQyMb7/99hQD49M9HSDCzNie+Jl5lXMM/qM9Yluibr311vnJjYziOImV57EtcfzEcZRVTGTE0wHKjSfRv2W9EyvEjRlx80zpo+PGk8zi6QDlZoDYrmwTsuX8GDdlrHQRMxrNrkQfRc3fSTg6zV2Gp96luexdiIt+3yp/92rudFzw++d/92iVd0Fu5mdf7e9euI1L/j+n++yjtX72ud+3ZW16us++zN2xq2nTRd9NjfvjqIH9cbT+/XGq5v1xvW06VXObrnN/XGWbDmV/XNim9sdN3h9P99+c5TkvvoMSyC5XcZP6wuugTKuC4yl7cd0ZIXrG9wR6B3q9ysKTf/iHf1i0PaViu07pT2vuY07XP5Y/X+nzD+yc5xqsknPeaIPGeVu6Pw50nFf1/rhBfcxp9se847xR0jbdoHNe5v1xqsX9car9/XHq9G0a7bf09aHlps14Am/ItCAyTYBeVjpH4BTvpM0cApaBYwyM4+7yCDgyDLzOFJ7dc8893eHDh/sVj5nFARwherRN/Mx0QC8nBvfRLtE+md/lHOI4ieMl2iaOnwwTMKcT/VgEtdGvRf+WXUz+3XXXXf0TNbI+IWThxFncoBHbk/E1DgsD9Lh4mZic6Gvcdx8qpZRSSm1kxWRMVISAZeV21qc53Xnnnf1TjzKOPwXo9SrjsrI98dh2K8+VUkoppdRW1MTERHfOObOv34onvoZM451UAXqLMgy4oDatHTctbU9L25J5e1ZagV7uAPyJn/iJ7ktf+lL32c9+tn/k6dpq96n/bPeSP1/09+v93buX/93r+r2nqaWfdTM/+7p/95m+g+X+f+P5Xnavt03P+rPvbmN/PMP3snsjP/tGfi+r2YfOpra6TTfys2/Y97JV++NmfC8tnzcyfPaV+sda98fl+5i4ZvnCF77QP679la985bKTM5kD9Myfe2gB+vT0dHf8eP4V6GV74rGa8Wef+cxnBtLHLPN7lvucVY4Jdm/YZ1/1NeVWt+mmjQk2+br6rD7zKn7PZu4z1bbpKr7X6vuY1X/29e2PF6/6s+9OPM7bnbRNa76u3pzPvvo2zfHZM8yD1bc/fuYz/29/XfmmN72pv84sN21agQ4AVB+glwuWt73tbWkmMQEAyrXN4cP3dm984xsX3RhYKlZwL/x32TpDCtCzrkBfGqCXnzHRufDfAwCAs7mO/s3f/M1F188CdAAgTYD+1re+tf/zeOVGTJYppZRSStVcJ06c6K9dbrnllu71r3+9AL3yAH2q8RXoLQXof/3Xf93/ebzubdzHuVJKKaWUylvPPfdcf135f/+P/yFABwDqZAU6ANCSMsly8MABAXqFhrQCffq8NgL00fwK9M8s+vcAAGA9ZuauJ61ABwCqJUAHAFpSJlkOCNCrNKQV6K08wn00NRKgAwCwaQH6pAAdAKiNAB0AaDNAPyhAT7ECfTakFaBneAe6AB0AgM1YgT4pQAcA6iJABwDafIS7AL3uAH2XAL0yAnQAALbCjAAdAKidAB0AGNoj3A8dOpQm1GxNmwH6nqbfgT41EqADALBxZgToAEDtBOgAwODegX7ICvRqHuE+1e470KenGwnQrUAHAGAzA/RJAToAUBkBOgDQ5CPcD3qEe4YAfWqy3QC9mUe4j0YCdAAANi1An5y7fhagAwDVEKADAG2+A/00K9AF6PWsQG84QJ9uJUC3Ah0AgE19hPuEAB0AqIsAHQBoiRXodRtSgN7MCnQBOgAAG2hGgA4A1E6ADgAM7h3oAvTxB+i72n8H+nnnNfIO9JEAHQCAzXwH+oQAHQCoiwAdAGiJAL1uTa5A37PCI9ynrUAHAIClvAMdAKieAB0AaIlHuCcL0BtegS5ABwCAU1mBDgBUT4AOALTECvRcAfpUCyvQvQMdAABWzQp0AKB6AnQAoMkV6AL0JCvQpxoO0Bt5B7oAHQCAzQzQJ2fHAgJ0AKAaAnQAoCVWoNetxRXoe6xABwCAVbMCHQCongAdABjaO9APHTqUJtRsfgV6AwG6R7gDAMBZvANdgA4A1EaADgC0xAr0ZCvQp/IH6M2vQB8J0AEA2MxHuE8I0AGAugjQAYCWCNCTBOi7hvAO9EYCdCvQAQDYzBXok96BDgBURoAOAAztEe4C9JpWoLccoE8L0AEA4Iwr0AXoAEBlBOgAQEsE6HXzDvR6CdABANgKM96BDgDUToAOALTEI9zrNqQAfXq6lRXoIwE6AAAbZkaADgDUToAOAAwtQD906FCaULM1QwrQrUAHAIBTCdABgOoJ0AGANgN0j3BP8Q70hgP09CvQRwJ0AAC24B3oEwJ0AKAyAnQAoCUe4V63Ia1Anz4veYBuBToAAJtgxgp0AKB2AnQAoCVlkuWgAL1KQwrQW3mE+0iADgDABpoRoAMAtROgAwAt8Qj3bAH6bDgrQB8/K9ABABhPgD4pQAcA6iJABwBa4hHudbMCvV4CdAAAtsKMFegAQO0E6ABAk49wP2gFet0B+q4BrEBv5B3oIwE6AAAbZ8YKdACgdgJ0AGBoK9APHTqUJtRsTZMr0PfsWTZAn55uJEC3Ah0AgA00YwU6AFA7AToA0BIr0JMF6HPhbOoAvflHuI8E6AAAbF6APmkFOgBQGQE6ANAS70CvW5Mr0FcI0KebCdCtQAcAYOPMWIEOANROgA4AtLkC3SPca9RigL5nhUe4t7MCXYAOAMDGmRGgAwC1E6ADAC3xCPdsj3CfbPgR7t6BDgAAZ36EuwAdAKiMAB0AaIlHuOcK0KesQK+GAB0AgHEE6JNWoAMAtRGgAwAtEaDXbVDvQJ8WoAMAwFIe4Q4AVE+ADgC0RIBet2E9wl2ADgAAZ1yB7hHuAEBtBOgAQEsE6NkC9KmGA3TvQAcAgDO/A312LCBABwCqIUAHAJoM0A8eFKBneAd6AyvQ96z0CPdWAvSRAB0AgI0zYwU6AFA7AToAMLQA/dChQ2lCzdYM6R3o+R/hPrICHQCADTfjHegAQO0E6ABAS8oky0Er0KvU4gr0dgP0qUVBugAdAICNMGMFOgBQOwE6ANAS70BPEqDvKu9AF6DXHqCPPMIdAIBNfQf6hAAdAKjLEAL0uChTSiml1DDqxIkT/fn/lltuEaAnCNBLSNtmgN7IO9AbeYR7tEHsf+Puo5RSSimlNqoyXGMuJz774hXos2MBAToAUI0hBOgAwPCube69997ujW98owC9Mt6BXv9EZqsBOgAAdQboE96BPp7BTKYv+HRisNXSICXaJsOAeC1tk2FAvBrRLmUioAXRNq30A7EdLfUD2qYOQwjQYxIwJvx2797dXXzxxafU7mX+2apq9zr/u4t3n/l3rft3n+H/U/7ZKn7/qr+XdX723af9vKf5nLs3qP1O+V27N6hNd2/w97LK//e6v5eN++yr+t2r2YeytOlGf/YN+92r/OyrqM3sHze7j1n793KafXSjvofN7h/Puk13j+F7P5vPvnwf89nPfrb7whe+0H3yk5/sXvnKVy64vtk+H6YfOnSov0bIOobLPP4cUoA+bQV6Fcp3f//993d/9Vd/1X3uc59bR/+4hr5+I/vHCq5j6jtfb9RnX/05b0Ovq1dZq/7s6/heBjEm2MrvZUPadPWffX374+q/h3WPRy/eyj5m+XHe7k1s07Oad1jH97Luz76R441N++wXJ+tjdlc5DxZjns9//vPd8ePHu4xmBOjjvTh+5JFH+ke23X777d0zzzzTZRYHQQzwb7755v6CP8NA8nQef/zx7tZbb+0PgqNHj3aZxeA/VjZE29xzzz3pBpJLRXtEu0T7HDlyJMUg/3STGXG8RNvE8ZP1ZFI8++yz3cGDB/t+Lfq3zG0TJ76HHnqob5s77rijO3bsWJdZTIrFdsT2PPDAA6lO7C0H6NEHxPn/7rvv7t7whjcsu/pMKaWUUsOsrCvQ43rs8OHD3U033dSPccrj6jMZUoDezgr0UdoAPb73OE5iruMrX/nKovZRSimllMpcca121VVX9XO62RZEzix9hLsAfevEhPl1113XXXbZZX1F6JRh8LWSCGgvv/zyfluuvvrq7rHHHuuyeu6557obb7xxvm0iDMw0+FrqwQcfnG+bK664og8Fs4pBZQTnpW1uuOGG+dA5w2B/uRs1rrzyyn5boo1ioinjdoQ4AUY/Vtom+renn366y+qpp57qrrnmmvntiQnMrG0Tn/uuu+6a35bYrrhoyaTFAL1sU9ycccftt3c/9VM/1W/L6JxRf3G5sEajJX8/deq/M19L/t2YTJz95yv9N6NTfv9KVf690TK/Y/n/9+o/e/87l/0coxU/e/yu0Sq/l1M/++gMn32N38vpPvuy38viz7quz76BbTq1CW26MfvjaJj749Sw98dRE/vj2vuYjd4fq2nTlT57//nH3aZj3B/LsTcXyJZ6+ctf3lesSo/rt4XXDFnETc4xtomQOa4977vvvnTbIUCvV6sr0GPiNeYH/umf/qnfjpe9/OUb3D9ONX0NVv05b8VrsLW3aRvXYKvYH5f7HFt9DbaeNs2wPw74Gmzs4zzzDhvephuzPw7snDe1NX1M7H9xvRnjmmuvvbZfbJfNjBXo4xN3lkaIUQaVEQpmuwNjobizPLYjticCwcwhbayiXXhzw759++YH0BlFKFsC2qgygZFRDOzLzQ2xr0XnGzc8ZBnsL/Xwww/321FucIhJskwd7tITSrm5IbYp+rcnn3wybdtEUBt9WemjDxw4kLZt4vuPJ52UfiDu+nv00Ue7TFoL0Mv2xKNbP/ShD3UXXnhh94pXvGLsd4UqpZRSarz1l3/5l92ePXu673znOylXboeYHLv00kv7m7fjZ7kRIJMhBejT0x7hPi7l+47g/CMf+Uj3x3/8x91v/MZv9NvhqVRKKaWUaqFi7vb8P/iDfu7z05/+dJfJjAB9vIOYGEhGQBNhbeYV2yFWmkawGYPkCJoyP4o6dvgImSNkioA2bgbIMJBcSaxujFX00TbxM/OjqKMdoj0inI0nHUQ7ZeqglorjJI6XaJs4fjKv2C4D/7179/b9WvRvmW8KihNkrDqPtrn++uvTrdhe7qateGJDbE+E6dluCmotQC+f801vetOi7Si1mrs9l71TdBX/zuwdoqdfEbfiHaYr/PWZ7r5d12df5m7g1d4Ju57//9n8t6f/3s/ms6+lTac2rU0357Ofzf5y+u2ofX9cVZuu+7sYjbFNt6aPGSXoY/Lsj6ts0w36LlrcHzeyTUejc/prgG9961v9Dd2ZRfC/f//+/sbNuBm9bE+mMfWgAvRGVqCPEgboZS4jJl+XGxNs37H9lNWDZ98/Oued6btZX7kG2/o2Pf12LGrTTRzP1Lk/1jLOG9XfpsZ57c07LLeyPEsf09g5b7kw/XWve12XyYwAfbxisBWDyRisZBiorGagHNuTYaCymraJoDlWN7fQNjEBEK8NyBaaLSc6pGiXaJ9MndNK4niJ4ybrCpOF4liJ/iy2J8Nk0momm1rpo+Pzxw0bWfvoVgP0t771rbMTfqPZdzYqpZRSaphVVpvGE53KdWjm68+43ozxZ9YxztIAfarhAL2dR7jnewd6mc+Im+rjs58zOse7z5VSSinVXJVr6Te+8Y1dJjPegQ4A1G5IK9Djr3fv3t1PCn75y19WSiml1EDqi1/8YsrV2i0a0gr0dgL0dlagl587d+7s/vmf/7nvG8bdPymllFJKrbYuueSS7lWvetUpQboV6OMnQAeAxgwpQI+LseyvcwAAaCNA3zUXnM+GswL08RvCI9zL6qZ4H3rI/Go0AGCY3vCGN7z0pK3trQTokwJ0AKAuQwvQjxw50m9zTN7GxZpSSimlhlEZAsxhrkBvIUDfs2yAPj093USAHu8NbSVAL23zrnf9ev/n8Qq7cfdNSimllFKrrbjGWRigb29mBfqkAB0AqMtQV6BnmMQEAGg+QJ9qeQV6IwF6QyvQy+RsWYGeYVsAAFZcgd5KgD4pQAcAKtNsgL5zpwAdAKDyAH3KO9DrD9BHo4YC9MWPcM+wLQAACy1agd7II9wnvQMdAKhNswG6FegAAAke4d5ugD7dSoDe0gr0uf1MgA4AZNXkCvQJAToAUBkBOgAAW2VIAXozK9BbCtCtQAcAkhOg10mADgCNaTZA3ylABwCoNkDfVd6B3kKAvqftd6CPBOgAALVoMkCfFKADAJVpNkC3Ah0AoDpDWoE+PW0Fem0BetnPBOgAQFZNBugTAnQAoDICdAAAxhagN7EC3SPc0wToVqADAMk1GaBPCtABgMoI0AEA2CpDWoEuQK/wEe5zk7MCdAAgqxYD9Ekr0AGA2gjQAQAYV4BewtkWA/TpVt6B3lKAbgU6AJBckwH6pAAdAKiMAB0AgLEF6FagVxygj5oL0D3CHQBoKUDfvm17GwH6hAAdAKiMAB0AgK3iEe71sgIdACDZCvTtbaxAnxCgAwC1aTVA37lTgA4AUP8j3PMH6HsaD9BHo4YCdO9ABwCSa3EF+oRHuAMAtWk1QLcCHQCg4gB919wK9Ibfgd5KgN7WCvTZ/UyADgBk1eQK9MnZazQBOgBQjWYDdCvQAQCqM6wV6NMC9NregW4FOgDQUoC+rY0AfVKADgDUptkA3Qp0AIDqeAd6vYYQoHsHOgCQXYsB+oR3oAMAtWk3QN8pQAcAqMyQAvTp6VZWoI8E6AAAlRCg10mADgCNaTdAtwIdAKA2QwrQrUCvMECf288E6ABAVgL0OgnQAaAxAnQAAMb2DvSGA/T0K9BHDQboVqADAMm1GKBPCtABgNoI0AEA2CpDWoE+fV7yAL3FFegTVqADALm1GKBPCNABgNq0GqDvFKADAFRnSCvQW3mE+6ihd6BPCtABgIYC9O2NBOiTAnQAoDatBuhWoAMAZFiBPhvSCtDHbwgr0MvkrAAdAMiqzRXokwJ0AKAuAnQAALbKkB7hLkCvMECfFKADALm1GaBPCNABgLo0G6DvFKADANQboO9qfgV6M+9AH7UToHsHOgCQXYuPcJ+wAh0AqE2zAboV6AAA1RnSCvTp6UYC9IZWoE9YgQ4AJGcFep0E6ADQGAE6AADjCtCnptoN0Nt5hPuonQDdCnQAoKUAfXsbAfrk3FhAgA4AVEOADgDAVhnUCvRmAvSGVqDPtY0AHQBoYwX69iYC9Akr0AGA2gjQAQDYKi0G6Hv27Gl8BXpDAfrcfiZABwCyavMd6BMCdACgLgJ0AADGFqA3/Qj3Rt6BPmooQLcCHQBIrsl3oE8K0AGAygjQAQAY2zvQrUCvxhBWoJf9TIAOAGTVYoA+aQU6AFAbAToAAFtlUO9Anxag1xegW4EOAOTWYoA+IUAHAGojQAcAYKu0uAJ95Ue4C9DHRYAOALSqxQB9UoAOANRGgA4AwPjegT7VcIDeyDvQGwrQvQMdAMiuxQB9Ym4sIEAHAKohQAcAYGwr0Kfyr0DfI0CvjgAdAGhViwH65NxTggToAEA1BOgAAGyVIb0DPf8j3EcCdACAmgP07W0E6BMe4Q4A1EaADgDAVmlxBXq7AfrUoiBdgA4AMH5WoNdJgA4AjRGgAwCw5QH6rvIOdAF69QH6qKUV6LP7mQAdAGghQN/eygr0Se9ABwAqI0AHAGBcAXoJadsM0L0DvbYAfdIKdAAguTZXoE8K0AGAugjQAQDYKt6BXq9BBOhzjwcVoAMAWbUYoE94BzoAUBsBOgAAW2VIAfp0MyvQvQMdAKAWAvQ6CdABoDHtBug7BegAAJUZUoDezgp0AToAQJXvQG8kQJ8UoI9HfMFKKaXqqpgQi5+MX7sBersr0Md9/CqllFIZizoI0Os1hEe4T8ztZy0E6LFPlXG1UkoppYYzH20Fep3SBegZBigAQ9ZKPx3bkXVbBOi5ZP3cADBurV13Zt2eIQXo09OtPMK9oQC9kRXomfsAABi37OdQAXqd0gXoJ06c6K7bu7e74YYblFJKVVL79u3rrr322u7uu+9q4qIlu1YD9J2NBujh5ptv7q6//vqxH8tKKaVUlorzZtagrDWDCtAbWYE+ailAb2AFetmXnn322X5cHePrcfexSimlVIbau3dvd/vBg4vOp/kD9NkQXYA+ftuyffmXX375KZPnSimlxlvlhPiud72r76tjUinTyXCpuOCKUPbxxx/vjh8/3mXTaoDe2gr0OEbixsAjR470F8XjPo6VUkqpLFVWZkSIXq4Vsl0HLBTXzo899lgfnrUQoE9NTjUboHuEe30Benm/ZtYAPfajOIbi57/+678uOnaUUkoptXItneeM82mG683hrECfXNROAvRNFBeSR48+2f37v//7/MV+DGCUUkqNv0aj0fyE0iOPPNI9dfSpLrMIzuPO/5js279/f7oQXYCexxNPHOluvvmm7vWvf/38xeW4j2ellFKq9irh0re+9a3umWeeSXsdECKMvfHGG/vrzlhBc/To0XTbM6QV6AL0CgP0ybwBetmHjh071j3wwAPd3//93/fbEuPrcfezSimlVO1Vrmfe8pa39PPR5Zo0ozYD9AkB+laIHf8b3/hG9+Uvf7n7xCc+ccqOpJRSarxVToRvfvObu0suuaT7u7/7u+6aa65JdUIs4jMfOHCgu+yyy/qnnlx11VX9RVgmAvS6lc/5X//1X93f/u3fdhdffHH3qle9auzHsVJKKZWtPvWpT3Vf+tKXuv/9v/9PmuuapR5++OHu0ksv7a688sr+56FDh7psXgrQd/XtMmkFejWG8Aj3rCvQFz62Pdrni1/8YvfhD3940bYppZRSauUqGeFP//RP93PR/+t//X/9a1AWnmdTBujb21yBvn///v7PM+UFVQfoZSePuzBXOkBiQKaUUmp8tXRwXyaX3v72t88/hjLTRUt81nvvvbcP0GMSM1aiP/VUrhX1AvS6lQvFn/3Zn110wV9q3Me0UkopVXOtNDcQ1z2ZrgeKJ598srviiiv6a8+omP/IvwK9hQB9z/LvQJ+ebiJAb2kF+kTSFehle+L9rQv3MXOeSiml1Jlr6Xmz/P073/nOVNcDhRXodUoRoD/44IPzg68Jd2EqpVS1FSf5c845p//rd7zjHakmlxaK91IfPny4O3jwYP8+ymyfX4Bet3Kh+PM///OLJjCVUkoptbaK64C4LohzadYAPT5vPO0oJpTuv//++QA3k1MC9Llrm5jDyRugt70CvakAfW51U9YAPVbKlce2W3mulFJKra/KfHS264GmA/RJ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28Vxu4jnRb8QERERqYMVvHDddddlE+377bffxCf9NU3TNE0b3mJMJ8bnY76IiIjIfGEQEb2PTbl96Yltta22ovIohOphv/fZGK7nMLpbVf3pk5EJ6IOI6W0E9OLf+Qs9jgLVZtfqbste5rhdd56LiIiItEUBXdM0TdNm0xTQRUREZL5Td+fevjbkqhlOj+1qWV5Nt2uvWnCRrz/JCOhdV5EM4gBdHKPsszonKgr0XR2uTuAv+7/L+ZuOHXfa+zp317S3KdO6BRhdra1wnq//IiIiIl2hvwHewl3TNE3TZvsW7jHmi4iIiMw36sTQUWuIiu3D264er3+Xzarj2sQ6lh3oeQZdTTIqp9C0QXaZV9XdfN0WERERGYbYp7j22mvDAQccMPFJf03TNE3ThjdiOrE9H+tFREREZG/aiqqjFNa1XSPR3rraJBirgJ7P5KAXqcwB8u+1dRAdafauS5eyL6szw9TJMid2ICwiIiJ9ccMNN4TTTjstHH744WHhwoXZ7V8XLFigaZqmadqUGzGb2E0MJ5YT00VERESkv93oCurTa5/3pLk1/T8TO9CL9CFatnWSolBaJqAWC7RMdK06Z9WxVUJtnaBb5eCppb1rOqqOaZv2sr/7cNKiwxb/FhERERk19Gl27twZduzYoWmapmlaYkYMJ5aLiIiISDllGkyZaDqsVqilJZp/XqHNjZqJC+hQJUpOi/UtwJr2NNNerKNl/4uIiIj0TewXiYiISPrEuQ4RERERGZxJ60Xa573rb9PGRAX0ohAZX6tES02bpJXV27L/RUREREZNH/2aSfetpjXdZb8xqd9Nwbw2XptpTbfXpttvWCajTbeIiIiIdKep/1o8TkvPIk3vT4Kp2IFeRdWFqXKY4sWddMFraVmxblXVOxERERERERERERERERk9bbSdquPbfF8bj/b2eUNZtSnbcTLVAnqR/MUqXriyz8ouctn/xffLzl38rO25qypKXdrrKldVesvS12fam6572bmrHKMp7XXHDZr2NmXalUk7r4iIiIiIiIiIiIiIiIjMYwG9jiahtE44bzpX3WqHptUQXYT+tuceVugvO39VeuvS3ibffaS963VpSntdOkRERERERERERERERGS6qdOoyo7RJmd5mj6fFpIX0Pu8sFUi63xP+7ivQ0ppFxERERERERERERERkcnRJN52eb/tuar+HvQcwwrUfaYF+hTPUxDMZ05AFxEREREREREREREREREpoy8xuKtIP+02rmuTIgroIiIiIiIiIiIiIiIiIiIiCugiIiIiIiIiIiIiIiIiIiJzKKCLiIiIiIiIiIiIiIiIiEiQEP4fT57nGX3Z5jsAAAAASUVORK5CYII=",
"media_type": "image/png"
}
}
]
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "704dbecd-ae8b-4014-913d-46264320db64",
"tool_use_result": {
"type": "image",
"file": {
"base64": "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C9a+fUfZt2+/uJfbbrtdG9icbAlnW3QkNMann34qv//+u1x4YWcV1K0nNzp0sWIJGS4qLjQuIjyhR44cJd9//738+uuv8uijj7n+WXr3wd/mmAly55136rF++OEHvREKFSrsCcmQvfO2ZaOuCC9w7733aV3s8ueff8ratWu1k1mB2HbGjJ01ULiFjKHOvWEfgl8LtGP37j3kxIkT8vPPP2s9Tp48qfz2229at2XLlqk1jW9IioxhJawlS8WKlWX/fnNtccPBakWvVSb18d58JvQCrtmxY8ecNkKdNmzYoDdIft0QhJCsE2xwQgLhHtx6PgMI6ZmF/yOEEEJItBPqPSCc7bNafqTPlxBCCCE5IWvzAO7//5Ge54gegs1VEUKIG/NsMJGPoQNCaJ48eYocPXpU/vjjD/nf//4ngZa//vpLfz906LAKueXLV/DR0QI/c8x6aJ7QHaFZ2gXfIdbbVDBuLQ0OxNBK69VrIG+99bZql0ePviPNm7dQjS+Qg7F1ZF6yZKmWDX3tvvvW6rb2nFHXIkWKqub63XffydSp09QYILQ3fbrqc61btzFGBI0aS5EixdQIoHfvPh76SufOF6k+izbB9qgLtM+cYfOgJ6nOCt34kkv66/+//EgBnacCOhodjQQB9JNPjmunuP322/UkX3ttu/597733OgI6LCEgKD/++BP6299//62f3bp11wuCi4vGQqdp27a9JCWZEATeTlVSjwerhA8//Eg7NJYXXnjR9U/TNCi+42LiBhk0aLBuawXuZcuWqwifEwHdhmOAVchzz23Vcnfv3q2dF+zatUvXvfTSy7qNvUFsKAb/G8y7Pt0nbAN+Q9vZDoltzM2THkRALya9evWWU6dOyZdffilPP/20bNq0SXnyySe1PsOGXalGBdZgwV2+O/S+DdtQoUJFeeONN/R80ImtZz06ta1fsIeHFfVHjx6j+3/99deydOkyfWA99dTTuu7gwYNqYZObofUJIbmPvc/dg5RID55ig8gP1AkhhBCSm5Pf5v87xkXuUHsg0OQ43pns+M6bUistRNkmJZfd3vweuGxCCCGExAv+cwiRnsuIHvznnyI9P0YIiXaM5gahF06dhw8fluws+/btk0GDhqjGGMy5FeshhM+bN1/32bt3n4rQ+PuTTz7RdYjujG2s5mb2MwL6Qw895DjkfvvttypiW63UfRxo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eaYA3SPcAQAAABgKAToAAAzbSSvQAQAAAGD5AH1qckqADgAAA3LyjCvQz+//XIAOAAAAQPOsQAcAgGE7KUAHAAAAgKUB+q654NwKdAAAGJKTZ3yEuwAdAAAAgMGuQBegAwDAkJw84wp070AHAAAAYKgB+pQAHQAAhuSkAB0AAAAAZnkHOgAADNtJ70AHAAAAgFkCdAAAGLaTZwjQz/cOdAAAAACGovUA/YUXXui3cWZmRimllFJKKTVzav3whz/sr53/5E/+ZIUA3SPcAQAAABjsO9DbCtABAIDVrUD/+Mc/bgX6OMQXe+LEifmGyC4Gj8ePH0+1w5xOuSO7BXGHebRN/GylbcqkRnZxvETbtDL5EsdM9GstaK2Pju1oqY+OttFH16mlPrq0jT663vNna310K1o6f7Y2xnH+rFecO1vqo2PFRtbzZ4sr0KNNyrH/H//xH9073/nO7n3ve1/37ne/WymllFJKKfXuxfV7v/d7fUj+c//9v/djgBKeT0xM9H/9gQ98YP46O4s0AXoM8u+///7uhhtu6G655Zbu6NGjXWbPPfdcd+DAge7666/v7r777tSTMrHDP/zww92+ffu6m266qTty5EiXWUwq3XHHHd11113X/8w+KfP444/37RLt88gjj6TqoJaK4ySOlzhu4vg5duxYl9lTTz3V3XzzzX2/Fv1b5snMmAw7fPhw3za33npr9/TTT3eZPfvss93+/fv77bnnnntSTfYt9cKLL3QPPvhgv5/F/vbEE090mcXk8sGDB/u2OXToUPrg+dFHH+375xtvvLF77LHHuszifBltEufPaKPy6Kas4liJdolj56GHHuoyi2A2+rI4bqJviz4uszjHxHggtifOPZmvbeLcf9999/XbEtsU1waZxbVZOX/GNVvm82eIMU70Aa2McW6//fb5MU7282eMceL8Ge0T59LsfXQ5f952220pz5/zAfqutlagx+eN9vjzP//zRdujlFJKKaWU2raqKivQ42bUkGkOZ1umibK9e/d2l112WV8RnmUbfC0UE0oxiIy66qqr+mAz80RZTF6UtomAJvMNAQ888EB3+eWX921zxRVX9H+feaIsJmOjXWJ7YjIz44RMEeFStElsS7TRvffem6rDXTpRFv1YaZvo3zJPmsdNTVdfffV8PxATtFnbJj73nXfeOd82sV2ZJ82feeaZfkK2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rDWDCtAbWYE+ailAb2AFetmXnn322X5cHePrcfexSimlVIbau3dvd/vBg4vOp/kD9NkQXYA+ftuyffmXX375KZPnSimlxlvlhPiud72r76tjUinTyXCpuOCKUPbxxx/vjh8/3mXTaoDe2gr0OEbixsAjR470F8XjPo6VUkqpLFVWZkSIXq4Vsl0HLBTXzo899lgfnrUQoE9NTjUboHuEe30Benm/ZtYAPfajOIbi57/+678uOnaUUkoptXItneeM82mG683hrECfXNROAvRNFBeSR48+2f37v//7/MV+DGCUUkqNv0aj0fyE0iOPPNI9dfSpLrMIzuPO/5js279/f7oQXYCexxNPHOluvvmm7vWvf/38xeW4j2ellFKq9irh0re+9a3umWeeSXsdECKMvfHGG/vrzlhBc/To0XTbM6QV6AL0CgP0ybwBetmHjh071j3wwAPd3//93/fbEuPrcfezSimlVO1Vrmfe8pa39PPR5Zo0ozYD9AkB+laIHf8b3/hG9+Uvf7n7xCc+ccqOpJRSarxVToRvfvObu0suuaT7u7/7u+6aa65JdUIs4jMfOHCgu+yyy/qnnlx11VX9RVgmAvS6lc/5X//1X93f/u3fdhdffHH3qle9auzHsVJKKZWtPvWpT3Vf+tKXuv/9v/9PmuuapR5++OHu0ksv7a688sr+56FDh7psXgrQd/XtMmkFejWG8Aj3rCvQFz62Pdrni1/8YvfhD3940bYppZRSauUqGeFP//RP93PR/+t//X/9a1AWnmdTBujb21yBvn///v7PM+UFVQfoZSePuzBXOkBiQKaUUmp8tXRwXyaX3v72t88/hjLTRUt81nvvvbcP0GMSM1aiP/VUrhX1AvS6lQvFn/3Zn110wV9q3Me0UkopVXOtNDcQ1z2ZrgeKJ598srviiiv6a8+omP/IvwK9hQB9z/LvQJ+ebiJAb2kF+kTSFehle+L9rQv3MXOeSiml1Jlr6Xmz/P073/nOVNcDhRXodUoRoD/44IPzg68Jd2EqpVS1FSf5c845p//rd7zjHakmlxaK91IfPny4O3jwYP8+ymyfX4Bet3Kh+PM///OLJjCVUkoptbaK64C4LohzadYAPT5vPO0oJpTuv//++QA3k1MC9Llrm5jDyRugt70CvakAfW51U9YAPVbKlce2W3mulFJKra/KfHS264GmA/RJ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28Vxu4jnRb8QERERqYMVvHDddddlE+377bffxCf9NU3TNE0b3mJMJ8bnY76IiIjIfGEQEb2PTbl96Yltta22ovIohOphv/fZGK7nMLpbVf3pk5EJ6IOI6W0E9OLf+Qs9jgLVZtfqbste5rhdd56LiIiItEUBXdM0TdNm0xTQRUREZL5Td+fevjbkqhlOj+1qWV5Nt2uvWnCRrz/JCOhdV5EM4gBdHKPsszonKgr0XR2uTuAv+7/L+ZuOHXfa+zp317S3KdO6BRhdra1wnq//IiIiIl2hvwHewl3TNE3TZvsW7jHmi4iIiMw36sTQUWuIiu3D264er3+Xzarj2sQ6lh3oeQZdTTIqp9C0QXaZV9XdfN0WERERGYbYp7j22mvDAQccMPFJf03TNE3ThjdiOrE9H+tFREREZG/aiqqjFNa1XSPR3rraJBirgJ7P5KAXqcwB8u+1dRAdafauS5eyL6szw9TJMid2ICwiIiJ9ccMNN4TTTjstHH744WHhwoXZ7V8XLFigaZqmadqUGzGb2E0MJ5YT00VERESkv93oCurTa5/3pLk1/T8TO9CL9CFatnWSolBaJqAWC7RMdK06Z9WxVUJtnaBb5eCppb1rOqqOaZv2sr/7cNKiwxb/FhERERk19Gl27twZduzYoWmapmlaYkYMJ5aLiIiISDllGkyZaDqsVqilJZp/XqHNjZqJC+hQJUpOi/UtwJr2NNNerKNl/4uIiIj0TewXiYiISPrEuQ4RERERGZxJ60Xa573rb9PGRAX0ohAZX6tES02bpJXV27L/RUREREZNH/2aSfetpjXdZb8xqd9Nwbw2XptpTbfXpttvWCajTbeIiIiIdKep/1o8TkvPIk3vT4Kp2IFeRdWFqXKY4sWddMFraVmxblXVOxERERERERERERERERk9bbSdquPbfF8bj/b2eUNZtSnbcTLVAnqR/MUqXriyz8ouctn/xffLzl38rO25qypKXdrrKldVesvS12fam6572bmrHKMp7XXHDZr2NmXalUk7r4iIiIiIiIiIiIiIiIjMYwG9jiahtE44bzpX3WqHptUQXYT+tuceVugvO39VeuvS3ibffaS963VpSntdOkRERERERERERERERGS6qdOoyo7RJmd5mj6fFpIX0Pu8sFUi63xP+7ivQ0ppFxERERERERERERERkcnRJN52eb/tuar+HvQcwwrUfaYF+hTPUxDMZ05AFxEREREREREREREREREpoy8xuKtIP+02rmuTIgroIiIiIiIiIiIiIiIiIiIiCugiIiIiIiIiIiIiIiIiIiJzKKCLiIiIiIiIiIiIiIiIiEiQEP4fT57nGX3Z5jsAAAAASUVORK5CYII=",
"type": "image/png",
"originalSize": 729821,
"dimensions": {
"originalWidth": 2732,
"originalHeight": 2048,
"displayWidth": 2000,
"displayHeight": 1499
}
}
}
}
[2026-02-07T22:21:10.546Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "text",
"text": "[Image: original 2732x2048, displayed at 2000x1499. Multiply coordinates by 1.37 to map to original image.]"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f1f1b472-cb47-4fcd-ae17-b82944cba367",
"isSynthetic": true
}
[2026-02-07T22:21:10.559Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01TB3aURAZFhQQkZi2FNnYrm",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "473e84fa-7f68-4229-bcba-47c2a8e1a0fc"
}
[2026-02-07T22:21:10.580Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01TB3aURAZFhQQkZi2FNnYrm",
"type": "tool_result",
"content": " 1→/**\n 2→ * Atomic Solutions - All-at-once TSP algorithms\n 3→ */\n 4→\n 5→export { sonarSolution } from './sonar.js';\n 6→export { mooreSolution } from './moore.js';\n 7→export { gosperSolution } from './gosper.js';\n 8→export { peanoSolution } from './peano.js';\n 9→export { sierpinskiSolution } from './sierpinski.js';\n 10→export { combSolution } from './comb.js';\n 11→export { sawSolution } from './saw.js';\n 12→export { kochSolution } from './koch.js';\n 13→export { spaceFillingTreeSolution } from './space-filling-tree.js';\n 14→export {\n 15→ bruteForceSolution,\n 16→ calculateOptimalityRatio,\n 17→ BRUTE_FORCE_MAX_POINTS,\n 18→} from './brute-force.js';\n 19→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "5c64e831-2ba6-4889-8ef1-8ac406208f69",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/atomic/solution/index.js",
"content": "/**\n * Atomic Solutions - All-at-once TSP algorithms\n */\n\nexport { sonarSolution } from './sonar.js';\nexport { mooreSolution } from './moore.js';\nexport { gosperSolution } from './gosper.js';\nexport { peanoSolution } from './peano.js';\nexport { sierpinskiSolution } from './sierpinski.js';\nexport { combSolution } from './comb.js';\nexport { sawSolution } from './saw.js';\nexport { kochSolution } from './koch.js';\nexport { spaceFillingTreeSolution } from './space-filling-tree.js';\nexport {\n bruteForceSolution,\n calculateOptimalityRatio,\n BRUTE_FORCE_MAX_POINTS,\n} from './brute-force.js';\n",
"numLines": 19,
"startLine": 1,
"totalLines": 19
}
}
}
[2026-02-07T22:21:11.071Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01F6uwpdvUU34cb15CQGPCGA",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "fe98801e-ec2c-45f9-a001-1f06ccbed311"
}
[2026-02-07T22:21:11.075Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01F6uwpdvUU34cb15CQGPCGA",
"type": "tool_result",
"content": " 1→/**\n 2→ * Progressive Solutions - Step-by-step TSP algorithms\n 3→ */\n 4→\n 5→export { sonarAlgorithmSteps, sonarSolution } from './sonar.js';\n 6→export {\n 7→ mooreAlgorithmSteps,\n 8→ mooreSolution,\n 9→ generateMooreCurve,\n 10→ mooreCurveToPoints,\n 11→} from './moore.js';\n 12→export { combAlgorithmSteps, combSolution } from './comb.js';\n 13→export { sawAlgorithmSteps, sawSolution } from './saw.js';\n 14→export {\n 15→ kochAlgorithmSteps,\n 16→ kochSolution,\n 17→ generateKochSnowflake,\n 18→ kochCurveToPoints,\n 19→ calculateKochOrder,\n 20→} from './koch.js';\n 21→export {\n 22→ spaceFillingTreeAlgorithmSteps,\n 23→ spaceFillingTreeSolution,\n 24→} from './space-filling-tree.js';\n 25→export {\n 26→ sierpinskiAlgorithmSteps,\n 27→ sierpinskiSolution,\n 28→ generateSierpinskiCurve,\n 29→ sierpinskiCurveToPoints,\n 30→} from './sierpinski.js';\n 31→export {\n 32→ peanoAlgorithmSteps,\n 33→ peanoSolution,\n 34→ generatePeanoCurve,\n 35→ peanoCurveToPoints,\n 36→} from './peano.js';\n 37→export {\n 38→ gosperAlgorithmSteps,\n 39→ gosperSolution,\n 40→ generateGosperCurve,\n 41→ gosperCurveToPoints,\n 42→ calculateGosperOrder,\n 43→} from './gosper.js';\n 44→export {\n 45→ bruteForceAlgorithmSteps,\n 46→ bruteForceSolution,\n 47→ calculateOptimalityRatio,\n 48→ BRUTE_FORCE_MAX_POINTS,\n 49→} from './brute-force.js';\n 50→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9b804fce-5cea-4e66-8127-a2a90677c31a",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/progressive/solution/index.js",
"content": "/**\n * Progressive Solutions - Step-by-step TSP algorithms\n */\n\nexport { sonarAlgorithmSteps, sonarSolution } from './sonar.js';\nexport {\n mooreAlgorithmSteps,\n mooreSolution,\n generateMooreCurve,\n mooreCurveToPoints,\n} from './moore.js';\nexport { combAlgorithmSteps, combSolution } from './comb.js';\nexport { sawAlgorithmSteps, sawSolution } from './saw.js';\nexport {\n kochAlgorithmSteps,\n kochSolution,\n generateKochSnowflake,\n kochCurveToPoints,\n calculateKochOrder,\n} from './koch.js';\nexport {\n spaceFillingTreeAlgorithmSteps,\n spaceFillingTreeSolution,\n} from './space-filling-tree.js';\nexport {\n sierpinskiAlgorithmSteps,\n sierpinskiSolution,\n generateSierpinskiCurve,\n sierpinskiCurveToPoints,\n} from './sierpinski.js';\nexport {\n peanoAlgorithmSteps,\n peanoSolution,\n generatePeanoCurve,\n peanoCurveToPoints,\n} from './peano.js';\nexport {\n gosperAlgorithmSteps,\n gosperSolution,\n generateGosperCurve,\n gosperCurveToPoints,\n calculateGosperOrder,\n} from './gosper.js';\nexport {\n bruteForceAlgorithmSteps,\n bruteForceSolution,\n calculateOptimalityRatio,\n BRUTE_FORCE_MAX_POINTS,\n} from './brute-force.js';\n",
"numLines": 50,
"startLine": 1,
"totalLines": 50
}
}
}
[2026-02-07T22:21:11.885Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01Fba5dXueMAFLPUz7AtTVEq",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "de291da7-492a-4db5-851b-1a2be05408c1"
}
[2026-02-07T22:21:11.964Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01Fba5dXueMAFLPUz7AtTVEq",
"type": "tool_result",
"content": " 1→/**\n 2→ * TSP Algorithms Library\n 3→ *\n 4→ * This module provides two types of TSP algorithms:\n 5→ *\n 6→ * 1. Progressive (step-by-step) - Returns arrays of steps for visualization/animation\n 7→ * 2. Atomic (all-at-once) - Returns final result directly\n 8→ *\n 9→ * Each type includes:\n 10→ * - Solutions: Initial tour construction algorithms (Sonar, Moore, Gosper, Peano, Sierpiński, Comb, SAW, Koch, Space-Filling Tree, Brute-Force)\n 11→ * - Optimizations: Generic tour improvement algorithms (2-opt, 3-opt, k-opt, LK, LKH, Zigzag)\n 12→ *\n 13→ * Additionally, verification algorithms prove tour optimality:\n 14→ * - Lower bound (1-tree): Mathematical proof when upper bound = lower bound\n 15→ *\n 16→ * Available solution algorithms:\n 17→ * - Sonar (Radial Sweep): Sorts points by polar angle from centroid\n 18→ * - Moore Curve: Orders points along a Moore space-filling curve (2^n grid)\n 19→ * - Gosper Curve: Orders points along a hexagonal space-filling curve (60° turns)\n 20→ * - Peano Curve: Orders points along a Peano space-filling curve (3^n grid)\n 21→ * - Sierpiński Curve: Orders points along a Sierpiński space-filling curve\n 22→ * - Comb (Serpentine Scan): Visits points row by row in alternating directions\n 23→ * - Self-Avoiding Walk (SAW): Nearest-neighbor walk that never revisits a point\n 24→ * - Koch Snowflake: Orders points along a Koch snowflake fractal curve\n 25→ * - Space-Filling Tree: Orders points via DFS traversal of a recursive quadtree\n 26→ * - Brute-Force: Exhaustive search for the true optimal tour (small instances)\n 27→ *\n 28→ * Available optimizations (generic, work with any tour):\n 29→ * - 2-opt: Standard segment reversal optimization\n 30→ * - 3-opt: Three-edge exchange optimization\n 31→ * - k-opt: Generalized k-edge exchange (combines 2-opt and 3-opt)\n 32→ * - Lin-Kernighan: Variable-depth edge exchange heuristic\n 33→ * - Lin-Kernighan-Helsgaun: LK with perturbation for escaping local optima\n 34→ * - Zigzag: Adjacent pair swapping optimization\n 35→ * - Combined: Alternates zigzag and 2-opt until no improvement\n 36→ *\n 37→ * @example\n 38→ * // Progressive (for visualization)\n 39→ * import { sonarAlgorithmSteps, sawAlgorithmSteps, kochAlgorithmSteps, twoOptSteps, bruteForceAlgorithmSteps } from './algorithms';\n 40→ * const solutionSteps = sonarAlgorithmSteps(points);\n 41→ * const kochSteps = kochAlgorithmSteps(points, mooreGridSize);\n 42→ * const optSteps = twoOptSteps(points, tour);\n 43→ * const bruteSteps = bruteForceAlgorithmSteps(points);\n 44→ *\n 45→ * @example\n 46→ * // Atomic (for direct computation)\n 47→ * import { sonarSolution, sawSolution, bruteForceSolution } from './algorithms/atomic';\n 48→ * import { twoOpt } from './algorithms/atomic';\n 49→ * const { tour } = sonarSolution(points);\n 50→ * const optimal = bruteForceSolution(points);\n 51→ *\n 52→ * @example\n 53→ * // Verification (prove optimality)\n 54→ * import { verifyOptimality } from './algorithms/verification';\n 55→ * const result = verifyOptimality(tourDistance, points);\n 56→ * if (result.isOptimal) console.log('Tour is proven optimal!');\n 57→ */\n 58→\n 59→// Utility functions\n 60→export * from './utils.js';\n 61→\n 62→// Progressive algorithms (step-by-step)\n 63→export * as progressive from './progressive/index.js';\n 64→\n 65→// Atomic algorithms (all-at-once)\n 66→export * as atomic from './atomic/index.js';\n 67→\n 68→// Verification algorithms (optimality proofs)\n 69→export * as verification from './verification/index.js';\n 70→\n 71→// Export progressive functions at top level for convenience\n 72→export {\n 73→ // Solutions\n 74→ sonarAlgorithmSteps,\n 75→ mooreAlgorithmSteps,\n 76→ generateMooreCurve,\n 77→ mooreCurveToPoints,\n 78→ gosperAlgorithmSteps,\n 79→ generateGosperCurve,\n 80→ gosperCurveToPoints,\n 81→ calculateGosperOrder,\n 82→ peanoAlgorithmSteps,\n 83→ generatePeanoCurve,\n 84→ peanoCurveToPoints,\n 85→ sierpinskiAlgorithmSteps,\n 86→ generateSierpinskiCurve,\n 87→ sierpinskiCurveToPoints,\n 88→ combAlgorithmSteps,\n 89→ sawAlgorithmSteps,\n 90→ sawSolution,\n 91→ kochAlgorithmSteps,\n 92→ generateKochSnowflake,\n 93→ kochCurveToPoints,\n 94→ calculateKochOrder,\n 95→ spaceFillingTreeAlgorithmSteps,\n 96→ bruteForceAlgorithmSteps,\n 97→ bruteForceSolution,\n 98→ calculateOptimalityRatio,\n 99→ BRUTE_FORCE_MAX_POINTS,\n 100→ // Generic optimizations\n 101→ twoOptSteps,\n 102→ threeOptSteps,\n 103→ kOptSteps,\n 104→ zigzagOptSteps,\n 105→ combinedOptSteps,\n 106→ linKernighanSteps,\n 107→ lkHelsgaunSteps,\n 108→ // Legacy aliases for backward compatibility\n 109→ sonarOptimizationSteps,\n 110→ mooreOptimizationSteps,\n 111→} from './progressive/index.js';\n 112→\n 113→// Export verification functions at top level for convenience\n 114→export {\n 115→ oneTreeLowerBound,\n 116→ verifyOptimality,\n 117→ // Backward-compatible aliases\n 118→ bruteForceOptimalTour,\n 119→ bruteForceSteps,\n 120→} from './verification/index.js';\n 121→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c78a4634-5419-4ebd-96d8-8933d8b8da4c",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/index.js",
"content": "/**\n * TSP Algorithms Library\n *\n * This module provides two types of TSP algorithms:\n *\n * 1. Progressive (step-by-step) - Returns arrays of steps for visualization/animation\n * 2. Atomic (all-at-once) - Returns final result directly\n *\n * Each type includes:\n * - Solutions: Initial tour construction algorithms (Sonar, Moore, Gosper, Peano, Sierpiński, Comb, SAW, Koch, Space-Filling Tree, Brute-Force)\n * - Optimizations: Generic tour improvement algorithms (2-opt, 3-opt, k-opt, LK, LKH, Zigzag)\n *\n * Additionally, verification algorithms prove tour optimality:\n * - Lower bound (1-tree): Mathematical proof when upper bound = lower bound\n *\n * Available solution algorithms:\n * - Sonar (Radial Sweep): Sorts points by polar angle from centroid\n * - Moore Curve: Orders points along a Moore space-filling curve (2^n grid)\n * - Gosper Curve: Orders points along a hexagonal space-filling curve (60° turns)\n * - Peano Curve: Orders points along a Peano space-filling curve (3^n grid)\n * - Sierpiński Curve: Orders points along a Sierpiński space-filling curve\n * - Comb (Serpentine Scan): Visits points row by row in alternating directions\n * - Self-Avoiding Walk (SAW): Nearest-neighbor walk that never revisits a point\n * - Koch Snowflake: Orders points along a Koch snowflake fractal curve\n * - Space-Filling Tree: Orders points via DFS traversal of a recursive quadtree\n * - Brute-Force: Exhaustive search for the true optimal tour (small instances)\n *\n * Available optimizations (generic, work with any tour):\n * - 2-opt: Standard segment reversal optimization\n * - 3-opt: Three-edge exchange optimization\n * - k-opt: Generalized k-edge exchange (combines 2-opt and 3-opt)\n * - Lin-Kernighan: Variable-depth edge exchange heuristic\n * - Lin-Kernighan-Helsgaun: LK with perturbation for escaping local optima\n * - Zigzag: Adjacent pair swapping optimization\n * - Combined: Alternates zigzag and 2-opt until no improvement\n *\n * @example\n * // Progressive (for visualization)\n * import { sonarAlgorithmSteps, sawAlgorithmSteps, kochAlgorithmSteps, twoOptSteps, bruteForceAlgorithmSteps } from './algorithms';\n * const solutionSteps = sonarAlgorithmSteps(points);\n * const kochSteps = kochAlgorithmSteps(points, mooreGridSize);\n * const optSteps = twoOptSteps(points, tour);\n * const bruteSteps = bruteForceAlgorithmSteps(points);\n *\n * @example\n * // Atomic (for direct computation)\n * import { sonarSolution, sawSolution, bruteForceSolution } from './algorithms/atomic';\n * import { twoOpt } from './algorithms/atomic';\n * const { tour } = sonarSolution(points);\n * const optimal = bruteForceSolution(points);\n *\n * @example\n * // Verification (prove optimality)\n * import { verifyOptimality } from './algorithms/verification';\n * const result = verifyOptimality(tourDistance, points);\n * if (result.isOptimal) console.log('Tour is proven optimal!');\n */\n\n// Utility functions\nexport * from './utils.js';\n\n// Progressive algorithms (step-by-step)\nexport * as progressive from './progressive/index.js';\n\n// Atomic algorithms (all-at-once)\nexport * as atomic from './atomic/index.js';\n\n// Verification algorithms (optimality proofs)\nexport * as verification from './verification/index.js';\n\n// Export progressive functions at top level for convenience\nexport {\n // Solutions\n sonarAlgorithmSteps,\n mooreAlgorithmSteps,\n generateMooreCurve,\n mooreCurveToPoints,\n gosperAlgorithmSteps,\n generateGosperCurve,\n gosperCurveToPoints,\n calculateGosperOrder,\n peanoAlgorithmSteps,\n generatePeanoCurve,\n peanoCurveToPoints,\n sierpinskiAlgorithmSteps,\n generateSierpinskiCurve,\n sierpinskiCurveToPoints,\n combAlgorithmSteps,\n sawAlgorithmSteps,\n sawSolution,\n kochAlgorithmSteps,\n generateKochSnowflake,\n kochCurveToPoints,\n calculateKochOrder,\n spaceFillingTreeAlgorithmSteps,\n bruteForceAlgorithmSteps,\n bruteForceSolution,\n calculateOptimalityRatio,\n BRUTE_FORCE_MAX_POINTS,\n // Generic optimizations\n twoOptSteps,\n threeOptSteps,\n kOptSteps,\n zigzagOptSteps,\n combinedOptSteps,\n linKernighanSteps,\n lkHelsgaunSteps,\n // Legacy aliases for backward compatibility\n sonarOptimizationSteps,\n mooreOptimizationSteps,\n} from './progressive/index.js';\n\n// Export verification functions at top level for convenience\nexport {\n oneTreeLowerBound,\n verifyOptimality,\n // Backward-compatible aliases\n bruteForceOptimalTour,\n bruteForceSteps,\n} from './verification/index.js';\n",
"numLines": 121,
"startLine": 1,
"totalLines": 121
}
}
}
[2026-02-07T22:21:12.335Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01UuVdX826FYE4ct8DQ7MZW8",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01GFbfuW2gBA1BDcxgBnVNup",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/utils.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 4071,
"cache_read_input_tokens": 34683,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 4071
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "28bd8d4e-8c50-4048-aa39-947243a0ad00"
}
[2026-02-07T22:21:12.385Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01GFbfuW2gBA1BDcxgBnVNup",
"type": "tool_result",
"content": " 1→/**\n 2→ * Utility functions for TSP algorithms\n 3→ */\n 4→\n 5→/**\n 6→ * Valid grid sizes for Moore curve algorithm.\n 7→ * A Moore curve of order n fills a 2^n x 2^n grid.\n 8→ * These correspond to L-system iteration counts 0..7 (effective orders 1..8).\n 9→ */\n 10→export const VALID_GRID_SIZES = [2, 4, 8, 16, 32, 64, 128];\n 11→\n 12→/**\n 13→ * Valid grid sizes for Peano curve algorithm.\n 14→ * A Peano curve of order n fills a 3^n x 3^n grid.\n 15→ * These correspond to L-system iteration counts 1..4 (orders 1..4).\n 16→ */\n 17→export const VALID_PEANO_GRID_SIZES = [3, 9, 27, 81];\n 18→\n 19→/**\n 20→ * Calculate the Moore grid size based on user-specified grid size\n 21→ * Moore curve fills a grid of size 2^n x 2^n.\n 22→ * Returns the smallest valid Moore grid size >= gridSize.\n 23→ * @param {number} gridSize - User-specified grid size\n 24→ * @returns {number} Moore grid size (power of 2)\n 25→ */\n 26→export const calculateMooreGridSize = (gridSize) => {\n 27→ // Find smallest valid grid size >= gridSize\n 28→ for (const size of VALID_GRID_SIZES) {\n 29→ if (size >= gridSize) {\n 30→ return size;\n 31→ }\n 32→ }\n 33→ return VALID_GRID_SIZES[VALID_GRID_SIZES.length - 1];\n 34→};\n 35→\n 36→/**\n 37→ * Calculate the Peano grid size based on user-specified grid size\n 38→ * Peano curve fills a grid of size 3^n x 3^n.\n 39→ * Returns the smallest valid Peano grid size >= gridSize.\n 40→ * @param {number} gridSize - User-specified grid size\n 41→ * @returns {number} Peano grid size (power of 3)\n 42→ */\n 43→export const calculatePeanoGridSize = (gridSize) => {\n 44→ // Find smallest valid Peano grid size >= gridSize\n 45→ for (const size of VALID_PEANO_GRID_SIZES) {\n 46→ if (size >= gridSize) {\n 47→ return size;\n 48→ }\n 49→ }\n 50→ return VALID_PEANO_GRID_SIZES[VALID_PEANO_GRID_SIZES.length - 1];\n 51→};\n 52→\n 53→/**\n 54→ * Generate random points on the Moore grid\n 55→ * @param {number} mooreGridSize - Size of the Moore grid\n 56→ * @param {number} numPoints - Number of points to generate\n 57→ * @returns {Array<{x: number, y: number, id: number}>} Array of point objects\n 58→ */\n 59→export const generateRandomPoints = (mooreGridSize, numPoints) => {\n 60→ const points = [];\n 61→ const usedPositions = new Set();\n 62→ // Points are placed at grid intersections (0 to mooreGridSize-1 inclusive)\n 63→ const maxPoints = Math.min(numPoints, mooreGridSize * mooreGridSize);\n 64→\n 65→ while (points.length < maxPoints) {\n 66→ // Generate integer coordinates aligned to Moore grid vertices [0, mooreGridSize-1]\n 67→ const x = Math.floor(Math.random() * mooreGridSize);\n 68→ const y = Math.floor(Math.random() * mooreGridSize);\n 69→ const key = `${x},${y}`;\n 70→\n 71→ if (!usedPositions.has(key)) {\n 72→ usedPositions.add(key);\n 73→ points.push({ x, y, id: points.length });\n 74→ }\n 75→ }\n 76→ return points;\n 77→};\n 78→\n 79→/**\n 80→ * Calculate Euclidean distance between two points\n 81→ * @param {{x: number, y: number}} p1 - First point\n 82→ * @param {{x: number, y: number}} p2 - Second point\n 83→ * @returns {number} Euclidean distance\n 84→ */\n 85→export const distance = (p1, p2) => Math.hypot(p2.x - p1.x, p2.y - p1.y);\n 86→\n 87→/**\n 88→ * Calculate total tour distance (closed loop)\n 89→ * @param {number[]} tour - Array of point indices forming the tour\n 90→ * @param {Array<{x: number, y: number}>} points - Array of point coordinates\n 91→ * @returns {number} Total distance of the tour\n 92→ */\n 93→export const calculateTotalDistance = (tour, points) => {\n 94→ if (tour.length < 2) {\n 95→ return 0;\n 96→ }\n 97→ let total = 0;\n 98→ for (let i = 0; i < tour.length - 1; i++) {\n 99→ total += distance(points[tour[i]], points[tour[i + 1]]);\n 100→ }\n 101→ // Close the loop\n 102→ total += distance(points[tour[tour.length - 1]], points[tour[0]]);\n 103→ return total;\n 104→};\n 105→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "8a0458a4-f69c-4f66-909e-bd9718e62b99",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/lib/algorithms/utils.js",
"content": "/**\n * Utility functions for TSP algorithms\n */\n\n/**\n * Valid grid sizes for Moore curve algorithm.\n * A Moore curve of order n fills a 2^n x 2^n grid.\n * These correspond to L-system iteration counts 0..7 (effective orders 1..8).\n */\nexport const VALID_GRID_SIZES = [2, 4, 8, 16, 32, 64, 128];\n\n/**\n * Valid grid sizes for Peano curve algorithm.\n * A Peano curve of order n fills a 3^n x 3^n grid.\n * These correspond to L-system iteration counts 1..4 (orders 1..4).\n */\nexport const VALID_PEANO_GRID_SIZES = [3, 9, 27, 81];\n\n/**\n * Calculate the Moore grid size based on user-specified grid size\n * Moore curve fills a grid of size 2^n x 2^n.\n * Returns the smallest valid Moore grid size >= gridSize.\n * @param {number} gridSize - User-specified grid size\n * @returns {number} Moore grid size (power of 2)\n */\nexport const calculateMooreGridSize = (gridSize) => {\n // Find smallest valid grid size >= gridSize\n for (const size of VALID_GRID_SIZES) {\n if (size >= gridSize) {\n return size;\n }\n }\n return VALID_GRID_SIZES[VALID_GRID_SIZES.length - 1];\n};\n\n/**\n * Calculate the Peano grid size based on user-specified grid size\n * Peano curve fills a grid of size 3^n x 3^n.\n * Returns the smallest valid Peano grid size >= gridSize.\n * @param {number} gridSize - User-specified grid size\n * @returns {number} Peano grid size (power of 3)\n */\nexport const calculatePeanoGridSize = (gridSize) => {\n // Find smallest valid Peano grid size >= gridSize\n for (const size of VALID_PEANO_GRID_SIZES) {\n if (size >= gridSize) {\n return size;\n }\n }\n return VALID_PEANO_GRID_SIZES[VALID_PEANO_GRID_SIZES.length - 1];\n};\n\n/**\n * Generate random points on the Moore grid\n * @param {number} mooreGridSize - Size of the Moore grid\n * @param {number} numPoints - Number of points to generate\n * @returns {Array<{x: number, y: number, id: number}>} Array of point objects\n */\nexport const generateRandomPoints = (mooreGridSize, numPoints) => {\n const points = [];\n const usedPositions = new Set();\n // Points are placed at grid intersections (0 to mooreGridSize-1 inclusive)\n const maxPoints = Math.min(numPoints, mooreGridSize * mooreGridSize);\n\n while (points.length < maxPoints) {\n // Generate integer coordinates aligned to Moore grid vertices [0, mooreGridSize-1]\n const x = Math.floor(Math.random() * mooreGridSize);\n const y = Math.floor(Math.random() * mooreGridSize);\n const key = `${x},${y}`;\n\n if (!usedPositions.has(key)) {\n usedPositions.add(key);\n points.push({ x, y, id: points.length });\n }\n }\n return points;\n};\n\n/**\n * Calculate Euclidean distance between two points\n * @param {{x: number, y: number}} p1 - First point\n * @param {{x: number, y: number}} p2 - Second point\n * @returns {number} Euclidean distance\n */\nexport const distance = (p1, p2) => Math.hypot(p2.x - p1.x, p2.y - p1.y);\n\n/**\n * Calculate total tour distance (closed loop)\n * @param {number[]} tour - Array of point indices forming the tour\n * @param {Array<{x: number, y: number}>} points - Array of point coordinates\n * @returns {number} Total distance of the tour\n */\nexport const calculateTotalDistance = (tour, points) => {\n if (tour.length < 2) {\n return 0;\n }\n let total = 0;\n for (let i = 0; i < tour.length - 1; i++) {\n total += distance(points[tour[i]], points[tour[i + 1]]);\n }\n // Close the loop\n total += distance(points[tour[tour.length - 1]], points[tour[0]]);\n return total;\n};\n",
"numLines": 105,
"startLine": 1,
"totalLines": 105
}
}
}
[2026-02-07T22:21:16.121Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01PJMHzp2XnCwxaW9tadurjS",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "\n\nNow I can see the pattern clearly. The image shows three rectangular \"double spiral\" patterns at different scales - they are rectangular spirals that spiral inward from the outside to the center, creating a space-filling pattern. Each one shows increasing detail/resolution. Let me now read the remaining key files needed for implementation."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 3,
"cache_creation_input_tokens": 6579,
"cache_read_input_tokens": 38754,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 6579
},
"output_tokens": 2,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "2afb14f6-6006-487a-90b1-ef9aa509b547"
}
[2026-02-07T22:21:23.723Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01PJMHzp2XnCwxaW9tadurjS",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01AGtSGrJG9oa84j856kWY7z",
"name": "TodoWrite",
"input": {
"todos": [
{
"content": "Analyze reference image and understand double spiral pattern",
"status": "completed",
"activeForm": "Analyzing reference image"
},
{
"content": "Study Moore Curve implementation as reference pattern",
"status": "completed",
"activeForm": "Studying Moore Curve implementation"
},
{
"content": "Create atomic double spiral algorithm (src/lib/algorithms/atomic/solution/spiral.js)",
"status": "pending",
"activeForm": "Creating atomic double spiral algorithm"
},
{
"content": "Create progressive double spiral algorithm (src/lib/algorithms/progressive/solution/spiral.js)",
"status": "pending",
"activeForm": "Creating progressive double spiral algorithm"
},
{
"content": "Register algorithm in export barrel files (atomic/solution/index.js, progressive/solution/index.js, algorithms/index.js)",
"status": "pending",
"activeForm": "Registering algorithm in export files"
},
{
"content": "Register algorithm in UI components (Controls.jsx, TSPVisualization.jsx, Legend.jsx, VisualizationPanel.jsx, i18n.js)",
"status": "pending",
"activeForm": "Registering algorithm in UI"
},
{
"content": "Register algorithm in CLI (cli/index.js)",
"status": "pending",
"activeForm": "Registering algorithm in CLI"
},
{
"content": "Create test file (src/tests/spiral-algorithm.test.js)",
"status": "pending",
"activeForm": "Creating spiral algorithm tests"
},
{
"content": "Run all tests and fix any failures",
"status": "pending",
"activeForm": "Running tests and fixing failures"
},
{
"content": "Run lint/format checks",
"status": "pending",
"activeForm": "Running lint/format checks"
},
{
"content": "Commit, push, and update PR",
"status": "pending",
"activeForm": "Committing and updating PR"
}
]
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 3,
"cache_creation_input_tokens": 6579,
"cache_read_input_tokens": 38754,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 6579
},
"output_tokens": 2,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "88b9e90e-c3ee-4835-8ebc-c53f4fd3eb1b"
}
[2026-02-07T22:21:23.736Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01AGtSGrJG9oa84j856kWY7z",
"type": "tool_result",
"content": "Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "17aecfe8-a020-460f-9a54-5fcbcc9d8634",
"tool_use_result": {
"oldTodos": [],
"newTodos": [
{
"content": "Analyze reference image and understand double spiral pattern",
"status": "completed",
"activeForm": "Analyzing reference image"
},
{
"content": "Study Moore Curve implementation as reference pattern",
"status": "completed",
"activeForm": "Studying Moore Curve implementation"
},
{
"content": "Create atomic double spiral algorithm (src/lib/algorithms/atomic/solution/spiral.js)",
"status": "pending",
"activeForm": "Creating atomic double spiral algorithm"
},
{
"content": "Create progressive double spiral algorithm (src/lib/algorithms/progressive/solution/spiral.js)",
"status": "pending",
"activeForm": "Creating progressive double spiral algorithm"
},
{
"content": "Register algorithm in export barrel files (atomic/solution/index.js, progressive/solution/index.js, algorithms/index.js)",
"status": "pending",
"activeForm": "Registering algorithm in export files"
},
{
"content": "Register algorithm in UI components (Controls.jsx, TSPVisualization.jsx, Legend.jsx, VisualizationPanel.jsx, i18n.js)",
"status": "pending",
"activeForm": "Registering algorithm in UI"
},
{
"content": "Register algorithm in CLI (cli/index.js)",
"status": "pending",
"activeForm": "Registering algorithm in CLI"
},
{
"content": "Create test file (src/tests/spiral-algorithm.test.js)",
"status": "pending",
"activeForm": "Creating spiral algorithm tests"
},
{
"content": "Run all tests and fix any failures",
"status": "pending",
"activeForm": "Running tests and fixing failures"
},
{
"content": "Run lint/format checks",
"status": "pending",
"activeForm": "Running lint/format checks"
},
{
"content": "Commit, push, and update PR",
"status": "pending",
"activeForm": "Committing and updating PR"
}
]
}
}
[2026-02-07T22:21:25.540Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01RZsgJ419DEWLaqsivjj9Cb",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Let me read the remaining files I need to understand how the UI handles algorithms."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 585,
"cache_read_input_tokens": 45333,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 585
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9a8fc3bf-0f14-431e-bed3-10d2d273b608"
}
[2026-02-07T22:21:26.605Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01RZsgJ419DEWLaqsivjj9Cb",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_013zay49HNNUMm8LmRMJFfYb",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Controls.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 585,
"cache_read_input_tokens": 45333,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 585
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f8b5cab5-c182-4f7f-8978-b8bd3ccec59d"
}
[2026-02-07T22:21:26.610Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_013zay49HNNUMm8LmRMJFfYb",
"type": "tool_result",
"content": " 1→/**\n 2→ * Controls Component\n 3→ *\n 4→ * Control panel for TSP solver including:\n 5→ * - Algorithm selection dropdowns (left and right panels)\n 6→ * - Grid size selector (valid Moore curve sizes)\n 7→ * - Points count input\n 8→ * - Animation speed slider\n 9→ * - Action buttons (New Points, Start, Stop, 2-opt Optimize, Zigzag Optimize)\n 10→ */\n 11→\n 12→import { VALID_GRID_SIZES } from '../../../lib/algorithms/utils.js';\n 13→import { t } from '../i18n.js';\n 14→\n 15→/**\n 16→ * Available algorithms for selection.\n 17→ * Each entry maps an id to a display label.\n 18→ */\n 19→export const ALGORITHM_OPTIONS = [\n 20→ { id: 'sonar', label: 'Sonar Visit' },\n 21→ { id: 'moore', label: 'Moore Curve' },\n 22→ { id: 'gosper', label: 'Gosper Curve' },\n 23→ { id: 'peano', label: 'Peano Curve' },\n 24→ { id: 'sierpinski', label: 'Sierpiński Curve' },\n 25→ { id: 'comb', label: 'Comb Scan' },\n 26→ { id: 'saw', label: 'Self-Avoiding Walk' },\n 27→ { id: 'koch', label: 'Koch Snowflake' },\n 28→ { id: 'space-filling-tree', label: 'Space-Filling Tree' },\n 29→ { id: 'brute-force', label: 'Brute-Force' },\n 30→];\n 31→\n 32→/**\n 33→ * Controls - Control panel for TSP solver\n 34→ *\n 35→ * @param {Object} props\n 36→ * @param {number} props.gridSize - Current grid size (must be a valid Moore curve size)\n 37→ * @param {function} props.setGridSize - Grid size setter\n 38→ * @param {number} props.numPoints - Number of points\n 39→ * @param {function} props.setNumPoints - Points count setter\n 40→ * @param {number} props.speed - Animation speed in ms\n 41→ * @param {function} props.setSpeed - Speed setter\n 42→ * @param {number} props.mooreGridSize - Actual Moore grid size\n 43→ * @param {boolean} props.isRunning - Whether animation is running\n 44→ * @param {boolean} props.canOptimize - Whether optimization can start\n 45→ * @param {string|null} props.activeOptimization - Currently active optimization method\n 46→ * @param {function} props.onGeneratePoints - Generate new points handler\n 47→ * @param {function} props.onStart - Start algorithm handler\n 48→ * @param {function} props.onStop - Stop animation handler\n 49→ * @param {function} props.onOptimize - Start optimization handler (receives method name)\n 50→ * @param {number} props.pointsCount - Current points count (for Start button state)\n 51→ * @param {boolean} props.startDisabled - Whether Start button should be disabled\n 52→ * @param {string} props.startDisabledReason - Tooltip explaining why Start is disabled\n 53→ * @param {string} props.lang - Current language code\n 54→ */\n 55→const Controls = ({\n 56→ gridSize,\n 57→ setGridSize,\n 58→ numPoints,\n 59→ setNumPoints,\n 60→ speed,\n 61→ setSpeed,\n 62→ mooreGridSize,\n 63→ isRunning,\n 64→ canOptimize,\n 65→ activeOptimization,\n 66→ onGeneratePoints,\n 67→ onStart,\n 68→ onStop,\n 69→ onOptimize,\n 70→ pointsCount,\n 71→ startDisabled,\n 72→ startDisabledReason,\n 73→ lang = 'en',\n 74→}) => {\n 75→ const maxPoints = mooreGridSize * mooreGridSize;\n 76→ return (\n 77→ <div className=\"controls\">\n 78→ <div className=\"control-group\">\n 79→ <label>{t(lang, 'gridSize')}</label>\n 80→ <select\n 81→ value={gridSize}\n 82→ onChange={(e) => setGridSize(parseInt(e.target.value))}\n 83→ disabled={isRunning}\n 84→ >\n 85→ {VALID_GRID_SIZES.map((size) => (\n 86→ <option key={size} value={size}>\n 87→ {size}×{size}\n 88→ </option>\n 89→ ))}\n 90→ </select>\n 91→ </div>\n 92→\n 93→ <div className=\"control-group\">\n 94→ <label>\n 95→ {t(lang, 'points')} ({t(lang, 'max')} {maxPoints})\n 96→ </label>\n 97→ <input\n 98→ type=\"number\"\n 99→ min=\"1\"\n 100→ max={maxPoints}\n 101→ value={numPoints}\n 102→ onChange={(e) => {\n 103→ const val = parseInt(e.target.value);\n 104→ if (isNaN(val) || val < 1) {\n 105→ setNumPoints(e.target.value === '' ? '' : 1);\n 106→ return;\n 107→ }\n 108→ setNumPoints(Math.min(val, maxPoints));\n 109→ }}\n 110→ onBlur={() => {\n 111→ const val =\n 112→ typeof numPoints === 'number' ? numPoints : parseInt(numPoints);\n 113→ if (isNaN(val) || val < 3) {\n 114→ setNumPoints(3);\n 115→ } else if (val > maxPoints) {\n 116→ setNumPoints(maxPoints);\n 117→ }\n 118→ }}\n 119→ disabled={isRunning}\n 120→ />\n 121→ </div>\n 122→\n 123→ <div className=\"control-group\">\n 124→ <label>{t(lang, 'animationSpeed')}</label>\n 125→ <div className=\"speed-control\">\n 126→ <span>{t(lang, 'fast')}</span>\n 127→ <input\n 128→ type=\"range\"\n 129→ min=\"50\"\n 130→ max=\"1000\"\n 131→ value={speed}\n 132→ onChange={(e) => setSpeed(parseInt(e.target.value))}\n 133→ />\n 134→ <span>{t(lang, 'slow')}</span>\n 135→ </div>\n 136→ </div>\n 137→\n 138→ <div className=\"buttons\">\n 139→ <button\n 140→ className=\"btn-outline\"\n 141→ onClick={onGeneratePoints}\n 142→ disabled={isRunning}\n 143→ >\n 144→ {t(lang, 'newPoints')}\n 145→ </button>\n 146→\n 147→ {!isRunning ? (\n 148→ <>\n 149→ <span\n 150→ className={startDisabled ? 'tooltip-wrapper' : ''}\n 151→ data-tooltip={startDisabledReason || undefined}\n 152→ >\n 153→ <button\n 154→ className=\"btn-primary\"\n 155→ onClick={onStart}\n 156→ disabled={pointsCount === 0 || startDisabled}\n 157→ title={startDisabledReason || ''}\n 158→ >\n 159→ {t(lang, 'start')}\n 160→ </button>\n 161→ </span>\n 162→\n 163→ {canOptimize && (\n 164→ <>\n 165→ <button\n 166→ className={`btn-secondary${activeOptimization === '2-opt' ? ' btn-active' : ''}`}\n 167→ onClick={() => onOptimize('2-opt')}\n 168→ >\n 169→ 2-opt\n 170→ </button>\n 171→ <button\n 172→ className={`btn-secondary${activeOptimization === '3-opt' ? ' btn-active' : ''}`}\n 173→ onClick={() => onOptimize('3-opt')}\n 174→ >\n 175→ 3-opt\n 176→ </button>\n 177→ <button\n 178→ className={`btn-secondary${activeOptimization === 'k-opt' ? ' btn-active' : ''}`}\n 179→ onClick={() => onOptimize('k-opt')}\n 180→ >\n 181→ k-opt\n 182→ </button>\n 183→ <button\n 184→ className={`btn-secondary${activeOptimization === 'lin-kernighan' ? ' btn-active' : ''}`}\n 185→ onClick={() => onOptimize('lin-kernighan')}\n 186→ >\n 187→ LK\n 188→ </button>\n 189→ <button\n 190→ className={`btn-secondary${activeOptimization === 'lkh' ? ' btn-active' : ''}`}\n 191→ onClick={() => onOptimize('lkh')}\n 192→ >\n 193→ LKH\n 194→ </button>\n 195→ <button\n 196→ className={`btn-secondary${activeOptimization === 'zigzag' ? ' btn-active' : ''}`}\n 197→ onClick={() => onOptimize('zigzag')}\n 198→ >\n 199→ Zigzag\n 200→ </button>\n 201→ </>\n 202→ )}\n 203→ </>\n 204→ ) : (\n 205→ <button className=\"btn-secondary\" onClick={onStop}>\n 206→ {t(lang, 'stop')}\n 207→ </button>\n 208→ )}\n 209→ </div>\n 210→ </div>\n 211→ );\n 212→};\n 213→\n 214→export { Controls };\n 215→export default Controls;\n 216→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "766cb878-1ca6-48d9-98e7-45eb68efb85a",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Controls.jsx",
"content": "/**\n * Controls Component\n *\n * Control panel for TSP solver including:\n * - Algorithm selection dropdowns (left and right panels)\n * - Grid size selector (valid Moore curve sizes)\n * - Points count input\n * - Animation speed slider\n * - Action buttons (New Points, Start, Stop, 2-opt Optimize, Zigzag Optimize)\n */\n\nimport { VALID_GRID_SIZES } from '../../../lib/algorithms/utils.js';\nimport { t } from '../i18n.js';\n\n/**\n * Available algorithms for selection.\n * Each entry maps an id to a display label.\n */\nexport const ALGORITHM_OPTIONS = [\n { id: 'sonar', label: 'Sonar Visit' },\n { id: 'moore', label: 'Moore Curve' },\n { id: 'gosper', label: 'Gosper Curve' },\n { id: 'peano', label: 'Peano Curve' },\n { id: 'sierpinski', label: 'Sierpiński Curve' },\n { id: 'comb', label: 'Comb Scan' },\n { id: 'saw', label: 'Self-Avoiding Walk' },\n { id: 'koch', label: 'Koch Snowflake' },\n { id: 'space-filling-tree', label: 'Space-Filling Tree' },\n { id: 'brute-force', label: 'Brute-Force' },\n];\n\n/**\n * Controls - Control panel for TSP solver\n *\n * @param {Object} props\n * @param {number} props.gridSize - Current grid size (must be a valid Moore curve size)\n * @param {function} props.setGridSize - Grid size setter\n * @param {number} props.numPoints - Number of points\n * @param {function} props.setNumPoints - Points count setter\n * @param {number} props.speed - Animation speed in ms\n * @param {function} props.setSpeed - Speed setter\n * @param {number} props.mooreGridSize - Actual Moore grid size\n * @param {boolean} props.isRunning - Whether animation is running\n * @param {boolean} props.canOptimize - Whether optimization can start\n * @param {string|null} props.activeOptimization - Currently active optimization method\n * @param {function} props.onGeneratePoints - Generate new points handler\n * @param {function} props.onStart - Start algorithm handler\n * @param {function} props.onStop - Stop animation handler\n * @param {function} props.onOptimize - Start optimization handler (receives method name)\n * @param {number} props.pointsCount - Current points count (for Start button state)\n * @param {boolean} props.startDisabled - Whether Start button should be disabled\n * @param {string} props.startDisabledReason - Tooltip explaining why Start is disabled\n * @param {string} props.lang - Current language code\n */\nconst Controls = ({\n gridSize,\n setGridSize,\n numPoints,\n setNumPoints,\n speed,\n setSpeed,\n mooreGridSize,\n isRunning,\n canOptimize,\n activeOptimization,\n onGeneratePoints,\n onStart,\n onStop,\n onOptimize,\n pointsCount,\n startDisabled,\n startDisabledReason,\n lang = 'en',\n}) => {\n const maxPoints = mooreGridSize * mooreGridSize;\n return (\n <div className=\"controls\">\n <div className=\"control-group\">\n <label>{t(lang, 'gridSize')}</label>\n <select\n value={gridSize}\n onChange={(e) => setGridSize(parseInt(e.target.value))}\n disabled={isRunning}\n >\n {VALID_GRID_SIZES.map((size) => (\n <option key={size} value={size}>\n {size}×{size}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"control-group\">\n <label>\n {t(lang, 'points')} ({t(lang, 'max')} {maxPoints})\n </label>\n <input\n type=\"number\"\n min=\"1\"\n max={maxPoints}\n value={numPoints}\n onChange={(e) => {\n const val = parseInt(e.target.value);\n if (isNaN(val) || val < 1) {\n setNumPoints(e.target.value === '' ? '' : 1);\n return;\n }\n setNumPoints(Math.min(val, maxPoints));\n }}\n onBlur={() => {\n const val =\n typeof numPoints === 'number' ? numPoints : parseInt(numPoints);\n if (isNaN(val) || val < 3) {\n setNumPoints(3);\n } else if (val > maxPoints) {\n setNumPoints(maxPoints);\n }\n }}\n disabled={isRunning}\n />\n </div>\n\n <div className=\"control-group\">\n <label>{t(lang, 'animationSpeed')}</label>\n <div className=\"speed-control\">\n <span>{t(lang, 'fast')}</span>\n <input\n type=\"range\"\n min=\"50\"\n max=\"1000\"\n value={speed}\n onChange={(e) => setSpeed(parseInt(e.target.value))}\n />\n <span>{t(lang, 'slow')}</span>\n </div>\n </div>\n\n <div className=\"buttons\">\n <button\n className=\"btn-outline\"\n onClick={onGeneratePoints}\n disabled={isRunning}\n >\n {t(lang, 'newPoints')}\n </button>\n\n {!isRunning ? (\n <>\n <span\n className={startDisabled ? 'tooltip-wrapper' : ''}\n data-tooltip={startDisabledReason || undefined}\n >\n <button\n className=\"btn-primary\"\n onClick={onStart}\n disabled={pointsCount === 0 || startDisabled}\n title={startDisabledReason || ''}\n >\n {t(lang, 'start')}\n </button>\n </span>\n\n {canOptimize && (\n <>\n <button\n className={`btn-secondary${activeOptimization === '2-opt' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('2-opt')}\n >\n 2-opt\n </button>\n <button\n className={`btn-secondary${activeOptimization === '3-opt' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('3-opt')}\n >\n 3-opt\n </button>\n <button\n className={`btn-secondary${activeOptimization === 'k-opt' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('k-opt')}\n >\n k-opt\n </button>\n <button\n className={`btn-secondary${activeOptimization === 'lin-kernighan' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('lin-kernighan')}\n >\n LK\n </button>\n <button\n className={`btn-secondary${activeOptimization === 'lkh' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('lkh')}\n >\n LKH\n </button>\n <button\n className={`btn-secondary${activeOptimization === 'zigzag' ? ' btn-active' : ''}`}\n onClick={() => onOptimize('zigzag')}\n >\n Zigzag\n </button>\n </>\n )}\n </>\n ) : (\n <button className=\"btn-secondary\" onClick={onStop}>\n {t(lang, 'stop')}\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport { Controls };\nexport default Controls;\n",
"numLines": 216,
"startLine": 1,
"totalLines": 216
}
}
}
[2026-02-07T22:21:27.141Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01RZsgJ419DEWLaqsivjj9Cb",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01NCD8ckEh54mY8dK7EgveUF",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/TSPVisualization.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 585,
"cache_read_input_tokens": 45333,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 585
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "221f9158-7893-41f4-80e3-559ce111e141"
}
[2026-02-07T22:21:27.144Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01NCD8ckEh54mY8dK7EgveUF",
"type": "tool_result",
"content": " 1→/**\n 2→ * TSPVisualization Component\n 3→ *\n 4→ * SVG-based visualization for TSP algorithms.\n 5→ * Displays points, tour paths, and algorithm-specific elements\n 6→ * (sweep line for Sonar, curve for Moore).\n 7→ */\n 8→\n 9→import { useState, useEffect, useRef } from 'react';\n 10→\n 11→/**\n 12→ * Convert point coordinates to SVG space\n 13→ * @param {{x: number, y: number}} p - Point in grid coordinates\n 14→ * @param {number} padding - SVG padding\n 15→ * @param {number} scale - Coordinate scale factor\n 16→ * @returns {{x: number, y: number}} Point in SVG coordinates\n 17→ */\n 18→const toSvgCoords = (p, padding, scale) => ({\n 19→ x: padding + p.x * scale,\n 20→ y: padding + p.y * scale,\n 21→});\n 22→\n 23→/**\n 24→ * TSPVisualization - SVG renderer for TSP algorithms\n 25→ *\n 26→ * @param {Object} props\n 27→ * @param {Array<{x: number, y: number, id: number}>} props.points - Array of points\n 28→ * @param {Array<Object>} props.steps - Array of algorithm steps\n 29→ * @param {number} props.currentStep - Current step index\n 30→ * @param {string} props.algorithm - Algorithm type ('sonar', 'moore', 'peano', 'sierpinski', 'comb', 'saw', 'koch', 'space-filling-tree', or 'brute-force')\n 31→ * @param {number} props.mooreGridSize - Size of the grid\n 32→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 33→ */\n 34→const TSPVisualization = ({\n 35→ points,\n 36→ steps,\n 37→ currentStep,\n 38→ algorithm,\n 39→ mooreGridSize,\n 40→ showOptimization,\n 41→}) => {\n 42→ const containerRef = useRef(null);\n 43→ const [svgSize, setSvgSize] = useState(400);\n 44→ const padding = 20;\n 45→\n 46→ // Responsive SVG sizing\n 47→ useEffect(() => {\n 48→ const updateSize = () => {\n 49→ if (containerRef.current) {\n 50→ const containerWidth = containerRef.current.clientWidth;\n 51→ // Max size 400, min size 280, responsive to container\n 52→ const newSize = Math.min(400, Math.max(280, containerWidth - 32));\n 53→ setSvgSize(newSize);\n 54→ }\n 55→ };\n 56→\n 57→ updateSize();\n 58→ window.addEventListener('resize', updateSize);\n 59→ return () => window.removeEventListener('resize', updateSize);\n 60→ }, []);\n 61→\n 62→ const size = svgSize;\n 63→\n 64→ // Get current step data\n 65→ const step =\n 66→ currentStep >= 0 && currentStep < steps.length ? steps[currentStep] : null;\n 67→\n 68→ // Both algorithms use the same Moore grid size for perfect alignment\n 69→ // Grid coordinates range from 0 to mooreGridSize-1\n 70→ const displayGridSize = mooreGridSize - 1;\n 71→\n 72→ const scale = (size - 2 * padding) / displayGridSize;\n 73→\n 74→ // Generate grid lines at each integer coordinate [0, mooreGridSize-1]\n 75→ const gridLines = [];\n 76→ for (let i = 0; i <= displayGridSize; i++) {\n 77→ const pos = padding + i * scale;\n 78→ gridLines.push(\n 79→ <line\n 80→ key={`v-${i}`}\n 81→ x1={pos}\n 82→ y1={padding}\n 83→ x2={pos}\n 84→ y2={size - padding}\n 85→ className=\"grid-line\"\n 86→ strokeWidth=\"1\"\n 87→ />\n 88→ );\n 89→ gridLines.push(\n 90→ <line\n 91→ key={`h-${i}`}\n 92→ x1={padding}\n 93→ y1={pos}\n 94→ x2={size - padding}\n 95→ y2={pos}\n 96→ className=\"grid-line\"\n 97→ strokeWidth=\"1\"\n 98→ />\n 99→ );\n 100→ }\n 101→\n 102→ // Generate space-filling curve path - progressive animation\n 103→ // Used for Moore, Gosper, Peano, Sierpiński, and Koch curves\n 104→ // Draw visited portion in green, remaining portion in gray\n 105→ let mooreCurvePath = null;\n 106→ let mooreCurveGrayPath = null;\n 107→ const isCurveAlgorithm =\n 108→ algorithm === 'moore' ||\n 109→ algorithm === 'gosper' ||\n 110→ algorithm === 'peano' ||\n 111→ algorithm === 'sierpinski' ||\n 112→ algorithm === 'koch';\n 113→ if (isCurveAlgorithm && step?.curvePoints && step.curvePoints.length > 0) {\n 114→ // Determine the curve position up to which we've progressed\n 115→ const curvePosition =\n 116→ step.curvePosition !== undefined ? step.curvePosition : 0;\n 117→\n 118→ // Split curve into visited (green) and unvisited (gray) portions\n 119→ const visitedPoints = step.curvePoints.slice(0, curvePosition + 1);\n 120→ const unvisitedPoints = step.curvePoints.slice(curvePosition);\n 121→\n 122→ // Draw the unvisited (gray) portion first (so green appears on top)\n 123→ if (unvisitedPoints.length > 1) {\n 124→ const grayPathData = unvisitedPoints\n 125→ .map((p, i) => {\n 126→ const coords = toSvgCoords(p, padding, scale);\n 127→ return i === 0\n 128→ ? `M ${coords.x} ${coords.y}`\n 129→ : `L ${coords.x} ${coords.y}`;\n 130→ })\n 131→ .join(' ');\n 132→ mooreCurveGrayPath = (\n 133→ <path\n 134→ d={grayPathData}\n 135→ fill=\"none\"\n 136→ stroke=\"rgba(156, 163, 175, 0.5)\"\n 137→ strokeWidth=\"3\"\n 138→ strokeLinecap=\"square\"\n 139→ strokeLinejoin=\"miter\"\n 140→ />\n 141→ );\n 142→ }\n 143→\n 144→ // Draw the visited (green) portion\n 145→ if (visitedPoints.length > 0) {\n 146→ const greenPathData = visitedPoints\n 147→ .map((p, i) => {\n 148→ const coords = toSvgCoords(p, padding, scale);\n 149→ return i === 0\n 150→ ? `M ${coords.x} ${coords.y}`\n 151→ : `L ${coords.x} ${coords.y}`;\n 152→ })\n 153→ .join(' ');\n 154→ mooreCurvePath = (\n 155→ <path\n 156→ d={greenPathData}\n 157→ fill=\"none\"\n 158→ stroke=\"rgba(34, 197, 94, 0.6)\"\n 159→ strokeWidth=\"3\"\n 160→ strokeLinecap=\"square\"\n 161→ strokeLinejoin=\"miter\"\n 162→ />\n 163→ );\n 164→ }\n 165→ }\n 166→\n 167→ // Generate space-filling tree edges\n 168→ let treeEdgesPath = null;\n 169→ if (\n 170→ algorithm === 'space-filling-tree' &&\n 171→ step?.treeEdges &&\n 172→ step.treeEdges.length > 0\n 173→ ) {\n 174→ treeEdgesPath = (\n 175→ <g>\n 176→ {step.treeEdges.map((edge, i) => {\n 177→ const from = toSvgCoords(edge.from, padding, scale);\n 178→ const to = toSvgCoords(edge.to, padding, scale);\n 179→ return (\n 180→ <line\n 181→ key={`tree-edge-${i}`}\n 182→ x1={from.x}\n 183→ y1={from.y}\n 184→ x2={to.x}\n 185→ y2={to.y}\n 186→ stroke=\"rgba(255, 165, 0, 0.5)\"\n 187→ strokeWidth={Math.max(1, 3 - edge.depth * 0.3)}\n 188→ strokeLinecap=\"round\"\n 189→ />\n 190→ );\n 191→ })}\n 192→ </g>\n 193→ );\n 194→ }\n 195→\n 196→ // Generate sweep line for Sonar\n 197→ let sweepLine = null;\n 198→ let centroidCircle = null;\n 199→ if (algorithm === 'sonar' && step?.type === 'sweep' && step?.centroid) {\n 200→ const center = toSvgCoords(step.centroid, padding, scale);\n 201→ const lineLength = size;\n 202→ sweepLine = (\n 203→ <line\n 204→ x1={center.x}\n 205→ y1={center.y}\n 206→ x2={center.x + lineLength * Math.cos(step.angle)}\n 207→ y2={center.y + lineLength * Math.sin(step.angle)}\n 208→ stroke=\"rgba(13, 110, 253, 0.3)\"\n 209→ strokeWidth=\"2\"\n 210→ />\n 211→ );\n 212→ centroidCircle = (\n 213→ <circle\n 214→ cx={center.x}\n 215→ cy={center.y}\n 216→ r=\"5\"\n 217→ fill=\"rgba(128, 0, 128, 0.3)\"\n 218→ stroke=\"purple\"\n 219→ strokeWidth=\"1.5\"\n 220→ strokeDasharray=\"3 2\"\n 221→ />\n 222→ );\n 223→ }\n 224→\n 225→ // Generate tour path\n 226→ let tourPath = null;\n 227→ if (step?.tour && step.tour.length > 1) {\n 228→ const isOptimization = step.type === 'optimize' || showOptimization;\n 229→ const tourPoints = step.tour.map((idx) =>\n 230→ toSvgCoords(points[idx], padding, scale)\n 231→ );\n 232→\n 233→ // Determine which edges are modified (for optimization highlighting)\n 234→ let modifiedEdges = null;\n 235→ if (isOptimization && step.reversed) {\n 236→ // 2-opt: edges around the reversed segment are modified\n 237→ const [rStart, rEnd] = step.reversed;\n 238→ modifiedEdges = new Set();\n 239→ modifiedEdges.add(rStart - 1 >= 0 ? rStart - 1 : step.tour.length - 1);\n 240→ modifiedEdges.add(rEnd);\n 241→ for (let e = rStart; e < rEnd; e++) {\n 242→ modifiedEdges.add(e);\n 243→ }\n 244→ } else if (isOptimization && step.swapped) {\n 245→ // Zigzag: highlight edges around swapped points\n 246→ modifiedEdges = new Set();\n 247→ for (let e = 0; e < step.tour.length; e++) {\n 248→ const nextE = (e + 1) % step.tour.length;\n 249→ if (\n 250→ step.swapped.includes(step.tour[e]) ||\n 251→ step.swapped.includes(step.tour[nextE])\n 252→ ) {\n 253→ modifiedEdges.add(e);\n 254→ }\n 255→ }\n 256→ }\n 257→\n 258→ if (isOptimization && modifiedEdges && modifiedEdges.size > 0) {\n 259→ // Draw unmodified edges in blue, modified edges in green\n 260→ const edgeElements = [];\n 261→ const isClosed = step.tour.length === points.length;\n 262→ const edgeCount = isClosed ? tourPoints.length : tourPoints.length - 1;\n 263→ for (let i = 0; i < edgeCount; i++) {\n 264→ const from = tourPoints[i];\n 265→ const to = tourPoints[(i + 1) % tourPoints.length];\n 266→ const isModified = modifiedEdges.has(i);\n 267→ edgeElements.push(\n 268→ <line\n 269→ key={`edge-${i}`}\n 270→ x1={from.x}\n 271→ y1={from.y}\n 272→ x2={to.x}\n 273→ y2={to.y}\n 274→ stroke={isModified ? '#198754' : '#0d6efd'}\n 275→ strokeWidth={isModified ? 3 : 2}\n 276→ strokeLinecap=\"round\"\n 277→ />\n 278→ );\n 279→ }\n 280→ tourPath = <g>{edgeElements}</g>;\n 281→ } else {\n 282→ let pathData = tourPoints\n 283→ .map((p, i) => (i === 0 ? `M ${p.x} ${p.y}` : `L ${p.x} ${p.y}`))\n 284→ .join(' ');\n 285→ // Close the loop if tour is complete\n 286→ if (step.tour.length === points.length) {\n 287→ pathData += ' Z';\n 288→ }\n 289→ tourPath = (\n 290→ <path\n 291→ d={pathData}\n 292→ fill=\"none\"\n 293→ stroke={isOptimization ? '#198754' : '#0d6efd'}\n 294→ strokeWidth=\"2\"\n 295→ strokeLinecap=\"round\"\n 296→ strokeLinejoin=\"round\"\n 297→ />\n 298→ );\n 299→ }\n 300→ }\n 301→\n 302→ // Generate point circles\n 303→ const pointCircles = points.map((point, idx) => {\n 304→ const p = toSvgCoords(point, padding, scale);\n 305→ const isInTour = step?.tour?.includes(idx);\n 306→ const isLastAdded = step?.tour && step.tour[step.tour.length - 1] === idx;\n 307→\n 308→ let fill = '#6c757d';\n 309→ if (isLastAdded) {\n 310→ fill = '#dc3545';\n 311→ } else if (isInTour) {\n 312→ fill = '#0d6efd';\n 313→ }\n 314→\n 315→ return (\n 316→ <g key={`point-${idx}`}>\n 317→ <circle cx={p.x} cy={p.y} r={isLastAdded ? 6 : 4} fill={fill}>\n 318→ <title>\n 319→ Point {idx} ({point.x}, {point.y})\n 320→ </title>\n 321→ </circle>\n 322→ </g>\n 323→ );\n 324→ });\n 325→\n 326→ return (\n 327→ <div\n 328→ ref={containerRef}\n 329→ style={{ width: '100%', display: 'flex', justifyContent: 'center' }}\n 330→ >\n 331→ <svg\n 332→ width={size}\n 333→ height={size}\n 334→ viewBox={`0 0 ${size} ${size}`}\n 335→ className=\"tsp-svg\"\n 336→ >\n 337→ {/* Grid lines */}\n 338→ <g>{gridLines}</g>\n 339→ {/* Moore curve - gray (unvisited) portion first, then green (visited) on top */}\n 340→ {mooreCurveGrayPath}\n 341→ {mooreCurvePath}\n 342→ {/* Space-filling tree edges */}\n 343→ {treeEdgesPath}\n 344→ {/* Sweep line for Sonar */}\n 345→ {sweepLine}\n 346→ {centroidCircle}\n 347→ {/* Tour path */}\n 348→ {tourPath}\n 349→ {/* Points */}\n 350→ <g>{pointCircles}</g>\n 351→ </svg>\n 352→ </div>\n 353→ );\n 354→};\n 355→\n 356→// Alias for backward compatibility\n 357→const TSPCanvas = TSPVisualization;\n 358→\n 359→export { TSPVisualization, TSPCanvas };\n 360→export default TSPVisualization;\n 361→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "dc49abdf-1737-449b-8ccb-c92d42e0df50",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/TSPVisualization.jsx",
"content": "/**\n * TSPVisualization Component\n *\n * SVG-based visualization for TSP algorithms.\n * Displays points, tour paths, and algorithm-specific elements\n * (sweep line for Sonar, curve for Moore).\n */\n\nimport { useState, useEffect, useRef } from 'react';\n\n/**\n * Convert point coordinates to SVG space\n * @param {{x: number, y: number}} p - Point in grid coordinates\n * @param {number} padding - SVG padding\n * @param {number} scale - Coordinate scale factor\n * @returns {{x: number, y: number}} Point in SVG coordinates\n */\nconst toSvgCoords = (p, padding, scale) => ({\n x: padding + p.x * scale,\n y: padding + p.y * scale,\n});\n\n/**\n * TSPVisualization - SVG renderer for TSP algorithms\n *\n * @param {Object} props\n * @param {Array<{x: number, y: number, id: number}>} props.points - Array of points\n * @param {Array<Object>} props.steps - Array of algorithm steps\n * @param {number} props.currentStep - Current step index\n * @param {string} props.algorithm - Algorithm type ('sonar', 'moore', 'peano', 'sierpinski', 'comb', 'saw', 'koch', 'space-filling-tree', or 'brute-force')\n * @param {number} props.mooreGridSize - Size of the grid\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n */\nconst TSPVisualization = ({\n points,\n steps,\n currentStep,\n algorithm,\n mooreGridSize,\n showOptimization,\n}) => {\n const containerRef = useRef(null);\n const [svgSize, setSvgSize] = useState(400);\n const padding = 20;\n\n // Responsive SVG sizing\n useEffect(() => {\n const updateSize = () => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;\n // Max size 400, min size 280, responsive to container\n const newSize = Math.min(400, Math.max(280, containerWidth - 32));\n setSvgSize(newSize);\n }\n };\n\n updateSize();\n window.addEventListener('resize', updateSize);\n return () => window.removeEventListener('resize', updateSize);\n }, []);\n\n const size = svgSize;\n\n // Get current step data\n const step =\n currentStep >= 0 && currentStep < steps.length ? steps[currentStep] : null;\n\n // Both algorithms use the same Moore grid size for perfect alignment\n // Grid coordinates range from 0 to mooreGridSize-1\n const displayGridSize = mooreGridSize - 1;\n\n const scale = (size - 2 * padding) / displayGridSize;\n\n // Generate grid lines at each integer coordinate [0, mooreGridSize-1]\n const gridLines = [];\n for (let i = 0; i <= displayGridSize; i++) {\n const pos = padding + i * scale;\n gridLines.push(\n <line\n key={`v-${i}`}\n x1={pos}\n y1={padding}\n x2={pos}\n y2={size - padding}\n className=\"grid-line\"\n strokeWidth=\"1\"\n />\n );\n gridLines.push(\n <line\n key={`h-${i}`}\n x1={padding}\n y1={pos}\n x2={size - padding}\n y2={pos}\n className=\"grid-line\"\n strokeWidth=\"1\"\n />\n );\n }\n\n // Generate space-filling curve path - progressive animation\n // Used for Moore, Gosper, Peano, Sierpiński, and Koch curves\n // Draw visited portion in green, remaining portion in gray\n let mooreCurvePath = null;\n let mooreCurveGrayPath = null;\n const isCurveAlgorithm =\n algorithm === 'moore' ||\n algorithm === 'gosper' ||\n algorithm === 'peano' ||\n algorithm === 'sierpinski' ||\n algorithm === 'koch';\n if (isCurveAlgorithm && step?.curvePoints && step.curvePoints.length > 0) {\n // Determine the curve position up to which we've progressed\n const curvePosition =\n step.curvePosition !== undefined ? step.curvePosition : 0;\n\n // Split curve into visited (green) and unvisited (gray) portions\n const visitedPoints = step.curvePoints.slice(0, curvePosition + 1);\n const unvisitedPoints = step.curvePoints.slice(curvePosition);\n\n // Draw the unvisited (gray) portion first (so green appears on top)\n if (unvisitedPoints.length > 1) {\n const grayPathData = unvisitedPoints\n .map((p, i) => {\n const coords = toSvgCoords(p, padding, scale);\n return i === 0\n ? `M ${coords.x} ${coords.y}`\n : `L ${coords.x} ${coords.y}`;\n })\n .join(' ');\n mooreCurveGrayPath = (\n <path\n d={grayPathData}\n fill=\"none\"\n stroke=\"rgba(156, 163, 175, 0.5)\"\n strokeWidth=\"3\"\n strokeLinecap=\"square\"\n strokeLinejoin=\"miter\"\n />\n );\n }\n\n // Draw the visited (green) portion\n if (visitedPoints.length > 0) {\n const greenPathData = visitedPoints\n .map((p, i) => {\n const coords = toSvgCoords(p, padding, scale);\n return i === 0\n ? `M ${coords.x} ${coords.y}`\n : `L ${coords.x} ${coords.y}`;\n })\n .join(' ');\n mooreCurvePath = (\n <path\n d={greenPathData}\n fill=\"none\"\n stroke=\"rgba(34, 197, 94, 0.6)\"\n strokeWidth=\"3\"\n strokeLinecap=\"square\"\n strokeLinejoin=\"miter\"\n />\n );\n }\n }\n\n // Generate space-filling tree edges\n let treeEdgesPath = null;\n if (\n algorithm === 'space-filling-tree' &&\n step?.treeEdges &&\n step.treeEdges.length > 0\n ) {\n treeEdgesPath = (\n <g>\n {step.treeEdges.map((edge, i) => {\n const from = toSvgCoords(edge.from, padding, scale);\n const to = toSvgCoords(edge.to, padding, scale);\n return (\n <line\n key={`tree-edge-${i}`}\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n stroke=\"rgba(255, 165, 0, 0.5)\"\n strokeWidth={Math.max(1, 3 - edge.depth * 0.3)}\n strokeLinecap=\"round\"\n />\n );\n })}\n </g>\n );\n }\n\n // Generate sweep line for Sonar\n let sweepLine = null;\n let centroidCircle = null;\n if (algorithm === 'sonar' && step?.type === 'sweep' && step?.centroid) {\n const center = toSvgCoords(step.centroid, padding, scale);\n const lineLength = size;\n sweepLine = (\n <line\n x1={center.x}\n y1={center.y}\n x2={center.x + lineLength * Math.cos(step.angle)}\n y2={center.y + lineLength * Math.sin(step.angle)}\n stroke=\"rgba(13, 110, 253, 0.3)\"\n strokeWidth=\"2\"\n />\n );\n centroidCircle = (\n <circle\n cx={center.x}\n cy={center.y}\n r=\"5\"\n fill=\"rgba(128, 0, 128, 0.3)\"\n stroke=\"purple\"\n strokeWidth=\"1.5\"\n strokeDasharray=\"3 2\"\n />\n );\n }\n\n // Generate tour path\n let tourPath = null;\n if (step?.tour && step.tour.length > 1) {\n const isOptimization = step.type === 'optimize' || showOptimization;\n const tourPoints = step.tour.map((idx) =>\n toSvgCoords(points[idx], padding, scale)\n );\n\n // Determine which edges are modified (for optimization highlighting)\n let modifiedEdges = null;\n if (isOptimization && step.reversed) {\n // 2-opt: edges around the reversed segment are modified\n const [rStart, rEnd] = step.reversed;\n modifiedEdges = new Set();\n modifiedEdges.add(rStart - 1 >= 0 ? rStart - 1 : step.tour.length - 1);\n modifiedEdges.add(rEnd);\n for (let e = rStart; e < rEnd; e++) {\n modifiedEdges.add(e);\n }\n } else if (isOptimization && step.swapped) {\n // Zigzag: highlight edges around swapped points\n modifiedEdges = new Set();\n for (let e = 0; e < step.tour.length; e++) {\n const nextE = (e + 1) % step.tour.length;\n if (\n step.swapped.includes(step.tour[e]) ||\n step.swapped.includes(step.tour[nextE])\n ) {\n modifiedEdges.add(e);\n }\n }\n }\n\n if (isOptimization && modifiedEdges && modifiedEdges.size > 0) {\n // Draw unmodified edges in blue, modified edges in green\n const edgeElements = [];\n const isClosed = step.tour.length === points.length;\n const edgeCount = isClosed ? tourPoints.length : tourPoints.length - 1;\n for (let i = 0; i < edgeCount; i++) {\n const from = tourPoints[i];\n const to = tourPoints[(i + 1) % tourPoints.length];\n const isModified = modifiedEdges.has(i);\n edgeElements.push(\n <line\n key={`edge-${i}`}\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n stroke={isModified ? '#198754' : '#0d6efd'}\n strokeWidth={isModified ? 3 : 2}\n strokeLinecap=\"round\"\n />\n );\n }\n tourPath = <g>{edgeElements}</g>;\n } else {\n let pathData = tourPoints\n .map((p, i) => (i === 0 ? `M ${p.x} ${p.y}` : `L ${p.x} ${p.y}`))\n .join(' ');\n // Close the loop if tour is complete\n if (step.tour.length === points.length) {\n pathData += ' Z';\n }\n tourPath = (\n <path\n d={pathData}\n fill=\"none\"\n stroke={isOptimization ? '#198754' : '#0d6efd'}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n );\n }\n }\n\n // Generate point circles\n const pointCircles = points.map((point, idx) => {\n const p = toSvgCoords(point, padding, scale);\n const isInTour = step?.tour?.includes(idx);\n const isLastAdded = step?.tour && step.tour[step.tour.length - 1] === idx;\n\n let fill = '#6c757d';\n if (isLastAdded) {\n fill = '#dc3545';\n } else if (isInTour) {\n fill = '#0d6efd';\n }\n\n return (\n <g key={`point-${idx}`}>\n <circle cx={p.x} cy={p.y} r={isLastAdded ? 6 : 4} fill={fill}>\n <title>\n Point {idx} ({point.x}, {point.y})\n </title>\n </circle>\n </g>\n );\n });\n\n return (\n <div\n ref={containerRef}\n style={{ width: '100%', display: 'flex', justifyContent: 'center' }}\n >\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n className=\"tsp-svg\"\n >\n {/* Grid lines */}\n <g>{gridLines}</g>\n {/* Moore curve - gray (unvisited) portion first, then green (visited) on top */}\n {mooreCurveGrayPath}\n {mooreCurvePath}\n {/* Space-filling tree edges */}\n {treeEdgesPath}\n {/* Sweep line for Sonar */}\n {sweepLine}\n {centroidCircle}\n {/* Tour path */}\n {tourPath}\n {/* Points */}\n <g>{pointCircles}</g>\n </svg>\n </div>\n );\n};\n\n// Alias for backward compatibility\nconst TSPCanvas = TSPVisualization;\n\nexport { TSPVisualization, TSPCanvas };\nexport default TSPVisualization;\n",
"numLines": 361,
"startLine": 1,
"totalLines": 361
}
}
}
[2026-02-07T22:21:27.511Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01RZsgJ419DEWLaqsivjj9Cb",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01HQQKwfQmyLRrWnqLCoxVPW",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Legend.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 585,
"cache_read_input_tokens": 45333,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 585
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "274253e5-1843-40cc-82eb-265f050a597e"
}
[2026-02-07T22:21:27.521Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01HQQKwfQmyLRrWnqLCoxVPW",
"type": "tool_result",
"content": " 1→/**\n 2→ * Legend Component\n 3→ *\n 4→ * Displays the color legend for TSP visualizations.\n 5→ * Different legends for Sonar and Moore algorithms.\n 6→ */\n 7→\n 8→import { t } from '../i18n.js';\n 9→\n 10→/**\n 11→ * LegendItem - Single legend entry\n 12→ *\n 13→ * @param {Object} props\n 14→ * @param {string} props.color - Background color for the legend marker\n 15→ * @param {string} props.label - Text label for the legend entry\n 16→ */\n 17→const LegendItem = ({ color, label }) => (\n 18→ <div className=\"legend-item\">\n 19→ <div className=\"legend-color\" style={{ background: color }}></div>\n 20→ <span>{label}</span>\n 21→ </div>\n 22→);\n 23→\n 24→/**\n 25→ * SonarLegend - Legend for Sonar algorithm visualization\n 26→ *\n 27→ * @param {Object} props\n 28→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 29→ * @param {string} props.lang - Language code\n 30→ */\n 31→const SonarLegend = ({ showOptimization, lang = 'en' }) => (\n 32→ <div className=\"legend\">\n 33→ <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n 34→ <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n 35→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 36→ <LegendItem color=\"rgba(128, 0, 128, 0.3)\" label={t(lang, 'centroid')} />\n 37→ {showOptimization && (\n 38→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 39→ )}\n 40→ </div>\n 41→);\n 42→\n 43→/**\n 44→ * MooreLegend - Legend for Moore Curve algorithm visualization\n 45→ *\n 46→ * @param {Object} props\n 47→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 48→ * @param {string} props.lang - Language code\n 49→ */\n 50→const MooreLegend = ({ showOptimization, lang = 'en' }) => (\n 51→ <div className=\"legend\">\n 52→ <LegendItem\n 53→ color=\"rgba(34, 197, 94, 0.6)\"\n 54→ label={t(lang, 'visitedCurve')}\n 55→ />\n 56→ <LegendItem\n 57→ color=\"rgba(156, 163, 175, 0.5)\"\n 58→ label={t(lang, 'unvisitedCurve')}\n 59→ />\n 60→ <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n 61→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 62→ {showOptimization && (\n 63→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 64→ )}\n 65→ </div>\n 66→);\n 67→\n 68→/**\n 69→ * BruteForceLegend - Legend for Brute-Force algorithm visualization\n 70→ *\n 71→ * @param {Object} props\n 72→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 73→ * @param {string} props.lang - Language code\n 74→ */\n 75→const BruteForceLegend = ({ showOptimization, lang = 'en' }) => (\n 76→ <div className=\"legend\">\n 77→ <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n 78→ <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n 79→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 80→ {showOptimization && (\n 81→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 82→ )}\n 83→ </div>\n 84→);\n 85→\n 86→/**\n 87→ * CombLegend - Legend for Comb algorithm visualization\n 88→ *\n 89→ * @param {Object} props\n 90→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 91→ * @param {string} props.lang - Language code\n 92→ */\n 93→const CombLegend = ({ showOptimization, lang = 'en' }) => (\n 94→ <div className=\"legend\">\n 95→ <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n 96→ <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n 97→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 98→ {showOptimization && (\n 99→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 100→ )}\n 101→ </div>\n 102→);\n 103→\n 104→/**\n 105→ * SAWLegend - Legend for Self-Avoiding Walk algorithm visualization\n 106→ *\n 107→ * @param {Object} props\n 108→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 109→ * @param {string} props.lang - Language code\n 110→ */\n 111→const SAWLegend = ({ showOptimization, lang = 'en' }) => (\n 112→ <div className=\"legend\">\n 113→ <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n 114→ <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n 115→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 116→ {showOptimization && (\n 117→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 118→ )}\n 119→ </div>\n 120→);\n 121→\n 122→/**\n 123→ * KochLegend - Legend for Koch Snowflake algorithm visualization\n 124→ *\n 125→ * @param {Object} props\n 126→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 127→ * @param {string} props.lang - Language code\n 128→ */\n 129→const KochLegend = ({ showOptimization, lang = 'en' }) => (\n 130→ <div className=\"legend\">\n 131→ <LegendItem\n 132→ color=\"rgba(34, 197, 94, 0.6)\"\n 133→ label={t(lang, 'visitedCurve')}\n 134→ />\n 135→ <LegendItem\n 136→ color=\"rgba(156, 163, 175, 0.5)\"\n 137→ label={t(lang, 'unvisitedCurve')}\n 138→ />\n 139→ <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n 140→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 141→ {showOptimization && (\n 142→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 143→ )}\n 144→ </div>\n 145→);\n 146→\n 147→/**\n 148→ * SpaceFillingTreeLegend - Legend for Space-Filling Tree algorithm visualization\n 149→ *\n 150→ * @param {Object} props\n 151→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 152→ * @param {string} props.lang - Language code\n 153→ */\n 154→const SpaceFillingTreeLegend = ({ showOptimization, lang = 'en' }) => (\n 155→ <div className=\"legend\">\n 156→ <LegendItem\n 157→ color=\"rgba(255, 165, 0, 0.5)\"\n 158→ label={t(lang, 'treeStructure')}\n 159→ />\n 160→ <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n 161→ <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n 162→ {showOptimization && (\n 163→ <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n 164→ )}\n 165→ </div>\n 166→);\n 167→\n 168→/**\n 169→ * Legend - Generic legend component\n 170→ *\n 171→ * @param {Object} props\n 172→ * @param {string} props.algorithm - Algorithm type ('sonar', 'moore', 'gosper', 'peano', 'sierpinski', 'comb', 'saw', 'koch', 'space-filling-tree', or 'brute-force')\n 173→ * @param {boolean} props.showOptimization - Whether showing optimization phase\n 174→ * @param {string} props.lang - Language code\n 175→ */\n 176→const Legend = ({ algorithm, showOptimization, lang = 'en' }) => {\n 177→ if (algorithm === 'sonar') {\n 178→ return <SonarLegend showOptimization={showOptimization} lang={lang} />;\n 179→ }\n 180→ if (algorithm === 'comb') {\n 181→ return <CombLegend showOptimization={showOptimization} lang={lang} />;\n 182→ }\n 183→ if (algorithm === 'saw') {\n 184→ return <SAWLegend showOptimization={showOptimization} lang={lang} />;\n 185→ }\n 186→ if (algorithm === 'koch') {\n 187→ return <KochLegend showOptimization={showOptimization} lang={lang} />;\n 188→ }\n 189→ if (algorithm === 'brute-force') {\n 190→ return <BruteForceLegend showOptimization={showOptimization} lang={lang} />;\n 191→ }\n 192→ if (algorithm === 'space-filling-tree') {\n 193→ return (\n 194→ <SpaceFillingTreeLegend showOptimization={showOptimization} lang={lang} />\n 195→ );\n 196→ }\n 197→ // 'moore', 'peano' and 'sierpinski' all use curve-based visualization\n 198→ return <MooreLegend showOptimization={showOptimization} lang={lang} />;\n 199→};\n 200→\n 201→export {\n 202→ Legend,\n 203→ SonarLegend,\n 204→ MooreLegend,\n 205→ CombLegend,\n 206→ SAWLegend,\n 207→ KochLegend,\n 208→ SpaceFillingTreeLegend,\n 209→ BruteForceLegend,\n 210→ LegendItem,\n 211→};\n 212→export default Legend;\n 213→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "f428982e-b9bc-47c4-bec1-2b55ce4acde2",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/Legend.jsx",
"content": "/**\n * Legend Component\n *\n * Displays the color legend for TSP visualizations.\n * Different legends for Sonar and Moore algorithms.\n */\n\nimport { t } from '../i18n.js';\n\n/**\n * LegendItem - Single legend entry\n *\n * @param {Object} props\n * @param {string} props.color - Background color for the legend marker\n * @param {string} props.label - Text label for the legend entry\n */\nconst LegendItem = ({ color, label }) => (\n <div className=\"legend-item\">\n <div className=\"legend-color\" style={{ background: color }}></div>\n <span>{label}</span>\n </div>\n);\n\n/**\n * SonarLegend - Legend for Sonar algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst SonarLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n <LegendItem color=\"rgba(128, 0, 128, 0.3)\" label={t(lang, 'centroid')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * MooreLegend - Legend for Moore Curve algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst MooreLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem\n color=\"rgba(34, 197, 94, 0.6)\"\n label={t(lang, 'visitedCurve')}\n />\n <LegendItem\n color=\"rgba(156, 163, 175, 0.5)\"\n label={t(lang, 'unvisitedCurve')}\n />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * BruteForceLegend - Legend for Brute-Force algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst BruteForceLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * CombLegend - Legend for Comb algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst CombLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * SAWLegend - Legend for Self-Avoiding Walk algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst SAWLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem color=\"#6c757d\" label={t(lang, 'unvisited')} />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'inTour')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * KochLegend - Legend for Koch Snowflake algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst KochLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem\n color=\"rgba(34, 197, 94, 0.6)\"\n label={t(lang, 'visitedCurve')}\n />\n <LegendItem\n color=\"rgba(156, 163, 175, 0.5)\"\n label={t(lang, 'unvisitedCurve')}\n />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * SpaceFillingTreeLegend - Legend for Space-Filling Tree algorithm visualization\n *\n * @param {Object} props\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst SpaceFillingTreeLegend = ({ showOptimization, lang = 'en' }) => (\n <div className=\"legend\">\n <LegendItem\n color=\"rgba(255, 165, 0, 0.5)\"\n label={t(lang, 'treeStructure')}\n />\n <LegendItem color=\"#0d6efd\" label={t(lang, 'tourPath')} />\n <LegendItem color=\"#dc3545\" label={t(lang, 'current')} />\n {showOptimization && (\n <LegendItem color=\"#198754\" label={t(lang, 'modifiedEdge')} />\n )}\n </div>\n);\n\n/**\n * Legend - Generic legend component\n *\n * @param {Object} props\n * @param {string} props.algorithm - Algorithm type ('sonar', 'moore', 'gosper', 'peano', 'sierpinski', 'comb', 'saw', 'koch', 'space-filling-tree', or 'brute-force')\n * @param {boolean} props.showOptimization - Whether showing optimization phase\n * @param {string} props.lang - Language code\n */\nconst Legend = ({ algorithm, showOptimization, lang = 'en' }) => {\n if (algorithm === 'sonar') {\n return <SonarLegend showOptimization={showOptimization} lang={lang} />;\n }\n if (algorithm === 'comb') {\n return <CombLegend showOptimization={showOptimization} lang={lang} />;\n }\n if (algorithm === 'saw') {\n return <SAWLegend showOptimization={showOptimization} lang={lang} />;\n }\n if (algorithm === 'koch') {\n return <KochLegend showOptimization={showOptimization} lang={lang} />;\n }\n if (algorithm === 'brute-force') {\n return <BruteForceLegend showOptimization={showOptimization} lang={lang} />;\n }\n if (algorithm === 'space-filling-tree') {\n return (\n <SpaceFillingTreeLegend showOptimization={showOptimization} lang={lang} />\n );\n }\n // 'moore', 'peano' and 'sierpinski' all use curve-based visualization\n return <MooreLegend showOptimization={showOptimization} lang={lang} />;\n};\n\nexport {\n Legend,\n SonarLegend,\n MooreLegend,\n CombLegend,\n SAWLegend,\n KochLegend,\n SpaceFillingTreeLegend,\n BruteForceLegend,\n LegendItem,\n};\nexport default Legend;\n",
"numLines": 213,
"startLine": 1,
"totalLines": 213
}
}
}
[2026-02-07T22:21:29.704Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01F3oSaWN1n2nqYBy43WaPCd",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Now let me read the remaining UI files and the CLI to understand the full integration pattern."
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 11030,
"cache_read_input_tokens": 45918,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 11030
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "9f8a371e-4775-4497-9a56-ccc0a2d06efb"
}
[2026-02-07T22:21:30.889Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01F3oSaWN1n2nqYBy43WaPCd",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01Bg9j1gK7LiQHWW1eYBMEBx",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/VisualizationPanel.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 11030,
"cache_read_input_tokens": 45918,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 11030
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "c0491a03-ca1a-4651-b5e5-2122a4c39686"
}
[2026-02-07T22:21:30.892Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01Bg9j1gK7LiQHWW1eYBMEBx",
"type": "tool_result",
"content": " 1→/**\n 2→ * VisualizationPanel Component\n 3→ *\n 4→ * A complete visualization panel including:\n 5→ * - Header with algorithm selector dropdown and distance\n 6→ * - Algorithm aliases/description\n 7→ * - TSP visualization canvas\n 8→ * - Step info display\n 9→ * - Color legend\n 10→ */\n 11→\n 12→/**\n 13→ * VisualizationPanel - Complete visualization panel for a single algorithm\n 14→ *\n 15→ * @param {Object} props\n 16→ * @param {string} props.selectedAlgorithm - Currently selected algorithm id\n 17→ * @param {function} props.onAlgorithmChange - Algorithm change handler\n 18→ * @param {Array} props.algorithmOptions - Available algorithm options (filtered)\n 19→ * @param {boolean} props.isRunning - Whether animation is running\n 20→ * @param {string} props.aliases - Alternative algorithm names\n 21→ * @param {string} props.distanceInfo - Formatted distance string with optional optimality info\n 22→ * @param {React.ReactNode} props.visualization - TSPVisualization component\n 23→ * @param {string} props.stepDescription - Current step description\n 24→ * @param {React.ReactNode} props.legend - Legend component\n 25→ */\n 26→const VisualizationPanel = ({\n 27→ selectedAlgorithm,\n 28→ onAlgorithmChange,\n 29→ algorithmOptions,\n 30→ isRunning,\n 31→ aliases,\n 32→ distanceInfo,\n 33→ visualization,\n 34→ stepDescription,\n 35→ defaultStepText,\n 36→ legend,\n 37→}) => {\n 38→ return (\n 39→ <div className=\"visualization\">\n 40→ <div className=\"visualization-header\">\n 41→ <select\n 42→ className=\"algorithm-select\"\n 43→ value={selectedAlgorithm}\n 44→ onChange={(e) => onAlgorithmChange(e.target.value)}\n 45→ disabled={isRunning}\n 46→ >\n 47→ {algorithmOptions.map((opt) => (\n 48→ <option key={opt.id} value={opt.id}>\n 49→ {opt.label}\n 50→ </option>\n 51→ ))}\n 52→ </select>\n 53→ <span className=\"visualization-stats\">{distanceInfo}</span>\n 54→ </div>\n 55→ <div className=\"algorithm-aliases\">{aliases}</div>\n 56→ <div className=\"canvas-wrapper\">{visualization}</div>\n 57→ <div className=\"step-info\">\n 58→ {stepDescription || defaultStepText || 'Click Start to begin'}\n 59→ </div>\n 60→ {legend}\n 61→ </div>\n 62→ );\n 63→};\n 64→\n 65→export { VisualizationPanel };\n 66→export default VisualizationPanel;\n 67→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "1e810cda-4847-4711-b190-13e1944d6d4e",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/app/ui/components/VisualizationPanel.jsx",
"content": "/**\n * VisualizationPanel Component\n *\n * A complete visualization panel including:\n * - Header with algorithm selector dropdown and distance\n * - Algorithm aliases/description\n * - TSP visualization canvas\n * - Step info display\n * - Color legend\n */\n\n/**\n * VisualizationPanel - Complete visualization panel for a single algorithm\n *\n * @param {Object} props\n * @param {string} props.selectedAlgorithm - Currently selected algorithm id\n * @param {function} props.onAlgorithmChange - Algorithm change handler\n * @param {Array} props.algorithmOptions - Available algorithm options (filtered)\n * @param {boolean} props.isRunning - Whether animation is running\n * @param {string} props.aliases - Alternative algorithm names\n * @param {string} props.distanceInfo - Formatted distance string with optional optimality info\n * @param {React.ReactNode} props.visualization - TSPVisualization component\n * @param {string} props.stepDescription - Current step description\n * @param {React.ReactNode} props.legend - Legend component\n */\nconst VisualizationPanel = ({\n selectedAlgorithm,\n onAlgorithmChange,\n algorithmOptions,\n isRunning,\n aliases,\n distanceInfo,\n visualization,\n stepDescription,\n defaultStepText,\n legend,\n}) => {\n return (\n <div className=\"visualization\">\n <div className=\"visualization-header\">\n <select\n className=\"algorithm-select\"\n value={selectedAlgorithm}\n onChange={(e) => onAlgorithmChange(e.target.value)}\n disabled={isRunning}\n >\n {algorithmOptions.map((opt) => (\n <option key={opt.id} value={opt.id}>\n {opt.label}\n </option>\n ))}\n </select>\n <span className=\"visualization-stats\">{distanceInfo}</span>\n </div>\n <div className=\"algorithm-aliases\">{aliases}</div>\n <div className=\"canvas-wrapper\">{visualization}</div>\n <div className=\"step-info\">\n {stepDescription || defaultStepText || 'Click Start to begin'}\n </div>\n {legend}\n </div>\n );\n};\n\nexport { VisualizationPanel };\nexport default VisualizationPanel;\n",
"numLines": 67,
"startLine": 1,
"totalLines": 67
}
}
}
[2026-02-07T22:21:31.877Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01F3oSaWN1n2nqYBy43WaPCd",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01G7dmHYTptRransyr6hbtSP",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/app/ui/App.jsx"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 11030,
"cache_read_input_tokens": 45918,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 11030
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "56feca1f-8617-4401-8450-766e1b6c56a7"
}
[2026-02-07T22:21:31.942Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_01G7dmHYTptRransyr6hbtSP",
"type": "tool_result",
"content": " 1→/**\n 2→ * Main App Component for TSP Visual Solver\n 3→ *\n 4→ * Orchestrates the TSP solver application including:\n 5→ * - State management for points, algorithm steps, and animation\n 6→ * - Algorithm execution with user-selectable algorithms for side-by-side comparison\n 7→ * - Verification of optimal tour distance via lower bound and brute-force\n 8→ * - UI layout with controls and side-by-side visualizations\n 9→ */\n 10→\n 11→import { useState, useEffect, useRef, useCallback } from 'react';\n 12→\n 13→import { LANGUAGES, detectLanguage, t } from './i18n.js';\n 14→\n 15→// Import algorithm functions from lib\n 16→import {\n 17→ calculateMooreGridSize,\n 18→ calculatePeanoGridSize,\n 19→ generateRandomPoints,\n 20→ calculateTotalDistance,\n 21→ sonarAlgorithmSteps,\n 22→ mooreAlgorithmSteps,\n 23→ gosperAlgorithmSteps,\n 24→ peanoAlgorithmSteps,\n 25→ sierpinskiAlgorithmSteps,\n 26→ combAlgorithmSteps,\n 27→ sawAlgorithmSteps,\n 28→ kochAlgorithmSteps,\n 29→ spaceFillingTreeAlgorithmSteps,\n 30→ bruteForceAlgorithmSteps,\n 31→ bruteForceSolution,\n 32→ calculateOptimalityRatio,\n 33→ BRUTE_FORCE_MAX_POINTS,\n 34→ // Generic optimizations that can work with any tour\n 35→ zigzagOptSteps,\n 36→ twoOptSteps,\n 37→ threeOptSteps,\n 38→ kOptSteps,\n 39→ linKernighanSteps,\n 40→ lkHelsgaunSteps,\n 41→ // Verification\n 42→ verifyOptimality,\n 43→} from '../../lib/index.js';\n 44→\n 45→// Import UI components\n 46→import { TSPVisualization } from './components/TSPVisualization.jsx';\n 47→import { Controls, ALGORITHM_OPTIONS } from './components/Controls.jsx';\n 48→import { Legend } from './components/Legend.jsx';\n 49→import { VisualizationPanel } from './components/VisualizationPanel.jsx';\n 50→\n 51→/**\n 52→ * Get algorithm metadata using i18n translations\n 53→ */\n 54→const getAlgorithmMeta = (lang) => ({\n 55→ sonar: {\n 56→ title: t(lang, 'sonarTitle'),\n 57→ aliases: t(lang, 'sonarAliases'),\n 58→ vizType: 'sonar',\n 59→ },\n 60→ moore: {\n 61→ title: t(lang, 'mooreTitle'),\n 62→ aliases: t(lang, 'mooreAliases'),\n 63→ vizType: 'moore',\n 64→ },\n 65→ gosper: {\n 66→ title: t(lang, 'gosperTitle'),\n 67→ aliases: t(lang, 'gosperAliases'),\n 68→ vizType: 'gosper',\n 69→ },\n 70→ peano: {\n 71→ title: t(lang, 'peanoTitle'),\n 72→ aliases: t(lang, 'peanoAliases'),\n 73→ vizType: 'peano',\n 74→ },\n 75→ sierpinski: {\n 76→ title: t(lang, 'sierpinskiTitle'),\n 77→ aliases: t(lang, 'sierpinskiAliases'),\n 78→ vizType: 'sierpinski',\n 79→ },\n 80→ comb: {\n 81→ title: t(lang, 'combTitle'),\n 82→ aliases: t(lang, 'combAliases'),\n 83→ vizType: 'comb',\n 84→ },\n 85→ saw: {\n 86→ title: t(lang, 'sawTitle'),\n 87→ aliases: t(lang, 'sawAliases'),\n 88→ vizType: 'saw',\n 89→ },\n 90→ koch: {\n 91→ title: t(lang, 'kochTitle'),\n 92→ aliases: t(lang, 'kochAliases'),\n 93→ vizType: 'koch',\n 94→ },\n 95→ 'space-filling-tree': {\n 96→ title: t(lang, 'spaceFillingTreeTitle'),\n 97→ aliases: t(lang, 'spaceFillingTreeAliases'),\n 98→ vizType: 'space-filling-tree',\n 99→ },\n 100→ 'brute-force': {\n 101→ title: t(lang, 'bruteForceTitle'),\n 102→ aliases: t(lang, 'bruteForceAliases'),\n 103→ vizType: 'brute-force',\n 104→ },\n 105→});\n 106→\n 107→/**\n 108→ * Run the specified algorithm on the given points.\n 109→ * Returns steps array for progressive visualization.\n 110→ */\n 111→const runAlgorithmSteps = (algorithmId, points, mooreGridSize) => {\n 112→ switch (algorithmId) {\n 113→ case 'sonar':\n 114→ return sonarAlgorithmSteps(points);\n 115→ case 'moore':\n 116→ return mooreAlgorithmSteps(points, mooreGridSize);\n 117→ case 'gosper':\n 118→ return gosperAlgorithmSteps(points, mooreGridSize);\n 119→ case 'peano':\n 120→ return peanoAlgorithmSteps(points, calculatePeanoGridSize(mooreGridSize));\n 121→ case 'sierpinski':\n 122→ return sierpinskiAlgorithmSteps(points, mooreGridSize);\n 123→ case 'comb':\n 124→ return combAlgorithmSteps(points);\n 125→ case 'saw':\n 126→ return sawAlgorithmSteps(points);\n 127→ case 'koch':\n 128→ return kochAlgorithmSteps(points, mooreGridSize);\n 129→ case 'space-filling-tree':\n 130→ return spaceFillingTreeAlgorithmSteps(points);\n 131→ case 'brute-force':\n 132→ return bruteForceAlgorithmSteps(points);\n 133→ default:\n 134→ return [];\n 135→ }\n 136→};\n 137→\n 138→/**\n 139→ * Check if an algorithm is execution-limited for the given number of points.\n 140→ */\n 141→const isAlgorithmLimited = (algorithmId, numPoints) =>\n 142→ algorithmId === 'brute-force' && numPoints > BRUTE_FORCE_MAX_POINTS;\n 143→\n 144→/**\n 145→ * App - Main application component\n 146→ */\n 147→const App = () => {\n 148→ const [gridSize, setGridSize] = useState(16);\n 149→ const [numPoints, setNumPoints] = useState(15);\n 150→ const [points, setPoints] = useState([]);\n 151→ const [speed, setSpeed] = useState(500);\n 152→ const [isRunning, setIsRunning] = useState(false);\n 153→ const [showOptimization, setShowOptimization] = useState(false);\n 154→ const [activeOptimization, setActiveOptimization] = useState(null);\n 155→\n 156→ // Algorithm selection state\n 157→ const [leftAlgorithm, setLeftAlgorithm] = useState('sonar');\n 158→ const [rightAlgorithm, setRightAlgorithm] = useState('moore');\n 159→\n 160→ // Calculate Moore grid size - this is the unified grid both algorithms use\n 161→ const mooreGridSize = calculateMooreGridSize(gridSize);\n 162→ const maxPoints = mooreGridSize * mooreGridSize;\n 163→\n 164→ // Left panel state\n 165→ const [leftSteps, setLeftSteps] = useState([]);\n 166→ const [leftOptSteps, setLeftOptSteps] = useState([]);\n 167→ const [leftCurrentStep, setLeftCurrentStep] = useState(-1);\n 168→\n 169→ // Right panel state\n 170→ const [rightSteps, setRightSteps] = useState([]);\n 171→ const [rightOptSteps, setRightOptSteps] = useState([]);\n 172→ const [rightCurrentStep, setRightCurrentStep] = useState(-1);\n 173→\n 174→ // Verification state\n 175→ const [optimalResult, setOptimalResult] = useState(null);\n 176→ const [verificationResult, setVerificationResult] = useState(null);\n 177→\n 178→ const animationRef = useRef(null);\n 179→\n 180→ // Enforce points limit when grid size changes (Issue #5)\n 181→ useEffect(() => {\n 182→ if (numPoints > maxPoints) {\n 183→ setNumPoints(Math.max(3, maxPoints));\n 184→ }\n 185→ }, [maxPoints, numPoints]);\n 186→\n 187→ const generatePoints = useCallback(() => {\n 188→ const actualNumPoints = Math.min(numPoints, maxPoints);\n 189→ const newPoints = generateRandomPoints(mooreGridSize, actualNumPoints);\n 190→ setPoints(newPoints);\n 191→ setLeftSteps([]);\n 192→ setLeftOptSteps([]);\n 193→ setLeftCurrentStep(-1);\n 194→ setRightSteps([]);\n 195→ setRightOptSteps([]);\n 196→ setRightCurrentStep(-1);\n 197→ setIsRunning(false);\n 198→ setShowOptimization(false);\n 199→ setActiveOptimization(null);\n 200→ setOptimalResult(null);\n 201→ setVerificationResult(null);\n 202→ }, [mooreGridSize, numPoints, maxPoints]);\n 203→\n 204→ useEffect(() => {\n 205→ generatePoints();\n 206→ }, []);\n 207→\n 208→ // Compute optimal tour when points change (brute-force for small sets)\n 209→ useEffect(() => {\n 210→ if (points.length >= 2 && points.length <= BRUTE_FORCE_MAX_POINTS) {\n 211→ const result = bruteForceSolution(points);\n 212→ setOptimalResult(result);\n 213→ } else {\n 214→ setOptimalResult(null);\n 215→ }\n 216→ }, [points]);\n 217→\n 218→ // Compute lower-bound verification when points change\n 219→ useEffect(() => {\n 220→ if (points.length >= 2) {\n 221→ // We use a dummy distance of 0 — we just need the lower bound value\n 222→ const result = verifyOptimality(0, points);\n 223→ setVerificationResult(result);\n 224→ } else {\n 225→ setVerificationResult(null);\n 226→ }\n 227→ }, [points]);\n 228→\n 229→ // Issue #8: Check if either algorithm is limited\n 230→ const startDisabled =\n 231→ isAlgorithmLimited(leftAlgorithm, points.length) ||\n 232→ isAlgorithmLimited(rightAlgorithm, points.length);\n 233→\n 234→ const startDisabledReason = startDisabled\n 235→ ? `Brute-Force limited to ${BRUTE_FORCE_MAX_POINTS} points (current: ${points.length})`\n 236→ : '';\n 237→\n 238→ const startSolution = useCallback(() => {\n 239→ if (points.length === 0 || startDisabled) return;\n 240→\n 241→ const newLeftSteps = runAlgorithmSteps(\n 242→ leftAlgorithm,\n 243→ points,\n 244→ mooreGridSize\n 245→ );\n 246→ const newRightSteps = runAlgorithmSteps(\n 247→ rightAlgorithm,\n 248→ points,\n 249→ mooreGridSize\n 250→ );\n 251→\n 252→ setLeftSteps(newLeftSteps);\n 253→ setRightSteps(newRightSteps);\n 254→ setLeftCurrentStep(0);\n 255→ setRightCurrentStep(0);\n 256→ setShowOptimization(false);\n 257→ setActiveOptimization(null);\n 258→ setLeftOptSteps([]);\n 259→ setRightOptSteps([]);\n 260→ setIsRunning(true);\n 261→ }, [points, mooreGridSize, leftAlgorithm, rightAlgorithm, startDisabled]);\n 262→\n 263→ const stopAnimation = useCallback(() => {\n 264→ setIsRunning(false);\n 265→ if (animationRef.current) {\n 266→ clearTimeout(animationRef.current);\n 267→ }\n 268→ }, []);\n 269→\n 270→ // Issue #6: Get the current tour for a side (considering optimization)\n 271→ const getCurrentTour = useCallback(\n 272→ (side) => {\n 273→ if (side === 'left') {\n 274→ if (showOptimization && leftOptSteps.length > 0) {\n 275→ return leftOptSteps[leftOptSteps.length - 1]?.tour || [];\n 276→ }\n 277→ return leftSteps.length > 0\n 278→ ? leftSteps[leftSteps.length - 1]?.tour || []\n 279→ : [];\n 280→ }\n 281→ if (showOptimization && rightOptSteps.length > 0) {\n 282→ return rightOptSteps[rightOptSteps.length - 1]?.tour || [];\n 283→ }\n 284→ return rightSteps.length > 0\n 285→ ? rightSteps[rightSteps.length - 1]?.tour || []\n 286→ : [];\n 287→ },\n 288→ [showOptimization, leftOptSteps, rightOptSteps, leftSteps, rightSteps]\n 289→ );\n 290→\n 291→ const startOptimization = useCallback(\n 292→ (method) => {\n 293→ // Issue #6: Use current tour (possibly already optimized)\n 294→ const leftTour = getCurrentTour('left');\n 295→ const rightTour = getCurrentTour('right');\n 296→ if (leftTour.length === 0 || rightTour.length === 0) return;\n 297→\n 298→ const optFnMap = {\n 299→ '2-opt': twoOptSteps,\n 300→ '3-opt': threeOptSteps,\n 301→ 'k-opt': kOptSteps,\n 302→ 'lin-kernighan': linKernighanSteps,\n 303→ lkh: lkHelsgaunSteps,\n 304→ zigzag: zigzagOptSteps,\n 305→ };\n 306→ const optFn = optFnMap[method] || twoOptSteps;\n 307→ let newLeftOptSteps = optFn(points, leftTour);\n 308→ let newRightOptSteps = optFn(points, rightTour);\n 309→\n 310→ const optimalDistance = optimalResult?.distance;\n 311→ const methodLabelMap = {\n 312→ '2-opt': '2-opt',\n 313→ '3-opt': '3-opt',\n 314→ 'k-opt': 'k-opt',\n 315→ 'lin-kernighan': 'LK',\n 316→ lkh: 'LKH',\n 317→ zigzag: 'Zigzag',\n 318→ };\n 319→ const methodLabel = methodLabelMap[method] || method;\n 320→\n 321→ // When optimization finds no improvements, create a step with\n 322→ // comparison to the true optimal distance (if available)\n 323→ if (newLeftOptSteps.length === 0) {\n 324→ const leftDist = calculateTotalDistance(leftTour, points);\n 325→ let description;\n 326→ if (optimalDistance && Math.abs(leftDist - optimalDistance) < 0.001) {\n 327→ description = `${methodLabel}: Tour is already optimal (verified)`;\n 328→ } else if (optimalDistance) {\n 329→ const ratio = calculateOptimalityRatio(leftDist, optimalDistance);\n 330→ description = `${methodLabel}: No improvements found (${((ratio - 1) * 100).toFixed(1)}% above optimal)`;\n 331→ } else {\n 332→ // Use lower-bound verification for larger instances\n 333→ const verification = verifyOptimality(leftDist, points);\n 334→ if (verification.isOptimal) {\n 335→ description = `${methodLabel}: Tour is already optimal (verified by ${verification.method} bound)`;\n 336→ } else {\n 337→ description = `${methodLabel}: No improvements found (${verification.gapPercent.toFixed(1)}% above lower bound)`;\n 338→ }\n 339→ }\n 340→ newLeftOptSteps = [\n 341→ {\n 342→ type: 'optimize',\n 343→ tour: [...leftTour],\n 344→ improvement: 0,\n 345→ description,\n 346→ },\n 347→ ];\n 348→ }\n 349→ if (newRightOptSteps.length === 0) {\n 350→ const rightDist = calculateTotalDistance(rightTour, points);\n 351→ let description;\n 352→ if (optimalDistance && Math.abs(rightDist - optimalDistance) < 0.001) {\n 353→ description = `${methodLabel}: Tour is already optimal (verified)`;\n 354→ } else if (optimalDistance) {\n 355→ const ratio = calculateOptimalityRatio(rightDist, optimalDistance);\n 356→ description = `${methodLabel}: No improvements found (${((ratio - 1) * 100).toFixed(1)}% above optimal)`;\n 357→ } else {\n 358→ const verification = verifyOptimality(rightDist, points);\n 359→ if (verification.isOptimal) {\n 360→ description = `${methodLabel}: Tour is already optimal (verified by ${verification.method} bound)`;\n 361→ } else {\n 362→ description = `${methodLabel}: No improvements found (${verification.gapPercent.toFixed(1)}% above lower bound)`;\n 363→ }\n 364→ }\n 365→ newRightOptSteps = [\n 366→ {\n 367→ type: 'optimize',\n 368→ tour: [...rightTour],\n 369→ improvement: 0,\n 370→ description,\n 371→ },\n 372→ ];\n 373→ }\n 374→\n 375→ setLeftOptSteps(newLeftOptSteps);\n 376→ setRightOptSteps(newRightOptSteps);\n 377→ setLeftCurrentStep(0);\n 378→ setRightCurrentStep(0);\n 379→ setShowOptimization(true);\n 380→ setActiveOptimization(method);\n 381→ setIsRunning(true);\n 382→ },\n 383→ [points, getCurrentTour, optimalResult]\n 384→ );\n 385→\n 386→ // Animation loop\n 387→ useEffect(() => {\n 388→ if (!isRunning) return;\n 389→\n 390→ const currentLeftSteps = showOptimization ? leftOptSteps : leftSteps;\n 391→ const currentRightSteps = showOptimization ? rightOptSteps : rightSteps;\n 392→\n 393→ const leftDone = leftCurrentStep >= currentLeftSteps.length - 1;\n 394→ const rightDone = rightCurrentStep >= currentRightSteps.length - 1;\n 395→\n 396→ if (leftDone && rightDone) {\n 397→ setIsRunning(false);\n 398→ return;\n 399→ }\n 400→\n 401→ animationRef.current = setTimeout(() => {\n 402→ if (!leftDone) {\n 403→ setLeftCurrentStep((prev) =>\n 404→ Math.min(prev + 1, currentLeftSteps.length - 1)\n 405→ );\n 406→ }\n 407→ if (!rightDone) {\n 408→ setRightCurrentStep((prev) =>\n 409→ Math.min(prev + 1, currentRightSteps.length - 1)\n 410→ );\n 411→ }\n 412→ }, speed);\n 413→\n 414→ return () => {\n 415→ if (animationRef.current) {\n 416→ clearTimeout(animationRef.current);\n 417→ }\n 418→ };\n 419→ }, [\n 420→ isRunning,\n 421→ leftCurrentStep,\n 422→ rightCurrentStep,\n 423→ speed,\n 424→ showOptimization,\n 425→ leftSteps,\n 426→ rightSteps,\n 427→ leftOptSteps,\n 428→ rightOptSteps,\n 429→ ]);\n 430→\n 431→ const getLeftStep = () => {\n 432→ const steps = showOptimization ? leftOptSteps : leftSteps;\n 433→ return steps[leftCurrentStep];\n 434→ };\n 435→\n 436→ const getRightStep = () => {\n 437→ const steps = showOptimization ? rightOptSteps : rightSteps;\n 438→ return steps[rightCurrentStep];\n 439→ };\n 440→\n 441→ const calculateLeftDistance = () => {\n 442→ const step = getLeftStep();\n 443→ if (!step?.tour || step.tour.length < 2) return 0;\n 444→ return calculateTotalDistance(step.tour, points);\n 445→ };\n 446→\n 447→ const calculateRightDistance = () => {\n 448→ const step = getRightStep();\n 449→ if (!step?.tour || step.tour.length < 2) return 0;\n 450→ return calculateTotalDistance(step.tour, points);\n 451→ };\n 452→\n 453→ // Issue #6: canOptimize when solution is done (not running) and we have steps\n 454→ const solutionComplete =\n 455→ leftSteps.length > 0 &&\n 456→ rightSteps.length > 0 &&\n 457→ !isRunning &&\n 458→ (showOptimization\n 459→ ? leftCurrentStep >= leftOptSteps.length - 1\n 460→ : leftCurrentStep >= leftSteps.length - 1);\n 461→\n 462→ const canOptimize = solutionComplete;\n 463→\n 464→ // Issue #1: Format distance info with % of optimal and exact length\n 465→ const formatDistanceInfo = (dist) => {\n 466→ const distLabel = t(lang, 'distance');\n 467→ if (dist === 0) {\n 468→ return `${distLabel}: \\u2014`;\n 469→ }\n 470→ if (optimalResult) {\n 471→ const pct = ((dist / optimalResult.distance) * 100).toFixed(1);\n 472→ return `${distLabel}: ${dist.toFixed(2)} (${pct}% ${t(lang, 'ofOptimal')} ${optimalResult.distance.toFixed(2)})`;\n 473→ }\n 474→ if (verificationResult) {\n 475→ const lb = verificationResult.lowerBound;\n 476→ if (lb > 0) {\n 477→ const pct = ((dist / lb) * 100).toFixed(1);\n 478→ return `${distLabel}: ${dist.toFixed(2)} (${pct}% ${t(lang, 'ofLowerBound')} ${lb.toFixed(2)})`;\n 479→ }\n 480→ }\n 481→ return `${distLabel}: ${dist.toFixed(2)}`;\n 482→ };\n 483→\n 484→ // Dark/light theme state - default to system preference\n 485→ const [theme, setTheme] = useState(() => {\n 486→ if (\n 487→ typeof window !== 'undefined' &&\n 488→ window.matchMedia?.('(prefers-color-scheme: dark)').matches\n 489→ ) {\n 490→ return 'dark';\n 491→ }\n 492→ return 'light';\n 493→ });\n 494→ const toggleTheme = useCallback(() => {\n 495→ setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));\n 496→ }, []);\n 497→\n 498→ // Language state - default to browser preference\n 499→ const [lang, setLang] = useState(detectLanguage);\n 500→\n 501→ // Apply theme to document root for CSS custom properties\n 502→ useEffect(() => {\n 503→ document.documentElement.setAttribute('data-theme', theme);\n 504→ }, [theme]);\n 505→\n 506→ const algorithmMeta = getAlgorithmMeta(lang);\n 507→ const leftMeta = algorithmMeta[leftAlgorithm];\n 508→ const rightMeta = algorithmMeta[rightAlgorithm];\n 509→\n 510→ // Map algorithm ids to i18n keys\n 511→ const algorithmLabelKeys = {\n 512→ sonar: 'sonarVisit',\n 513→ moore: 'mooreCurve',\n 514→ gosper: 'gosperCurve',\n 515→ peano: 'peanoCurve',\n 516→ sierpinski: 'sierpinskiCurve',\n 517→ comb: 'combScan',\n 518→ saw: 'selfAvoidingWalk',\n 519→ koch: 'kochSnowflake',\n 520→ 'space-filling-tree': 'spaceFillingTree',\n 521→ 'brute-force': 'bruteForce',\n 522→ };\n 523→\n 524→ // Translated algorithm options\n 525→ const translatedAlgorithmOptions = ALGORITHM_OPTIONS.map((opt) => ({\n 526→ ...opt,\n 527→ label: t(lang, algorithmLabelKeys[opt.id]),\n 528→ }));\n 529→\n 530→ // Filtered options for algorithm selects (exclude the other side's selection)\n 531→ const leftAlgorithmOptions = translatedAlgorithmOptions.filter(\n 532→ (opt) => opt.id !== rightAlgorithm\n 533→ );\n 534→ const rightAlgorithmOptions = translatedAlgorithmOptions.filter(\n 535→ (opt) => opt.id !== leftAlgorithm\n 536→ );\n 537→\n 538→ return (\n 539→ <div className=\"app\">\n 540→ <div className=\"app-header\">\n 541→ <div className=\"language-selector\">\n 542→ <select\n 543→ value={lang}\n 544→ onChange={(e) => setLang(e.target.value)}\n 545→ aria-label=\"Language\"\n 546→ >\n 547→ {LANGUAGES.map((l) => (\n 548→ <option key={l.code} value={l.code}>\n 549→ {l.flag} {l.name}\n 550→ </option>\n 551→ ))}\n 552→ </select>\n 553→ </div>\n 554→ <h1>{t(lang, 'title')}</h1>\n 555→ <button\n 556→ className=\"theme-toggle\"\n 557→ onClick={toggleTheme}\n 558→ aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}\n 559→ title={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}\n 560→ >\n 561→ {theme === 'light' ? '\\u{263E}' : '\\u{2600}'}\n 562→ </button>\n 563→ </div>\n 564→\n 565→ <Controls\n 566→ gridSize={gridSize}\n 567→ setGridSize={setGridSize}\n 568→ numPoints={numPoints}\n 569→ setNumPoints={setNumPoints}\n 570→ speed={speed}\n 571→ setSpeed={setSpeed}\n 572→ mooreGridSize={mooreGridSize}\n 573→ isRunning={isRunning}\n 574→ canOptimize={canOptimize}\n 575→ activeOptimization={activeOptimization}\n 576→ onGeneratePoints={generatePoints}\n 577→ onStart={startSolution}\n 578→ onStop={stopAnimation}\n 579→ onOptimize={startOptimization}\n 580→ pointsCount={points.length}\n 581→ startDisabled={startDisabled}\n 582→ startDisabledReason={startDisabledReason}\n 583→ lang={lang}\n 584→ />\n 585→\n 586→ <div className=\"visualization-container\">\n 587→ <VisualizationPanel\n 588→ selectedAlgorithm={leftAlgorithm}\n 589→ onAlgorithmChange={setLeftAlgorithm}\n 590→ algorithmOptions={leftAlgorithmOptions}\n 591→ isRunning={isRunning}\n 592→ aliases={leftMeta.aliases}\n 593→ distanceInfo={formatDistanceInfo(calculateLeftDistance())}\n 594→ visualization={\n 595→ <TSPVisualization\n 596→ points={points}\n 597→ steps={showOptimization ? leftOptSteps : leftSteps}\n 598→ currentStep={leftCurrentStep}\n 599→ algorithm={leftMeta.vizType}\n 600→ mooreGridSize={mooreGridSize}\n 601→ showOptimization={showOptimization}\n 602→ />\n 603→ }\n 604→ stepDescription={getLeftStep()?.description}\n 605→ defaultStepText={t(lang, 'clickStart')}\n 606→ legend={\n 607→ <Legend\n 608→ algorithm={leftMeta.vizType}\n 609→ showOptimization={showOptimization}\n 610→ lang={lang}\n 611→ />\n 612→ }\n 613→ />\n 614→\n 615→ <VisualizationPanel\n 616→ selectedAlgorithm={rightAlgorithm}\n 617→ onAlgorithmChange={setRightAlgorithm}\n 618→ algorithmOptions={rightAlgorithmOptions}\n 619→ isRunning={isRunning}\n 620→ aliases={rightMeta.aliases}\n 621→ distanceInfo={formatDistanceInfo(calculateRightDistance())}\n 622→ visualization={\n 623→ <TSPVisualization\n 624→ points={points}\n 625→ steps={showOptimization ? rightOptSteps : rightSteps}\n 626→ currentStep={rightCurrentStep}\n 627→ algorithm={rightMeta.vizType}\n 628→ mooreGridSize={mooreGridSize}\n 629→ showOptimization={showOptimization}\n 630→ />\n 631→ }\n 632→ stepDescription={getRightStep()?.description}\n 633→ defaultStepText={t(lang, 'clickStart')}\n 634→ legend={\n 635→ <Legend\n 636→ algorithm={rightMeta.vizType}\n 637→ showOptimization={showOptimization}\n 638→ lang={lang}\n 639→ />\n 640→ }\n 641→ />\n 642→ </div>\n 643→ </div>\n 644→ );\n 645→};\n 646→\n 647→export { App };\n 648→export default App;\n 649→\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n"
}
]
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "a3a6759e-28ba-47d9-843f-7f3198a10d81",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/tmp/gh-issue-solver-1770502731119/src/app/ui/App.jsx",
"content": "/**\n * Main App Component for TSP Visual Solver\n *\n * Orchestrates the TSP solver application including:\n * - State management for points, algorithm steps, and animation\n * - Algorithm execution with user-selectable algorithms for side-by-side comparison\n * - Verification of optimal tour distance via lower bound and brute-force\n * - UI layout with controls and side-by-side visualizations\n */\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\n\nimport { LANGUAGES, detectLanguage, t } from './i18n.js';\n\n// Import algorithm functions from lib\nimport {\n calculateMooreGridSize,\n calculatePeanoGridSize,\n generateRandomPoints,\n calculateTotalDistance,\n sonarAlgorithmSteps,\n mooreAlgorithmSteps,\n gosperAlgorithmSteps,\n peanoAlgorithmSteps,\n sierpinskiAlgorithmSteps,\n combAlgorithmSteps,\n sawAlgorithmSteps,\n kochAlgorithmSteps,\n spaceFillingTreeAlgorithmSteps,\n bruteForceAlgorithmSteps,\n bruteForceSolution,\n calculateOptimalityRatio,\n BRUTE_FORCE_MAX_POINTS,\n // Generic optimizations that can work with any tour\n zigzagOptSteps,\n twoOptSteps,\n threeOptSteps,\n kOptSteps,\n linKernighanSteps,\n lkHelsgaunSteps,\n // Verification\n verifyOptimality,\n} from '../../lib/index.js';\n\n// Import UI components\nimport { TSPVisualization } from './components/TSPVisualization.jsx';\nimport { Controls, ALGORITHM_OPTIONS } from './components/Controls.jsx';\nimport { Legend } from './components/Legend.jsx';\nimport { VisualizationPanel } from './components/VisualizationPanel.jsx';\n\n/**\n * Get algorithm metadata using i18n translations\n */\nconst getAlgorithmMeta = (lang) => ({\n sonar: {\n title: t(lang, 'sonarTitle'),\n aliases: t(lang, 'sonarAliases'),\n vizType: 'sonar',\n },\n moore: {\n title: t(lang, 'mooreTitle'),\n aliases: t(lang, 'mooreAliases'),\n vizType: 'moore',\n },\n gosper: {\n title: t(lang, 'gosperTitle'),\n aliases: t(lang, 'gosperAliases'),\n vizType: 'gosper',\n },\n peano: {\n title: t(lang, 'peanoTitle'),\n aliases: t(lang, 'peanoAliases'),\n vizType: 'peano',\n },\n sierpinski: {\n title: t(lang, 'sierpinskiTitle'),\n aliases: t(lang, 'sierpinskiAliases'),\n vizType: 'sierpinski',\n },\n comb: {\n title: t(lang, 'combTitle'),\n aliases: t(lang, 'combAliases'),\n vizType: 'comb',\n },\n saw: {\n title: t(lang, 'sawTitle'),\n aliases: t(lang, 'sawAliases'),\n vizType: 'saw',\n },\n koch: {\n title: t(lang, 'kochTitle'),\n aliases: t(lang, 'kochAliases'),\n vizType: 'koch',\n },\n 'space-filling-tree': {\n title: t(lang, 'spaceFillingTreeTitle'),\n aliases: t(lang, 'spaceFillingTreeAliases'),\n vizType: 'space-filling-tree',\n },\n 'brute-force': {\n title: t(lang, 'bruteForceTitle'),\n aliases: t(lang, 'bruteForceAliases'),\n vizType: 'brute-force',\n },\n});\n\n/**\n * Run the specified algorithm on the given points.\n * Returns steps array for progressive visualization.\n */\nconst runAlgorithmSteps = (algorithmId, points, mooreGridSize) => {\n switch (algorithmId) {\n case 'sonar':\n return sonarAlgorithmSteps(points);\n case 'moore':\n return mooreAlgorithmSteps(points, mooreGridSize);\n case 'gosper':\n return gosperAlgorithmSteps(points, mooreGridSize);\n case 'peano':\n return peanoAlgorithmSteps(points, calculatePeanoGridSize(mooreGridSize));\n case 'sierpinski':\n return sierpinskiAlgorithmSteps(points, mooreGridSize);\n case 'comb':\n return combAlgorithmSteps(points);\n case 'saw':\n return sawAlgorithmSteps(points);\n case 'koch':\n return kochAlgorithmSteps(points, mooreGridSize);\n case 'space-filling-tree':\n return spaceFillingTreeAlgorithmSteps(points);\n case 'brute-force':\n return bruteForceAlgorithmSteps(points);\n default:\n return [];\n }\n};\n\n/**\n * Check if an algorithm is execution-limited for the given number of points.\n */\nconst isAlgorithmLimited = (algorithmId, numPoints) =>\n algorithmId === 'brute-force' && numPoints > BRUTE_FORCE_MAX_POINTS;\n\n/**\n * App - Main application component\n */\nconst App = () => {\n const [gridSize, setGridSize] = useState(16);\n const [numPoints, setNumPoints] = useState(15);\n const [points, setPoints] = useState([]);\n const [speed, setSpeed] = useState(500);\n const [isRunning, setIsRunning] = useState(false);\n const [showOptimization, setShowOptimization] = useState(false);\n const [activeOptimization, setActiveOptimization] = useState(null);\n\n // Algorithm selection state\n const [leftAlgorithm, setLeftAlgorithm] = useState('sonar');\n const [rightAlgorithm, setRightAlgorithm] = useState('moore');\n\n // Calculate Moore grid size - this is the unified grid both algorithms use\n const mooreGridSize = calculateMooreGridSize(gridSize);\n const maxPoints = mooreGridSize * mooreGridSize;\n\n // Left panel state\n const [leftSteps, setLeftSteps] = useState([]);\n const [leftOptSteps, setLeftOptSteps] = useState([]);\n const [leftCurrentStep, setLeftCurrentStep] = useState(-1);\n\n // Right panel state\n const [rightSteps, setRightSteps] = useState([]);\n const [rightOptSteps, setRightOptSteps] = useState([]);\n const [rightCurrentStep, setRightCurrentStep] = useState(-1);\n\n // Verification state\n const [optimalResult, setOptimalResult] = useState(null);\n const [verificationResult, setVerificationResult] = useState(null);\n\n const animationRef = useRef(null);\n\n // Enforce points limit when grid size changes (Issue #5)\n useEffect(() => {\n if (numPoints > maxPoints) {\n setNumPoints(Math.max(3, maxPoints));\n }\n }, [maxPoints, numPoints]);\n\n const generatePoints = useCallback(() => {\n const actualNumPoints = Math.min(numPoints, maxPoints);\n const newPoints = generateRandomPoints(mooreGridSize, actualNumPoints);\n setPoints(newPoints);\n setLeftSteps([]);\n setLeftOptSteps([]);\n setLeftCurrentStep(-1);\n setRightSteps([]);\n setRightOptSteps([]);\n setRightCurrentStep(-1);\n setIsRunning(false);\n setShowOptimization(false);\n setActiveOptimization(null);\n setOptimalResult(null);\n setVerificationResult(null);\n }, [mooreGridSize, numPoints, maxPoints]);\n\n useEffect(() => {\n generatePoints();\n }, []);\n\n // Compute optimal tour when points change (brute-force for small sets)\n useEffect(() => {\n if (points.length >= 2 && points.length <= BRUTE_FORCE_MAX_POINTS) {\n const result = bruteForceSolution(points);\n setOptimalResult(result);\n } else {\n setOptimalResult(null);\n }\n }, [points]);\n\n // Compute lower-bound verification when points change\n useEffect(() => {\n if (points.length >= 2) {\n // We use a dummy distance of 0 — we just need the lower bound value\n const result = verifyOptimality(0, points);\n setVerificationResult(result);\n } else {\n setVerificationResult(null);\n }\n }, [points]);\n\n // Issue #8: Check if either algorithm is limited\n const startDisabled =\n isAlgorithmLimited(leftAlgorithm, points.length) ||\n isAlgorithmLimited(rightAlgorithm, points.length);\n\n const startDisabledReason = startDisabled\n ? `Brute-Force limited to ${BRUTE_FORCE_MAX_POINTS} points (current: ${points.length})`\n : '';\n\n const startSolution = useCallback(() => {\n if (points.length === 0 || startDisabled) return;\n\n const newLeftSteps = runAlgorithmSteps(\n leftAlgorithm,\n points,\n mooreGridSize\n );\n const newRightSteps = runAlgorithmSteps(\n rightAlgorithm,\n points,\n mooreGridSize\n );\n\n setLeftSteps(newLeftSteps);\n setRightSteps(newRightSteps);\n setLeftCurrentStep(0);\n setRightCurrentStep(0);\n setShowOptimization(false);\n setActiveOptimization(null);\n setLeftOptSteps([]);\n setRightOptSteps([]);\n setIsRunning(true);\n }, [points, mooreGridSize, leftAlgorithm, rightAlgorithm, startDisabled]);\n\n const stopAnimation = useCallback(() => {\n setIsRunning(false);\n if (animationRef.current) {\n clearTimeout(animationRef.current);\n }\n }, []);\n\n // Issue #6: Get the current tour for a side (considering optimization)\n const getCurrentTour = useCallback(\n (side) => {\n if (side === 'left') {\n if (showOptimization && leftOptSteps.length > 0) {\n return leftOptSteps[leftOptSteps.length - 1]?.tour || [];\n }\n return leftSteps.length > 0\n ? leftSteps[leftSteps.length - 1]?.tour || []\n : [];\n }\n if (showOptimization && rightOptSteps.length > 0) {\n return rightOptSteps[rightOptSteps.length - 1]?.tour || [];\n }\n return rightSteps.length > 0\n ? rightSteps[rightSteps.length - 1]?.tour || []\n : [];\n },\n [showOptimization, leftOptSteps, rightOptSteps, leftSteps, rightSteps]\n );\n\n const startOptimization = useCallback(\n (method) => {\n // Issue #6: Use current tour (possibly already optimized)\n const leftTour = getCurrentTour('left');\n const rightTour = getCurrentTour('right');\n if (leftTour.length === 0 || rightTour.length === 0) return;\n\n const optFnMap = {\n '2-opt': twoOptSteps,\n '3-opt': threeOptSteps,\n 'k-opt': kOptSteps,\n 'lin-kernighan': linKernighanSteps,\n lkh: lkHelsgaunSteps,\n zigzag: zigzagOptSteps,\n };\n const optFn = optFnMap[method] || twoOptSteps;\n let newLeftOptSteps = optFn(points, leftTour);\n let newRightOptSteps = optFn(points, rightTour);\n\n const optimalDistance = optimalResult?.distance;\n const methodLabelMap = {\n '2-opt': '2-opt',\n '3-opt': '3-opt',\n 'k-opt': 'k-opt',\n 'lin-kernighan': 'LK',\n lkh: 'LKH',\n zigzag: 'Zigzag',\n };\n const methodLabel = methodLabelMap[method] || method;\n\n // When optimization finds no improvements, create a step with\n // comparison to the true optimal distance (if available)\n if (newLeftOptSteps.length === 0) {\n const leftDist = calculateTotalDistance(leftTour, points);\n let description;\n if (optimalDistance && Math.abs(leftDist - optimalDistance) < 0.001) {\n description = `${methodLabel}: Tour is already optimal (verified)`;\n } else if (optimalDistance) {\n const ratio = calculateOptimalityRatio(leftDist, optimalDistance);\n description = `${methodLabel}: No improvements found (${((ratio - 1) * 100).toFixed(1)}% above optimal)`;\n } else {\n // Use lower-bound verification for larger instances\n const verification = verifyOptimality(leftDist, points);\n if (verification.isOptimal) {\n description = `${methodLabel}: Tour is already optimal (verified by ${verification.method} bound)`;\n } else {\n description = `${methodLabel}: No improvements found (${verification.gapPercent.toFixed(1)}% above lower bound)`;\n }\n }\n newLeftOptSteps = [\n {\n type: 'optimize',\n tour: [...leftTour],\n improvement: 0,\n description,\n },\n ];\n }\n if (newRightOptSteps.length === 0) {\n const rightDist = calculateTotalDistance(rightTour, points);\n let description;\n if (optimalDistance && Math.abs(rightDist - optimalDistance) < 0.001) {\n description = `${methodLabel}: Tour is already optimal (verified)`;\n } else if (optimalDistance) {\n const ratio = calculateOptimalityRatio(rightDist, optimalDistance);\n description = `${methodLabel}: No improvements found (${((ratio - 1) * 100).toFixed(1)}% above optimal)`;\n } else {\n const verification = verifyOptimality(rightDist, points);\n if (verification.isOptimal) {\n description = `${methodLabel}: Tour is already optimal (verified by ${verification.method} bound)`;\n } else {\n description = `${methodLabel}: No improvements found (${verification.gapPercent.toFixed(1)}% above lower bound)`;\n }\n }\n newRightOptSteps = [\n {\n type: 'optimize',\n tour: [...rightTour],\n improvement: 0,\n description,\n },\n ];\n }\n\n setLeftOptSteps(newLeftOptSteps);\n setRightOptSteps(newRightOptSteps);\n setLeftCurrentStep(0);\n setRightCurrentStep(0);\n setShowOptimization(true);\n setActiveOptimization(method);\n setIsRunning(true);\n },\n [points, getCurrentTour, optimalResult]\n );\n\n // Animation loop\n useEffect(() => {\n if (!isRunning) return;\n\n const currentLeftSteps = showOptimization ? leftOptSteps : leftSteps;\n const currentRightSteps = showOptimization ? rightOptSteps : rightSteps;\n\n const leftDone = leftCurrentStep >= currentLeftSteps.length - 1;\n const rightDone = rightCurrentStep >= currentRightSteps.length - 1;\n\n if (leftDone && rightDone) {\n setIsRunning(false);\n return;\n }\n\n animationRef.current = setTimeout(() => {\n if (!leftDone) {\n setLeftCurrentStep((prev) =>\n Math.min(prev + 1, currentLeftSteps.length - 1)\n );\n }\n if (!rightDone) {\n setRightCurrentStep((prev) =>\n Math.min(prev + 1, currentRightSteps.length - 1)\n );\n }\n }, speed);\n\n return () => {\n if (animationRef.current) {\n clearTimeout(animationRef.current);\n }\n };\n }, [\n isRunning,\n leftCurrentStep,\n rightCurrentStep,\n speed,\n showOptimization,\n leftSteps,\n rightSteps,\n leftOptSteps,\n rightOptSteps,\n ]);\n\n const getLeftStep = () => {\n const steps = showOptimization ? leftOptSteps : leftSteps;\n return steps[leftCurrentStep];\n };\n\n const getRightStep = () => {\n const steps = showOptimization ? rightOptSteps : rightSteps;\n return steps[rightCurrentStep];\n };\n\n const calculateLeftDistance = () => {\n const step = getLeftStep();\n if (!step?.tour || step.tour.length < 2) return 0;\n return calculateTotalDistance(step.tour, points);\n };\n\n const calculateRightDistance = () => {\n const step = getRightStep();\n if (!step?.tour || step.tour.length < 2) return 0;\n return calculateTotalDistance(step.tour, points);\n };\n\n // Issue #6: canOptimize when solution is done (not running) and we have steps\n const solutionComplete =\n leftSteps.length > 0 &&\n rightSteps.length > 0 &&\n !isRunning &&\n (showOptimization\n ? leftCurrentStep >= leftOptSteps.length - 1\n : leftCurrentStep >= leftSteps.length - 1);\n\n const canOptimize = solutionComplete;\n\n // Issue #1: Format distance info with % of optimal and exact length\n const formatDistanceInfo = (dist) => {\n const distLabel = t(lang, 'distance');\n if (dist === 0) {\n return `${distLabel}: \\u2014`;\n }\n if (optimalResult) {\n const pct = ((dist / optimalResult.distance) * 100).toFixed(1);\n return `${distLabel}: ${dist.toFixed(2)} (${pct}% ${t(lang, 'ofOptimal')} ${optimalResult.distance.toFixed(2)})`;\n }\n if (verificationResult) {\n const lb = verificationResult.lowerBound;\n if (lb > 0) {\n const pct = ((dist / lb) * 100).toFixed(1);\n return `${distLabel}: ${dist.toFixed(2)} (${pct}% ${t(lang, 'ofLowerBound')} ${lb.toFixed(2)})`;\n }\n }\n return `${distLabel}: ${dist.toFixed(2)}`;\n };\n\n // Dark/light theme state - default to system preference\n const [theme, setTheme] = useState(() => {\n if (\n typeof window !== 'undefined' &&\n window.matchMedia?.('(prefers-color-scheme: dark)').matches\n ) {\n return 'dark';\n }\n return 'light';\n });\n const toggleTheme = useCallback(() => {\n setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));\n }, []);\n\n // Language state - default to browser preference\n const [lang, setLang] = useState(detectLanguage);\n\n // Apply theme to document root for CSS custom properties\n useEffect(() => {\n document.documentElement.setAttribute('data-theme', theme);\n }, [theme]);\n\n const algorithmMeta = getAlgorithmMeta(lang);\n const leftMeta = algorithmMeta[leftAlgorithm];\n const rightMeta = algorithmMeta[rightAlgorithm];\n\n // Map algorithm ids to i18n keys\n const algorithmLabelKeys = {\n sonar: 'sonarVisit',\n moore: 'mooreCurve',\n gosper: 'gosperCurve',\n peano: 'peanoCurve',\n sierpinski: 'sierpinskiCurve',\n comb: 'combScan',\n saw: 'selfAvoidingWalk',\n koch: 'kochSnowflake',\n 'space-filling-tree': 'spaceFillingTree',\n 'brute-force': 'bruteForce',\n };\n\n // Translated algorithm options\n const translatedAlgorithmOptions = ALGORITHM_OPTIONS.map((opt) => ({\n ...opt,\n label: t(lang, algorithmLabelKeys[opt.id]),\n }));\n\n // Filtered options for algorithm selects (exclude the other side's selection)\n const leftAlgorithmOptions = translatedAlgorithmOptions.filter(\n (opt) => opt.id !== rightAlgorithm\n );\n const rightAlgorithmOptions = translatedAlgorithmOptions.filter(\n (opt) => opt.id !== leftAlgorithm\n );\n\n return (\n <div className=\"app\">\n <div className=\"app-header\">\n <div className=\"language-selector\">\n <select\n value={lang}\n onChange={(e) => setLang(e.target.value)}\n aria-label=\"Language\"\n >\n {LANGUAGES.map((l) => (\n <option key={l.code} value={l.code}>\n {l.flag} {l.name}\n </option>\n ))}\n </select>\n </div>\n <h1>{t(lang, 'title')}</h1>\n <button\n className=\"theme-toggle\"\n onClick={toggleTheme}\n aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}\n title={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}\n >\n {theme === 'light' ? '\\u{263E}' : '\\u{2600}'}\n </button>\n </div>\n\n <Controls\n gridSize={gridSize}\n setGridSize={setGridSize}\n numPoints={numPoints}\n setNumPoints={setNumPoints}\n speed={speed}\n setSpeed={setSpeed}\n mooreGridSize={mooreGridSize}\n isRunning={isRunning}\n canOptimize={canOptimize}\n activeOptimization={activeOptimization}\n onGeneratePoints={generatePoints}\n onStart={startSolution}\n onStop={stopAnimation}\n onOptimize={startOptimization}\n pointsCount={points.length}\n startDisabled={startDisabled}\n startDisabledReason={startDisabledReason}\n lang={lang}\n />\n\n <div className=\"visualization-container\">\n <VisualizationPanel\n selectedAlgorithm={leftAlgorithm}\n onAlgorithmChange={setLeftAlgorithm}\n algorithmOptions={leftAlgorithmOptions}\n isRunning={isRunning}\n aliases={leftMeta.aliases}\n distanceInfo={formatDistanceInfo(calculateLeftDistance())}\n visualization={\n <TSPVisualization\n points={points}\n steps={showOptimization ? leftOptSteps : leftSteps}\n currentStep={leftCurrentStep}\n algorithm={leftMeta.vizType}\n mooreGridSize={mooreGridSize}\n showOptimization={showOptimization}\n />\n }\n stepDescription={getLeftStep()?.description}\n defaultStepText={t(lang, 'clickStart')}\n legend={\n <Legend\n algorithm={leftMeta.vizType}\n showOptimization={showOptimization}\n lang={lang}\n />\n }\n />\n\n <VisualizationPanel\n selectedAlgorithm={rightAlgorithm}\n onAlgorithmChange={setRightAlgorithm}\n algorithmOptions={rightAlgorithmOptions}\n isRunning={isRunning}\n aliases={rightMeta.aliases}\n distanceInfo={formatDistanceInfo(calculateRightDistance())}\n visualization={\n <TSPVisualization\n points={points}\n steps={showOptimization ? rightOptSteps : rightSteps}\n currentStep={rightCurrentStep}\n algorithm={rightMeta.vizType}\n mooreGridSize={mooreGridSize}\n showOptimization={showOptimization}\n />\n }\n stepDescription={getRightStep()?.description}\n defaultStepText={t(lang, 'clickStart')}\n legend={\n <Legend\n algorithm={rightMeta.vizType}\n showOptimization={showOptimization}\n lang={lang}\n />\n }\n />\n </div>\n </div>\n );\n};\n\nexport { App };\nexport default App;\n",
"numLines": 649,
"startLine": 1,
"totalLines": 649
}
}
}
[2026-02-07T22:21:32.517Z] [INFO] {
"type": "assistant",
"message": {
"model": "claude-opus-4-6",
"id": "msg_01F3oSaWN1n2nqYBy43WaPCd",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_012aAoZeNKjNNS2HJyMB5swb",
"name": "Read",
"input": {
"file_path": "/tmp/gh-issue-solver-1770502731119/src/cli/index.js"
}
}
],
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 1,
"cache_creation_input_tokens": 11030,
"cache_read_input_tokens": 45918,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 11030
},
"output_tokens": 1,
"service_tier": "standard",
"inference_geo": "not_available"
},
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "98276873-523b-4a38-b382-8dec13a6021c",
"uuid": "905cb1b0-574d-48e0-a6a5-3f9b07fd1b64"
}
[2026-02-07T22:21:32.521Z] [INFO] {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_012aAoZeNKjNNS2HJyMB5swb",
"type": "tool_result",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment