Skip to content
Merged
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
2 changes: 1 addition & 1 deletion apps/docs/src/components/CliPreview.astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@

<span class="tf-cli-green"> ✓ Gate passed. Checkpoint saved.</span>

<span class="tf-cli-dim"> ⎯ qwen3.6-27b · ctx ~12k/33k 36% · 2 turns · 8s · done · entire workspace</span></pre>
<span class="tf-cli-dim"> ⎯ deepseek-v4-flash · ctx ~12k/33k 36% · 2 turns · 8s · done · entire workspace</span></pre>
</div>
</section>
30 changes: 15 additions & 15 deletions apps/docs/src/content/docs/agent/delegation.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
title: Delegate to subagents
description: "tsforge's orchestrator delegates focused, read-only investigation to specialist subagents on its own — you describe a task, it decides what to explore, research, or verify and renders them as a live tree while they work."
description: "tsforge's orchestrator delegates focused, read-only investigation to specialist subagents on its own. You describe a task, it decides what to explore, research, or verify, and renders them as a live tree while they work."
---

You think in tasks, bugs, and features — never in subagents. So delegation in tsforge is **orchestrator-driven**: the model you're talking to decides, on its own, when a task needs focused investigation, hands it to a specialist subagent, and folds the findings back into its answer. You never name an agent, pass ids, or run a command for it.
You think in tasks, bugs, and features. Never in subagents. So delegation in tsforge is **orchestrator-driven**: the model you're talking to decides, on its own, when a task needs focused investigation, hands it to a specialist subagent, and folds the findings back into its answer. You never name an agent, pass ids, or run a command for it.

Ask it to "figure out how the gate decides a run is done and check there's no race in the scheduler," and it may spawn an `explore` agent for the first and a `verify` agent for the second in parallel while it keeps working.
Ask it to "figure out how the gate decides a run is done and check there's no race in the scheduler," and it may spawn an `explore` agent for the first and a `verify` agent for the second in parallel while it keeps working.

## Why delegate

A subagent runs in its **own context window** and returns only a concise, cited summary. That keeps the orchestrator's context small on exploration-heavy work (it doesn't have to read twenty files itself), and when several run at once shortens wall-clock. Subagents are **read-only**: they explore, research, and verify; only the orchestrator edits files.
A subagent runs in its **own context window** and returns only a concise, cited summary. That keeps the orchestrator's context small on exploration-heavy work (it doesn't have to read twenty files itself), and when several run at once, it shortens wall-clock. Subagents are **read-only**: they explore, research, and verify; only the orchestrator edits files.

## Built-in specialists

These ship in the binary — delegation works with zero configuration:
These ship in the binary. Delegation works with zero configuration:

| Specialist | What it does |
| ---------- | ------------ |
Expand All @@ -22,9 +22,9 @@ These ship in the binary — delegation works with zero configuration:
| `verify` | Adversarially checks a specific claim or finding against the real code; returns a verdict. |
| `review-lens` | Reviews a change for correctness / regressions from a senior-engineer lens. |

Each is a read-only agent with a prompt that mandates real investigation and cited findings — it must read before it answers.
Each is a read-only agent with a prompt that mandates real investigation and cited findings. It must read before it answers.

**Structured findings.** A specialist doesn't return a wall of prose. It finishes by calling `agent_result` with a **structured** payload a one-line `summary` plus a list of `findings`, each carrying its own `source` (a `file:line` for code, a URL for external docs) and a `confidence`. The schema *forces* evidence onto every point, which is exactly what separates a grounded answer from a confident hallucination; the orchestrator receives a consistent `summary + cited findings` block it can act on directly.
**Structured findings.** A specialist doesn't return a wall of prose. It finishes by calling `agent_result` with a **structured** payload: a one-line `summary` plus a list of `findings`, each carrying its own `source` (a `file:line` for code, a URL for external docs) and a `confidence`. The schema *forces* evidence onto every point, which is exactly what separates a grounded answer from a confident hallucination; the orchestrator receives a consistent `summary + cited findings` block it can act on directly.

### Add or override a specialist

Expand All @@ -39,21 +39,21 @@ Drop a JSON file in `.tsforge/agents/<id>.json` (project) or `~/.tsforge/agents/
}
```

`tools` is intersected with the read-only tool set — a spec can never grant a subagent the ability to write.
`tools` is intersected with the read-only tool set. A spec can never grant a subagent the ability to write.

## The live agent tree

While subagents run, they render as a live tree pinned above the input row — so a delegated run is never a black box:
While subagents run, they render as a live tree pinned above the input row. A delegated run is never a black box:

```
● agents · 1 running · 1/2 done
├─ ✓ explore · 1.2s · 3 turns
└─ ⠹ verify
```

Rows appear the moment they're spawned, animate a spinner while running, and finish with their wall-clock and turn count. Beneath the tree, a detail pane streams the **focused** agent's live output (the files it reads, what it finds) — it follows the newest running agent automatically. The tree repaints in place (it never scrolls your transcript) and collapses to `… +N more` past a dozen rows. Ctrl-C cancels the turn and all its subagents.
Rows appear the moment they're spawned, animate a spinner while running, and finish with their wall-clock and turn count. Beneath the tree, a detail pane streams the **focused** agent's live output (the files it reads, what it finds). It follows the newest running agent automatically. The tree repaints in place (it never scrolls your transcript) and collapses to `… +N more` past a dozen rows. Ctrl-C cancels the turn and all its subagents.

**Watch any agent.** Press **↑/↓** while subagents are running to move the detail pane between them — pick one and watch what it's doing, instead of only seeing the newest. This works in both input modes (the default multi-line editor and the basic input row); in the editor it's only bound while the input is empty, so the arrows still edit a message you're composing mid-run. Auto-follow resumes on a fresh turn.
**Watch any agent.** Press **↑/↓** while subagents are running to move the detail pane between them. Pick one and watch what it's doing, instead of only seeing the newest. This works in both input modes (the default multi-line editor and the basic input row); in the editor it's only bound while the input is empty, so the arrows still edit a message you're composing mid-run. Auto-follow resumes on a fresh turn.

## Concurrency

Expand All @@ -63,7 +63,7 @@ How many subagents run at once is capped by [`agents.concurrency`](/guardrails/c
{ "agents": { "concurrency": 4 } }
```

When the orchestrator spawns several agents in one turn, up to this many run in parallel; the rest queue (shown as pending `○` rows) until a slot frees. At `concurrency: 1` they run one at a time — you still get the context-isolation win, just no wall-clock overlap. The config is discovered by walking up from the working directory, so it applies even when tsforge runs from a subdirectory. The REPL prints the resolved setup at startup:
When the orchestrator spawns several agents in one turn, up to this many run in parallel; the rest queue (shown as pending `○` rows) until a slot frees. At `concurrency: 1` they run one at a time. You still get the context-isolation win, just no wall-clock overlap. The config is discovered by walking up from the working directory, so it applies even when tsforge runs from a subdirectory. The REPL prints the resolved setup at startup:

```
↳ delegation: 4 specialists (explore, research, review-lens, verify) · cap 4
Expand All @@ -75,9 +75,9 @@ If you set `concurrency` above 1 but agents still run serially, either the cap i

- **Read-only.** A subagent's tools are the read-only set ∩ its spec; the executor hard-rejects any mutation, and the policy layer evaluates every call.
- **No recursion.** A subagent is never offered `spawn_agent`, so delegation depth is capped at one.
- **Never overflows.** A subagent auto-compacts its own conversation before a request would exceed the model's context window (and recovers from an overflow rejection by compacting and retrying) — so a long, read-heavy investigation can't fail on length.
- **Policy-aware.** Delegation is its own policy action class — a repo can `deny`/`ask` it via [permissions](/guardrails/policy/), and each subagent inherits the session's policy mode.
- **Never overflows.** A subagent auto-compacts its own conversation before a request would exceed the model's context window (and recovers from an overflow rejection by compacting and retrying). A long, read-heavy investigation can't fail on length.
- **Policy-aware.** Delegation is its own policy action class. A repo can `deny`/`ask` it via [permissions](/guardrails/policy/), and each subagent inherits the session's policy mode.

## Turning it off

Delegation is on by default. Set `TSFORGE_NO_DELEGATION=1` to withhold the `spawn_agent` tool entirely — the orchestrator runs as a single stream with no subagents (the startup line reads `↳ delegation: OFF`). Useful as a control when measuring delegation's effect, or to force a pure single-agent run.
Delegation is on by default. Set `TSFORGE_NO_DELEGATION=1` to withhold the `spawn_agent` tool entirely. The orchestrator runs as a single stream with no subagents (the startup line reads `↳ delegation: OFF`). Useful as a control when measuring delegation's effect, or to force a pure single-agent run.
8 changes: 4 additions & 4 deletions apps/docs/src/content/docs/agent/model-agent.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Model agent
description: One turn of the loopprompt, tools, edits, gate, repair.
description: "One turn of the loop: prompt, tools, edits, gate, repair."
---

The **model agent** is what runs when you give tsforge a task. It is not a separate program you invoke. It is the loop inside tsforge: send context to the model, run tool calls, check the gate, feed errors back, repeat.
Expand All @@ -21,10 +21,10 @@ One approved task can involve many agent cycles until the gate passes or tsforge
| --- | --- | --- |
| Core | `read`, `run`, `edit`, `create` | always |
| Line edits | `edit_lines` | always (line-number edits with hash verification) |
| Script | `script` | always (programmatic tool calling batch multi-step tool use in one program); withhold with `TSFORGE_NO_SCRIPT=1` for eval |
| Script | `script` | always (programmatic tool calling: batch multi-step tool use in one program); withhold with `TSFORGE_NO_SCRIPT=1` for eval |
| Navigation | `search`, `symbol_search`, `find_references`, `type_at`, `diagnostics`, `rename_symbol`, `move_file`, `organize_imports` | existing-code repos |
| Git context | `git_context` | existing-code repos (read-only: diff/log/blame/show to scope a change) |
| Conventions | `pull_conventions` | build backends that ship a convention library (BoringStack) fetch a how-to guide on demand |
| Conventions | `pull_conventions` | build backends that ship a convention library (BoringStack): fetch a how-to guide on demand |
| Web research | `package_info`, `package_docs`, `web_fetch`, `web_search`, `web_browse` | when **Web tools** is on in `/config` (no required API keys or paid browser/search service) |

On greenfield specs, navigation tools are often withheld so the model focuses on creating files instead of exploring an empty tree. See [TypeScript language server](/lsp/typescript-server/).
Expand All @@ -35,6 +35,6 @@ On greenfield specs, navigation tools are often withheld so the model focuses on

## File context

The model cannot edit a file it has not read. Specs and tasks should list which files are in scope (`files:` / `context:`). See [Spec format](/spec/format/). Some paths are **always** read-only regardless of scope — see [Vendored & read-only scope](/edit/engine/#vendored--read-only-scope).
The model cannot edit a file it has not read. Specs and tasks should list which files are in scope (`files:` / `context:`). See [Spec format](/spec/format/). Some paths are **always** read-only regardless of scope. See [Vendored & read-only scope](/edit/engine/#vendored--read-only-scope).

→ [Big picture](/big-picture/) · [When the gate fails](/loop/validation/)
18 changes: 9 additions & 9 deletions apps/docs/src/content/docs/agent/skills-and-harness.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
title: Skills and the harness
description: How IDE agent skills relate to tsforge enforcement — skills guide maintainers; the gate is the runtime oracle.
description: How IDE agent skills relate to tsforge enforcement. Skills guide maintainers; the gate is the runtime oracle.
---

tsforge is **enforcement-first**. During a run, the harness does not load `SKILL.md` files. Instead it uses deterministic gates, [rule packs](/guardrails/rule-packs/), and [bad/good feedback cards](/loop/validation/) to tell the model what failed and how to fix it.

**Agent skills** are a separate layer for maintainers and IDE workflows release, harness audits, skill authoring. They live in the repo under `.claude/skills/` and are discovered by Claude Code / compatible agents at session start.
**Agent skills** are a separate layer for maintainers and IDE workflows: release, harness audits, skill authoring. They live in the repo under `.claude/skills/` and are discovered by Claude Code / compatible agents at session start.

## Two layers

| Layer | What it does | Where it lives |
| --- | --- | --- |
| **Harness** | Enforces invariants; work is not done until the gate passes | `packages/core/` rule packs, meta-rules, gate, `rule-docs` |
| **Harness** | Enforces invariants; work is not done until the gate passes | `packages/core/` (rule packs, meta-rules, gate, `rule-docs`) |
| **Skills** | Repeatable procedures for humans/agents outside the run loop | `.claude/skills/<category>/<name>/SKILL.md` |

```mermaid
Expand All @@ -29,9 +29,9 @@ Skills **inform** how you write rules and docs. They do **not** replace the gate

```
.claude/skills/
├── harness/ harness-review adversarial subsystem audit
├── release/ tsforge-release npm + GitHub release
└── authoring/ effective-tsforge-skills how to write skills here
├── harness/ harness-review (adversarial subsystem audit)
├── release/ tsforge-release (npm + GitHub release)
└── authoring/ effective-tsforge-skills (how to write skills here)
```

Each skill folder name must match its frontmatter `name`. See `effective-tsforge-skills` for the ship checklist.
Expand All @@ -50,12 +50,12 @@ Do not put enforceable invariants only in a skill. If the model must not ship wi

## Recipes vs skills

[Recipes](/cli/recipes/) compose **existing CLI options** gate, scope, models, `profile`, plan mode, greenfield. They are data (`*.json`), not procedures.
[Recipes](/cli/recipes/) compose **existing CLI options**: gate, scope, models, `profile`, plan mode, greenfield. They are data (`*.json`), not procedures.

Skills compose **methodology** repro-before-report harness reviews, release scripts with failure modes. A recipe might set `profile: "strict"`; a skill teaches how to run `bun run validate` before tagging.
Skills compose **methodology**: repro-before-report harness reviews, release scripts with failure modes. A recipe might set `profile: "strict"`; a skill teaches how to run `bun run validate` before tagging.

## Learned rules

tsforge mines gate failure→fix pairs into [`.tsforge/learned-rules.json`](/uplift/memory/) and promotes recurring patterns to TTSR triggers. These are repo-local "micro-skills" machine triggers, not markdown runbooks. High-confidence patterns can later be promoted to committed `IRuleDoc` entries or maintainer skills.
tsforge mines gate failure→fix pairs into [`.tsforge/learned-rules.json`](/uplift/memory/) and promotes recurring patterns to TTSR triggers. These are repo-local "micro-skills": machine triggers, not markdown runbooks. High-confidence patterns can later be promoted to committed `IRuleDoc` entries or maintainer skills.

→ [Recipes](/cli/recipes/) · [Rule packs](/guardrails/rule-packs/) · [When the gate fails](/loop/validation/) · [Contributing](https://github.com/agjs/tsforge/blob/main/CONTRIBUTING.md)
Loading
Loading