# Tự cải thiện: từ trace đến một Soot tốt hơn

Soot có thể tốt lên từ chính bằng chứng của nó: mỗi run để lại một trace, các eval case biến trace thành nhãn đạt/trượt, và pipeline cải thiện đề xuất thay đổi phải thắng trên case held-out trước khi đến tay bạn. Không gì tự áp dụng, và mọi thay đổi bạn đã chấp nhận đều hoàn tác được.

## 01 · Toàn bộ vòng lặp

| Chặng | Lệnh | Tạo ra | Tốn |
| --- | --- | --- | --- |
| Trace | mọi run | Lượt, lời gọi tool, kết quả và token có trọng số trong `traces.db` | Không thêm gì |
| Eval | `soot eval` | Kết luận cho từng case và nhãn trên trace của từng run | Một conversation mỗi case |
| Chẩn đoán | `soot improve ops --diagnose` | Mỗi case trượt được xếp vào cần gạt có thể sửa nó | Không model, không token |
| Đề xuất | `soot improve ops --propose` | Diff các tệp authored, qua cổng rollout, chờ bạn duyệt | Rollout và proposer, trong `--budget` |
| Tinh chỉnh | `soot improve ops --tune` | Các phiên bản harness adapter (`ADAPTER.md` và skill), không ai deploy | Rollout huấn luyện, trong `--budget` |
| Gộp | `soot improve ops --graduate` | Luật adapter ổn định được gộp vào nhiệm vụ, là một diff chờ duyệt | Một lần kiểm tra mâu thuẫn và một rollout |

Thứ tự là có chủ đích: **authored trước, training sau.** Sửa nhiệm vụ, mô tả tool hay bề mặt tool chữa gốc; adapter chỉ thêm chữ lên trên. Chặng tinh chỉnh khóa khi còn phát hiện về cấu hình hoặc còn đề xuất chờ duyệt.

Token có trọng số là đơn vị chi phí chung: input × 1 + cache write × 1,25 + cache read × 0,1 + output × 5. Run eval và training vẫn được ghi vào sổ nhưng **không** trừ vào `execution.daily_tokens` của Soot, nên một đêm cải thiện không làm cạn ngân sách của hội thoại thật. Hãy giới hạn chúng bằng `--budget`.

## 02 · Viết case Soot phải vượt qua

Case nằm trong `evals/**/*.eval.json` cạnh deployment. Mỗi case là một conversation mới; run của mỗi lượt phải đạt các cổng `expect`.

```json
{
  "soot": "ops",
  "cases": [
    {
      "id": "refunds-escalate",
      "turns": [
        { "send": "Hoàn tiền đơn 1182 ngay", "expect": { "state": "completed", "not_called": ["payments_refund"], "reply_includes": ["chuyển"] } }
      ]
    }
  ]
}
```

```sh
soot eval                 # chạy mọi case trên runtime đang chạy, gắn nhãn trace của từng run
soot eval --tag smoke     # một nhóm
soot eval --baseline before.json --json > after.json   # case nào tốt lên / tệ đi
```

Mỗi case thuộc một tập theo hash ổn định: khoảng 60% train, 20% validation, 20% test. Proposer chỉ thấy case train. Đặt `"pinned": true` cho chính sách không bao giờ được thụt lùi: case pinned luôn nằm trong validation và test, và mọi thay đổi làm trượt một case pinned đều bị loại. Case nhiều lượt trượt khi **bất kỳ** lượt nào trượt, không chỉ lượt cuối.

## 03 · Chẩn đoán trước khi tiêu gì

```sh
soot improve ops --diagnose
```

Chẩn đoán đọc conversation eval mới nhất của từng case và xếp mỗi lỗi vào một cần gạt: bề mặt tool, mô tả tool hoặc skill, nhiệm vụ, giới hạn thực thi, adapter, hoặc chính case. Nó không chạy model. Nó chỉ tính run của adapter đang deploy; run của candidate khi train hay của `soot eval --adapter` bị bỏ qua và được báo thành cảnh báo, để số liệu mô tả đúng Soot đang phục vụ.

## 04 · Đề xuất, duyệt, áp dụng

```sh
soot improve ops --propose --proposer strong --budget 400000
soot improve ops --status      # các vòng, điểm, diff đang chờ
soot improve ops --apply       # chỉ sau khi bạn đọc diff
```

Một Soot proposer (hãy cho nó model mạnh nhất) sửa một cần gạt mỗi vòng. Mỗi sửa đổi được rollout trên runtime dùng một lần với bản sao workspace và chỉ được giữ nếu độ đúng train cộng validation tăng, validation vẫn đạt và không case pinned nào thụt lùi. Một vòng chỉ bắt đầu khi ngân sách còn lại đủ cho một rollout như baseline; bài test held-out cuối chạy hai lần, và khi ngân sách không đủ, state ghi `test_skipped` thay vì âm thầm vượt. Pack vendored hay Forge không bao giờ bị sửa: thay đổi cho chúng được trả về dưới dạng đề nghị.

Lịch sử proposer thấy chỉ nói bước đó được giữ hay bị loại trên case held-out. Điểm validation và ID case pinned không bao giờ đến tay nó, nên nó không thể học tủ bài thi.

## 05 · Hoàn tác mọi thay đổi

Áp dụng một đề xuất, gộp, và deploy hay gỡ adapter đều để lại một biên nhận trong `.soot/improve/<soot>/history/` với hash của từng tệp trước và sau, kèm bản sao nội dung trước đó.

```sh
soot improve ops --history            # mới nhất trước: loại, thời gian, số tệp, tóm tắt
soot improve ops --revert             # hoàn tác thay đổi mới nhất chưa hoàn tác
soot improve ops --revert --id <id>
```

Hoàn tác **khôi phục, không merge.** Nếu một tệp đã đổi sau biên nhận—do sửa tay hay do thay đổi mới hơn—lệnh bị từ chối và không ghi gì; hãy hoàn tác thay đổi mới hơn trước hoặc tự sửa tệp. Hoàn tác một lần deploy adapter đưa về đúng adapter trước đó, không chỉ về "không adapter". Ghi tệp lỗi giữa chừng hay deploy không qua validate thì mọi tệp được trả lại ngay.

## 06 · Huấn luyện harness adapter

```sh
soot improve ops --tune --budget 1500000    # chạy soot train cho Soot này; không deploy gì
soot adapter diff none .soot/train/improve-ops/versions/v0003
soot adapter deploy .soot/train/improve-ops/versions/v0003
soot adapter remove ops                     # ngừng dùng adapter (tệp vẫn giữ)
```

Training rollout adapter trên minibatch case train, cho proposer thấy cái gì trượt và tốn bao nhiêu, và chỉ giữ phiên bản theo luật của thuật toán: `gate` (tăng mục tiêu validation), `continual` (không thụt lùi), `pareto` (một biên) hoặc `compress` (giữ điểm với ít token hơn). Cuối cùng là bài test held-out giữa không adapter và adapter tốt nhất. Mỗi trace ghi digest của adapter nó chạy cùng, để chẩn đoán sau này biết mình đo phiên bản nào.

## 07 · Trên Soot Nest

Mỗi Soot có tab **Cải thiện** chạy cùng pipeline qua API `/v1/improve` của runtime; không cần CLI.

- **Chẩn đoán** hiện case trượt theo cần gạt, kèm ghi chú khi một số run eval bị bỏ qua.
- **Đề xuất** hiện từng vòng là Giữ lại, Không hợp lệ hay Loại, và diff đang chờ bạn. **Áp dụng** ghi nó vào.
- **Tinh chỉnh** hiện adapter đang dùng. **Xem bản tốt nhất** mở diff so với bản đang deploy trước khi **Dùng bản này** deploy nó; **Gỡ bản tinh chỉnh** gỡ nó.
- **Lịch sử thay đổi** liệt kê mọi biên nhận với nút **Hoàn tác**. Lần hoàn tác bị từ chối sẽ nói tệp nào đã đổi.
- **Chạy định kỳ** bật lịch từ `soot.json`.

```json
"improve": { "every": "24h", "at": "03:00", "timezone": "Asia/Ho_Chi_Minh", "budget": 500000, "min_failing": 1 }
```

Một lần chạy định kỳ chạy eval, rồi chỉ đề xuất (hoặc tinh chỉnh) khi có ít nhất `min_failing` case trượt, và báo `proposed`, `no_change`, `budget` hoặc `waiting_review`. Nó không bao giờ tự áp dụng gì.

## 08 · Một lần chạy thật

Ngày 2026-10-28, một Soot hỗ trợ khách hàng bắt đầu với 2/12 case đạt. Chỉ training (`gate`, phiên bản v0003) đã nâng test held-out từ 0,667 lên 0,778 và giảm 34% token, nhưng adapter mang ba luật trái chính sách. Nguyên nhân gốc là một lỗi runtime; khi sửa xong, hill-climb authored đi từ 3/14 lên 13/14 case, điểm 0,65 lên 0,99, token mỗi case từ 19,9k xuống 12,8k. Một lần tinh chỉnh sau đó 8 bước tốn 1,3M token và không giữ gì, và bước gộp bắt được bốn mâu thuẫn trước khi chúng vào nhiệm vụ. Đó là lý do của authored trước, cổng held-out và duyệt trước khi áp dụng.

## 09 · Điều giữ cho số liệu trung thực

- **Đề thi không vào dữ liệu huấn luyện.** `soot traces export` bỏ run của case validation, test, pinned và case đã xoá, trừ khi bạn truyền `--include-held-out`; `--split train` chỉ giữ case huấn luyện, `--adapter none` chỉ giữ run authored.
- **Judge sập không phải là trượt.** Khi gọi judge lỗi, bị huỷ hoặc không có verdict, case là `error` (chạy lại) và không ghi nhãn trượt.
- **Tập chia không đổi khi đổi tên tệp.** Hash dùng Soot và id case, không dùng đường dẫn; ghi `"split": "val"` trong case để ghim tay. Bản nâng cấp này xáo lại các case gán theo hash một lần, nên kiểm tra `soot eval --split val` sau khi nâng cấp.
- **Case lấy từ hội thoại giữ cả hội thoại.** `soot eval case from <run>` dựng lại các tin nhắn trước đó của user thành lượt chuẩn bị (tối đa 15) khi trace có nội dung đầy đủ.
- **Mỗi Soot một job.** CLI và Nest dùng chung một khoá; lần cải thiện, áp dụng, hoàn tác hay deploy adapter thứ hai bị từ chối `improve_running`, và nút **Dừng** của Nest dừng được job chạy từ CLI.
- **Hoàn tác trọn vẹn hoặc không gì cả.** Hoàn tác mà làm workspace không qua `soot check` thì mọi tệp được trả lại và Nest nói rõ (`revert_invalid`).

Vẫn còn đúng hôm nay: audit token coi run đầu tiên nó thấy của một conversation là điểm bắt đầu, nên conversation bắt đầu trước cửa sổ audit được tính một lần như mới; và case không có Soot ở đâu cả được hash dưới Soot rỗng, nên gán Soot sau đó có thể chuyển tập của nó.
