Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ vendor/
coverage/
.cache/
tmp/
.gradle/


# Added by cargo
Expand Down
28 changes: 24 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@
- For subc mode (when `subc.connection_file` is set): send `{name, arguments}` as a data-plane request over a tool-provider route channel opened and cached per session identity (`BindIdentity`) -- `packages/aft-bridge/src/subc-transport.ts`
3. Dispatch the request to the target command or executor. Under standalone mode, dispatch through the Rust stdin NDJSON loop. Under subc mode, process frames via the TCP loopback client loop. Local `configure` commands are satisfied locally on bind. Native plumbing tools (`bash_drain_completions`, `bash_ack_completions`, `bash_regex_match`) bypass the tool manifest check but reinject the BIND session ID to keep sessions isolated. The execution outcome is processed through the server-side text formatter (`crates/aft/src/subc_format.rs`) and a pending response finalizer seam (`crates/aft/src/response_finalize.rs`). Subc response frames contain `structuredContent` for first-party binds to re-lift the full flat response shape into `ToolCallResult` at the transport boundary, maintaining parity with standalone mode. For untrusted (MCP) binds, the server returns text-only replies (omitting `structuredContent` entirely) to prevent models like Claude Code from consuming raw JSON dumps and to save token costs. Monotonic phase traces (`PhaseTrace` and `ToolCallPhaseDurations`) track the timing/performance of subc tool calls across multiple phases (queuing, translation, execution, formatting, finalization, and egress) for slow-call diagnostics. Under subc mode, the initial attach loop retries transient connection and authentication failures (using an exponential backoff with jitter up to a 60-second budget) to recover from temporary daemon unavailability. Retry request dispatch once when a route is proven absent (receiving daemon `unknown_channel` or client `StaleRouteHandleError` before write). A cancelled route bind (e.g. Goodbye or deadline expiry) signals the configure job's cooperative `JobCancellation` handle; the running configure command checks this at phase boundaries (`configure_cancelled` and `root_commit_probe_cancelled`) to abort early and avoid building indexes or running git root commit probes for a dead route.

**Deadline and executor flow:**

1. Bound Pi-facing synchronous calls below the host's hard 30-second limit. The Pi adapter assigns a 25-second transport budget and emits progress updates every 5 seconds without treating them as keepalives -- `packages/pi-plugin/src/tools/_shared.ts`.
2. Carry one absolute request budget through bridge route opening and request dispatch. A route-open retry does not reset the caller's budget, and caller-scoped `not_sent` expiry does not invalidate the shared client -- `packages/aft-bridge/src/bridge.ts`, `packages/aft-bridge/src/subc-transport.ts`.
3. Normalize the remaining wire budget into a local absolute deadline and submit interactive work with at most 24 seconds of Rust execution time -- `crates/aft/src/subc/mod.rs`, `crates/aft/src/executor/mod.rs`.
4. Admit jobs into bounded process-wide and per-actor queues. Interactive and maintenance jobs use separate capacity accounting. Interactive admission prefers readers, promotes deadline-pressured writers, and prunes expired jobs before dispatch. The executor rotates active actors with deficit round-robin scheduling and reserves capacity for maintenance progress -- `crates/aft/src/executor/mod.rs`.
5. Promote unfinished synchronous bash waits to background tasks before the host deadline. Return the task identity so a later call can observe completion -- `packages/pi-plugin/src/tools/bash.ts`, `crates/aft/src/commands/bash_orchestrate.rs`.

**Edit pipeline:**

1. Validate path and verify symlink safety (recursively follow components up to 40 hops to reject escaping paths), resolving relative paths against the bound project root via `AppContext::resolve_relative_path` before validation and safety keying -- `crates/aft/src/context.rs`
Expand All @@ -107,8 +115,10 @@

1. Index project files using a disk-backed, pread-based trigram search index that keeps memory overhead bounded -- `crates/aft/src/search_index.rs`. To prevent redundant disk hashing and index re-verification loops during configure bind/warmup sequences, a verification memo with a 10-minute TTL manages cache freshness checks, utilizing metadata stat checks (`VerifyStrategy::StatFirst`) when possible rather than strict content hashing. For grafted history roots, canonicalize the sorted, deduplicated set of root commits before hashing artifact keys to prevent Git traversal-order changes from triggering redundant index rebuilds.
2. Optionally index with dense embeddings (fastembed, OpenAI-compatible, Ollama, or Synapse over SubC) -- `crates/aft/src/semantic_index.rs`, `crates/aft/src/synapse_embed.rs`. Serialize cold semantic warmups by gating callgraph store building and Tier 2 diagnostics refreshes behind active cold semantic index seeds. Coalesce watcher-driven semantic re-embeds under a 15-second quiet window (`SEMANTIC_REFRESH_QUIET_WINDOW_MS`) to bundle edit bursts into a single collection pass, while masking changed files from search results until indexed to preserve query correctness. Reconfiguring semantic settings or project roots cancels superseded semantic builders while adopting matching live builders. In tests, override this quiet window via the `AFT_SEMANTIC_QUIET_WINDOW_MS` environment variable. Limit process-wide semantic refresh concurrency using the `ColdBuildLimiter` (sharing the slot budget with other heavy maintenance operations) to prevent concurrent background refreshes from overloading remote or local embedding backends -- `crates/aft/src/cold_build_limiter.rs`, `crates/aft/src/commands/configure.rs`.
3. Classify query shape (prose vs code) using the query shape parser -- `crates/aft/src/query_shape.rs`. Identify "type-concept identifier queries" (TitleCase PascalCase types combined with lowercase concepts) to trigger definition semantic priors.
4. Serve `grep` (trigram, full-text) and `aft_search` (semantic + hybrid) queries, delegating to `GrepExecutor` for accelerated path evaluation and enforcing execution safety limits (like `MAX_FALLBACK_WALK_FILES` and `FALLBACK_WALK_BUDGET`) during fallback walks when indexes are building or unavailable -- `crates/aft/src/grep_executor.rs`, `crates/aft/src/commands/grep.rs`, `crates/aft/src/commands/semantic_search.rs`. Under standalone bridge mode, interactive semantic searches support cancellable deferred polling in the main event loop. Borrow-only lexical and semantic snapshot opens bypass the cold-build limiter to prevent fresh-worktree search starvation while first searches wait cancellation-aware for a bounded loading window (2.5s). Interactive query embeddings and search artifact waits are bounded by dedicated budgets (`QueryBudget` and bounded interactive search artifact wait timeouts; `query_timeout_ms` clamped to 500..15000ms, defaulting to 3000ms) to keep interactive requests fast without affecting background build/refresh timeouts, falling back to lexical search if query embedding fails or times out. Downrank generated documentation artifacts (e.g. minified CSS/JS, maps, SVGs) in lexical and hybrid search results. For external search requests, resolve and cache external git roots, querying cached read-only search and semantic indexes from the `borrowed_index_cache` (capped at 4 concurrent entries) to avoid redundant git probes and disk parsing.
3. Schedule standing-root search, semantic, and callgraph construction through the process-wide pressure-aware deficit round-robin scheduler -- `crates/aft/src/standing_scheduler.rs`, `crates/aft/src/resource_policy.rs`, `crates/aft/src/subc/standing.rs`. The scheduler admits at most the configured cold-build concurrency, rotates unfinished roots after each durable slice, and charges measured elapsed work against each root's deficit. Search, semantic, and callgraph builders persist versioned staging state and publish atomically only after the complete corpus is ready. The default `index.resource_policy = "balanced"` pauses new slices under battery saving or CPU, memory, and I/O pressure and resumes with hysteresis. `"performance"` bypasses resource admission for users who accept the power cost, but retains bounded concurrency, fair rotation, resumable checkpoints, and OS background thread priority.
4. Keep standing-root reconciliation off the steady-state transport hot path -- `crates/aft/src/subc/standing.rs`. The standing actor caches the effective `storage_dir` and `index.roots`; an unchanged key skips SQLite access and root resolution on the 250 ms maintenance tick. Resource-policy-only changes do not trigger reconciliation.
5. Classify query shape (prose vs code) using the query shape parser -- `crates/aft/src/query_shape.rs`. Identify "type-concept identifier queries" (TitleCase PascalCase types combined with lowercase concepts) to trigger definition semantic priors.
6. Serve `grep` (trigram, full-text) and `aft_search` (semantic + hybrid) queries, delegating to `GrepExecutor` for accelerated path evaluation and enforcing execution safety limits (like `MAX_FALLBACK_WALK_FILES` and `FALLBACK_WALK_BUDGET`) during fallback walks when indexes are building or unavailable -- `crates/aft/src/grep_executor.rs`, `crates/aft/src/commands/grep.rs`, `crates/aft/src/commands/semantic_search.rs`. Under standalone bridge mode, interactive semantic searches support cancellable deferred polling in the main event loop. Borrow-only lexical and semantic snapshot opens bypass the cold-build limiter to prevent fresh-worktree search starvation while first searches wait cancellation-aware for a bounded loading window (2.5s). Interactive query embeddings and search artifact waits are bounded by dedicated budgets (`QueryBudget` and bounded interactive search artifact wait timeouts; `query_timeout_ms` clamped to 500..15000ms, defaulting to 3000ms) to keep interactive requests fast without affecting background build/refresh timeouts, falling back to lexical search if query embedding fails or times out. Downrank generated documentation artifacts (e.g. minified CSS/JS, maps, SVGs) in lexical and hybrid search results. For external search requests, resolve and cache external git roots, querying cached read-only search and semantic indexes from the `borrowed_index_cache` (capped at 4 concurrent entries) to avoid redundant git probes and disk parsing.

**File read flow:**

Expand Down Expand Up @@ -265,6 +275,16 @@
- Location: `crates/aft/src/callgraph.rs`
- Pattern: Lazy workspace index with invalidation on watcher events.

**StandingScheduler / ResourcePolicy:**
- Purpose: Share bounded cold-build capacity fairly across configured standing roots while respecting laptop resource pressure.
- Location: `crates/aft/src/standing_scheduler.rs`, `crates/aft/src/resource_policy.rs`, `crates/aft/src/subc/standing.rs`
- Pattern: Process-wide deficit round-robin scheduling over durable artifact slices. The balanced policy pauses admission with hysteresis under power, CPU, memory, or I/O pressure. The performance policy bypasses pressure admission but retains bounded concurrency and fair rotation.

**ThreadPriority:**
- Purpose: Keep maintenance CPU and I/O work below interactive and transport work.
- Location: `crates/aft/src/thread_priority.rs`
- Pattern: Cross-platform background demotion with restoration guards for Linux, macOS, and Windows maintenance workers.

**SearchIndex:**
- Purpose: Provide fast trigram-based full-text search across the project.
- Location: `crates/aft/src/search_index.rs`
Expand Down Expand Up @@ -342,8 +362,8 @@
**MemoryEstimate / MemorySnapshot:**
- Purpose: Track, attribute, and report process-wide and subsystem-specific memory usage.
- Location: `crates/aft/src/memory.rs`
- Pattern: Diagnostic structures and OS memory allocators hook.
- Contains: Subsystem memory estimation helpers, SQLite allocator query bindings (`sqlite3_memory_used`), platform-specific resident set size (RSS) and macOS kernel physical footprint (`phys_footprint_bytes` via `proc_pid_rusage RUSAGE_INFO_V4`) queries to exclude `MADV_FREE` allocator noise, and macOS-specific pressure relief bindings (`malloc_zone_pressure_relief`) to release unused pages during idle sweeps and periodic ticks.
- Pattern: Diagnostic structures and OS memory allocator hooks.
- Contains: Subsystem memory estimation helpers, SQLite allocator query bindings (`sqlite3_memory_used`), platform-specific resident set size (RSS), and macOS kernel physical footprint (`phys_footprint_bytes` via `proc_pid_rusage RUSAGE_INFO_V4`) queries. Periodic allocator slack scans run on a detached background-priority `aft-mem-relief` thread because allocator inspection can block. Transport and stdin ticks only perform a cheap cadence check.

**FleetStatusClient:**
- Purpose: Publish AFT's project-scoped status segment to the fleet status-holder plane (`prefrontal-core`).
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ Adding a command means implementing it in Rust (`crates/aft/src/commands/`) and
---

## Documentation
- [Architecture for new contributors](docs/architecture-for-contributors.md): a visual guide to the request path and main code areas

- [Tool reference](docs/tools.md): complete documentation for every tool
- [Configuration](docs/config.md): config schema, LSP, auto-install
Expand Down
9 changes: 7 additions & 2 deletions STRUCTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,15 @@ opencode-aft/
- Key files: `crates/aft/src/lsp/manager.rs`, `crates/aft/src/lsp/client.rs`, `crates/aft/src/lsp/diagnostics.rs`, `crates/aft/src/lsp/roots.rs`, `crates/aft/src/lsp/child_registry.rs`

**`crates/aft/src/executor/`:**
- Purpose: Orchestrate background maintenance, interactive tools, and job queues.
- Contains: Actor scheduler, job classes and priority queues, worker thread loop, and cooperative cancellation tokens.
- Purpose: Orchestrate bounded background maintenance and interactive tool queues across project-root actors.
- Contains: Process-wide and per-actor capacity accounting, interactive and maintenance job classes, reader-first admission, deadline-aware writer promotion, queue-deadline pruning, deficit round-robin actor scheduling, worker lanes, dispatch telemetry, and cooperative cancellation tokens.
- Key files: `crates/aft/src/executor/mod.rs`, `crates/aft/src/executor/tests.rs`

**Standing-root scheduling and resource control:**
- Purpose: Share cold-build slots fairly across standing roots without making a developer laptop unresponsive.
- Contains: Process-wide deficit round-robin root scheduling, balanced and performance resource policies, pressure sampling with hysteresis, durable slice coordination, and cross-platform background thread priority control.
- Key files: `crates/aft/src/standing_scheduler.rs`, `crates/aft/src/resource_policy.rs`, `crates/aft/src/subc/standing.rs`, `crates/aft/src/thread_priority.rs`

**`crates/aft/src/bash_background/`:**
- Purpose: Manage background bash tasks, PTY sessions, async pattern watches, and output compression.
- Contains: Process pool, PTY runtime, watchdog thread, persistence, restart fate preservation (`FateUnknown`), process start-time liveness checks, buffer management, async pattern watches
Expand Down
Loading