{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Ollama Worker Demo\n", "\n", "This notebook demonstrates the structured local worker flow:\n", "\n", "1. Create a task packet\n", "2. Create a worker\n", "3. Run the worker with a live Ollama-backed task\n", "4. Inspect worker state\n", "5. Resume the last packet\n", "6. Close the worker\n", "\n", "The notebook captures the `worker_id` programmatically. No manual copy/paste is required." ] }, { "cell_type": "code", "execution_count": 1, "id": "e9f6a34f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Workspace root: /Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\n", "Python: /Users/wongdowling/opt/anaconda3/bin/python\n" ] } ], "source": [ "from __future__ import annotations\n", "\n", "import json\n", "import shlex\n", "import subprocess\n", "import sys\n", "import urllib.error\n", "import urllib.request\n", "from pathlib import Path\n", "\n", "def is_repo_root(candidate: Path) -> bool:\n", " return (candidate / \"src\" / \"main.py\").exists() and (candidate / \"tests\" / \"test_porting_workspace.py\").exists()\n", "\n", "def find_repo_root(start: Path | None = None) -> Path:\n", " current = (start or Path.cwd()).resolve()\n", " for candidate in (current, *current.parents):\n", " if is_repo_root(candidate):\n", " return candidate\n", " for nested in (candidate / \"claw-code\", candidate / \"harness\" / \"claw-code\"):\n", " if is_repo_root(nested):\n", " return nested\n", " raise RuntimeError(\n", " f\"Could not locate the claw-code repo from {current}. Start the notebook from the repo, its notebooks directory, or the enclosing autoresearch workspace.\"\n", " )\n", "\n", "ROOT = find_repo_root()\n", "PYTHON = sys.executable\n", "NOTEBOOK_DIR = ROOT / \"notebooks\"\n", "NOTEBOOK_DIR.mkdir(parents=True, exist_ok=True)\n", "\n", "def run_cmd(args: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:\n", " print(\"$\", \" \".join(shlex.quote(arg) for arg in args))\n", " result = subprocess.run(args, cwd=ROOT, capture_output=True, text=True)\n", " if result.stdout:\n", " print(result.stdout)\n", " if result.stderr:\n", " print(result.stderr, file=sys.stderr)\n", " if check and result.returncode != 0:\n", " details = result.stderr.strip() or result.stdout.strip() or \"no output\"\n", " raise RuntimeError(f\"command failed with exit code {result.returncode}: {details}\")\n", " return result\n", "\n", "def run_json(args: list[str], check: bool = True):\n", " result = run_cmd(args, check=check)\n", " return json.loads(result.stdout)\n", "\n", "def ollama_ready(host: str = \"http://localhost:11434\") -> bool:\n", " try:\n", " with urllib.request.urlopen(f\"{host.rstrip('/')}/api/tags\", timeout=2) as response:\n", " return response.status == 200\n", " except (urllib.error.URLError, TimeoutError):\n", " return False\n", "\n", "print(f\"Workspace root: {ROOT}\")\n", "print(f\"Python: {PYTHON}\")" ] }, { "cell_type": "code", "execution_count": 2, "id": "62a8107a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'ollama_host': 'http://localhost:11434', 'ollama_ready': True}\n" ] } ], "source": [ "OLLAMA_HOST = \"http://localhost:11434\"\n", "OLLAMA_MODEL = \"qwen2.5-coder:7b\"\n", "OLLAMA_IS_READY = ollama_ready(OLLAMA_HOST)\n", "print({\"ollama_host\": OLLAMA_HOST, \"ollama_ready\": OLLAMA_IS_READY})\n", "if not OLLAMA_IS_READY:\n", " raise RuntimeError(\"Ollama is not reachable. Start Ollama before running the live smoke test.\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "b58cc4d9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PosixPath('/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code/notebooks/demo_task.json')" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "task_packet = {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", "}\n", "\n", "task_path = NOTEBOOK_DIR / \"demo_task.json\"\n", "task_path.write_text(json.dumps(task_packet, indent=2), encoding=\"utf-8\")\n", "task_path" ] }, { "cell_type": "code", "execution_count": 4, "id": "e2c19f73", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "$ /Users/wongdowling/opt/anaconda3/bin/python -m src.main worker create --root /Users/wongdowling/Documents/autoresearch_harness/harness/claw-code --model qwen2.5-coder:7b --host http://localhost:11434\n", "{\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"root\": \"/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\",\n", " \"model\": \"qwen2.5-coder:7b\",\n", " \"host\": \"http://localhost:11434\",\n", " \"state\": \"ready\",\n", " \"created_at\": \"2026-04-07T20:09:34Z\",\n", " \"updated_at\": \"2026-04-07T20:09:34Z\",\n", " \"run_count\": 0,\n", " \"last_packet\": null,\n", " \"last_result\": null,\n", " \"last_error\": null\n", "}\n", "\n" ] }, { "data": { "text/plain": [ "{'worker_id': '07786cd4905d4275ab8666a113bf7e10',\n", " 'root': '/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code',\n", " 'model': 'qwen2.5-coder:7b',\n", " 'host': 'http://localhost:11434',\n", " 'state': 'ready',\n", " 'created_at': '2026-04-07T20:09:34Z',\n", " 'updated_at': '2026-04-07T20:09:34Z',\n", " 'run_count': 0,\n", " 'last_packet': None,\n", " 'last_result': None,\n", " 'last_error': None}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "worker = run_json([\n", " PYTHON,\n", " \"-m\",\n", " \"src.main\",\n", " \"worker\",\n", " \"create\",\n", " \"--root\",\n", " str(ROOT),\n", " \"--model\",\n", " OLLAMA_MODEL,\n", " \"--host\",\n", " OLLAMA_HOST,\n", "])\n", "worker_id = worker[\"worker_id\"]\n", "worker" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "$ /Users/wongdowling/opt/anaconda3/bin/python -m src.main worker run 07786cd4905d4275ab8666a113bf7e10 --packet /Users/wongdowling/Documents/autoresearch_harness/harness/claw-code/notebooks/demo_task.json --trace\n", "{\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"root\": \"/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\",\n", " \"model\": \"qwen2.5-coder:7b\",\n", " \"host\": \"http://localhost:11434\",\n", " \"state\": \"finished\",\n", " \"created_at\": \"2026-04-07T20:09:34Z\",\n", " \"updated_at\": \"2026-04-07T20:10:20Z\",\n", " \"run_count\": 1,\n", " \"last_packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"last_result\": {\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"state\": \"finished\",\n", " \"packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"tool_calls\": [\n", " \"read_file\"\n", " ],\n", " \"tool_trace\": [\n", " {\n", " \"turn\": 1,\n", " \"name\": \"read_file\",\n", " \"arguments\": {\n", " \"path\": \"src/main.py\"\n", " },\n", " \"success\": true,\n", " \"output\": \"1\\tfrom __future__ import annotations\\n2\\t\\n3\\timport argparse\\n4\\timport json\\n5\\timport sys\\n6\\tfrom pathlib import Path\\n7\\t\\n8\\tfrom .autoresearch_runner import parse_run_log, setup_autoresearch\\n9\\tfrom .autoresearch_worker import run_autoresearch_packet\\n10\\tfrom .bootstrap_graph import build_bootstrap_graph\\n11\\tfrom .command_graph import build_command_graph\\n12\\tfrom .commands import execute_command, get_command, get_commands, render_command_index\\n13\\tfrom .agent_loop import DEFAULT_AGENT_SYSTEM_PROMPT, run_agent_task\\n14\\tfrom .llm_backend import DEFAULT_OLLAMA_HOST, DEFAULT_OLLAMA_MODEL, LLMBackendError\\n15\\tfrom .direct_modes import run_deep_link, run_direct_connect\\n16\\tfrom .parity_audit import run_parity_audit\\n17\\tfrom .permissions import ToolPermissionContext\\n18\\tfrom .port_manifest import build_port_manifest\\n19\\tfrom .query_engine import QueryEnginePort\\n20\\tfrom .remote_runtime import run_remote_mode, run_ssh_mode, run_teleport_mode\\n21\\tfrom .runtime import PortRuntime\\n22\\tfrom .session_store import load_session\\n23\\tfrom .setup import run_setup\\n24\\tfrom .task import DEFAULT_SYSTEM_PROMPT, run_local_task\\n25\\tfrom .worker_api import close_worker, create_worker, list_workers, load_worker, resume_worker, run_worker\\n26\\tfrom .tool_pool import assemble_tool_pool\\n27\\tfrom .tools import execute_tool, get_tool, get_tools, render_tool_index\\n28\\t\\n29\\t\\n30\\tdef build_parser() -> argparse.ArgumentParser:\\n31\\t parser = argparse.ArgumentParser(description='Python porting workspace for the Claude Code rewrite effort')\\n32\\t subparsers = parser.add_subparsers(dest='command', required=True)\\n33\\t subparsers.add_parser('summary', help='render a Markdown summary of the Python porting workspace')\\n34\\t subparsers.add_parser('manifest', help='print the current Python workspace manifest')\\n35\\t subparsers.add_parser('parity-audit', help='compare the Python workspace against the local ignored TypeScript archive when available')\\n36\\t subparsers.add_parser('setup-report', help='render the startup/prefetch setup report')\\n37\\t subparsers.add_parser('command-graph', help='show command graph segmentation')\\n38\\t subparsers.add_parser('tool-pool', help='show assembled tool pool with default settings')\\n39\\t subparsers.add_parser('bootstrap-graph', help='show the mirrored bootstrap/runtime graph stages')\\n40\\t list_parser = subparsers.add_parser('subsystems', help='list the current Python modules in the workspace')\\n41\\t list_parser.add_argument('--limit', type=int, default=32)\\n42\\t\\n43\\t commands_parser = subparsers.add_parser('commands', help='list mirrored command entries from the archived snapshot')\\n44\\t commands_parser.add_argument('--limit', type=int, default=20)\\n45\\t commands_parser.add_argument('--query')\\n46\\t commands_parser.add_argument('--no-plugin-commands', action='store_true')\\n47\\t commands_parser.add_argument('--no-skill-commands', action='store_true')\\n48\\t\\n49\\t tools_parser = subparsers.add_parser('tools', help='list mirrored tool entries from the archived snapshot')\\n50\\t tools_parser.add_argument('--limit', type=int, default=20)\\n51\\t tools_parser.add_argument('--query')\\n52\\t tools_parser.add_argument('--simple-mode', action='store_true')\\n53\\t tools_parser.add_argument('--no-mcp', action='store_true')\\n54\\t tools_parser.add_argument('--deny-tool', action='append', default=[])\\n55\\t tools_parser.add_argument('--deny-prefix', action='append', default=[])\\n56\\t\\n57\\t route_parser = subparsers.add_parser('route', help='route a prompt across mirrored command/tool inventories')\\n58\\t route_parser.add_argument('prompt')\\n59\\t route_parser.add_argument('--limit', type=int, default=5)\\n60\\t\\n61\\t bootstrap_parser = subparsers.add_parser('bootstrap', help='build a runtime-style session report from the mirrored inventories')\\n62\\t bootstrap_parser.add_argument('prompt')\\n63\\t bootstrap_parser.add_argument('--limit', type=int, default=5)\\n64\\t\\n65\\t loop_parser = subparsers.add_parser('turn-loop', help='run a small stateful turn loop for the mirrored runtime')\\n66\\t loop_parser.add_argument('prompt')\\n67\\t loop_parser.add_argument('--limit', type=int, default=5)\\n68\\t loop_parser.add_argument('--max-turns', type=int, default=3)\\n69\\t loop_parser.add_argument('--structured-output', action='store_true')\\n70\\t\\n71\\t flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')\\n72\\t flush_parser.add_argument('prompt')\\n73\\t\\n74\\t load_session_parser = subparsers.add_parser('load-session', help='load a previously persisted session')\\n75\\t load_session_parser.add_argument('session_id')\\n76\\t\\n77\\t remote_parser = subparsers.add_parser('remote-mode', help='simulate remote-control runtime branching')\\n78\\t remote_parser.add_argument('target')\\n79\\t ssh_parser = subparsers.add_parser('ssh-mode', help='simulate SSH runtime branching')\\n80\\t ssh_parser.add_argument('target')\\n81\\t teleport_parser = subparsers.add_parser('teleport-mode', help='simulate teleport runtime branching')\\n82\\t teleport_parser.add_argument('target')\\n83\\t direct_parser = subparsers.add_parser('direct-connect-mode', help='simulate direct-connect runtime branching')\\n84\\t direct_parser.add_argument('target')\\n85\\t deep_link_parser = subparsers.add_parser('deep-link-mode', help='simulate deep-link runtime branching')\\n86\\t deep_link_parser.add_argument('target')\\n87\\t\\n88\\t show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')\\n89\\t show_command.add_argument('name')\\n90\\t show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')\\n91\\t show_tool.add_argument('name')\\n92\\t\\n93\\t exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')\\n94\\t exec_command_parser.add_argument('name')\\n95\\t exec_command_parser.add_argument('prompt')\\n96\\t\\n97\\t exec_tool_parser = subparsers.add_parser('exec-tool', help='execute a mirrored tool shim by exact name')\\n98\\t exec_tool_parser.add_argument('name')\\n99\\t exec_tool_parser.add_argument('payload')\\n100\\t\\n101\\t chat_parser = subparsers.add_parser('chat', help='send a prompt to a local Ollama model')\\n102\\t chat_parser.add_argument('prompt', nargs='?')\\n103\\t chat_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n104\\t chat_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n105\\t chat_parser.add_argument('--system')\\n106\\t\\n107\\t agent_parser = subparsers.add_parser('agent', help='run the local Ollama agent loop with executable workspace tools')\\n108\\t agent_parser.add_argument('prompt', nargs='?')\\n109\\t agent_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n110\\t agent_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n111\\t agent_parser.add_argument('--system')\\n112\\t agent_parser.add_argument('--max-turns', type=int, default=8)\\n113\\t agent_parser.add_argument('--deny-tool', action='append', default=[])\\n114\\t agent_parser.add_argument('--deny-prefix', action='append', default=[])\\n115\\t agent_parser.add_argument('--trace', action='store_true')\\n116\\t\\n117\\t worker_parser = subparsers.add_parser('worker', help='manage structured local Ollama workers')\\n118\\t worker_subparsers = worker_parser.add_subparsers(dest='worker_command', required=True)\\n119\\t\\n120\\t worker_create = worker_subparsers.add_parser('create', help='create a worker record')\\n121\\t worker_create.add_argument('--root', default='.')\\n122\\t worker_create.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n123\\t worker_create.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n124\\t\\n125\\t worker_subparsers.add_parser('list', help='list stored worker records')\\n126\\t\\n127\\t worker_run = worker_subparsers.add_parser('run', help='run a task packet on a worker')\\n128\\t worker_run.add_argument('worker_id')\\n129\\t worker_run.add_argument('--packet', required=True)\\n130\\t worker_run.add_argument('--trace', action='store_true')\\n131\\t\\n132\\t worker_status = worker_subparsers.add_parser('status', help='show worker state')\\n133\\t worker_status.add_argument('worker_id')\\n134\\t\\n135\\t worker_resume = worker_subparsers.add_parser('resume', help='rerun the last stored task packet')\\n136\\t worker_resume.add_argument('worker_id')\\n137\\t worker_resume.add_argument('--trace', action='store_true')\\n138\\t\\n139\\t worker_close = worker_subparsers.add_parser('close', help='close a worker record')\\n140\\t worker_close.add_argument('worker_id')\\n141\\t\\n142\\t autoresearch_parser = subparsers.add_parser('autoresearch', help='project-specific control plane for autoresearch experiments')\\n143\\t autoresearch_subparsers = autoresearch_parser.add_subparsers(dest='autoresearch_command', required=True)\\n144\\t\\n145\\t autoresearch_setup = autoresearch_subparsers.add_parser('setup', help='verify autoresearch repo state and initialize results.tsv')\\n146\\t autoresearch_setup.add_argument('--root')\\n147\\t autoresearch_setup.add_argument('--no-init-results', action='store_true')\\n148\\t\\n149\\t autoresearch_run = autoresearch_subparsers.add_parser('run', help='run one autoresearch experiment packet through the worker + experiment runner')\\n150\\t autoresearch_run.add_argument('--root')\\n151\\t autoresearch_run.add_argument('--packet', required=True)\\n152\\t autoresearch_run.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n153\\t autoresearch_run.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n154\\t autoresearch_run.add_argument('--trace', action='store_true')\\n155\\t\\n156\\t autoresearch_parse_log = autoresearch_subparsers.add_parser('parse-log', help='parse a train.py run log into machine-readable metrics')\\n157\\t autoresearch_parse_log.add_argument('--root')\\n158\\t autoresearch_parse_log.add_argument('log_path')\\n159\\t return parser\\n160\\t\\n161\\t\\n162\\tdef resolve_chat_prompt(args: argparse.Namespace, parser: argparse.ArgumentParser) -> str:\\n163\\t if args.prompt:\\n164\\t return args.prompt\\n165\\t prompt = sys.stdin.read().strip()\\n166\\t if prompt:\\n167\\t return prompt\\n168\\t command_name = getattr(args, 'command', 'command')\\n169\\t parser.error(f'{command_name} requires a prompt argument or stdin input')\\n170\\t raise AssertionError('unreachable')\\n171\\t\\n172\\t\\n173\\tdef main(argv: list[str] | None = None) -> int:\\n174\\t parser = build_parser()\\n175\\t args = parser.parse_args(argv)\\n176\\t manifest = build_port_manifest()\\n177\\t if args.command == 'summary':\\n178\\t print(QueryEnginePort(manifest).render_summary())\\n179\\t return 0\\n180\\t if args.command == 'manifest':\\n181\\t print(manifest.to_markdown())\\n182\\t return 0\\n183\\t if args.command == 'parity-audit':\\n184\\t print(run_parity_audit().to_markdown())\\n185\\t return 0\\n186\\t if args.command == 'setup-report':\\n187\\t print(run_setup().as_markdown())\\n188\\t return 0\\n189\\t if args.command == 'command-graph':\\n190\\t print(build_command_graph().as_markdown())\\n191\\t return 0\\n192\\t if args.command == 'tool-pool':\\n193\\t print(assemble_tool_pool().as_markdown())\\n194\\t return 0\\n195\\t if args.command == 'bootstrap-graph':\\n196\\t print(build_bootstrap_graph().as_markdown())\\n197\\t return 0\\n198\\t if args.command == 'subsystems':\\n199\\t for subsystem in manifest.top_level_modules[: args.limit]:\\n200\\t print(f'{subsystem.name}\\\\t{subsystem.file_count}\\\\t{subsystem.notes}')\\n201\\t return 0\\n202\\t if args.command == 'commands':\\n203\\t if args.query:\\n204\\t print(render_command_index(limit=args.limit, query=args.query))\\n205\\t else:\\n206\\t commands = get_commands(include_plugin_commands=not args.no_plugin_commands, include_skill_commands=not args.no_skill_commands)\\n207\\t output_lines = [f'Command entries: {len(commands)}', '']\\n208\\t output_lines.extend(f'- {module.name} \\u2014 {module.source_hint}' for module in commands[: args.limit])\\n209\\t print('\\\\n'.join(output_lines))\\n210\\t return 0\\n...[truncated]\",\n", " \"metadata\": {\n", " \"path\": \"src/main.py\",\n", " \"start_line\": 1,\n", " \"end_line\": 386,\n", " \"line_count\": 386\n", " },\n", " \"error\": null\n", " }\n", " ],\n", " \"artifacts\": [],\n", " \"changed_files\": [],\n", " \"verification\": {\n", " \"acceptance_tests\": [\n", " {\n", " \"command\": \"python3 -m unittest tests/test_porting_workspace.py\",\n", " \"success\": true,\n", " \"exit_code\": 0,\n", " \"output\": \".........................................\\n----------------------------------------------------------------------\\nRan 41 tests in 4.739s\\n\\nOK\"\n", " }\n", " ],\n", " \"tool_runs\": {\n", " \"run_tests\": [],\n", " \"run_build\": []\n", " }\n", " },\n", " \"final_answer\": \"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\",\n", " \"stop_reason\": \"completed\",\n", " \"turns\": 3,\n", " \"trace_events\": [\n", " \"assistant_raw[1]={\\\"type\\\":\\\"tool_call\\\",\\\"name\\\":\\\"read_file\\\",\\\"arguments\\\":{\\\"path\\\":\\\"src/main.py\\\"}}\",\n", " \"tool_call[1]=read_file {\\\"path\\\": \\\"src/main.py\\\"}\",\n", " \"tool_result[1]=read_file success=True error=None\",\n", " \"assistant_raw[2]={\\\"response\\\": \\\"The provided code snippet is from a Python script located at 'src/main.py'. It appears to be the main entry point for a command-line interface (CLI) application. The script defines several subcommands and their corresponding functionalities, such as building parsers, resolving chat prompts, and executing various commands like 'summary', 'manifest', 'parity-audit', etc. Each subcommand is handled within conditional statements in the `main` function. The script also includes functions for parsing logs, running experiments, and managing workers. Overall, this script serves as a control plane for managing and interacting with an autoresearch experiment environment.\\\"}\",\n", " \"protocol_error[2]=Response type must be either \\\"tool_call\\\" or \\\"final\\\".\",\n", " \"assistant_raw[3]={\\\"type\\\":\\\"final\\\",\\\"content\\\":\\\"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\\\"}\"\n", " ]\n", " },\n", " \"last_error\": null\n", "}\n", "\n" ] }, { "data": { "text/plain": [ "('finished', 'completed')" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "worker_run = run_json([\n", " PYTHON,\n", " \"-m\",\n", " \"src.main\",\n", " \"worker\",\n", " \"run\",\n", " worker_id,\n", " \"--packet\",\n", " str(task_path),\n", " \"--trace\",\n", "])\n", "worker_run[\"state\"], worker_run[\"last_result\"][\"stop_reason\"]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tool_calls: ['read_file']\n", "changed_files: []\n", "verification:\n", "{\n", " \"acceptance_tests\": [\n", " {\n", " \"command\": \"python3 -m unittest tests/test_porting_workspace.py\",\n", " \"success\": true,\n", " \"exit_code\": 0,\n", " \"output\": \".........................................\\n----------------------------------------------------------------------\\nRan 41 tests in 4.739s\\n\\nOK\"\n", " }\n", " ],\n", " \"tool_runs\": {\n", " \"run_tests\": [],\n", " \"run_build\": []\n", " }\n", "}\n", "final_answer:\n", "I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\n" ] } ], "source": [ "result = worker_run[\"last_result\"]\n", "print(\"tool_calls:\", result[\"tool_calls\"])\n", "print(\"changed_files:\", result[\"changed_files\"])\n", "print(\"verification:\")\n", "print(json.dumps(result[\"verification\"], indent=2))\n", "print(\"final_answer:\")\n", "print(result[\"final_answer\"])\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "$ /Users/wongdowling/opt/anaconda3/bin/python -m src.main worker status 07786cd4905d4275ab8666a113bf7e10\n", "{\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"root\": \"/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\",\n", " \"model\": \"qwen2.5-coder:7b\",\n", " \"host\": \"http://localhost:11434\",\n", " \"state\": \"finished\",\n", " \"created_at\": \"2026-04-07T20:09:34Z\",\n", " \"updated_at\": \"2026-04-07T20:10:20Z\",\n", " \"run_count\": 1,\n", " \"last_packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"last_result\": {\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"state\": \"finished\",\n", " \"packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"tool_calls\": [\n", " \"read_file\"\n", " ],\n", " \"tool_trace\": [\n", " {\n", " \"turn\": 1,\n", " \"name\": \"read_file\",\n", " \"arguments\": {\n", " \"path\": \"src/main.py\"\n", " },\n", " \"success\": true,\n", " \"output\": \"1\\tfrom __future__ import annotations\\n2\\t\\n3\\timport argparse\\n4\\timport json\\n5\\timport sys\\n6\\tfrom pathlib import Path\\n7\\t\\n8\\tfrom .autoresearch_runner import parse_run_log, setup_autoresearch\\n9\\tfrom .autoresearch_worker import run_autoresearch_packet\\n10\\tfrom .bootstrap_graph import build_bootstrap_graph\\n11\\tfrom .command_graph import build_command_graph\\n12\\tfrom .commands import execute_command, get_command, get_commands, render_command_index\\n13\\tfrom .agent_loop import DEFAULT_AGENT_SYSTEM_PROMPT, run_agent_task\\n14\\tfrom .llm_backend import DEFAULT_OLLAMA_HOST, DEFAULT_OLLAMA_MODEL, LLMBackendError\\n15\\tfrom .direct_modes import run_deep_link, run_direct_connect\\n16\\tfrom .parity_audit import run_parity_audit\\n17\\tfrom .permissions import ToolPermissionContext\\n18\\tfrom .port_manifest import build_port_manifest\\n19\\tfrom .query_engine import QueryEnginePort\\n20\\tfrom .remote_runtime import run_remote_mode, run_ssh_mode, run_teleport_mode\\n21\\tfrom .runtime import PortRuntime\\n22\\tfrom .session_store import load_session\\n23\\tfrom .setup import run_setup\\n24\\tfrom .task import DEFAULT_SYSTEM_PROMPT, run_local_task\\n25\\tfrom .worker_api import close_worker, create_worker, list_workers, load_worker, resume_worker, run_worker\\n26\\tfrom .tool_pool import assemble_tool_pool\\n27\\tfrom .tools import execute_tool, get_tool, get_tools, render_tool_index\\n28\\t\\n29\\t\\n30\\tdef build_parser() -> argparse.ArgumentParser:\\n31\\t parser = argparse.ArgumentParser(description='Python porting workspace for the Claude Code rewrite effort')\\n32\\t subparsers = parser.add_subparsers(dest='command', required=True)\\n33\\t subparsers.add_parser('summary', help='render a Markdown summary of the Python porting workspace')\\n34\\t subparsers.add_parser('manifest', help='print the current Python workspace manifest')\\n35\\t subparsers.add_parser('parity-audit', help='compare the Python workspace against the local ignored TypeScript archive when available')\\n36\\t subparsers.add_parser('setup-report', help='render the startup/prefetch setup report')\\n37\\t subparsers.add_parser('command-graph', help='show command graph segmentation')\\n38\\t subparsers.add_parser('tool-pool', help='show assembled tool pool with default settings')\\n39\\t subparsers.add_parser('bootstrap-graph', help='show the mirrored bootstrap/runtime graph stages')\\n40\\t list_parser = subparsers.add_parser('subsystems', help='list the current Python modules in the workspace')\\n41\\t list_parser.add_argument('--limit', type=int, default=32)\\n42\\t\\n43\\t commands_parser = subparsers.add_parser('commands', help='list mirrored command entries from the archived snapshot')\\n44\\t commands_parser.add_argument('--limit', type=int, default=20)\\n45\\t commands_parser.add_argument('--query')\\n46\\t commands_parser.add_argument('--no-plugin-commands', action='store_true')\\n47\\t commands_parser.add_argument('--no-skill-commands', action='store_true')\\n48\\t\\n49\\t tools_parser = subparsers.add_parser('tools', help='list mirrored tool entries from the archived snapshot')\\n50\\t tools_parser.add_argument('--limit', type=int, default=20)\\n51\\t tools_parser.add_argument('--query')\\n52\\t tools_parser.add_argument('--simple-mode', action='store_true')\\n53\\t tools_parser.add_argument('--no-mcp', action='store_true')\\n54\\t tools_parser.add_argument('--deny-tool', action='append', default=[])\\n55\\t tools_parser.add_argument('--deny-prefix', action='append', default=[])\\n56\\t\\n57\\t route_parser = subparsers.add_parser('route', help='route a prompt across mirrored command/tool inventories')\\n58\\t route_parser.add_argument('prompt')\\n59\\t route_parser.add_argument('--limit', type=int, default=5)\\n60\\t\\n61\\t bootstrap_parser = subparsers.add_parser('bootstrap', help='build a runtime-style session report from the mirrored inventories')\\n62\\t bootstrap_parser.add_argument('prompt')\\n63\\t bootstrap_parser.add_argument('--limit', type=int, default=5)\\n64\\t\\n65\\t loop_parser = subparsers.add_parser('turn-loop', help='run a small stateful turn loop for the mirrored runtime')\\n66\\t loop_parser.add_argument('prompt')\\n67\\t loop_parser.add_argument('--limit', type=int, default=5)\\n68\\t loop_parser.add_argument('--max-turns', type=int, default=3)\\n69\\t loop_parser.add_argument('--structured-output', action='store_true')\\n70\\t\\n71\\t flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')\\n72\\t flush_parser.add_argument('prompt')\\n73\\t\\n74\\t load_session_parser = subparsers.add_parser('load-session', help='load a previously persisted session')\\n75\\t load_session_parser.add_argument('session_id')\\n76\\t\\n77\\t remote_parser = subparsers.add_parser('remote-mode', help='simulate remote-control runtime branching')\\n78\\t remote_parser.add_argument('target')\\n79\\t ssh_parser = subparsers.add_parser('ssh-mode', help='simulate SSH runtime branching')\\n80\\t ssh_parser.add_argument('target')\\n81\\t teleport_parser = subparsers.add_parser('teleport-mode', help='simulate teleport runtime branching')\\n82\\t teleport_parser.add_argument('target')\\n83\\t direct_parser = subparsers.add_parser('direct-connect-mode', help='simulate direct-connect runtime branching')\\n84\\t direct_parser.add_argument('target')\\n85\\t deep_link_parser = subparsers.add_parser('deep-link-mode', help='simulate deep-link runtime branching')\\n86\\t deep_link_parser.add_argument('target')\\n87\\t\\n88\\t show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')\\n89\\t show_command.add_argument('name')\\n90\\t show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')\\n91\\t show_tool.add_argument('name')\\n92\\t\\n93\\t exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')\\n94\\t exec_command_parser.add_argument('name')\\n95\\t exec_command_parser.add_argument('prompt')\\n96\\t\\n97\\t exec_tool_parser = subparsers.add_parser('exec-tool', help='execute a mirrored tool shim by exact name')\\n98\\t exec_tool_parser.add_argument('name')\\n99\\t exec_tool_parser.add_argument('payload')\\n100\\t\\n101\\t chat_parser = subparsers.add_parser('chat', help='send a prompt to a local Ollama model')\\n102\\t chat_parser.add_argument('prompt', nargs='?')\\n103\\t chat_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n104\\t chat_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n105\\t chat_parser.add_argument('--system')\\n106\\t\\n107\\t agent_parser = subparsers.add_parser('agent', help='run the local Ollama agent loop with executable workspace tools')\\n108\\t agent_parser.add_argument('prompt', nargs='?')\\n109\\t agent_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n110\\t agent_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n111\\t agent_parser.add_argument('--system')\\n112\\t agent_parser.add_argument('--max-turns', type=int, default=8)\\n113\\t agent_parser.add_argument('--deny-tool', action='append', default=[])\\n114\\t agent_parser.add_argument('--deny-prefix', action='append', default=[])\\n115\\t agent_parser.add_argument('--trace', action='store_true')\\n116\\t\\n117\\t worker_parser = subparsers.add_parser('worker', help='manage structured local Ollama workers')\\n118\\t worker_subparsers = worker_parser.add_subparsers(dest='worker_command', required=True)\\n119\\t\\n120\\t worker_create = worker_subparsers.add_parser('create', help='create a worker record')\\n121\\t worker_create.add_argument('--root', default='.')\\n122\\t worker_create.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n123\\t worker_create.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n124\\t\\n125\\t worker_subparsers.add_parser('list', help='list stored worker records')\\n126\\t\\n127\\t worker_run = worker_subparsers.add_parser('run', help='run a task packet on a worker')\\n128\\t worker_run.add_argument('worker_id')\\n129\\t worker_run.add_argument('--packet', required=True)\\n130\\t worker_run.add_argument('--trace', action='store_true')\\n131\\t\\n132\\t worker_status = worker_subparsers.add_parser('status', help='show worker state')\\n133\\t worker_status.add_argument('worker_id')\\n134\\t\\n135\\t worker_resume = worker_subparsers.add_parser('resume', help='rerun the last stored task packet')\\n136\\t worker_resume.add_argument('worker_id')\\n137\\t worker_resume.add_argument('--trace', action='store_true')\\n138\\t\\n139\\t worker_close = worker_subparsers.add_parser('close', help='close a worker record')\\n140\\t worker_close.add_argument('worker_id')\\n141\\t\\n142\\t autoresearch_parser = subparsers.add_parser('autoresearch', help='project-specific control plane for autoresearch experiments')\\n143\\t autoresearch_subparsers = autoresearch_parser.add_subparsers(dest='autoresearch_command', required=True)\\n144\\t\\n145\\t autoresearch_setup = autoresearch_subparsers.add_parser('setup', help='verify autoresearch repo state and initialize results.tsv')\\n146\\t autoresearch_setup.add_argument('--root')\\n147\\t autoresearch_setup.add_argument('--no-init-results', action='store_true')\\n148\\t\\n149\\t autoresearch_run = autoresearch_subparsers.add_parser('run', help='run one autoresearch experiment packet through the worker + experiment runner')\\n150\\t autoresearch_run.add_argument('--root')\\n151\\t autoresearch_run.add_argument('--packet', required=True)\\n152\\t autoresearch_run.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n153\\t autoresearch_run.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n154\\t autoresearch_run.add_argument('--trace', action='store_true')\\n155\\t\\n156\\t autoresearch_parse_log = autoresearch_subparsers.add_parser('parse-log', help='parse a train.py run log into machine-readable metrics')\\n157\\t autoresearch_parse_log.add_argument('--root')\\n158\\t autoresearch_parse_log.add_argument('log_path')\\n159\\t return parser\\n160\\t\\n161\\t\\n162\\tdef resolve_chat_prompt(args: argparse.Namespace, parser: argparse.ArgumentParser) -> str:\\n163\\t if args.prompt:\\n164\\t return args.prompt\\n165\\t prompt = sys.stdin.read().strip()\\n166\\t if prompt:\\n167\\t return prompt\\n168\\t command_name = getattr(args, 'command', 'command')\\n169\\t parser.error(f'{command_name} requires a prompt argument or stdin input')\\n170\\t raise AssertionError('unreachable')\\n171\\t\\n172\\t\\n173\\tdef main(argv: list[str] | None = None) -> int:\\n174\\t parser = build_parser()\\n175\\t args = parser.parse_args(argv)\\n176\\t manifest = build_port_manifest()\\n177\\t if args.command == 'summary':\\n178\\t print(QueryEnginePort(manifest).render_summary())\\n179\\t return 0\\n180\\t if args.command == 'manifest':\\n181\\t print(manifest.to_markdown())\\n182\\t return 0\\n183\\t if args.command == 'parity-audit':\\n184\\t print(run_parity_audit().to_markdown())\\n185\\t return 0\\n186\\t if args.command == 'setup-report':\\n187\\t print(run_setup().as_markdown())\\n188\\t return 0\\n189\\t if args.command == 'command-graph':\\n190\\t print(build_command_graph().as_markdown())\\n191\\t return 0\\n192\\t if args.command == 'tool-pool':\\n193\\t print(assemble_tool_pool().as_markdown())\\n194\\t return 0\\n195\\t if args.command == 'bootstrap-graph':\\n196\\t print(build_bootstrap_graph().as_markdown())\\n197\\t return 0\\n198\\t if args.command == 'subsystems':\\n199\\t for subsystem in manifest.top_level_modules[: args.limit]:\\n200\\t print(f'{subsystem.name}\\\\t{subsystem.file_count}\\\\t{subsystem.notes}')\\n201\\t return 0\\n202\\t if args.command == 'commands':\\n203\\t if args.query:\\n204\\t print(render_command_index(limit=args.limit, query=args.query))\\n205\\t else:\\n206\\t commands = get_commands(include_plugin_commands=not args.no_plugin_commands, include_skill_commands=not args.no_skill_commands)\\n207\\t output_lines = [f'Command entries: {len(commands)}', '']\\n208\\t output_lines.extend(f'- {module.name} \\u2014 {module.source_hint}' for module in commands[: args.limit])\\n209\\t print('\\\\n'.join(output_lines))\\n210\\t return 0\\n...[truncated]\",\n", " \"metadata\": {\n", " \"path\": \"src/main.py\",\n", " \"start_line\": 1,\n", " \"end_line\": 386,\n", " \"line_count\": 386\n", " },\n", " \"error\": null\n", " }\n", " ],\n", " \"artifacts\": [],\n", " \"changed_files\": [],\n", " \"verification\": {\n", " \"acceptance_tests\": [\n", " {\n", " \"command\": \"python3 -m unittest tests/test_porting_workspace.py\",\n", " \"success\": true,\n", " \"exit_code\": 0,\n", " \"output\": \".........................................\\n----------------------------------------------------------------------\\nRan 41 tests in 4.739s\\n\\nOK\"\n", " }\n", " ],\n", " \"tool_runs\": {\n", " \"run_tests\": [],\n", " \"run_build\": []\n", " }\n", " },\n", " \"final_answer\": \"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\",\n", " \"stop_reason\": \"completed\",\n", " \"turns\": 3,\n", " \"trace_events\": [\n", " \"assistant_raw[1]={\\\"type\\\":\\\"tool_call\\\",\\\"name\\\":\\\"read_file\\\",\\\"arguments\\\":{\\\"path\\\":\\\"src/main.py\\\"}}\",\n", " \"tool_call[1]=read_file {\\\"path\\\": \\\"src/main.py\\\"}\",\n", " \"tool_result[1]=read_file success=True error=None\",\n", " \"assistant_raw[2]={\\\"response\\\": \\\"The provided code snippet is from a Python script located at 'src/main.py'. It appears to be the main entry point for a command-line interface (CLI) application. The script defines several subcommands and their corresponding functionalities, such as building parsers, resolving chat prompts, and executing various commands like 'summary', 'manifest', 'parity-audit', etc. Each subcommand is handled within conditional statements in the `main` function. The script also includes functions for parsing logs, running experiments, and managing workers. Overall, this script serves as a control plane for managing and interacting with an autoresearch experiment environment.\\\"}\",\n", " \"protocol_error[2]=Response type must be either \\\"tool_call\\\" or \\\"final\\\".\",\n", " \"assistant_raw[3]={\\\"type\\\":\\\"final\\\",\\\"content\\\":\\\"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\\\"}\"\n", " ]\n", " },\n", " \"last_error\": null\n", "}\n", "\n" ] }, { "data": { "text/plain": [ "'finished'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "worker_status = run_json([\n", " PYTHON,\n", " \"-m\",\n", " \"src.main\",\n", " \"worker\",\n", " \"status\",\n", " worker_id,\n", "])\n", "worker_status[\"state\"]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "$ /Users/wongdowling/opt/anaconda3/bin/python -m src.main worker resume 07786cd4905d4275ab8666a113bf7e10 --trace\n", "{\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"root\": \"/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\",\n", " \"model\": \"qwen2.5-coder:7b\",\n", " \"host\": \"http://localhost:11434\",\n", " \"state\": \"finished\",\n", " \"created_at\": \"2026-04-07T20:09:34Z\",\n", " \"updated_at\": \"2026-04-07T20:10:59Z\",\n", " \"run_count\": 2,\n", " \"last_packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"last_result\": {\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"state\": \"finished\",\n", " \"packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"tool_calls\": [\n", " \"read_file\"\n", " ],\n", " \"tool_trace\": [\n", " {\n", " \"turn\": 1,\n", " \"name\": \"read_file\",\n", " \"arguments\": {\n", " \"path\": \"src/main.py\"\n", " },\n", " \"success\": true,\n", " \"output\": \"1\\tfrom __future__ import annotations\\n2\\t\\n3\\timport argparse\\n4\\timport json\\n5\\timport sys\\n6\\tfrom pathlib import Path\\n7\\t\\n8\\tfrom .autoresearch_runner import parse_run_log, setup_autoresearch\\n9\\tfrom .autoresearch_worker import run_autoresearch_packet\\n10\\tfrom .bootstrap_graph import build_bootstrap_graph\\n11\\tfrom .command_graph import build_command_graph\\n12\\tfrom .commands import execute_command, get_command, get_commands, render_command_index\\n13\\tfrom .agent_loop import DEFAULT_AGENT_SYSTEM_PROMPT, run_agent_task\\n14\\tfrom .llm_backend import DEFAULT_OLLAMA_HOST, DEFAULT_OLLAMA_MODEL, LLMBackendError\\n15\\tfrom .direct_modes import run_deep_link, run_direct_connect\\n16\\tfrom .parity_audit import run_parity_audit\\n17\\tfrom .permissions import ToolPermissionContext\\n18\\tfrom .port_manifest import build_port_manifest\\n19\\tfrom .query_engine import QueryEnginePort\\n20\\tfrom .remote_runtime import run_remote_mode, run_ssh_mode, run_teleport_mode\\n21\\tfrom .runtime import PortRuntime\\n22\\tfrom .session_store import load_session\\n23\\tfrom .setup import run_setup\\n24\\tfrom .task import DEFAULT_SYSTEM_PROMPT, run_local_task\\n25\\tfrom .worker_api import close_worker, create_worker, list_workers, load_worker, resume_worker, run_worker\\n26\\tfrom .tool_pool import assemble_tool_pool\\n27\\tfrom .tools import execute_tool, get_tool, get_tools, render_tool_index\\n28\\t\\n29\\t\\n30\\tdef build_parser() -> argparse.ArgumentParser:\\n31\\t parser = argparse.ArgumentParser(description='Python porting workspace for the Claude Code rewrite effort')\\n32\\t subparsers = parser.add_subparsers(dest='command', required=True)\\n33\\t subparsers.add_parser('summary', help='render a Markdown summary of the Python porting workspace')\\n34\\t subparsers.add_parser('manifest', help='print the current Python workspace manifest')\\n35\\t subparsers.add_parser('parity-audit', help='compare the Python workspace against the local ignored TypeScript archive when available')\\n36\\t subparsers.add_parser('setup-report', help='render the startup/prefetch setup report')\\n37\\t subparsers.add_parser('command-graph', help='show command graph segmentation')\\n38\\t subparsers.add_parser('tool-pool', help='show assembled tool pool with default settings')\\n39\\t subparsers.add_parser('bootstrap-graph', help='show the mirrored bootstrap/runtime graph stages')\\n40\\t list_parser = subparsers.add_parser('subsystems', help='list the current Python modules in the workspace')\\n41\\t list_parser.add_argument('--limit', type=int, default=32)\\n42\\t\\n43\\t commands_parser = subparsers.add_parser('commands', help='list mirrored command entries from the archived snapshot')\\n44\\t commands_parser.add_argument('--limit', type=int, default=20)\\n45\\t commands_parser.add_argument('--query')\\n46\\t commands_parser.add_argument('--no-plugin-commands', action='store_true')\\n47\\t commands_parser.add_argument('--no-skill-commands', action='store_true')\\n48\\t\\n49\\t tools_parser = subparsers.add_parser('tools', help='list mirrored tool entries from the archived snapshot')\\n50\\t tools_parser.add_argument('--limit', type=int, default=20)\\n51\\t tools_parser.add_argument('--query')\\n52\\t tools_parser.add_argument('--simple-mode', action='store_true')\\n53\\t tools_parser.add_argument('--no-mcp', action='store_true')\\n54\\t tools_parser.add_argument('--deny-tool', action='append', default=[])\\n55\\t tools_parser.add_argument('--deny-prefix', action='append', default=[])\\n56\\t\\n57\\t route_parser = subparsers.add_parser('route', help='route a prompt across mirrored command/tool inventories')\\n58\\t route_parser.add_argument('prompt')\\n59\\t route_parser.add_argument('--limit', type=int, default=5)\\n60\\t\\n61\\t bootstrap_parser = subparsers.add_parser('bootstrap', help='build a runtime-style session report from the mirrored inventories')\\n62\\t bootstrap_parser.add_argument('prompt')\\n63\\t bootstrap_parser.add_argument('--limit', type=int, default=5)\\n64\\t\\n65\\t loop_parser = subparsers.add_parser('turn-loop', help='run a small stateful turn loop for the mirrored runtime')\\n66\\t loop_parser.add_argument('prompt')\\n67\\t loop_parser.add_argument('--limit', type=int, default=5)\\n68\\t loop_parser.add_argument('--max-turns', type=int, default=3)\\n69\\t loop_parser.add_argument('--structured-output', action='store_true')\\n70\\t\\n71\\t flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')\\n72\\t flush_parser.add_argument('prompt')\\n73\\t\\n74\\t load_session_parser = subparsers.add_parser('load-session', help='load a previously persisted session')\\n75\\t load_session_parser.add_argument('session_id')\\n76\\t\\n77\\t remote_parser = subparsers.add_parser('remote-mode', help='simulate remote-control runtime branching')\\n78\\t remote_parser.add_argument('target')\\n79\\t ssh_parser = subparsers.add_parser('ssh-mode', help='simulate SSH runtime branching')\\n80\\t ssh_parser.add_argument('target')\\n81\\t teleport_parser = subparsers.add_parser('teleport-mode', help='simulate teleport runtime branching')\\n82\\t teleport_parser.add_argument('target')\\n83\\t direct_parser = subparsers.add_parser('direct-connect-mode', help='simulate direct-connect runtime branching')\\n84\\t direct_parser.add_argument('target')\\n85\\t deep_link_parser = subparsers.add_parser('deep-link-mode', help='simulate deep-link runtime branching')\\n86\\t deep_link_parser.add_argument('target')\\n87\\t\\n88\\t show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')\\n89\\t show_command.add_argument('name')\\n90\\t show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')\\n91\\t show_tool.add_argument('name')\\n92\\t\\n93\\t exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')\\n94\\t exec_command_parser.add_argument('name')\\n95\\t exec_command_parser.add_argument('prompt')\\n96\\t\\n97\\t exec_tool_parser = subparsers.add_parser('exec-tool', help='execute a mirrored tool shim by exact name')\\n98\\t exec_tool_parser.add_argument('name')\\n99\\t exec_tool_parser.add_argument('payload')\\n100\\t\\n101\\t chat_parser = subparsers.add_parser('chat', help='send a prompt to a local Ollama model')\\n102\\t chat_parser.add_argument('prompt', nargs='?')\\n103\\t chat_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n104\\t chat_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n105\\t chat_parser.add_argument('--system')\\n106\\t\\n107\\t agent_parser = subparsers.add_parser('agent', help='run the local Ollama agent loop with executable workspace tools')\\n108\\t agent_parser.add_argument('prompt', nargs='?')\\n109\\t agent_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n110\\t agent_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n111\\t agent_parser.add_argument('--system')\\n112\\t agent_parser.add_argument('--max-turns', type=int, default=8)\\n113\\t agent_parser.add_argument('--deny-tool', action='append', default=[])\\n114\\t agent_parser.add_argument('--deny-prefix', action='append', default=[])\\n115\\t agent_parser.add_argument('--trace', action='store_true')\\n116\\t\\n117\\t worker_parser = subparsers.add_parser('worker', help='manage structured local Ollama workers')\\n118\\t worker_subparsers = worker_parser.add_subparsers(dest='worker_command', required=True)\\n119\\t\\n120\\t worker_create = worker_subparsers.add_parser('create', help='create a worker record')\\n121\\t worker_create.add_argument('--root', default='.')\\n122\\t worker_create.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n123\\t worker_create.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n124\\t\\n125\\t worker_subparsers.add_parser('list', help='list stored worker records')\\n126\\t\\n127\\t worker_run = worker_subparsers.add_parser('run', help='run a task packet on a worker')\\n128\\t worker_run.add_argument('worker_id')\\n129\\t worker_run.add_argument('--packet', required=True)\\n130\\t worker_run.add_argument('--trace', action='store_true')\\n131\\t\\n132\\t worker_status = worker_subparsers.add_parser('status', help='show worker state')\\n133\\t worker_status.add_argument('worker_id')\\n134\\t\\n135\\t worker_resume = worker_subparsers.add_parser('resume', help='rerun the last stored task packet')\\n136\\t worker_resume.add_argument('worker_id')\\n137\\t worker_resume.add_argument('--trace', action='store_true')\\n138\\t\\n139\\t worker_close = worker_subparsers.add_parser('close', help='close a worker record')\\n140\\t worker_close.add_argument('worker_id')\\n141\\t\\n142\\t autoresearch_parser = subparsers.add_parser('autoresearch', help='project-specific control plane for autoresearch experiments')\\n143\\t autoresearch_subparsers = autoresearch_parser.add_subparsers(dest='autoresearch_command', required=True)\\n144\\t\\n145\\t autoresearch_setup = autoresearch_subparsers.add_parser('setup', help='verify autoresearch repo state and initialize results.tsv')\\n146\\t autoresearch_setup.add_argument('--root')\\n147\\t autoresearch_setup.add_argument('--no-init-results', action='store_true')\\n148\\t\\n149\\t autoresearch_run = autoresearch_subparsers.add_parser('run', help='run one autoresearch experiment packet through the worker + experiment runner')\\n150\\t autoresearch_run.add_argument('--root')\\n151\\t autoresearch_run.add_argument('--packet', required=True)\\n152\\t autoresearch_run.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n153\\t autoresearch_run.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n154\\t autoresearch_run.add_argument('--trace', action='store_true')\\n155\\t\\n156\\t autoresearch_parse_log = autoresearch_subparsers.add_parser('parse-log', help='parse a train.py run log into machine-readable metrics')\\n157\\t autoresearch_parse_log.add_argument('--root')\\n158\\t autoresearch_parse_log.add_argument('log_path')\\n159\\t return parser\\n160\\t\\n161\\t\\n162\\tdef resolve_chat_prompt(args: argparse.Namespace, parser: argparse.ArgumentParser) -> str:\\n163\\t if args.prompt:\\n164\\t return args.prompt\\n165\\t prompt = sys.stdin.read().strip()\\n166\\t if prompt:\\n167\\t return prompt\\n168\\t command_name = getattr(args, 'command', 'command')\\n169\\t parser.error(f'{command_name} requires a prompt argument or stdin input')\\n170\\t raise AssertionError('unreachable')\\n171\\t\\n172\\t\\n173\\tdef main(argv: list[str] | None = None) -> int:\\n174\\t parser = build_parser()\\n175\\t args = parser.parse_args(argv)\\n176\\t manifest = build_port_manifest()\\n177\\t if args.command == 'summary':\\n178\\t print(QueryEnginePort(manifest).render_summary())\\n179\\t return 0\\n180\\t if args.command == 'manifest':\\n181\\t print(manifest.to_markdown())\\n182\\t return 0\\n183\\t if args.command == 'parity-audit':\\n184\\t print(run_parity_audit().to_markdown())\\n185\\t return 0\\n186\\t if args.command == 'setup-report':\\n187\\t print(run_setup().as_markdown())\\n188\\t return 0\\n189\\t if args.command == 'command-graph':\\n190\\t print(build_command_graph().as_markdown())\\n191\\t return 0\\n192\\t if args.command == 'tool-pool':\\n193\\t print(assemble_tool_pool().as_markdown())\\n194\\t return 0\\n195\\t if args.command == 'bootstrap-graph':\\n196\\t print(build_bootstrap_graph().as_markdown())\\n197\\t return 0\\n198\\t if args.command == 'subsystems':\\n199\\t for subsystem in manifest.top_level_modules[: args.limit]:\\n200\\t print(f'{subsystem.name}\\\\t{subsystem.file_count}\\\\t{subsystem.notes}')\\n201\\t return 0\\n202\\t if args.command == 'commands':\\n203\\t if args.query:\\n204\\t print(render_command_index(limit=args.limit, query=args.query))\\n205\\t else:\\n206\\t commands = get_commands(include_plugin_commands=not args.no_plugin_commands, include_skill_commands=not args.no_skill_commands)\\n207\\t output_lines = [f'Command entries: {len(commands)}', '']\\n208\\t output_lines.extend(f'- {module.name} \\u2014 {module.source_hint}' for module in commands[: args.limit])\\n209\\t print('\\\\n'.join(output_lines))\\n210\\t return 0\\n...[truncated]\",\n", " \"metadata\": {\n", " \"path\": \"src/main.py\",\n", " \"start_line\": 1,\n", " \"end_line\": 386,\n", " \"line_count\": 386\n", " },\n", " \"error\": null\n", " }\n", " ],\n", " \"artifacts\": [],\n", " \"changed_files\": [],\n", " \"verification\": {\n", " \"acceptance_tests\": [\n", " {\n", " \"command\": \"python3 -m unittest tests/test_porting_workspace.py\",\n", " \"success\": true,\n", " \"exit_code\": 0,\n", " \"output\": \".........................................\\n----------------------------------------------------------------------\\nRan 41 tests in 3.865s\\n\\nOK\"\n", " }\n", " ],\n", " \"tool_runs\": {\n", " \"run_tests\": [],\n", " \"run_build\": []\n", " }\n", " },\n", " \"final_answer\": \"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\",\n", " \"stop_reason\": \"completed\",\n", " \"turns\": 3,\n", " \"trace_events\": [\n", " \"assistant_raw[1]={\\\"type\\\":\\\"tool_call\\\",\\\"name\\\":\\\"read_file\\\",\\\"arguments\\\":{\\\"path\\\":\\\"src/main.py\\\"}}\",\n", " \"tool_call[1]=read_file {\\\"path\\\": \\\"src/main.py\\\"}\",\n", " \"tool_result[1]=read_file success=True error=None\",\n", " \"assistant_raw[2]={\\\"response\\\": \\\"The provided code snippet is from a Python script located at 'src/main.py'. It appears to be the main entry point for a command-line interface (CLI) application. The script defines several subcommands and their corresponding functionalities, such as building parsers, resolving chat prompts, and executing various commands like 'summary', 'manifest', 'parity-audit', etc. Each subcommand is handled within conditional statements in the `main` function. The script also includes functions for parsing logs, running experiments, and managing workers. Overall, this script serves as a control plane for managing and interacting with an autoresearch experiment environment.\\\"}\",\n", " \"protocol_error[2]=Response type must be either \\\"tool_call\\\" or \\\"final\\\".\",\n", " \"assistant_raw[3]={\\\"type\\\":\\\"final\\\",\\\"content\\\":\\\"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\\\"}\"\n", " ]\n", " },\n", " \"last_error\": null\n", "}\n", "\n" ] }, { "data": { "text/plain": [ "2" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "worker_resumed = run_json([\n", " PYTHON,\n", " \"-m\",\n", " \"src.main\",\n", " \"worker\",\n", " \"resume\",\n", " worker_id,\n", " \"--trace\",\n", "])\n", "worker_resumed[\"run_count\"]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "$ /Users/wongdowling/opt/anaconda3/bin/python -m src.main worker close 07786cd4905d4275ab8666a113bf7e10\n", "{\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"root\": \"/Users/wongdowling/Documents/autoresearch_harness/harness/claw-code\",\n", " \"model\": \"qwen2.5-coder:7b\",\n", " \"host\": \"http://localhost:11434\",\n", " \"state\": \"closed\",\n", " \"created_at\": \"2026-04-07T20:09:34Z\",\n", " \"updated_at\": \"2026-04-07T20:10:59Z\",\n", " \"run_count\": 2,\n", " \"last_packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"last_result\": {\n", " \"worker_id\": \"07786cd4905d4275ab8666a113bf7e10\",\n", " \"state\": \"finished\",\n", " \"packet\": {\n", " \"objective\": \"Inspect the Python CLI and report the worker-related commands.\",\n", " \"scope\": \"Inspect src/main.py and worker modules only when needed.\",\n", " \"repo\": \"claw-code\",\n", " \"branch_policy\": \"Do not create or switch branches.\",\n", " \"acceptance_tests\": [\n", " \"python3 -m unittest tests/test_porting_workspace.py\"\n", " ],\n", " \"commit_policy\": \"Do not commit.\",\n", " \"reporting_contract\": \"Report worker commands, changed files, verification results, and blockers.\",\n", " \"escalation_policy\": \"Stop if Ollama is unavailable or a required tool fails repeatedly.\"\n", " },\n", " \"tool_calls\": [\n", " \"read_file\"\n", " ],\n", " \"tool_trace\": [\n", " {\n", " \"turn\": 1,\n", " \"name\": \"read_file\",\n", " \"arguments\": {\n", " \"path\": \"src/main.py\"\n", " },\n", " \"success\": true,\n", " \"output\": \"1\\tfrom __future__ import annotations\\n2\\t\\n3\\timport argparse\\n4\\timport json\\n5\\timport sys\\n6\\tfrom pathlib import Path\\n7\\t\\n8\\tfrom .autoresearch_runner import parse_run_log, setup_autoresearch\\n9\\tfrom .autoresearch_worker import run_autoresearch_packet\\n10\\tfrom .bootstrap_graph import build_bootstrap_graph\\n11\\tfrom .command_graph import build_command_graph\\n12\\tfrom .commands import execute_command, get_command, get_commands, render_command_index\\n13\\tfrom .agent_loop import DEFAULT_AGENT_SYSTEM_PROMPT, run_agent_task\\n14\\tfrom .llm_backend import DEFAULT_OLLAMA_HOST, DEFAULT_OLLAMA_MODEL, LLMBackendError\\n15\\tfrom .direct_modes import run_deep_link, run_direct_connect\\n16\\tfrom .parity_audit import run_parity_audit\\n17\\tfrom .permissions import ToolPermissionContext\\n18\\tfrom .port_manifest import build_port_manifest\\n19\\tfrom .query_engine import QueryEnginePort\\n20\\tfrom .remote_runtime import run_remote_mode, run_ssh_mode, run_teleport_mode\\n21\\tfrom .runtime import PortRuntime\\n22\\tfrom .session_store import load_session\\n23\\tfrom .setup import run_setup\\n24\\tfrom .task import DEFAULT_SYSTEM_PROMPT, run_local_task\\n25\\tfrom .worker_api import close_worker, create_worker, list_workers, load_worker, resume_worker, run_worker\\n26\\tfrom .tool_pool import assemble_tool_pool\\n27\\tfrom .tools import execute_tool, get_tool, get_tools, render_tool_index\\n28\\t\\n29\\t\\n30\\tdef build_parser() -> argparse.ArgumentParser:\\n31\\t parser = argparse.ArgumentParser(description='Python porting workspace for the Claude Code rewrite effort')\\n32\\t subparsers = parser.add_subparsers(dest='command', required=True)\\n33\\t subparsers.add_parser('summary', help='render a Markdown summary of the Python porting workspace')\\n34\\t subparsers.add_parser('manifest', help='print the current Python workspace manifest')\\n35\\t subparsers.add_parser('parity-audit', help='compare the Python workspace against the local ignored TypeScript archive when available')\\n36\\t subparsers.add_parser('setup-report', help='render the startup/prefetch setup report')\\n37\\t subparsers.add_parser('command-graph', help='show command graph segmentation')\\n38\\t subparsers.add_parser('tool-pool', help='show assembled tool pool with default settings')\\n39\\t subparsers.add_parser('bootstrap-graph', help='show the mirrored bootstrap/runtime graph stages')\\n40\\t list_parser = subparsers.add_parser('subsystems', help='list the current Python modules in the workspace')\\n41\\t list_parser.add_argument('--limit', type=int, default=32)\\n42\\t\\n43\\t commands_parser = subparsers.add_parser('commands', help='list mirrored command entries from the archived snapshot')\\n44\\t commands_parser.add_argument('--limit', type=int, default=20)\\n45\\t commands_parser.add_argument('--query')\\n46\\t commands_parser.add_argument('--no-plugin-commands', action='store_true')\\n47\\t commands_parser.add_argument('--no-skill-commands', action='store_true')\\n48\\t\\n49\\t tools_parser = subparsers.add_parser('tools', help='list mirrored tool entries from the archived snapshot')\\n50\\t tools_parser.add_argument('--limit', type=int, default=20)\\n51\\t tools_parser.add_argument('--query')\\n52\\t tools_parser.add_argument('--simple-mode', action='store_true')\\n53\\t tools_parser.add_argument('--no-mcp', action='store_true')\\n54\\t tools_parser.add_argument('--deny-tool', action='append', default=[])\\n55\\t tools_parser.add_argument('--deny-prefix', action='append', default=[])\\n56\\t\\n57\\t route_parser = subparsers.add_parser('route', help='route a prompt across mirrored command/tool inventories')\\n58\\t route_parser.add_argument('prompt')\\n59\\t route_parser.add_argument('--limit', type=int, default=5)\\n60\\t\\n61\\t bootstrap_parser = subparsers.add_parser('bootstrap', help='build a runtime-style session report from the mirrored inventories')\\n62\\t bootstrap_parser.add_argument('prompt')\\n63\\t bootstrap_parser.add_argument('--limit', type=int, default=5)\\n64\\t\\n65\\t loop_parser = subparsers.add_parser('turn-loop', help='run a small stateful turn loop for the mirrored runtime')\\n66\\t loop_parser.add_argument('prompt')\\n67\\t loop_parser.add_argument('--limit', type=int, default=5)\\n68\\t loop_parser.add_argument('--max-turns', type=int, default=3)\\n69\\t loop_parser.add_argument('--structured-output', action='store_true')\\n70\\t\\n71\\t flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')\\n72\\t flush_parser.add_argument('prompt')\\n73\\t\\n74\\t load_session_parser = subparsers.add_parser('load-session', help='load a previously persisted session')\\n75\\t load_session_parser.add_argument('session_id')\\n76\\t\\n77\\t remote_parser = subparsers.add_parser('remote-mode', help='simulate remote-control runtime branching')\\n78\\t remote_parser.add_argument('target')\\n79\\t ssh_parser = subparsers.add_parser('ssh-mode', help='simulate SSH runtime branching')\\n80\\t ssh_parser.add_argument('target')\\n81\\t teleport_parser = subparsers.add_parser('teleport-mode', help='simulate teleport runtime branching')\\n82\\t teleport_parser.add_argument('target')\\n83\\t direct_parser = subparsers.add_parser('direct-connect-mode', help='simulate direct-connect runtime branching')\\n84\\t direct_parser.add_argument('target')\\n85\\t deep_link_parser = subparsers.add_parser('deep-link-mode', help='simulate deep-link runtime branching')\\n86\\t deep_link_parser.add_argument('target')\\n87\\t\\n88\\t show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')\\n89\\t show_command.add_argument('name')\\n90\\t show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')\\n91\\t show_tool.add_argument('name')\\n92\\t\\n93\\t exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')\\n94\\t exec_command_parser.add_argument('name')\\n95\\t exec_command_parser.add_argument('prompt')\\n96\\t\\n97\\t exec_tool_parser = subparsers.add_parser('exec-tool', help='execute a mirrored tool shim by exact name')\\n98\\t exec_tool_parser.add_argument('name')\\n99\\t exec_tool_parser.add_argument('payload')\\n100\\t\\n101\\t chat_parser = subparsers.add_parser('chat', help='send a prompt to a local Ollama model')\\n102\\t chat_parser.add_argument('prompt', nargs='?')\\n103\\t chat_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n104\\t chat_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n105\\t chat_parser.add_argument('--system')\\n106\\t\\n107\\t agent_parser = subparsers.add_parser('agent', help='run the local Ollama agent loop with executable workspace tools')\\n108\\t agent_parser.add_argument('prompt', nargs='?')\\n109\\t agent_parser.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n110\\t agent_parser.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n111\\t agent_parser.add_argument('--system')\\n112\\t agent_parser.add_argument('--max-turns', type=int, default=8)\\n113\\t agent_parser.add_argument('--deny-tool', action='append', default=[])\\n114\\t agent_parser.add_argument('--deny-prefix', action='append', default=[])\\n115\\t agent_parser.add_argument('--trace', action='store_true')\\n116\\t\\n117\\t worker_parser = subparsers.add_parser('worker', help='manage structured local Ollama workers')\\n118\\t worker_subparsers = worker_parser.add_subparsers(dest='worker_command', required=True)\\n119\\t\\n120\\t worker_create = worker_subparsers.add_parser('create', help='create a worker record')\\n121\\t worker_create.add_argument('--root', default='.')\\n122\\t worker_create.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n123\\t worker_create.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n124\\t\\n125\\t worker_subparsers.add_parser('list', help='list stored worker records')\\n126\\t\\n127\\t worker_run = worker_subparsers.add_parser('run', help='run a task packet on a worker')\\n128\\t worker_run.add_argument('worker_id')\\n129\\t worker_run.add_argument('--packet', required=True)\\n130\\t worker_run.add_argument('--trace', action='store_true')\\n131\\t\\n132\\t worker_status = worker_subparsers.add_parser('status', help='show worker state')\\n133\\t worker_status.add_argument('worker_id')\\n134\\t\\n135\\t worker_resume = worker_subparsers.add_parser('resume', help='rerun the last stored task packet')\\n136\\t worker_resume.add_argument('worker_id')\\n137\\t worker_resume.add_argument('--trace', action='store_true')\\n138\\t\\n139\\t worker_close = worker_subparsers.add_parser('close', help='close a worker record')\\n140\\t worker_close.add_argument('worker_id')\\n141\\t\\n142\\t autoresearch_parser = subparsers.add_parser('autoresearch', help='project-specific control plane for autoresearch experiments')\\n143\\t autoresearch_subparsers = autoresearch_parser.add_subparsers(dest='autoresearch_command', required=True)\\n144\\t\\n145\\t autoresearch_setup = autoresearch_subparsers.add_parser('setup', help='verify autoresearch repo state and initialize results.tsv')\\n146\\t autoresearch_setup.add_argument('--root')\\n147\\t autoresearch_setup.add_argument('--no-init-results', action='store_true')\\n148\\t\\n149\\t autoresearch_run = autoresearch_subparsers.add_parser('run', help='run one autoresearch experiment packet through the worker + experiment runner')\\n150\\t autoresearch_run.add_argument('--root')\\n151\\t autoresearch_run.add_argument('--packet', required=True)\\n152\\t autoresearch_run.add_argument('--model', default=DEFAULT_OLLAMA_MODEL)\\n153\\t autoresearch_run.add_argument('--host', default=DEFAULT_OLLAMA_HOST)\\n154\\t autoresearch_run.add_argument('--trace', action='store_true')\\n155\\t\\n156\\t autoresearch_parse_log = autoresearch_subparsers.add_parser('parse-log', help='parse a train.py run log into machine-readable metrics')\\n157\\t autoresearch_parse_log.add_argument('--root')\\n158\\t autoresearch_parse_log.add_argument('log_path')\\n159\\t return parser\\n160\\t\\n161\\t\\n162\\tdef resolve_chat_prompt(args: argparse.Namespace, parser: argparse.ArgumentParser) -> str:\\n163\\t if args.prompt:\\n164\\t return args.prompt\\n165\\t prompt = sys.stdin.read().strip()\\n166\\t if prompt:\\n167\\t return prompt\\n168\\t command_name = getattr(args, 'command', 'command')\\n169\\t parser.error(f'{command_name} requires a prompt argument or stdin input')\\n170\\t raise AssertionError('unreachable')\\n171\\t\\n172\\t\\n173\\tdef main(argv: list[str] | None = None) -> int:\\n174\\t parser = build_parser()\\n175\\t args = parser.parse_args(argv)\\n176\\t manifest = build_port_manifest()\\n177\\t if args.command == 'summary':\\n178\\t print(QueryEnginePort(manifest).render_summary())\\n179\\t return 0\\n180\\t if args.command == 'manifest':\\n181\\t print(manifest.to_markdown())\\n182\\t return 0\\n183\\t if args.command == 'parity-audit':\\n184\\t print(run_parity_audit().to_markdown())\\n185\\t return 0\\n186\\t if args.command == 'setup-report':\\n187\\t print(run_setup().as_markdown())\\n188\\t return 0\\n189\\t if args.command == 'command-graph':\\n190\\t print(build_command_graph().as_markdown())\\n191\\t return 0\\n192\\t if args.command == 'tool-pool':\\n193\\t print(assemble_tool_pool().as_markdown())\\n194\\t return 0\\n195\\t if args.command == 'bootstrap-graph':\\n196\\t print(build_bootstrap_graph().as_markdown())\\n197\\t return 0\\n198\\t if args.command == 'subsystems':\\n199\\t for subsystem in manifest.top_level_modules[: args.limit]:\\n200\\t print(f'{subsystem.name}\\\\t{subsystem.file_count}\\\\t{subsystem.notes}')\\n201\\t return 0\\n202\\t if args.command == 'commands':\\n203\\t if args.query:\\n204\\t print(render_command_index(limit=args.limit, query=args.query))\\n205\\t else:\\n206\\t commands = get_commands(include_plugin_commands=not args.no_plugin_commands, include_skill_commands=not args.no_skill_commands)\\n207\\t output_lines = [f'Command entries: {len(commands)}', '']\\n208\\t output_lines.extend(f'- {module.name} \\u2014 {module.source_hint}' for module in commands[: args.limit])\\n209\\t print('\\\\n'.join(output_lines))\\n210\\t return 0\\n...[truncated]\",\n", " \"metadata\": {\n", " \"path\": \"src/main.py\",\n", " \"start_line\": 1,\n", " \"end_line\": 386,\n", " \"line_count\": 386\n", " },\n", " \"error\": null\n", " }\n", " ],\n", " \"artifacts\": [],\n", " \"changed_files\": [],\n", " \"verification\": {\n", " \"acceptance_tests\": [\n", " {\n", " \"command\": \"python3 -m unittest tests/test_porting_workspace.py\",\n", " \"success\": true,\n", " \"exit_code\": 0,\n", " \"output\": \".........................................\\n----------------------------------------------------------------------\\nRan 41 tests in 3.865s\\n\\nOK\"\n", " }\n", " ],\n", " \"tool_runs\": {\n", " \"run_tests\": [],\n", " \"run_build\": []\n", " }\n", " },\n", " \"final_answer\": \"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\",\n", " \"stop_reason\": \"completed\",\n", " \"turns\": 3,\n", " \"trace_events\": [\n", " \"assistant_raw[1]={\\\"type\\\":\\\"tool_call\\\",\\\"name\\\":\\\"read_file\\\",\\\"arguments\\\":{\\\"path\\\":\\\"src/main.py\\\"}}\",\n", " \"tool_call[1]=read_file {\\\"path\\\": \\\"src/main.py\\\"}\",\n", " \"tool_result[1]=read_file success=True error=None\",\n", " \"assistant_raw[2]={\\\"response\\\": \\\"The provided code snippet is from a Python script located at 'src/main.py'. It appears to be the main entry point for a command-line interface (CLI) application. The script defines several subcommands and their corresponding functionalities, such as building parsers, resolving chat prompts, and executing various commands like 'summary', 'manifest', 'parity-audit', etc. Each subcommand is handled within conditional statements in the `main` function. The script also includes functions for parsing logs, running experiments, and managing workers. Overall, this script serves as a control plane for managing and interacting with an autoresearch experiment environment.\\\"}\",\n", " \"protocol_error[2]=Response type must be either \\\"tool_call\\\" or \\\"final\\\".\",\n", " \"assistant_raw[3]={\\\"type\\\":\\\"final\\\",\\\"content\\\":\\\"I found a Python script at 'src/main.py' that serves as the main entry point for a CLI application. It includes various subcommands and functionalities such as building parsers, resolving chat prompts, and executing commands like 'summary', 'manifest', 'parity-audit', etc.\\\"}\"\n", " ]\n", " },\n", " \"last_error\": null\n", "}\n", "\n" ] }, { "data": { "text/plain": [ "'closed'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "worker_closed = run_json([\n", " PYTHON,\n", " \"-m\",\n", " \"src.main\",\n", " \"worker\",\n", " \"close\",\n", " worker_id,\n", "])\n", "worker_closed[\"state\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Smoke Test Success Criteria\n", "\n", "The smoke test is considered successful when:\n", "\n", "- the worker is created without manual `worker_id` handling\n", "- `worker run` returns JSON\n", "- `last_result.tool_calls` is non-empty\n", "- `last_result.verification.acceptance_tests` is present\n", "- `last_result.stop_reason` is `completed` or `verification_failed`\n", "- `worker status`, `worker resume`, and `worker close` all succeed" ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.20" } }, "nbformat": 4, "nbformat_minor": 5 }