adachsoft/rector-tool

AI tool wrapper for running Rector (analyze/fix) via adachsoft/rector-wrapper-lib.

Installs: 5

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

pkg:composer/adachsoft/rector-tool

0.2.3 2026-02-18 13:52 UTC

This package is not auto-updated.

Last update: 2026-02-18 12:58:54 UTC


README

Thin SPI adapter tool for running Rector through adachsoft/rector-wrapper-lib inside the adachsoft/ai-tool-call ecosystem.

The package exposes a single SPI tool:

  • Tool name: rector_analyze
  • Purpose: analyze or fix PHP code using Rector (dry-run or apply diffs)

It is designed to be a thin, testable adapter:

  • configuration is provided via ConfigMap in the SPI factory,
  • execution is delegated to RectorRunner, which uses rector-wrapper-lib.

Requirements

  • PHP ^8.3
  • adachsoft/ai-tool-call ^2.0.1
  • adachsoft/rector-wrapper-lib ^0.2.0
  • adachsoft/collection ^3.0.0
  • adachsoft/command-executor-lib ^2.0

These constraints are enforced transitively via Composer when you require this package.

Installation

composer require adachsoft/rector-tool

This will pull all required dependencies, including ai-tool-call and rector-wrapper-lib.

For development, you may also want to install Rector directly:

composer require --dev rector/rector

SPI Integration Overview

adachsoft/ai-tool-call 2.x uses a factory-based SPI model:

  • You implement tools via AdachSoft\AiToolCall\SPI\ToolInterface.
  • You register them via AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface.
  • Configuration is provided as AdachSoft\AiToolCall\SPI\Collection\ConfigMap.

This library provides:

  • AdachSoft\RectorTool\RectorTool – the SPI tool implementation.
  • AdachSoft\RectorTool\RectorToolFactory – the SPI factory that wires:
    • RectorToolConfig (base path, error limits, rector config path, excluded folders),
    • RectorRunner (delegates to rector-wrapper-lib),
    • Rector facade created by RectorWrapperFactory::createDefault().

You typically never instantiate RectorTool directly – the AI Tool Call builder uses the factory and a ConfigMap to create a fully configured tool.

Registering the Tool in AiToolCallFacadeBuilder

use AdachSoft\AiToolCall\PublicApi\Builder\AiToolCallFacadeBuilder;
use AdachSoft\AiToolCall\PublicApi\Dto\ToolCallRequestDto;
use AdachSoft\AiToolCall\SPI\Collection\ConfigMap;
use AdachSoft\RectorTool\RectorToolFactory;

$rectorFactory = new RectorToolFactory();

$rectorConfig = new ConfigMap([
    // Required: base path of the project where Rector should operate
    'base_path' => __DIR__,

    // Optional: maximum number of errors to collect before stopping
    'max_errors' => 50,

    // Optional: timeout in seconds for the underlying Rector process
    'timeout_seconds' => 120,

    // Optional: explicit path to rector.php (relative or absolute)
    'default_rector_config_path' => __DIR__ . '/rector.php',

    // Optional: list/map of forbidden values for the `path` parameter
    // - as list: ['.', ''] -> generic error message per entry
    // - as map: ['.' => 'Root is forbidden', '' => 'Empty path is forbidden']
    'excluded_folders' => [
        '.' => 'Running Rector on project root is forbidden. Use "src" or "tests" instead.',
        ''  => 'Empty path is not allowed. Please provide a valid relative directory.',
    ],
]);

$facade = AiToolCallFacadeBuilder::new()
    ->withSpiFactories([$rectorFactory])
    ->withToolConfigs([
        // Tool name must match RectorTool::getDefinition()->name
        'rector_analyze' => $rectorConfig,
    ])
    ->build();

// Example: dry-run analysis
$result = $facade->callTool(new ToolCallRequestDto(
    toolName: 'rector_analyze',
    parameters: [
        'path' => 'src',      // relative to base_path
        'fix'  => false,      // dry-run (check only)
    ],
));

// Example: apply fixes
$fixResult = $facade->callTool(new ToolCallRequestDto(
    toolName: 'rector_analyze',
    parameters: [
        'path' => 'src',
        'fix'  => true,       // execute Rector in fix mode
    ],
));

ConfigMap key rules

ConfigMap in ai-tool-call 2.x strictly validates keys:

  • non-empty string,
  • at most 32 characters,
  • lowercase a-z, digits 0-9, underscore _,
  • optional dot-separated segments (e.g. http_client.timeout).

This library uses the following keys (all valid under these rules):

  • base_path – required,
  • max_errors – optional,
  • timeout_seconds – optional, forwarded to BootstrapOptionsDto::timeoutSeconds,
  • default_rector_config_path – optional,
  • excluded_folders – optional, list/map of forbidden path values to error messages.

excluded_folders configuration

The excluded_folders key controls which values of the path parameter are rejected before Rector is executed.

Supported shapes:

  • Simple list – e.g. ['.', '', 'var']
    • each entry is treated as forbidden,
    • a generic message Folder "<path>" is forbidden for Rector execution. is used.
  • Associative map – e.g. ['.' => 'Root is forbidden', '' => 'Empty path is forbidden']
    • keys are forbidden path values,
    • values are custom error messages used in exceptions.

During rector_analyze calls:

  • if the requested path equals any key in the normalized map, RectorTool throws InvalidToolCallException before invoking Rector, with the configured message;
  • if excluded_folders is omitted or empty, no additional blocking happens beyond standard path validation (e.g. .., escaping base_path).

Tool Definition

RectorTool::getDefinition() returns:

  • name: rector_analyze
  • description:

    Analyzes or fixes PHP code using Rector. Use this tool to upgrade code, fix architectural issues, or improve code quality.

  • parametersSchema (JSON Schema-like array):

    {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "Relative path to the file or directory to analyze (e.g., 'src/Service')."
        },
        "fix": {
          "type": "boolean",
          "description": "Whether to apply fixes automatically. Defaults to false (dry-run)."
        }
      },
      "required": ["path"]
    }
    

Parameters

  • path (string, required)
    • Relative path (file or directory) inside base_path.
    • Examples: src, src/Service, app/Controller/UserController.php.
  • fix (bool, optional, default: false)
    • false – Rector runs in check / dry-run mode (no files are modified).
    • true – Rector runs in fix mode and writes changes to disk.

Path traversal is blocked:

  • any .. segment in path causes an InvalidArgumentException inside RectorRunner.
  • paths resolved outside of base_path are rejected.

Tool Result Structure

RectorTool::callTool() returns a ToolCallResultDto with result wrapped in a KeyValueMap built from a PHP array with the following shape:

[
    'status' => 'OK' | 'LIMIT_EXCEEDED' | 'RUNTIME_ERROR',

    'meta' => [
        'duration_ms'   => int,   // total runtime in milliseconds
        'total_files'   => int,   // total files inspected by Rector
        'changed_files' => int,   // files with diffs
    ],

    'errors' => [
        // list of runtime error strings reported by Rector
        'Some runtime error message',
        'Another error message'
    ],

    'diffs' => [
        [
            'file'            => 'path/to/file.php',
            'diff'            => "--- Original\n+++ New\n...",  // unified diff
            'applied_rectors' => [
                'Rector\\Rule\\SomeRule',
                'Rector\\Rule\\OtherRule'
            ],
        ],
        // more file diffs...
    ],
];

You can access this structure from the ToolCallResultDto via:

/** @var ToolCallResultDto $result */
$payload = $result->result->all();

$status = $payload['status'];
$meta   = $payload['meta'];
$errors = $payload['errors'];
$diffs  = $payload['diffs'];

Error Handling

The tool uses the standard SPI exception model from ai-tool-call:

  • InvalidToolCallException
    • thrown when required parameters are missing or invalid (e.g. missing/empty path, or path is explicitly forbidden via excluded_folders configuration);
    • for forbidden paths, the exception message is taken from excluded_folders or falls back to Folder "<path>" is forbidden for Rector execution..
  • ToolExecutionException
    • thrown when Rector execution fails, wraps the original exception from rector-wrapper-lib.
    • message is prefixed with: "Rector execution failed: ...".

From the Public API side (AiToolCallFacade), these are further mapped to PublicApi\Exception\ToolCallFailedException.

Safety & Limitations

  • Paths are always resolved relative to base_path and validated so they cannot escape the project directory (no .., no absolute paths outside base).
  • max_errors from RectorToolConfig is passed to rector-wrapper-lib as LimitsDto::maxErrors to prevent flooding the AI context with excessive errors.
  • You can additionally block dangerous or undesired path values (e.g. ., empty string, vendor) using the excluded_folders configuration, which will cause InvalidToolCallException before Rector is executed.
  • Actual Rector rules, sets and configuration are defined in your rector.php and are not controlled by this library.

Versioning

This library follows Semantic Versioning. The effective behavior is also constrained by the versions of:

  • adachsoft/ai-tool-call (factory-based SPI, ConfigMap key validation),
  • adachsoft/rector-wrapper-lib (DTO shapes, status enums, limits),
  • adachsoft/collection (immutable map/list semantics).

Always consult their respective CHANGELOGs when upgrading major versions.

Development

For development, install Rector as a dev dependency:

composer require --dev rector/rector

This allows you to run Rector on the project codebase itself.