AFT (Agentic File Tools)

repository·main·Indexed 41 days ago

https://github.com/cortexkit/aft

A 'sensorimotor cortex' for coding agents that provides IDE-like structural awareness and symbol-based editing to reduce token usage and increase reliability. Includes a comprehensive benchmark suite for search evaluation, exact-recall gating, and retrieval quality comparisons against CodeGraph and ripgrep.

Tokens
149K
Snippets
292
Records
637
Agent score
56%

What's inside AFT

  1. Overview of AFT Benchmark Harnesses

    main

    The benchmarks/ directory provides reproducible harnesses for evaluating AFT performance. Using Docker is the recommended approach as it eliminates the need to install AFT, Bun, Rust, CodeGraph, or OpenCode on your host machine. Results are automatically written to a results/ directory within each specific benchmark folder.

    BenchmarkEntry pointMeasures
    aft-search/bun run bench:aft-search or make run-aft-searchAFT aft_search retrieval on the in-tree fixture suite
    codegraph-replication/bun run bench:codegraph-replication (local) or bun run bench:codegraph-replication:dockerStructured CodeGraph-style retrieval cases run through AFT and lexical baselines
    codegraph-vs-aft-retrieval/bun run bench:codegraph-vs-aft-retrieval or make run-codegraph-vs-aft-retrievalPath A: No-LLM retrieval quality (AFT vs CodeGraph) using Recall/MRR/P@k
    codegraph-vs-aft-agent/bun run bench:codegraph-vs-aft-agent or make run-codegraph-vs-aft-agentPath B: OpenCode agent A/B testing (AFT plugin vs CodeGraph MCP)

    Important Distinction:

    • Path A (Retrieval): Focuses on retrieval quality without LLM involvement. Do not use these results to infer agent behavior.
    • Path B (Agent): Uses an LLM and involves real agent runs, meaning results will have run-to-run variance.
  2. Understand the AFT codebase structure

    main

    The AFT repository is organized into several key functional areas:

    • Core Engine (crates/aft/): The Rust-based execution engine, including the stdin/stdout protocol, shared analysis logic, and command handlers.
    • Tokenizer (crates/aft-tokenizer/): A standalone Rust crate for counting Claude API tokens.
    • Plugins (packages/opencode-plugin/, packages/pi-plugin/): TypeScript packages that resolve the AFT binary and register tools for specific coding agent harnesses (OpenCode and Pi).
    • Bridge (packages/aft-bridge/): The shared transport layer used by plugins to communicate with the subc daemon.
    • CLI (packages/aft-cli/): A unified entry point via npx @cortexkit/aft for setup, diagnostics (doctor), and LSP management.
    • Platform Binaries (packages/npm/): Platform-specific npm packages used to distribute bundled binaries for Darwin, Linux, and Win32.
  3. Understand the AFT agent-text habit audit findings

    main

    The AFT agent-text habit audit (2026-07) evaluates the text presented to agents (e.g., tool descriptions, workflow hints, error messages, and system notifications) against six ALF fleet habit-training defect classes. The goal is to identify strings that might inadvertently train an agent to develop incorrect, unbounded, or unsafe habits, such as infinite polling loops or assuming stale data is current.

    Defect Classes referenced in the audit:

    • A, B, C, D, E, F: These represent specific categories of agent habit defects (e.g., training an agent to treat a partial transaction as complete, or training an agent to use a polling loop instead of waiting for a notification).

    Key Audit Areas:

    • Formatter sets (crates/aft/src/subc_format.rs)
    • Response finalization and orchestration paths
    • Tool descriptions and schemas (crates/aft/src/subc_tool_schemas.json)
    • Plugin-injected workflow hints and permission/steering messages
  4. Understand views materialization emission and cache-row reconciliation

    main

    The views materialization process has been optimized to use in-place UPSERTs for view_bindings and view_file_surfaces instead of deleting and replacing cache owners. Removed owners are now deleted explicitly.

    Key Improvements:

    • Reconciliation: Changed-owner dependency rows are reconciled via a temporary primary-key table using set-based delete/insert. This avoids unnecessary B-tree cell churn for large payload tables.
    • Staged Emission: Emission is staged in memory by table and executed via one prepared statement per table.
    • Parallelism: Binding and surface payloads are decoded in parallel, reducing allocation latency.

    Performance Metrics observed:

    • Physical Writes: Reduced by ~27.9%.
    • WAL Size: Reduced by ~28.2%.
    • SQLite Page Writes: Reduced in individually attributed rows.
  5. Coordinate safe cache access with WriterLease

    main

    The WriterLease and ReadMarker system coordinates safe multi-session access to the root-keyed project cache.

    • WriterLease: Uses a file-locked writer lease to ensure single-writer exclusivity. It uses domain mapping (e.g., RootCacheDomain::Callgraph or RootCacheDomain::Inspect) and epoch validation.
    • ReadMarker: Uses private read-marker JSON files (created with 0600 permissions under <domain>/readers/) to track active reader processes.
    • Cleanup: The system automatically sweeps and cleans up dead-PID markers and expired cross-host markers.
  6. Understand the AFT episode lifecycle

    main

    An episode is the fundamental unit of measurement for AFT search evaluation. It consists of:

    1. One aft_search call.
    2. Up to three subsequent tool calls (the 'follow-up' window).

    Qualifying follow-up tools include:

    • aft_grep
    • ast_grep_search
    • Bash command segments using grep, rg, ag, or git grep.

    Success Criteria (Discrimination): An episode is considered 'discriminating' if a grep/search tool produces a path that was absent from the initial aft_search output, and a subsequent tool call within that three-call window opens or edits that path.

  7. Understand CI Flake Mechanism Classes

    main

    When debugging or writing tests for AFT, especially in CI environments, failures often fall into one of four mechanism classes. Understanding these helps in choosing the correct fix pattern:

    • S (Scheduler time charged as work time): A wall-clock budget starts before the operation enters the measured lifecycle state. Descheduling or queuing can exhaust the budget without the operation actually violating its contract.
    • P (Completion proxy): The test fixture waits on a correlated signal (like a PID, filesystem sample, or status request) instead of the producer's actual terminal event and authoritative store.
    • G (Unscoped global test control): A process-global variable or environment value is consumed by unrelated parallel tests, causing assertions to observe the wrong lifecycle.
    • F (Filesystem/PID observation race): A path or liveness probe is sampled while a deletion, rename, or process exit is still in progress, leading to race conditions.
  8. Understand the AFT tool response convention

    main

    AFT tool responses follow a tri-state contract to help agents distinguish between different execution outcomes. This ensures the agent knows if a result is complete, partial, or if the operation failed entirely.

    Success States

    • Failure: success: false indicates the work could not be performed. This response must include a code (e.g., path_not_found, no_lsp_server, project_too_large, invalid_request, ambiguous_match) and a message.
    • Complete Success: success: true with complete: true means the result is trustworthy. If the result is empty, it means the tool genuinely found nothing.
    • Partial Success: success: true with complete: false means the tool ran but the result is incomplete. The response will specify the gap using keys like:
      • pending_files, unchecked_files, walk_truncated: Files the tool did not reach.
      • skipped_files: [{file, reason}]: Files intentionally skipped (e.g., due to parse errors or unsupported languages).
      • scope_warnings, no_files_matched_scope: Paths or globs that resolved to zero files.

    Side-effect Skips

    If the primary task succeeded but a non-essential post-step (like formatting or validation) was skipped, the response includes a <step>_skipped_reason.

    format_skipped_reason values:

    • unsupported_language
    • no_formatter_configured
    • formatter_not_installed
    • formatter_excluded_path
    • timeout
    • error

    validate_skipped_reason values:

    • unsupported_language
    • no_checker_configured
    • checker_not_installed
    • timeout
    • error
  9. How bash task delivery and visibility work

    main

    AFT manages background bash tasks through two primary mechanisms: the Delivery arm and the Visibility arm.

    Delivery Arm (Pattern Matching)

    When a terminal performs an output scan, matches are written to bash_pattern_watches via persist_watch_match and emitted as a BashPatternMatch push.

    • Reliability: To prevent matches from being stranded, the system uses a repeating 'subc wake' (nudge).
    • Lifecycle: Terminalization marks task completion as delivered, preserves the pending durable watch until an acknowledgment (ack) is received, and then clears the in-memory watch state.
    • Fix/Best Practice: Ensure that pattern matches receive the same repeating subc wake as completions to prevent them from sitting indefinitely in the database if a direct push is missed during a route rebinding window.

    Visibility Arm (Status Lookups)

    bash_status determines task visibility through a tiered lookup:

    1. In-memory registry: The primary check.
    2. Metadata-only fallback: If the in-memory lookup misses (e.g., due to a registry rebind) or if the task bundle is missing, the system reads the intact terminal DB row into a metadata-only status snapshot.

    Note on Artifacts: A missing or corrupt task bundle does not mean the task is invisible. With the metadata fallback, missing artifacts result in empty/unavailable output rather than an invisible task. However, a task requires a valid bundle under the currently selected storage/session path to reconstruct a full in-memory task.

  10. Use the ListEnvelope for truncated command outputs

    main

    AFT uses a ListEnvelope to provide a uniform truncation and trailer contract for all list-shaped command outputs (e.g., callgraph, grep, search, outline).

    Truncation Logic: When results are truncated, the envelope follows a specific reason precedence: Walk > Depth > Budget > Cap.

    Output Format: If truncated, the output includes a standardized trailer following this grammar: shown <n> of <total> <unit> (<reason>) · narrow: <a>, <b>

    Example Trailer: shown 10 of 50 items (budget) · narrow: foo, bar

  11. Understand Ripwire risk annotations and metrics

    main

    Ripwire provides several risk annotations for ranked symbols during ingest and graph construction. These are computed when using flags like --for, --metrics, or --exemplar.

    Key metrics include:

    • tested=1: Indicates a symbol is transitively reachable from a syntactically identified test symbol via resolved outgoing calls. Note that dynamic dispatch, unbound callbacks, and subprocess tests are excluded.
    • purity: A least fixpoint metric where calls to a specific set of side-effecting intrinsics seed impurity, which then propagates backward to callers via the incoming CSR.
    • churn: The count of commits touching the symbol's file within a 12-month window, derived from an 18-month history walk.
    • amp: A mixed-granularity metric defined as direct caller count + number of distinct files that co-changed with this symbol's file.

    Note: While Ripwire uses these metrics, AFT approaches these questions differently (e.g., using Tree-sitter for complexity and path predicates like is_test_file for test origin).

  12. Analyze incremental derived-view materialization performance

    main

    Performance of derived-view materialization (the 'views' implementation) is measured against the 'legacy' implementation using correctness time (ms), CPU usage (s), and contention metrics.

    Key metrics for evaluating materialization efficiency include:

    • Correctness Time: The time from switch initiation to the first correct search-and-callgraph observation.
    • CPU Usage: Total CPU-seconds consumed during the measurement window.
    • Contention: Reported via build_progress and tier2_scheduled or tier2_phases (e.g., dead_code, unused_exports, duplicates, cycles, complexity).

    A successful implementation follows the 'owner's rule': "views beats legacy to correctness on every row with CPU not above legacy".