Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7c43399
feat(engine): adaptive-depth execution toward infinite OODA
wangxingjun778 Jul 22, 2026
cb694ae
fix(tui): adaptive input height and editor compose for long input
wangxingjun778 Jul 22, 2026
fc6629c
fix text input len
wangxingjun778 Jul 22, 2026
672ddab
fix(engine): harden long-task execution (compression, adaptive budget…
wangxingjun778 Jul 22, 2026
c858b77
fix(tui): prevent macOS Terminal crash during task execution (single …
wangxingjun778 Jul 22, 2026
e946121
feat(tools): add P0 coding tools (code_search, file_find, edit_file) …
wangxingjun778 Jul 23, 2026
e8e247a
feat(tools): P1 coding tools — git_query (structured read-only git) a…
wangxingjun778 Jul 23, 2026
6a55f65
feat(tools): P2 coding tools — test_run/lint_check (structured) and t…
wangxingjun778 Jul 23, 2026
0c2e986
feat(tools): polish coding tools (code_search context, edit_file diff…
wangxingjun778 Jul 23, 2026
b050e1e
feat(agent): P0 tool-calling/result hardening + P1 repo orientation &…
wangxingjun778 Jul 23, 2026
1af3882
fix(agent): restore shell/tool failure visibility + file_list recursi…
wangxingjun778 Jul 23, 2026
18b344c
fix(context): reduce tool-result truncation, adaptive convergence, an…
wangxingjun778 Jul 23, 2026
d45e809
fix(daemon): give waiting client immediate 'queued' feedback when eng…
wangxingjun778 Jul 23, 2026
e39dabf
refactor(engine): carry per-turn ids on the loop frame + isolate them…
wangxingjun778 Jul 23, 2026
c885ebe
test(engine): add xfail acceptance test for per-turn concurrency isol…
wangxingjun778 Jul 23, 2026
23fb5c2
feat(engine): per-session engine factory for concurrent isolated turn…
wangxingjun778 Jul 23, 2026
b4d13e5
feat(daemon): SessionRegistry infrastructure + concurrency config (P3…
wangxingjun778 Jul 23, 2026
c743b30
feat(daemon): route engine_chat turns to per-session engines via Sess…
wangxingjun778 Jul 23, 2026
5c3ba84
feat(daemon): per-request approval + cancel routing (P3-3)
wangxingjun778 Jul 23, 2026
6353cc2
feat(daemon): activate bounded cross-session turn concurrency via Tur…
wangxingjun778 Jul 23, 2026
ba49a63
feat(cli,daemon): thread session_id through engine_chat to enable end…
wangxingjun778 Jul 23, 2026
1553e22
fix(engine,daemon): restore session persistence + close per-turn stat…
wangxingjun778 Jul 23, 2026
b962e98
feat(cli,daemon,engine): distinct per-TUI sessions so any two fresh T…
wangxingjun778 Jul 23, 2026
2f45d59
fix(daemon): pin stream task context for approval routing
wangxingjun778 Jul 23, 2026
b47bfcd
refactor(engine): metadata-driven tool concurrency + bounded parallel…
wangxingjun778 Jul 23, 2026
e445c53
feat(daemon): default to three concurrent turns with visible admissio…
wangxingjun778 Jul 23, 2026
3e50c4c
fix multi leap tui
wangxingjun778 Jul 24, 2026
02970d0
feat(daemon): slim down leapd via coordinator split, session isolatio…
wangxingjun778 Jul 25, 2026
daa1d8f
fix(daemon): prevent leapd rpc timeout stalls
wangxingjun778 Jul 26, 2026
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
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,57 @@ The cognitive pipeline built on top:
The **Execution Layer** provides native OS interactions — screen capture, accessibility tree queries, and input injection. The default backend is `cua-driver` (macOS, MCP stdio transport), but the architecture is backend-agnostic via the Platform Adaptation Layer. **Perception** fuses raw signals into a causal timeline. The **Causal Engine** infers why things happened, not just what. The **World Model** builds an internal representation of the environment and learns from prediction errors. **Skill Synthesis** distills observations into parameterized, reusable skills with maturity tracking. The **Copilot** predicts your next workflow step and offers proactive suggestions — like GitHub Copilot, but for everything you do on your computer.


---

## Adaptive-Depth Execution (Toward Infinite OODA)

LeapFlow's agent loop adapts its **depth** to each task's difficulty and can — under strict governance — extend beyond a single turn. Rather than a fixed iteration cap, the loop treats depth and autonomy as *signal-driven, bounded gradients*: a hard task earns a wider budget and a research posture while a simple one stays short; long tasks keep a persistent research ledger; recursive subagents run the *same* adaptive loop on isolated frames; and outcome data can self-calibrate the difficulty thresholds. "Infinite" capability comes from **composing bounded OODA frames**, never from removing a frame's bounds — so every step stays accountable, inspectable, and safe.

Defaults benefit every session automatically (adaptive depth); the rest is **opt-in and off by default**:

| Capability | Config key (`leap config set …`) |
|---|---|
| Full adaptive loop for delegated subagents | `agent.subagent_full_loop` |
| Event-driven re-entry (resume on time/event) | `agent.reentry_enabled` |
| Online difficulty/threshold self-calibration | `agent.calibration_enabled` (+ `agent.calibration_interval_turns`) |
| Governed proactive outbound (trust + approval) | `agent.reentry_send_enabled` |
| Cache-stable compression write-back | `agent.compression_writeback` |

Inspect the agent's layered orientation and pending re-entries anytime with the read-only **`/orient`** command. Design methodology: [`docs/design/adaptive_depth_ooda.md`](docs/design/adaptive_depth_ooda.md).

---

## Built-in Coding Tools

LeapFlow ships a first-class coding toolset so the agent can *locate → read → edit → verify* code precisely instead of rewriting whole files or shelling out blindly. Every tool is registered with governance metadata (`x_leapflow`) so it flows through the existing idempotency, approval, redaction, path-sensitivity, and audit paths.

| Tool | Purpose | Governance |
|---|---|---|
| `repo_map` | Compact project orientation: languages, detected test/lint commands, top-level structure, entry points, VCS branch | read-only |
| `code_search` | Regex search across a tree (ripgrep-backed, structured `path:line:col`, optional `context_lines`); skips VCS/dep/build dirs | read-only |
| `file_find` | Locate files by recursive glob (e.g. `**/test_*.py`) | read-only |
| `edit_file` | Targeted **anchored** search-replace (unique-anchor or `replace_all`, `dry_run`) or apply a unified **`diff`** — a missing/ambiguous anchor is rejected, never a partial write | mutating · approval + path gate |
| `code_intel` | Document symbols (outline): Python via exact **AST**, other languages via heuristic | read-only |
| `git_query` | Structured read-only git: `diff` / `log` / `status` / `branch` / `show` | read-only |
| `git_write` | Mutating git: `commit` / `branch` / `checkout` | mutating · approval |
| `test_run` | Run the test suite (auto-detect pytest/npm/go/cargo); structured pass/fail | verify (via governed shell) |
| `lint_check` | Run the linter (auto-detect ruff/eslint/go vet/clippy); structured issues | verify (via governed shell) |
| `terminal_session` | Persistent shell sessions (`open`/`send`/`read`/`close`/`list`) for REPLs/dev servers | **off by default** · opt-in · approval |

**Notes**

- **Seamless search:** `code_search` always works with zero install via a pure-Python fallback; when [ripgrep](https://github.com/BurntSushi/ripgrep) is present it is used for speed, and a best-effort background install (macOS/Homebrew, no sudo) is attempted otherwise. A manual-install hint is surfaced if it stays unavailable.
- **`test_run`/`lint_check` semantics:** `ok=true` means the *runner executed* — a failing suite is informative feedback (`success`/`clean`), not a tool error.
- **Persistent terminals** are long-lived resources kept separate from one-shot execution (Transport-Lifecycle Separation); enabling is the operator opt-in and sessions are bounded with process-group cleanup.

Config keys (all via `leap config set …` / TUI `/config`):

| Key | Default | Meaning |
|---|---|---|
| `tools.ripgrep_autoinstall` | `true` | Best-effort seamless ripgrep provisioning (fallback + manual hint regardless) |
| `tools.test_command` / `tools.lint_command` | *(auto-detect)* | Override the test/lint command |
| `tools.terminal_session_enabled` | `false` | Enable persistent terminal sessions (high-risk, opt-in) |

---

## Prerequisites
Expand Down Expand Up @@ -213,6 +264,27 @@ Inside the TUI, the same control plane is available as `/config`. It supports ho

---

## Multi-Profile

LeapFlow supports multiple **profiles** — isolated runtime environments that can run in parallel. Each profile owns its own daemon process, databases, configuration, and credential vault.

Select a profile via the `LEAPFLOW_PROFILE` environment variable (defaults to `default`):

```bash
# Run with the default profile
leap

# Run a separate instance under a different profile
LEAPFLOW_PROFILE=work leap

# Check daemon status for a specific profile
LEAPFLOW_PROFILE=work leap daemon status
```

Profiles are stored under `~/.leapflow/profiles/<name>/`. Multiple profiles can run simultaneously without interference — useful for separating personal and work contexts, or running parallel experiments.

---

## Quick Start — Use the TUI First

LeapFlow's default experience is the interactive terminal UI. Start here for chat, tool execution, runtime status, session continuity, and progressively learning workflows from one surface.
Expand Down
197 changes: 197 additions & 0 deletions docs/design/adaptive_depth_ooda.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Adaptive-Depth Execution: Toward an Infinite OODA Loop

> A design-methodology document. It explains the *why*, the *how*, and the *when* of
> LeapFlow's adaptive-depth execution architecture. It is deliberately light on code:
> the goal is to convey the reasoning, the staged construction, and the usage model —
> not a line-by-line map.

## 1. Problem Statement

A capable agent must handle tasks whose intrinsic difficulty varies by orders of
magnitude — from a one-shot factual answer to a multi-hour investigation that spans
many tool calls, dead ends, and revisions. Yet most agent loops are built around a
*fixed* control budget: a constant iteration cap, a static context-disclosure policy,
and a single start→finish horizon. This mismatch produces two failure modes.

**Under-provisioning.** A hard task is cut off prematurely because the loop exhausts a
budget calibrated for the average case. The agent "gives up" while still making progress.

**Over-provisioning.** A trivial task carries the full apparatus — maximal tool
disclosure, aggressive context retention, many speculative iterations — inflating cost
and latency for no benefit.

A deeper limitation is *temporal*: the classical loop ends when the turn ends. It cannot
maintain orientation across sessions, resume when the environment changes, or act
proactively under governance. Real work is rarely a single bounded turn; it is an
ongoing engagement with a changing world.

The question this architecture answers is: **how can a single agent loop adapt its depth
to each task's difficulty, persist and refine its orientation over time, and — under
strict governance — extend into continuous, proactive operation, without ever becoming
unbounded or unsafe?**

## 2. Methodology

Five principles organize the design.

**Signal-driven, not rule-driven.** Depth, posture, and commitment are derived from
*observed signals* (difficulty estimates, effective token cost, tool-evidence
saturation), not from hardcoded keyword rules. Behavior that cannot be grounded in a
signal is out of scope.

**Boundedness by composition.** "Infinite" capability is achieved by *composing bounded
frames*, never by removing bounds from a single frame. Every unit of work — a turn, a
recursive subagent, a re-entry — is a frame with its own budget, deadline, and cost
ceiling. Unboundedness is an emergent property of chaining and nesting bounded frames,
which keeps every point in the system individually accountable.

**Progressive trust.** Autonomy is *earned*, never assumed. A proactive action is
auto-approved only after repeated human approvals of similar actions have raised the
relevant scope's trust; otherwise it falls back to explicit approval. Destructive or
first-time actions are never implicit.

**OODA as the organizing lens.** The loop is read as Observe → Orient → Decide → Act.
The design consistently invests in **Orient** — persistent findings, layered
orientation, learned calibration — because in OODA the quality of orientation cascades
into every downstream decision (see `ooda_framework.md`).

**Default-off, zero-regression.** Every new capability is gated behind configuration and
defaults to off, byte-equivalent to prior behavior. Adoption is a deliberate, reversible
choice, and each increment is independently verifiable.

These principles are realized as a **staged evolution S0 → S4**, where each stage adds a
capability while preserving the invariants of the ones below it.

## 3. S0 — The Adaptive-Depth Frame

The base stage makes a *single turn* elastic. Four coupled mechanisms:

- **Difficulty as a first-class signal.** Each turn continuously estimates task
difficulty from context-governance evidence (tool-call breadth, evidence sources,
convergence). Difficulty drives an **elastic iteration budget** whose cap widens from a
safe floor toward a ceiling in proportion to observed hardness — a hard task earns a
wider horizon; a simple one stays near the floor and self-stops.

- **Posture.** The turn adopts a research / expanding / finalizing posture, adjusting how
much context and tooling it discloses. Posture is a signal-driven gradient, not a
one-way ratchet.

- **Prefix commitment and cacheable stability.** Once a turn commits to a stable working
prefix, that prefix (system instructions, tool schema, task contract) is held
byte-stable across rounds so that provider prefix-caches are reused; volatile content
(live signals, the research ledger) is appended at the tail, never woven into the
cacheable prefix. Context compression is *append-only*: each historical window is
summarized once and then frozen, which both preserves long-task state (signal-to-noise
first) and keeps the frozen region cache-stable.

- **The research ledger.** A compact, durable record of findings, open questions,
decisions, and the next step accompanies the turn. It is the turn's working memory of
*intent and progress*, resistant to compression drift, and it supplies a reliable
sufficiency signal: a task with tracked open questions is never cut short by premature
convergence.

Finally, S0 makes the loop **recursive**: a subagent runs the *same* adaptive loop on an
isolated child frame with its own fresh budget and subsystems. Recursion is depth-gated
and state-isolated, so a subagent can decompose a hard problem without contaminating the
parent's orientation.

## 4. S1–S2 — Persistent Orientation and Event-Driven Re-entry

S1 lifts orientation beyond a single turn: the research ledger is persisted across
sessions, so a long-running task's accumulated understanding survives restarts and
resumes where it left off.

S2 breaks the start→finish horizon. A turn may register a **re-entry trigger** — a saved
orientation snapshot plus a firing condition (a delay, or an inbound environment event).
Later, that trigger fires *at most once* and seeds a fresh, isolated run from the saved
orientation. Crucially, re-entry is not a suspended coroutine held in memory; it is a
*finalize-then-reseed* pattern, which keeps the mechanism robust and the running system
uncontaminated. Inbound platform events enter as structured signals, are filtered and
classified, and only then may drive a governed re-entry — extending the agent's Observe
boundary into the collaboration environment.

## 5. S3 — Learning Closure

Orientation should improve with use. S3 closes a learning loop over the difficulty and
threshold machinery: each turn's *predicted* difficulty and posture are recorded
alongside its *actual* effort and outcome; offline analysis relates the two and proposes
a bounded adjustment to the difficulty-sensitivity weight and the finalize threshold;
and — when explicitly enabled — that adjustment is applied online, always derived from
the configured baseline (so it never compounds or drifts) and always reversible. The
difficulty signal thus migrates from hand-tuned toward learned, and the quality of
orientation rises monotonically with experience.

## 6. Governed Proactive Action

The most delicate capability is *acting outward* on the agent's own initiative — for
example, replying to the chat that originated a task once a background re-entry has
produced a result. The design refuses ungoverned autonomy. A proactive send passes a
pure decision kernel that combines a **send-scope trust ledger** (the progressive-trust
gradient), rate limits, idempotency, and a global budget. The verdict is one of:
auto-allow (only for non-destructive actions in a scope that has earned trust), queue for
asynchronous human approval (which, on approval, also accrues trust), or deny. Absent a
reachable approver, the default is to *not act*. External side effects are never silent.

## 7. D1 → S4 — Layered Orientation and the Infinite Loop

S4 is the north star: a **resident** agent that runs a continuous, resource-governed OODA
*tempo* — observing signals, maintaining a layered orientation, expanding bounded
subframes on demand, deciding through the trust-gated guidance described above, and
learning continuously — **with no hard horizon, only a governed cadence**.

The first, observe-only step of S4 (D1) is a **multi-layer orientation** query that
unifies three layers with time decay: *immediate* (live signals), *working* (the current
task ledger), and *long-term* (durable cross-session findings and retrieved memory).
Recent salience dominates while durable facts persist quietly. This makes Orient a
first-class, inspectable object — a prerequisite for any autonomous decision, and useful
on its own for diagnosis.

The remaining synthesis (a general implicit-guidance gate, a tempo governor with
backpressure, and the resident loop itself) is *designed but intentionally not enabled*:
a continuously autonomous, outward-acting loop is the highest-risk capability in the
system and is gated behind explicit authorization and review.

## 8. Safety and Governance

The architecture's safety rests on a small set of invariants that hold at every scale:

- **Bounded frames everywhere.** Cost ceilings, budgets, and deadlines apply to each
turn, each recursive subframe, and each re-entry point.
- **Default-off and reversible.** Autonomy, re-entry, outbound delivery, online
calibration, and full-loop subagents each require an explicit opt-in; disabled, the
system is byte-equivalent to its prior behavior.
- **Approval, redaction, and audit on every act.** Outbound and other side-effecting
actions flow through the existing approval, redaction, and audit paths; proactive
action additionally requires progressive trust.
- **Isolation.** Recursive subagents run on fresh state with their own session, and never
pollute the parent's learning or conversation.

## 9. Usage and Scenarios

By default the agent already benefits from S0: hard tasks transparently earn more depth
and a research posture; simple tasks stay short. No configuration is required, and the
current orientation can be inspected at any time through a read-only orientation view.

The remaining capabilities are opt-in and best adopted one at a time:

- **Long, multi-session investigations** benefit from persistent orientation and, when a
follow-up is warranted, event-driven re-entry.
- **Decomposable problems** benefit from full-loop recursive subagents, which give each
sub-task the full adaptive apparatus under isolation.
- **Environments with accumulating outcome data** benefit from online calibration, which
tunes the difficulty and finalize thresholds to the observed workload.
- **Collaboration settings** may, under progressive trust and human approval, let a
completed background task deliver its result back to its originating conversation.

Because every capability is bounded and reversible, the recommended path is to enable a
single feature, observe its behavior on a representative task, and expand adoption only as
confidence grows.

## 10. Conclusion

The design treats "depth" and "autonomy" not as switches but as *governed gradients*
driven by signals and earned through trust. By composing bounded OODA frames — adaptive
in depth, persistent in orientation, self-calibrating, and gated in action — the system
approaches the ideal of a continuous, infinite OODA loop while keeping every constituent
step accountable, inspectable, and safe. The infinite loop, in this view, is not the
removal of limits but their disciplined composition.
4 changes: 2 additions & 2 deletions src/leapflow/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def __exit__(self, exc_type: object, exc: object, traceback: object) -> None:

async def _async_daemon_main(args: argparse.Namespace) -> int:
"""Run chat/interactive through a shared leapd daemon."""
from leapflow.daemon.client import DaemonUnavailableError, ensure_daemon_client
from leapflow.daemon.client import DaemonUnavailableError, recover_daemon_client

settings = load_config()
mock_host = getattr(args, "mock_host", False)
Expand All @@ -136,7 +136,7 @@ def _status(message: str) -> None:

try:
with _StdinEchoGuard():
client = await ensure_daemon_client(
client = await recover_daemon_client(
settings,
mock_host=mock_host,
status_callback=_status,
Expand Down
7 changes: 6 additions & 1 deletion src/leapflow/cli/commands/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Any, AsyncIterator, Awaitable, Callable

from leapflow.cli.helpers import require_initialized
Expand Down Expand Up @@ -73,7 +74,11 @@ async def _handle_approval_event(event: Any, approval_resolver: ApprovalResolver
async def cmd_chat_daemon(client: "DaemonClient", prompt: str, thinking: bool) -> int:
"""Single-turn conversational mode backed by leapd."""
return await render_chat_stream(
client.engine_chat(prompt, enable_thinking=thinking),
client.engine_chat(
prompt,
enable_thinking=thinking,
workspace_root=str(Path.cwd().resolve()),
),
lambda pending_id, decision: client.approval_resolve(pending_id, decision),
)

Expand Down
Loading