[English](architecture.md) | 日本語

# Architecture Overview

MAESTRO は、ユーザーが投げたタスクを LLM 駆動のワークフロー（Piece）で実行する
エージェントオーケストレーターである。コントリビュータ向けのコードマップは
[../AGENTS.md](../AGENTS.md) も参照。

## 実行フロー

```
UI (POST /api/local/tasks)
  → bridge/server.ts (Express API)
  → Repository (SQLite: jobs テーブルに enqueue)
  → Worker.poll() が queued ジョブを取得
  → piece-classifier.ts: LLM がタスクを分類し Piece を選択
  → piece-runner.ts: pieces/*.yaml を読み、movements を順に実行
  → agent-loop.ts: 1 movement の ReAct ループ (LLM ↔ tool calls)
      ├─ 中間遷移: transition ツール
      └─ 終了:     complete ツール (success / aborted / needs_user_input)
  → ジョブ完了: DB 更新 + 進捗コメント。成果物は workspace/output/
```

1. **API 受付** — `bridge/server.ts` がタスクを受け、`Repository` 経由で `jobs` テーブルに `queued` で登録する。
2. **ワーカー** — `worker.ts` が DB をポーリングし、自分の `profiles`/`task_classes` に合致するジョブを取得（複数ワーカーが並走）。
3. **分類** — `piece-classifier.ts` がタスク本文と全 Piece の description を LLM に渡し、最適な Piece を選ぶ。
4. **Piece 実行** — `piece-runner.ts` が Piece の movements を順に回す。verify movement のフィードバックは次の execute に引き継がれ、`transition.lessons` で movement 間の教訓が蓄積される。
5. **ReAct ループ** — `agent-loop.ts` が 1 movement 内で LLM とツールを往復させる。`ContextManager` が LLM の `usage` からトークン使用量を追跡し、閾値（70/85/95%）で warn / prompt / force_transition を発火する。

## Piece と Movement

- **Piece** = `pieces/*.yaml`。`movements` 配列で構成。
- 各 **Movement** は `allowed_tools`（LLM に提示するツール）、`edit`（Write/Edit 可否）、`rules`（遷移条件）を持つ。`allowed_tools` 外のツールは LLM から見えない。
- **遷移**: 中間ホップは `transition`（`rules[].next` に列挙した宛先のみ選択可）、終了は `complete`。`complete.result` がユーザーに見える唯一の最終出力。
- **`default_next`** はエンジン内部の sentinel（コンテキスト溢れ時の強制遷移、ASK 上限時のフォールバック）。
- **Progressive pressure**: 同一 movement への連続訪問が増えると警告を注入し、閾値超過で ABORT。

## ツールランタイム

ツールは `src/engine/tools/*.ts` のモジュール群。`tools/index.ts` が動的にロードし dispatch する。各ツールは 1 行の description（毎 LLM 呼び出しに乗るため簡潔に）を持ち、詳細手順は `docs/tools/<name>.md`（`ReadToolDoc` で取得）に置く。主なモジュールは [../AGENTS.md](../AGENTS.md#tool-modules) の一覧を参照。

Read 系ツールは並列実行される。Write/Edit は movement の `edit: true` のときのみ提示され、書き込みは主に `workspace/output/` に限られる。

## Bash サンドボックス

エージェントの Bash 実行は、利用可能なら **bwrap サンドボックス**で隔離する:

- **ファイルシステム**: タスクの workspace のみ rw bind、`/usr` 等は ro、他タスクの workspace やホスト `/home` は不可視。
- **環境変数**: `--clearenv` + 最小 allowlist のみ注入（シークレット env はサンドボックス内から見えない）。
- **ネットワーク**: `--unshare-net` で遮断（外向き通信は SSRF ガード付きの WebFetch/MCP に集約）。
- **各 Bash コールは独立**したサンドボックス（揮発 `/tmp`・毎回新名前空間）。永続するのは workspace のみ。

`safety.bash_sandbox` でモードを選ぶ（`auto`/`always`/`off`）。bwrap 不在時は **hardened フォールバック**（コマンド許可リスト + パススコープ検査 + env スクラブ付き exec）になる。実行時 `pip`/`npm install` は全モードで拒否され、Python パッケージは `runtime/python-requirements.txt` からプリベイクされる。詳細は [operations/bash-sandbox-provisioning.md](operations/bash-sandbox-provisioning.md)。

## ワークスペース構造（ジョブ実行時）

```
{worktree_dir}/local/{taskId}/
  input/    アップロード・DownloadFile の保存先
  output/   成果物（Write/Edit が許可される主な場所）
  logs/     activity.log / 各種履歴
  subtasks/ SpawnSubTask の結果
  skills/   ReadSkill で materialize されたスキルファイル
```

## データベース

SQLite（better-sqlite3）。`db/schema.sql` が初期スキーマ。追加カラムは `db/migrate.ts` で
`PRAGMA table_info` → 存在チェック → `ALTER TABLE ADD COLUMN` のパターンで冪等に適用する
（バージョン管理テーブルは使わない）。主なテーブル: `jobs` / `local_tasks` /
`local_task_comments` / `audit_log` ほか。

## ジョブのライフサイクル

`queued` → `dispatching` → `running` → `succeeded` / `failed` / `waiting_human`（ASK 回答待ち）/ `waiting_subtasks`（並列サブタスク待ち）。失敗時は `retry` で再 `queued`（最大 `retry.max_attempts` 回）。

## オプションのサブシステム

- **LLM Gateway**（`src/gateway/`） — MAESTRO 自身を OpenAI 互換 LLM プロキシとして公開（仮想キー・予算・Prometheus メトリクス）。複数 GPU/チーム共有向け。env/接続種別が `AAO_*`/`aao_gateway` の歴史的接頭辞を使う。
- **MCP** — Model Context Protocol サーバー連携（`MCP_ENCRYPTION_KEY` 必須）。
- **Reflection** — ジョブ完了ごとにユーザーメモリを LLM が自動更新（既定 OFF、revert 可）。
- **認証** — Passport による Google/Gitea OAuth（任意）。`private`/`org`/`public` の可視性モデル。
- **スケジューラ** — cron 式の定期タスク。

## フロントエンド

React + Vite + TailwindCSS + @tanstack/react-query。`ui/src/App.tsx` がルート。2 カラム（list + detail）レイアウトで、タスク一覧・スケジュール・設定・スキル/Piece 管理を扱う。
