Skip to content

Trace source

trace_source

TraceSourceHook — enriched BFS trace with function source code.

Protocol hook that calls trace_flow(detail="source") and returns the complete trace as HookResult metadata. Registered as ast:trace-source via axm.hooks entry point.

TraceSourceHook dataclass

Run trace_flow(detail="source") and return the enriched trace.

Reads working_dir from context and entry from params. The result is injected into session context via inject_result.

Supports SWE-bench, pytest, and simple symbol entry formats. Automatically scopes analyze_package to the test directory for faster analysis on large repos.

Source code in packages/axm-ast/src/axm_ast/hooks/trace_source.py
@dataclass
class TraceSourceHook:
    """Run ``trace_flow(detail="source")`` and return the enriched trace.

    Reads ``working_dir`` from *context* and ``entry`` from *params*.
    The result is injected into session context via ``inject_result``.

    Supports SWE-bench, pytest, and simple symbol entry formats.
    Automatically scopes ``analyze_package`` to the test directory
    for faster analysis on large repos.
    """

    def execute(self, context: dict[str, Any], **params: Any) -> HookResult:
        """Execute the hook action.

        Args:
            context: Session context dictionary (must contain ``working_dir``).
            **params: Must include ``entry`` (symbol name to trace from).
                Optional ``max_depth`` (default 5), ``cross_module`` (default False).

        Returns:
            HookResult with ``trace`` list in metadata on success.
        """
        entry = params.get("entry")
        if not entry:
            return HookResult.fail("Missing required param 'entry'")

        path = params.get("path") or context.get("working_dir", ".")
        working_dir = Path(path)
        if not working_dir.is_dir():
            return HookResult.fail(f"working_dir not a directory: {working_dir}")

        try:
            # Lazy imports
            global analyze_package, trace_flow
            if analyze_package is None:
                from axm_ast.core.analyzer import (
                    analyze_package as _ap,
                )
                from axm_ast.core.flows import trace_flow as _tf

                analyze_package = _ap
                trace_flow = _tf

            # Parse entry format and scope analysis path
            symbol_name, test_dir = _parse_entry(entry)
            scoped_path = _resolve_scope(working_dir, test_dir)

            pkg = analyze_package(scoped_path)
            max_depth = int(params.get("max_depth", 5))
            cross_module = bool(params.get("cross_module", False))

            steps = trace_flow(
                pkg,
                symbol_name,
                max_depth=max_depth,
                cross_module=cross_module,
                detail="source",
            )
            return HookResult.ok(
                trace=[s.model_dump(exclude_none=True) for s in steps],
            )
        except Exception as exc:  # noqa: BLE001
            return HookResult.fail(f"Trace failed: {exc}")
execute(context, **params)

Execute the hook action.

Parameters:

Name Type Description Default
context dict[str, Any]

Session context dictionary (must contain working_dir).

required
**params Any

Must include entry (symbol name to trace from). Optional max_depth (default 5), cross_module (default False).

{}

Returns:

Type Description
HookResult

HookResult with trace list in metadata on success.

Source code in packages/axm-ast/src/axm_ast/hooks/trace_source.py
def execute(self, context: dict[str, Any], **params: Any) -> HookResult:
    """Execute the hook action.

    Args:
        context: Session context dictionary (must contain ``working_dir``).
        **params: Must include ``entry`` (symbol name to trace from).
            Optional ``max_depth`` (default 5), ``cross_module`` (default False).

    Returns:
        HookResult with ``trace`` list in metadata on success.
    """
    entry = params.get("entry")
    if not entry:
        return HookResult.fail("Missing required param 'entry'")

    path = params.get("path") or context.get("working_dir", ".")
    working_dir = Path(path)
    if not working_dir.is_dir():
        return HookResult.fail(f"working_dir not a directory: {working_dir}")

    try:
        # Lazy imports
        global analyze_package, trace_flow
        if analyze_package is None:
            from axm_ast.core.analyzer import (
                analyze_package as _ap,
            )
            from axm_ast.core.flows import trace_flow as _tf

            analyze_package = _ap
            trace_flow = _tf

        # Parse entry format and scope analysis path
        symbol_name, test_dir = _parse_entry(entry)
        scoped_path = _resolve_scope(working_dir, test_dir)

        pkg = analyze_package(scoped_path)
        max_depth = int(params.get("max_depth", 5))
        cross_module = bool(params.get("cross_module", False))

        steps = trace_flow(
            pkg,
            symbol_name,
            max_depth=max_depth,
            cross_module=cross_module,
            detail="source",
        )
        return HookResult.ok(
            trace=[s.model_dump(exclude_none=True) for s in steps],
        )
    except Exception as exc:  # noqa: BLE001
        return HookResult.fail(f"Trace failed: {exc}")