adachsoft/phpstan-tool

AI Tool-Call SPI tool for running PHPStan static analysis with normalized base_path semantics.

Installs: 2

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

pkg:composer/adachsoft/phpstan-tool

v0.2.0 2026-01-31 08:46 UTC

This package is not auto-updated.

Last update: 2026-01-31 20:32:52 UTC


README

AI Tool-Call SPI tool for running PHPStan static analysis with normalized base_path semantics.

This library exposes a single SPI tool, phpstan, that can be discovered and called through adachsoft/ai-tool-call. It runs PHPStan via adachsoft/command-executor-lib and resolves all user-provided paths relative to a configured base_path using adachsoft/normalized-safe-path.

Installation

Install via Composer:

composer require adachsoft/phpstan-tool

The exact version constraints for dependencies are defined in this package's composer.json.

High-level architecture

The package follows the AI Tool-Call architecture described in .docs/AI_TOOL_CALL_BASE_PATH_SEMANTICS_AND_TOOL_ARCHITECTURE_PL.md:

  • Tool (SPI)

    • AdachSoft\PhpstanTool\Tool\PhpStanTool
    • Implements AdachSoft\AiToolCall\SPI\ToolInterface.
    • Validates input parameters (KeyValueMap), applies configuration defaults, delegates work to the runner, and maps the result to ToolCallResultDto.
  • Factory (SPI)

    • AdachSoft\PhpstanTool\Tool\PhpStanToolFactory
    • Implements AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface.
    • Reads configuration from ConfigMap (snake_case keys), applies sensible defaults and assembles dependencies: PhpStanToolConfigPhpStanRunnerPhpStanTool.
  • Runner (service layer)

    • AdachSoft\PhpstanTool\Runner\PhpStanRunnerInterface
    • AdachSoft\PhpstanTool\Runner\PhpStanRunner
    • Responsible for:
      • resolving user paths against base_path using SafePathHelper::normalize(),
      • building the phpstan analyse command,
      • executing the command via CommandExecutorInterface::executeWithResult() with cwd = base_path,
      • mapping low-level failures to PhpStanExecutionException.
  • Output processing

    • AdachSoft\PhpstanTool\Runner\OutputProcessor
    • Post-processes raw stdout/stderr from PHPStan:
      • trims output to a fixed maximum size (10 000 characters total),
      • limits the number of reported errors (configured max_errors),
      • optionally filters errors by a simple substring (error_type),
      • sanitizes absolute occurrences of base_path from output for portability.
  • Configuration value object

    • AdachSoft\PhpstanTool\Config\PhpStanToolConfig
    • Immutable object storing resolved configuration for a single tool instance.

Factory configuration (ConfigMap)

PhpStanToolFactory reads configuration from AdachSoft\AiToolCall\SPI\Collection\ConfigMap. All keys are in snake_case and validated by ConfigMap:

  • base_path (string, optional)

    • Absolute path that acts as the root for resolving user paths.
    • Also used as the working directory (cwd) for command execution.
    • Default: getcwd() ?: '.'.
  • phpstan_path (string, optional)

    • Path to the PHPStan executable, relative to base_path or absolute.
    • Default: vendor/bin/phpstan.
  • default_timeout (int|null, optional)

    • Default timeout (seconds) for PHPStan execution when no per-call override is provided.
    • null means "no explicit timeout".
  • max_errors (int, optional)

    • Default maximum number of errors to include in the processed output.
    • 0 means "no limit" (only trimming by total output size applies).
    • Default: 30.

Invalid types or empty strings for required config values cause ToolConfigurationException.

Tool contract: phpstan

Tool name

  • phpstan

Parameters (per call)

All parameters are provided as entries in KeyValueMap (snake_case keys) and validated by PhpStanTool. When validation fails, InvalidToolCallException is thrown.

  • path (string, required)

    • Path to file or directory to analyse.
    • If relative, it is resolved against base_path using SafePathHelper::normalize().
  • error_type (string|null, optional)

    • Simple substring filter applied to error sections.
    • When set, only errors whose text contains this substring are kept.
  • timeout (int|null, optional)

    • Per-call timeout in seconds.
    • null → falls back to default_timeout from configuration.

Result shape

The tool always returns a ToolCallResultDto with a KeyValueMap result containing exactly these keys:

  • stdout (string)
  • stderr (string)
  • exit_code (int)
  • success (bool)

The stdout/stderr values may be trimmed and/or filtered by OutputProcessor according to the rules described above, but the structural shape of the result is stable.

If the runner fails (invalid path, execution error, timeout, etc.), PhpStanExecutionException is thrown in the runner layer and mapped to SpiToolExecutionException in the SPI tool layer.

base_path semantics

base_path follows the common semantics for AI tools built with adachsoft/ai-tool-call:

  • All relative user paths are resolved against base_path using SafePathHelper::normalize().
  • All CLI processes are executed with cwd = base_path.
  • Where appropriate, absolute occurrences of base_path in stdout/stderr are removed to keep outputs portable and avoid leaking environment details.
  • Unsafe paths (e.g. attempts to traverse outside base_path) result in a domain exception rather than direct command execution.

For full details, see .docs/AI_TOOL_CALL_BASE_PATH_SEMANTICS_AND_TOOL_ARCHITECTURE_PL.md.

Example usage (pseudo-code)

Below is a high-level example of how this tool can be wired with adachsoft/ai-tool-call. Exact wiring depends on your application and how you register tool factories.

use AdachSoft\AiToolCall\SPI\Collection\ConfigMap;
use AdachSoft\AiToolCall\SPI\Collection\KeyValueMap;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallRequestDto;
use AdachSoft\PhpstanTool\Tool\PhpStanToolFactory;

// 1) Configure the tool instance via ConfigMap
$configMap = new ConfigMap([
    'base_path' => '/app/project',
    'phpstan_path' => 'vendor/bin/phpstan',
    'default_timeout' => 60,
    'max_errors' => 30,
]);

$factory = new PhpStanToolFactory();
$tool = $factory->create($configMap);

// 2) Build a per-call request
$request = new ToolCallRequestDto(
    toolName: 'phpstan',
    parameters: new KeyValueMap([
        'path' => 'src',          // resolved as /app/project/src
    ]),
);

// 3) Execute tool
$result = $tool->callTool($request);

// 4) Consume structured result
$stdout = $result->result->get('stdout');
$stderr = $result->result->get('stderr');
$exitCode = $result->result->get('exit_code');
$success = $result->result->get('success');

In a real application, the PhpStanToolFactory is typically registered in your AI tool registry so that agents can discover and invoke phpstan dynamically.

License

This package is open-sourced software licensed under the MIT license.