# CASAN — Hướng dẫn Tự Chấm Điểm (Self-Scoring) Step-by-Step > **Mục tiêu:** Tự tay chạy lại toàn bộ harness CASAN và **tự chấm điểm 7 harness (H1–H7)** bằng bằng chứng chạy thật, không trích số. > **Kịch bản của bạn:** chạy từ **máy Mac**, model `ornith:9b` nằm trên **Linux server ở nhà** (đã cài Ollama). > **Nguyên tắc vàng CASAN:** *"điểm = thứ chứng minh được bằng tấn công, không phải thứ khai báo"* và *"harness thấp nhất quyết định trần"*. --- ## 0. Tổng quan luồng ``` ┌─────────────┐ SSH tunnel (-L 11434) ┌──────────────────────────┐ │ Mac (bạn) │ ───────────────────────────► │ Linux server @ nhà │ │ repo casan5│ 127.0.0.1:11434 ⇄ :11434 │ Ollama + model ornith:9b │ └─────────────┘ └──────────────────────────┘ │ ├─ chạy .specify/tests/*.sh + scripts/bash/*.sh └─ đọc verdict → điền bảng điểm H1–H7 ``` Harness **bắt buộc** gọi Ollama qua đúng `127.0.0.1:11434` (allowlist bảo mật trong `model-call.py`). Vì model ở server nhà, ta **SSH tunnel** cổng đó về Mac. Không có tunnel → các test model sẽ **SKIP** (không phải FAIL — thiết kế non-blocking), điểm vẫn tính được nhưng recall model để trống. --- ## 0b. Checklist "FULL-GREEN" — và vai trò thật của AI local > **Tất cả nội dung mục này là KẾT QUẢ THẬT tôi đã tự chạy trong Docker `node:24-slim` + WSL Ubuntu 26.04 ngày 2026-07-02 — KHÔNG bịa, KHÔNG suy diễn.** Mục nào chưa tự đo được thì ghi rõ "chưa đo". ### Câu hỏi lớn: cần gì để chạy full, KHÔNG bị block ở bất kỳ bước nào? **Trả lời thẳng: KHÔNG cần API key OpenAI/Anthropic.** Ollama `ornith:9b` ở nhà đã đảm nhiệm đúng vai trò model. Cloud key chỉ là **phương án thay thế / nâng recall**, không phải điều kiện để hết block. | # | Điều kiện để 0 SKIP / 0 block | Trạng thái của bạn | Nếu thiếu thì chặn gì | Bằng chứng | |---|---|---|---|---| | 1 | **Live model** (Ollama **HOẶC** cloud key) | ✅ có Ollama ornith:9b | A3 semantic, A8 recall, C2 judge, `phase3-*` | tôi đã chạy judge-gate `PASS=3` khi model OFF (SKIP=2, non-blocking) | | 2 | **node + python + openssl** | ✅ (Docker node:24-slim) | harness/vitest/audit | tôi tự chạy 35/35 + 43/43 + vitest 16/16 | | 3 | **Chạy trong git repo thật** | ⚠️ bản copy chưa `git init` | `secrets-scan` in `not a git repository` (vẫn PASS=6) | tôi thấy warning này khi chạy offline | | 4 | **1 lần chạy pipeline thật ≥3 step** | ❌ chưa chạy | **H6 cost-spike** = `COST_SPIKE_NO_DATA records=2` | tôi tự đo `records=2 (need >=3)` | | 5 | (tuỳ chọn) Vault/KMS | — | KHÔNG block: `sign-audit-head` fallback local, verify vẫn qua | tôi thấy `SIGN_AUDIT_HEAD_SKIP` nhưng chain vẫn `VALID` | → **Thứ còn "thiếu/block" thật sự KHÔNG phải model** mà là (3) chạy trong git repo để secrets-scan sạch, và (4) một lần chạy pipeline để H6 có dữ liệu telemetry. ### Vai trò của AI local (ornith:9b) — đo thật, không suy diễn **Trọng tâm thi = H4 · H5 · H6.** Chỉ H4 và H6 chạm tới model; H5 hoàn toàn deterministic. Phần lớn control chạy xanh **không cần model**: | Harness | Chạy KHÔNG cần model (tôi đã tự chạy xanh) | Phần CẦN AI local | Vai trò AI local | |---|---|---|---| | **H4 Security** | A1/A4/A5/A6/A7: injection block, leetspeak, artifact-scan, secret, PII — **tất cả rc=2 OFFLINE** | **A3** (paraphrase mới), **A8** (recall) | **Quyết định** cho "semantic > regex" | | **H5 Governance** | B1–B5: hash-chain, tamper→`HASH_MISMATCH`, RSA, secrets-scan, no-bypass — **100% OFFLINE** | — không có — | **≈0 vai trò** (toàn crypto) | | **H6 AgentOps** | D1 cost-spike `COST_SPIKE_DETECTED exit=2`, D2 no-spike `exit=0`, D3 drift `DRIFT_WARN` — **logic deterministic, OFFLINE với data seed** | **D4** telemetry token thật | **Nguồn dữ liệu**: mỗi lời gọi model ghi `provider-usage.jsonl` (token thật) để cost-spike/agent-metrics đo | **Con số recall THẬT (không bịa):** - Regex thuần trên paraphrase mới: **recall = 0.00** — *tôi tự chạy, câu paraphrase → `exit=0` lọt*. - Frontier model (tôi, làm judge trên 30 mẫu corpus): **recall = 1.00 (20/20)** — *tôi tự chấm trong phiên này*. - Ollama `ornith:9b`: **recall ≈ 0.85** — **con số này do casan5 tự báo, TÔI CHƯA tự đo** (chưa bật Ollama). Khi bạn chạy ở nhà, `phase3-redteam-metrics.sh` sẽ in recall thật của 9B → điền vào đây. **Kết luận trung thực về AI local (theo trọng tâm H4·H5·H6):** 1. AI local đóng **2 vai đo được thật**: (a) **tầng inferential** cho H4 (semantic recall, thắng regex 0.00); (b) **nguồn telemetry token thật** cho H6 (để cost-spike/agent-metrics có dữ liệu — tôi đã tự chứng logic cost-spike bằng data seed: `COST_SPIKE_DETECTED exit=2`). 2. **H5 không phụ thuộc model** — mạnh sẵn nhờ mật mã (đã tự chứng bằng tamper test). **Logic H6 cũng deterministic** — AI local chỉ *cấp dữ liệu*, không quyết định. 3. Giá trị lớn nhất của AI local **không nằm ở điểm số** mà ở **tự chủ dữ liệu** (red-team corpus/spec/audit/telemetry không rời máy) và **tái lập offline** (giám khảo replay không cần API key/mạng) — đúng trụ cột "Sovereign AI / Harness tự chủ" của FPT CASAN. 4. `ornith:9b` là **sàn, không phải trần**: đủ để **thắng regex (0.00)** và cấp telemetry thật, nhưng recall thua frontier — **hãy nói thẳng điều này khi thi** để đúng tinh thần "honest scope". --- macOS dùng BSD tools; harness cần vài công cụ GNU + `python` (không phải `python3`). Cài qua Homebrew: ```bash # 1.1 Công cụ nền brew install bash coreutils gnu-sed grep openssl@3 node git jq # 1.2 Đưa GNU coreutils/sed/grep lên đầu PATH cho phiên chấm điểm # (coreutils cung cấp sha256sum, timeout; gnu-sed/grep cung cấp sed/grep GNU) export PATH="$(brew --prefix coreutils)/libexec/gnubin:$(brew --prefix gnu-sed)/libexec/gnubin:$(brew --prefix grep)/libexec/gnubin:$PATH" # 1.3 Shim `python` -> `python3` (nhiều script gọi `python`) mkdir -p ~/bin printf '#!/usr/bin/env bash\nexec python3 "$@"\n' > ~/bin/python chmod +x ~/bin/python export PATH="$HOME/bin:$PATH" # 1.4 Kiểm tra for t in bash node python python3 openssl sha256sum timeout git jq; do printf "%-10s " "$t"; command -v "$t" >/dev/null && "$t" --version 2>/dev/null | head -1 || echo MISSING done ``` > **Vì sao cần bước này:** trên môi trường thiếu `python`/`sha256sum`/`timeout`, harness sẽ FAIL **giả** (lỗi môi trường, không phải control hỏng). Đây là bẫy phổ biến nhất khi tự chấm. **Tuỳ chọn — dùng Docker cho toolchain sạch (khỏi lo BSD):** ```bash docker run --rm -it --network host -v "$PWD":/work -w /work/casan5/AINative_OKR_CASAN5 node:24-slim bash -lc ' apt-get update -qq && apt-get install -y -qq python3 openssl git curl jq >/dev/null ln -sf "$(command -v python3)" /usr/local/bin/python bash # vào shell rồi chạy các bước Mục 4–6 ' ``` *(`--network host` để container thấy `127.0.0.1:11434` của tunnel. Trên Docker Desktop macOS, thay bằng `--add-host=host.docker.internal:host-gateway` và đặt `OLLAMA` qua host.docker.internal — xem Mục 3.3.)* --- ## 2. Lấy source về Mac ```bash # Copy/clone thư mục casan5 về Mac, rồi: cd <đường-dẫn>/casan5/AINative_OKR_CASAN5 ls .specify/tests/ # phải thấy run-casan4-harness-tests.sh, adversarial-harness-tests.sh, phase3-*.sh ``` --- ## 3. Kết nối tới Ollama ở nhà ### 3.1. Trên Linux server (một lần) — xác nhận model & Ollama lắng nghe ```bash ollama list # phải thấy dòng "ornith:9b" curl -s 127.0.0.1:11434/api/tags # trả JSON danh sách model # Nếu chưa có model, tạo/pull theo cách bạn đã dùng ở nhà (vd: ollama create ornith:9b -f Modelfile) ``` ### 3.2. Từ Mac — mở SSH tunnel (giữ terminal này chạy) ```bash ssh -N -L 11434:127.0.0.1:11434 @ ``` ### 3.3. Từ Mac — kiểm tra tunnel (terminal khác) ```bash curl -s 127.0.0.1:11434/api/tags | jq '.models[].name' # phải liệt kê ornith:9b ``` > Nếu bạn dùng tên model khác, xuất biến trước khi chạy gate: > ```bash > export CASAN_MODEL_PRIMARY="ollama:ornith:9b" # mặc định đã là giá trị này > ``` --- ## 4. Chạy các harness cốt lõi (không cần model) Các bước này chứng minh H1/H2/H3(rule)/H4(regex)/H5/H6/H7 — chạy được **không cần Ollama**. ```bash cd casan5/AINative_OKR_CASAN5 # 4.1 Harness chính (CASAN Level 4) — kỳ vọng: 35 PASS / 0 FAIL, exit 0 bash .specify/tests/run-casan4-harness-tests.sh; echo "exit=$?" # 4.2 Bộ adversarial (tấn công đối kháng) — kỳ vọng: 43–44 PASS / 0 FAIL, exit 0 bash .specify/tests/adversarial-harness-tests.sh; echo "exit=$?" # 4.3 Chuỗi audit ký + toàn vẹn (H5) — kỳ vọng: AUDIT_CHAIN_VALID bash .specify/scripts/bash/sign-audit-head.sh bash .specify/scripts/bash/verify-audit-chain.sh bash .specify/scripts/bash/verify-tool-audit.sh # kỳ vọng: TOOL_AUDIT_VALID ``` > **Lưu ý quan trọng:** `run-casan4-harness-tests.sh` **tự `rm -rf .specify/logs`** khi khởi động (reset trạng thái) rồi tự sinh lại. Đừng hoảng nếu thấy log cũ biến mất — đó là hành vi thiết kế. **Bài test tự kiểm chứng H5 (tùy chọn, rất thuyết phục):** cố tình sửa 1 record rồi verify lại — phải thấy `AUDIT_HASH_MISMATCH`: ```bash cp .specify/logs/audit/audit.jsonl /tmp/audit.bak sed -i '1s/high/LOW/' .specify/logs/audit/audit.jsonl bash .specify/scripts/bash/verify-audit-chain.sh # kỳ vọng: AUDIT_HASH_MISMATCH line=1 cp /tmp/audit.bak .specify/logs/audit/audit.jsonl # khôi phục ``` --- ## 5. Chạy các harness cần model (H3 judge + H4 semantic) — với ornith:9b Đảm bảo tunnel Mục 3 đang chạy (`curl 127.0.0.1:11434/api/tags` OK). ```bash export CASAN_MODEL_PRIMARY="ollama:ornith:9b" # 5.1 Model router hoạt động (classify/judge trả đúng 1 từ, fail-closed) bash .specify/tests/phase3-model-router-tests.sh; echo "exit=$?" # 5.2 Red-team metrics — precision/recall regex vs model trên 30 mẫu # Gate PASS khi: model_recall >= 0.8 VÀ model_recall > regex_recall bash .specify/tests/phase3-redteam-metrics.sh; echo "exit=$?" # 5.3 Judge-gate (H3): rule REJECT không gọi model; rule-pass thì tới model judge # Kỳ vọng với Ollama live: PASS=5 / FAIL=0 (không còn SKIP) bash .specify/tests/phase3-judge-gate-tests.sh; echo "exit=$?" ``` > Nếu tunnel **tắt**, các script trên in `BLOCKED: Ollama tunnel down` và **SKIP** (không FAIL). Điểm H3/H4 khi đó dựa trên phần rule + regex; recall model để trống. --- ## 6. Chạy test sản phẩm (frontend + backend) ```bash # 6.1 Frontend — kỳ vọng: 16 passed cd casan5/AINative_OKR_CASAN5 npm install --prefix frontend # lần đầu npm test -w frontend # vitest run -> 16/16 # 6.2 Backend (unit + e2e + LLM-judge). LLM-judge SKIP nếu không có API key/Ollama. npm ci npm run db:setup && npx prisma db seed -w backend 2>/dev/null || true node --import tsx --test-concurrency=1 --test "backend/test/**/*.test.ts" ``` --- ## 7. Chấm điểm một phát bằng cổng tổng hợp ```bash # Chạy TẤT CẢ gate bảo mật + model + frontend, in verdict tổng bash .specify/scripts/bash/security-gate.sh # Kỳ vọng khi tunnel + node đủ: == verdict: PASS=10 FAIL=0 SKIP=0 == # Nếu tunnel tắt: SKIP tăng (model gate), vẫn PASS phần còn lại. ``` Đây là lệnh chốt: **PASS=10 FAIL=0 SKIP=0** nghĩa là toàn bộ control xanh với model live. --- ## 8. Bảng tự chấm điểm 7 harness (điền sau khi chạy) Cách đọc: mỗi harness lấy điểm từ **bằng chứng chạy thật** ở Mục 4–7. Ngưỡng CASAN Level 4 = mọi harness ≥ 80; trung bình mục tiêu ~84. | Harness | Bằng chứng (lệnh) | Kỳ vọng | Điểm bạn đo | Ghi chú | |---|---|---|:--:|---| | **H1 Context** | `context-validate.sh` → `CONTEXT_VALID checked=N` | ~85 | ____ | artifact path đưa đúng agent | | **H2 Tool** | `verify-tool-audit.sh` → `TOOL_AUDIT_VALID`; rate-limit + JSON-schema trong adversarial | ~84 | ____ | least-privilege + timeout | | **H3 Evaluation** | `phase3-judge-gate-tests.sh` (PASS=5) + `npm test -w frontend` (16) | ~78–82 | ____ | rule AND model; fail-before | | **H4 Security** | `phase3-redteam-metrics.sh` (model_recall ≥ 0.8 > regex) + `security-check.sh` chặn injection | ~86 | ____ | semantic > regex | | **H5 Governance** | `verify-audit-chain.sh` → `AUDIT_CHAIN_VALID`; tamper → `HASH_MISMATCH` | ~83–85 | ____ | ký RSA, tách khoá | | **H6 AgentOps** | `metrics.jsonl` có `cost_source=provider_telemetry`; `cost-spike-detect.sh` | ~84 | ____ | đo token thật | | **H7 Orchestration** | adversarial: rollback checkpoint→restore (before==after); `drift-detect.sh` | ~86–87 | ____ | rollback thật | | | **Trung bình** | **~84** | ____ | mọi harness phải ≥ 80 | **Quy tắc chấm trung thực:** - Một harness chỉ được điểm cao nếu **chặn được một tấn công thật** (vd tamper → HASH_MISMATCH), không phải "có file cấu hình". - **SKIP ≠ FAIL:** test model SKIP khi thiếu Ollama là **non-blocking**; nhưng nếu bạn *có* Ollama mà vẫn FAIL → đó là vấn đề thật, trừ điểm. - Nếu harness thấp nhất < 80 → **cả pipeline chưa đạt Level 4 thật** (dù các harness khác cao). --- ## 9. Phân biệt FAIL thật vs FAIL môi trường (checklist khi gặp đỏ) | Triệu chứng | Nguyên nhân môi trường (KHÔNG trừ điểm) | Cách xử lý | |---|---|---| | `python: command not found` | script gọi `python`, Mac chỉ có `python3` | tạo shim Mục 1.3 | | `grep: character class syntax is [[:space:]]` | dùng BSD grep | đưa GNU grep lên PATH (Mục 1.2) | | `sha256sum: command not found` / `timeout: not found` | thiếu coreutils | `brew install coreutils` + gnubin PATH | | `AUDIT_CHAIN_MISSING` | harness vừa `rm -rf logs`, chưa sinh lại | chạy lại Mục 4.1 rồi 4.3 | | `BLOCKED: Ollama tunnel down` | tunnel chưa mở | kiểm tra Mục 3.2/3.3 | | `dofork ... 0xC000013A` | chỉ xảy ra trên Git Bash/Windows (fork msys) | chạy trên Mac/Linux/Docker là hết | > **Nguyên tắc:** trước khi kết luận "control hỏng", loại trừ hết 6 nguyên nhân môi trường ở trên. Đa số "FAIL" ban đầu là môi trường. --- ## 10. Script tự chấm một lệnh (tùy chọn — dán vào `selfscore.sh`) ```bash #!/usr/bin/env bash # Chạy: bash selfscore.sh (từ trong casan5/AINative_OKR_CASAN5) set -uo pipefail export PATH="$HOME/bin:$(brew --prefix coreutils)/libexec/gnubin:$(brew --prefix gnu-sed)/libexec/gnubin:$(brew --prefix grep)/libexec/gnubin:$PATH" export CASAN_MODEL_PRIMARY="ollama:ornith:9b" hr(){ printf '\n===== %s =====\n' "$1"; } ollama_up(){ curl -sS -m 5 http://127.0.0.1:11434/api/tags >/dev/null 2>&1; } hr "Ollama tunnel"; ollama_up && echo "UP (ornith:9b)" || echo "DOWN -> model tests will SKIP" hr "casan4 harness"; bash .specify/tests/run-casan4-harness-tests.sh >/tmp/c4.log 2>&1; echo "PASS=$(grep -c '^PASS' /tmp/c4.log) FAIL=$(grep -c '^FAIL' /tmp/c4.log) exit=$?" hr "adversarial"; bash .specify/tests/adversarial-harness-tests.sh >/tmp/adv.log 2>&1; echo "PASS=$(grep -c '^PASS' /tmp/adv.log) FAIL=$(grep -c '^FAIL' /tmp/adv.log) exit=$?" hr "audit chain"; bash .specify/scripts/bash/sign-audit-head.sh >/dev/null 2>&1; bash .specify/scripts/bash/verify-audit-chain.sh; bash .specify/scripts/bash/verify-tool-audit.sh if ollama_up; then hr "model router"; bash .specify/tests/phase3-model-router-tests.sh 2>&1 | tail -2 hr "red-team metrics"; bash .specify/tests/phase3-redteam-metrics.sh 2>&1 | tail -4 hr "judge gate"; bash .specify/tests/phase3-judge-gate-tests.sh 2>&1 | tail -2 fi hr "frontend vitest"; (npm test -w frontend 2>&1 | tail -4) hr "SECURITY GATE"; bash .specify/scripts/bash/security-gate.sh 2>&1 | tail -20 ``` --- ## 11. Tiêu chí "đạt" cuối cùng (để tuyên bố Level 4 thật) Bạn được quyền tuyên bố **casan5 = CASAN Level 4 chứng minh được** khi, trên máy có Ollama ornith:9b: - [ ] `run-casan4-harness-tests.sh` → **35 PASS / 0 FAIL** - [ ] `adversarial-harness-tests.sh` → **44 PASS / 0 FAIL** - [ ] `verify-audit-chain.sh` → **AUDIT_CHAIN_VALID** và tamper → **HASH_MISMATCH** - [ ] `verify-tool-audit.sh` → **TOOL_AUDIT_VALID** - [ ] `phase3-redteam-metrics.sh` → **model_recall ≥ 0.8 và > regex_recall** - [ ] `phase3-judge-gate-tests.sh` → **PASS=5 / FAIL=0** - [ ] `npm test -w frontend` → **16 passed** - [ ] `security-gate.sh` → **PASS=10 FAIL=0 SKIP=0** - [ ] Mọi harness H1–H7 ≥ 80; trung bình ~84 > Khi tất cả ô trên xanh, điểm không còn là "tự khai" — nó là **thứ bạn tái lập được bằng lệnh**, đúng tinh thần CASAN. --- ## 12. Ghi chú đối chiếu với báo cáo đánh giá - Tài liệu này là quy trình để **tự tái lập** phần **Phụ lục A + B** của `CASAN_OLD_vs_CASAN5_Executive_Assessment.md`. - Điểm số tham chiếu (~84, H1–H7) lấy từ `docs/output/casan/phase3-final-rescore.md` của dự án; mục 8 để bạn **điền số bạn tự đo** cạnh số tham chiếu → tự đối chứng. - Nếu muốn so **casan-old vs casan5**, chạy y hệt Mục 4–7 trong cả hai thư mục và điền hai cột. (Lưu ý: casan-old có bug `[:space:]` trong `security-check.sh` sẽ fail-open trên grep GNU — đây là khác biệt thật, không phải lỗi môi trường của bạn.) ```