drivers.claude

drivers.claude

Regeneration of one unit by Claude Code (spotregen claude).

The protocol of the regeneration experiment, made repeatable. The run is blind: Claude Code could read the repository, so the driver confines it, which makes the generator memoryless. It sees the regeneration bundle, not the old module, its unit tests or the history.

  1. The unit’s regeneration bundle is written into an empty workspace.
  2. Only the bundle and the files named by --allow are copied into that workspace.
  3. The generator, claude -p in restricted mode with the tools Read, Write and Edit, runs with the workspace as its only directory. It has no shell, so it can neither read the deleted module nor run the tests. Blindness is enforced, not requested.
  4. The written module is copied into a detached git worktree of HEAD in which the original was deleted, and scored by the unit’s evaluations, then its unit tests, then its dependents inside the repository: the declared code consumers are imported and the docstring examples of the original are run against the module. On failure, the evaluation output is handed back for another attempt.
  5. run.toml records model, CLI version, commit, hashes, attempts, the files the generator read and all three scores. The transcript and the generator’s report are kept.

--score FILE skips steps 1 to 3 and scores an existing module. --dry-run prepares the workspace and prints the generator command without calling it. An LLM call is not deterministic, so this command never belongs in make guard.

Usage::

spotregen claude core.calc --allow src/samplepkg/core/helpers.py --out /tmp/claude

Functions

Name Description
add_arguments Register the options of spotregen claude on parser.
failed Tool calls that failed for another reason than the confinement.
files_read Paths the generator read successfully, in first-read order.
final_result The generator’s closing message, from the result event of the transcript.
generator_command The claude -p call.
generator_env Environment of the generator; with base_url, Claude Code talks to that server.
refused Tool calls the harness refused, as "Tool path".
run_claude Regenerate one unit with claude -p and score the result.
session_info Tools and model from the init event; cost, turns and duration from the result.
tool_calls Every tool call: tool, path, whether it failed and whether the harness refused it.

add_arguments

drivers.claude.add_arguments(parser)

Register the options of spotregen claude on parser.

Parameters

Name Type Description Default
parser argparse.ArgumentParser The parser of the subcommand. required

Examples

import argparse

from spotregen.drivers.claude import add_arguments

parser = argparse.ArgumentParser(prog="spotregen claude")
add_arguments(parser)
args = parser.parse_args(["core.calc", "--attempts", "2", "--dry-run"])
print(args.unit, args.attempts, args.dry_run, args.model)
core.calc 2 True claude-opus-5-5

failed

drivers.claude.failed(transcript)

Tool calls that failed for another reason than the confinement.

Parameters

Name Type Description Default
transcript Path A stream-json transcript. required

Returns

Name Type Description
list[str] list[str]: "Tool path" for each such call.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import failed

use = {"type": "tool_use", "id": "1", "name": "Read", "input": {"file_path": "."}}
err = {"type": "tool_result", "tool_use_id": "1", "is_error": True, "content": "EISDIR"}
events = [
    {"type": "assistant", "message": {"content": [use]}},
    {"type": "user", "message": {"content": [err]}},
]
with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    transcript.write_text("\n".join(json.dumps(e) for e in events))
    print(failed(transcript))
['Read .']

files_read

drivers.claude.files_read(transcript)

Paths the generator read successfully, in first-read order.

Parameters

Name Type Description Default
transcript Path A stream-json transcript. required

Returns

Name Type Description
list[str] list[str]: The paths of successful Read calls, without repeats.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import files_read

def use(uid, path):
    block = {"type": "tool_use", "id": uid, "name": "Read", "input": {"file_path": path}}
    return {"type": "assistant", "message": {"content": [block]}}

with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    events = [use("1", "a.md"), use("2", "a.md"), use("3", "b.md")]
    transcript.write_text("\n".join(json.dumps(e) for e in events))
    print(files_read(transcript))
['a.md', 'b.md']

final_result

drivers.claude.final_result(transcript)

The generator’s closing message, from the result event of the transcript.

Parameters

Name Type Description Default
transcript Path A stream-json transcript. required

Returns

Name Type Description
str str The report text, or "" if the transcript has no result event.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import final_result

with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    transcript.write_text(json.dumps({"type": "result", "result": "## Report"}))
    print(final_result(transcript))
## Report

generator_command

drivers.claude.generator_command(prompt, model)

The claude -p call.

--restricted removes every code-running tool and confines the file tools to the working directory; --safe-mode disables CLAUDE.md, skills, plugins, hooks and custom agents, so no project knowledge from the user’s setup reaches the generator.

Parameters

Name Type Description Default
prompt str The prompt text. required
model str Model identifier. required

Returns

Name Type Description
list[str] list[str]: The argument vector, starting with claude -p <prompt>.

Examples

from spotregen.drivers.claude import generator_command

command = generator_command("PROMPT", "claude-opus-5-5")
print(command[:3], "--restricted" in command, "Bash" in " ".join(command))
['claude', '-p', 'PROMPT'] True False

generator_env

drivers.claude.generator_env(base_url, model, token, max_output=None)

Environment of the generator; with base_url, Claude Code talks to that server.

A local server with an Anthropic-compatible /v1/messages endpoint (LM Studio) serves the model. The helper-model variables point Claude Code’s background calls to the same model, and non-essential traffic (telemetry, update checks) is switched off, so neither code nor prompts leave the machine.

Parameters

Name Type Description Default
base_url str | None Server URL, or None to use the Anthropic API. required
model str Model identifier served at base_url. required
token str Authentication token for base_url. required
max_output int | None Output budget per model turn, or None. Defaults to None. None

Returns

Name Type Description
dict[str, str] dict[str, str]: The environment for the generator process.

Examples

from spotregen.drivers.claude import generator_env

env = generator_env("http://localhost:1234", "my-model", "token")
print(env["ANTHROPIC_BASE_URL"], env["ANTHROPIC_DEFAULT_OPUS_MODEL"])
print("ANTHROPIC_BASE_URL" in generator_env(None, "m", "t"))
http://localhost:1234 my-model
False

refused

drivers.claude.refused(transcript)

Tool calls the harness refused, as "Tool path".

Parameters

Name Type Description Default
transcript Path A stream-json transcript. required

Returns

Name Type Description
list[str] list[str]: One entry per call whose error is the confinement message.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import CONFINEMENT, refused

use = {"type": "tool_use", "id": "1", "name": "Read", "input": {"file_path": "/etc/passwd"}}
err = {"type": "tool_result", "tool_use_id": "1", "is_error": True, "content": CONFINEMENT}
events = [
    {"type": "assistant", "message": {"content": [use]}},
    {"type": "user", "message": {"content": [err]}},
]
with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    transcript.write_text("\n".join(json.dumps(e) for e in events))
    print(refused(transcript))
['Read /etc/passwd']

run_claude

drivers.claude.run_claude(spec, unit, args)

Regenerate one unit with claude -p and score the result.

Parameters

Name Type Description Default
spec RegenSpec The loaded spec; its root is the repository. required
unit Unit The unit to regenerate. required
args argparse.Namespace The parsed options, see add_arguments. required

Returns

Name Type Description
int int 0 if the last attempt’s evaluations and the dependents pass, 1 otherwise.

Raises

Name Type Description
ExternalToolError If git (or claude, unless --score or --dry-run) is not installed.
ConfigurationError If an --allow file lies outside the repository or --score names no file.

Examples

import argparse

from spotregen.drivers.claude import add_arguments

parser = argparse.ArgumentParser(prog="spotregen claude")
add_arguments(parser)
print(parser.parse_args(["core.calc", "--score", "candidate.py"]).score)
candidate.py

session_info

drivers.claude.session_info(transcript)

Tools and model from the init event; cost, turns and duration from the result.

Parameters

Name Type Description Default
transcript Path A stream-json transcript. required

Returns

Name Type Description
dict[str, object] dict[str, object]: tools and session_model if an init event exists, cost_usd, turns and duration_s if a result event exists.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import session_info

events = [
    {"type": "system", "subtype": "init", "tools": ["Read"], "model": "m"},
    {"type": "result", "total_cost_usd": 0.5, "num_turns": 4, "duration_ms": 12345},
]
with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    transcript.write_text("\n".join(json.dumps(e) for e in events))
    print(session_info(transcript))
{'tools': ['Read'], 'session_model': 'm', 'cost_usd': 0.5, 'turns': 4, 'duration_s': 12.3}

tool_calls

drivers.claude.tool_calls(transcript)

Every tool call: tool, path, whether it failed and whether the harness refused it.

A call is refused only when its error is the confinement message of --restricted; any other error (for example reading a directory) is a plain failure.

Parameters

Name Type Description Default
transcript Path A stream-json transcript written by claude -p. required

Returns

Name Type Description
list[dict[str, object]] list[dict[str, object]]: One dictionary per call with the keys tool, path, failed and refused.

Examples

import json
from pathlib import Path
from tempfile import TemporaryDirectory

from spotregen.drivers.claude import tool_calls

use = {"type": "tool_use", "id": "1", "name": "Read", "input": {"file_path": "a.md"}}
events = [{"type": "assistant", "message": {"content": [use]}}]
with TemporaryDirectory() as tmp:
    transcript = Path(tmp) / "t.jsonl"
    transcript.write_text("\n".join(json.dumps(e) for e in events))
    print(tool_calls(transcript))
[{'tool': 'Read', 'path': 'a.md', 'failed': False, 'refused': False}]