diff --git a/_acceptance/cache-l1-fingerprint/evidence-report.md b/_acceptance/cache-l1-fingerprint/evidence-report.md index 37d12da1..ae03486d 100644 --- a/_acceptance/cache-l1-fingerprint/evidence-report.md +++ b/_acceptance/cache-l1-fingerprint/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb # bypass_ack: human_signoff: Manh 2026-07-30 --- @@ -289,3 +289,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 16 eval máy exit 0 diff --git a/_acceptance/cache-l1-fingerprint/run-log.jsonl b/_acceptance/cache-l1-fingerprint/run-log.jsonl index b24af31d..154b9be4 100644 --- a/_acceptance/cache-l1-fingerprint/run-log.jsonl +++ b/_acceptance/cache-l1-fingerprint/run-log.jsonl @@ -33,3 +33,4 @@ {"ts": "2026-07-30T05:13:53Z", "round": 2, "evalId": "E16", "run_id": "minted-cache-l1-fingerprint-E16-r2", "exit_code": 0, "cmd": "cd sdk && PYTHONPATH=. uv run --no-project --with pytest --with tomli --with pydantic --with typing_extensions python -m pytest -q tests/test_fingerprint.py::test_dict_key_insertion_order_does_not_change_key"} {"ts": "2026-07-30T05:13:53Z", "round": 2, "kind": "baseline", "evals_hash": "09ebc70a2fc920b6c6e5aee9098691bc715fcec118115272addf600f055e9512", "non_discriminating": []} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"c000b4b6b32f29eea6217f8de26596a052737128","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0,"E14":0,"E15":0,"E16":0}} diff --git a/_acceptance/chong-doc-sai-em-ru/evidence-report.md b/_acceptance/chong-doc-sai-em-ru/evidence-report.md index 33f4000b..97d9d790 100644 --- a/_acceptance/chong-doc-sai-em-ru/evidence-report.md +++ b/_acceptance/chong-doc-sai-em-ru/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context machine lane (không hội đồng — xem §Vì sao LANE thay cho VÒNG) enforcement_mode: strict bypass_used: false -verified_commit: df22a16b63139b3d34ab753a1ebefa76615e6cb7 +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-08-29 --- @@ -275,3 +275,7 @@ sha: 665ff72bf34a07fc6156be70360d7dcf5dfc0592 · suites: 7 lệnh exit 0 ### Re-pin lần 1 — 2026-08-29, KHÔNG CẦN THIẾT; giữ lại vì phép đo là thật, nhưng lý do ban đầu thì sai. Nó được lấy vì `pre-merge-check.sh` báo hồ sơ này đã cũ — nhưng lượt chạy đó **thiếu `--base`**, chế độ mà chính công cụ in ra `rules ran=2 declared-off=2 expected=4` và `NOTE: T1-escape backstop skipped — no PR base given`. Chạy đúng cách CI gọi (`bash scripts/pre-merge-check.sh . --base origin/main`) thì tại `df22a16` — mốc **trước** lần re-pin này — cổng đã **sạch**. Đo lại từng mốc sau khi phát hiện: `129928a` 2 vi phạm (verdict PENDING-JUDGMENT + `conformance-l0` cũ), `3196853` 1 vi phạm (`conformance-l0` cũ), `df22a16` sạch. Tức chỉ lần re-pin `conformance-l0` là bắt buộc. Bài học ghi ở đây thay vì xoá dấu vết: **đọc số vi phạm từ một lượt chạy nửa số luật là đọc một phép đo khác với phép đo mình tưởng** — và công cụ đã nói thẳng điều đó ở dòng NOTE ngay trên con số. Bản thân số đo dưới đây vẫn đúng và vẫn dùng được: bộ đọc không đổi một byte, một phiên tươi chạy lại cả 12 suite máy trong worktree của nhánh, preflight GREEN, mọi lệnh exit 0 run_id: repin-chong-doc-sai-em-ru-20260829T134935Z sha: df22a16b63139b3d34ab753a1ebefa76615e6cb7 · suites: 12 lệnh exit 0 + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 12 eval máy exit 0 diff --git a/_acceptance/chong-doc-sai-em-ru/run-log.jsonl b/_acceptance/chong-doc-sai-em-ru/run-log.jsonl index d748e0ba..98b44e94 100644 --- a/_acceptance/chong-doc-sai-em-ru/run-log.jsonl +++ b/_acceptance/chong-doc-sai-em-ru/run-log.jsonl @@ -94,3 +94,4 @@ {"ts":"2026-08-28T23:47:56Z","sha":"665ff72bf34a07fc6156be70360d7dcf5dfc0592","round":7,"evalId":"E16","run_id":"minted-chong-doc-sai-em-ru-E16-r7","exit_code":0,"criterion":"AC-12"} {"ts":"2026-08-28T23:54:24Z","kind":"repin","run_id":"lane-chong-doc-sai-em-ru-20260828T133500Z","sha":"665ff72bf34a07fc6156be70360d7dcf5dfc0592","suites_exit":[0,0,0,0,0,0,0]} {"ts":"2026-08-29T13:49:35Z","kind":"repin","run_id":"repin-chong-doc-sai-em-ru-20260829T134935Z","sha":"df22a16b63139b3d34ab753a1ebefa76615e6cb7","suites_exit":[0,0,0,0,0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E14":0,"E16":0}} diff --git a/_acceptance/chong-mat-khoa-byo/evidence-report.md b/_acceptance/chong-mat-khoa-byo/evidence-report.md index ff68a285..77c5b855 100644 --- a/_acceptance/chong-mat-khoa-byo/evidence-report.md +++ b/_acceptance/chong-mat-khoa-byo/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-08-31 --- @@ -184,3 +184,7 @@ máy chung cho cả đợt, 8 ô đo bị chạm, cả 8 chạy lại và exit 0 KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 8 eval máy exit 0 diff --git a/_acceptance/chong-mat-khoa-byo/run-log.jsonl b/_acceptance/chong-mat-khoa-byo/run-log.jsonl index 0171cc3c..8f772381 100644 --- a/_acceptance/chong-mat-khoa-byo/run-log.jsonl +++ b/_acceptance/chong-mat-khoa-byo/run-log.jsonl @@ -92,3 +92,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E6","criterion":"AC-6","verifier":"config:executors.test.unit_byo_route_put_refuse","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E7","criterion":"AC-7","verifier":"config:executors.test.unit_byo_route_put_force","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E8","criterion":"AC-8","verifier":"config:executors.test.unit_byo_route_no_regression","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0}} diff --git a/_acceptance/ci-actions-bump/evidence-report.md b/_acceptance/ci-actions-bump/evidence-report.md index ca96d8be..0466d636 100644 --- a/_acceptance/ci-actions-bump/evidence-report.md +++ b/_acceptance/ci-actions-bump/evidence-report.md @@ -11,7 +11,7 @@ reason: >- verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -216,3 +216,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 8 eval máy exit 0 diff --git a/_acceptance/ci-actions-bump/run-log.jsonl b/_acceptance/ci-actions-bump/run-log.jsonl index 0a2c7944..32e1fb2f 100644 --- a/_acceptance/ci-actions-bump/run-log.jsonl +++ b/_acceptance/ci-actions-bump/run-log.jsonl @@ -7,3 +7,4 @@ {"ts":"2026-08-07T01:28:14Z","round":1,"evalId":"E7","run_id":"ci-actions-bump-E7-20260807T012801Z","exit_code":0,"cmd":"ACCEPTANCE_SLUG=ci-actions-bump bash scripts/ci/check-dispatch-run.sh desktop"} {"ts":"2026-08-07T01:28:24Z","round":1,"evalId":"E8","run_id":"ci-actions-bump-E8-20260807T012824Z","exit_code":0,"cmd":"ACCEPTANCE_SLUG=ci-actions-bump bash scripts/ci/check-workflow-drift.sh origin/main"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"a788985b3b30c7072dcfd95bc65db1f83b940984","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0}} diff --git a/_acceptance/ci-vitest-sdk-pin/evidence-report.md b/_acceptance/ci-vitest-sdk-pin/evidence-report.md index 12a39a6f..b00513ad 100644 --- a/_acceptance/ci-vitest-sdk-pin/evidence-report.md +++ b/_acceptance/ci-vitest-sdk-pin/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 5b94f33e53a74ea755bdf19331036d30050517c5 human_signoff: Manh 2026-08-07 --- @@ -327,3 +327,7 @@ máy chung cho cả đợt, 9 ô đo bị chạm, cả 9 chạy lại và exit 0 KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-11, do chiến dịch kit 2.11.0 +run_id: repin-20260911T092040Z-63189 +sha: 5b94f33e53a74ea755bdf19331036d30050517c5 · suites: 9 lệnh exit 0 · evals: 13/13 eval máy đạt kỳ vọng diff --git a/_acceptance/ci-vitest-sdk-pin/run-log.jsonl b/_acceptance/ci-vitest-sdk-pin/run-log.jsonl index cb6039e0..f93448ab 100644 --- a/_acceptance/ci-vitest-sdk-pin/run-log.jsonl +++ b/_acceptance/ci-vitest-sdk-pin/run-log.jsonl @@ -21,3 +21,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E10","criterion":"AC-10","verifier":"config:executors.script.b1_anchored_green","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E12","criterion":"AC-12","verifier":"config:executors.script.civ_eval_keys_intact","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E13","criterion":"AC-12","verifier":"config:executors.script.verify_plugins","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-11T09:20:40Z","kind":"repin","run_id":"repin-20260911T092040Z-63189","sha":"5b94f33e53a74ea755bdf19331036d30050517c5","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0}} diff --git a/_acceptance/compose-overlay/evidence-report.md b/_acceptance/compose-overlay/evidence-report.md index 73678ad2..738fd19b 100644 --- a/_acceptance/compose-overlay/evidence-report.md +++ b/_acceptance/compose-overlay/evidence-report.md @@ -14,7 +14,7 @@ reason: >- verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -495,3 +495,7 @@ máy chung cho cả đợt, 12 ô đo bị chạm, cả 12 chạy lại và exit KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 25 eval máy exit 0 diff --git a/_acceptance/compose-overlay/run-log.jsonl b/_acceptance/compose-overlay/run-log.jsonl index 48d256c1..cae4d36f 100644 --- a/_acceptance/compose-overlay/run-log.jsonl +++ b/_acceptance/compose-overlay/run-log.jsonl @@ -37,3 +37,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E19","criterion":"AC-13","verifier":"config:executors.test.unit_conformance","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E20","criterion":"AC-14","verifier":"config:executors.script.overlay_registration_synced","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E21","criterion":"AC-15","verifier":"config:executors.script.overlay_sdk_train","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1a":0,"E1b":0,"E2":0,"E3":0,"E4":0,"E5a":0,"E5b":0,"E6":0,"E7a":0,"E7b":0,"E8a":0,"E8b":0,"E9a":0,"E9b":0,"E10":0,"E14":0,"E15":0,"E16":0,"E17":0,"E12a":0,"E12b":0,"E18":0,"E19":0,"E20":0,"E21":0}} diff --git a/_acceptance/config.yaml b/_acceptance/config.yaml index 4b617bd4..53fa0752 100644 --- a/_acceptance/config.yaml +++ b/_acceptance/config.yaml @@ -824,6 +824,10 @@ risk_tiers: # workspace-record: vendor LẦN ĐẦU ở lượt này. Trước đây oneflow thiếu hẳn # file này nên nhánh đọc workspace của cổng chưa từng chạy. - "lib/workspace-record.cjs" + # lop-nhin-thay: mục thứ CHÍN của INIT-CI-COPY-LIST, vendor lần đầu ở kit + # 2.10.0. Thiếu nó thì NOTE lớp nhìn-thấy in «không kiểm được» và luật W8 + # tắt im ở kho này — cùng lớp measuring-stick với tám mục trên. + - "lib/lop-nhin-thay.cjs" # Lint configuration only — it constrains how source is written, never what # the product does at runtime, so a change here cannot invalidate evidence. - "biome.json" diff --git a/_acceptance/dang-ky-fork-openai/evidence-report.md b/_acceptance/dang-ky-fork-openai/evidence-report.md index eb9e2e5e..dd32d8ce 100644 --- a/_acceptance/dang-ky-fork-openai/evidence-report.md +++ b/_acceptance/dang-ky-fork-openai/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-09-01 --- @@ -263,3 +263,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 14 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 8 eval máy exit 0 diff --git a/_acceptance/dang-ky-fork-openai/run-log.jsonl b/_acceptance/dang-ky-fork-openai/run-log.jsonl index 471e6cac..97c7d22e 100644 --- a/_acceptance/dang-ky-fork-openai/run-log.jsonl +++ b/_acceptance/dang-ky-fork-openai/run-log.jsonl @@ -80,3 +80,4 @@ {"ts":"2026-09-03T23:13:51Z","kind":"repin","run_id":"repin-hang-rao-doc-nham-loi-20260903T231351Z","sha":"d1331546558e3ba13f3e77ef557f1393a44cffa9","prev_sha":"57c10c950893239c57559730ecdba193e75b0aab","suites_exit":[0,0,0,0,0,0,0]} {"ts":"2026-09-04T03:08:31Z","kind":"repin","run_id":"merge-repin-20260904T030830Z","sha":"792163491a11febaa0f5ff729f112442e3eecbef","prev_sha":"d1331546558e3ba13f3e77ef557f1393a44cffa9","suites_exit":[0,0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"792163491a11febaa0f5ff729f112442e3eecbef","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0}} diff --git a/_acceptance/dependency-refresh-2026-07/evidence-report.md b/_acceptance/dependency-refresh-2026-07/evidence-report.md index 3b54c6d8..05add56e 100644 --- a/_acceptance/dependency-refresh-2026-07/evidence-report.md +++ b/_acceptance/dependency-refresh-2026-07/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -172,3 +172,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 8 eval máy exit 0 diff --git a/_acceptance/dependency-refresh-2026-07/run-log.jsonl b/_acceptance/dependency-refresh-2026-07/run-log.jsonl index 986421e5..8feaaefe 100644 --- a/_acceptance/dependency-refresh-2026-07/run-log.jsonl +++ b/_acceptance/dependency-refresh-2026-07/run-log.jsonl @@ -7,3 +7,4 @@ {"ts":"2026-08-07T01:29:30Z","round":1,"evalId":"E7","run_id":"dependency-refresh-2026-07-E7-20260807T012930Z","exit_code":0,"cmd":"pnpm tsx scripts/measure/selftest-cogs.ts"} {"ts":"2026-08-07T01:29:41Z","round":1,"evalId":"E8","run_id":"dependency-refresh-2026-07-E8-20260807T012941Z","exit_code":0,"cmd":"ACCEPTANCE_SLUG=dependency-refresh-2026-07 bash scripts/deps/check-no-t3-drift.sh origin/main"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"a788985b3b30c7072dcfd95bc65db1f83b940984","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0}} diff --git a/_acceptance/gate-tooling-t1/evidence-report.md b/_acceptance/gate-tooling-t1/evidence-report.md index 76806a02..ba6ed537 100644 --- a/_acceptance/gate-tooling-t1/evidence-report.md +++ b/_acceptance/gate-tooling-t1/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-28 --- @@ -269,3 +269,7 @@ máy chung cho cả đợt, 12 ô đo bị chạm, cả 12 chạy lại và exit KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 3 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 12 eval máy exit 0 diff --git a/_acceptance/gate-tooling-t1/run-log.jsonl b/_acceptance/gate-tooling-t1/run-log.jsonl index ba5a8b9d..8426bf91 100644 --- a/_acceptance/gate-tooling-t1/run-log.jsonl +++ b/_acceptance/gate-tooling-t1/run-log.jsonl @@ -24,3 +24,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E10","criterion":"AC-9","verifier":"config:executors.script.gt1_no_stale_on_empty_diff","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E11","criterion":"AC-10","verifier":"config:executors.script.gt1_no_golden_claim","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E12","criterion":"AC-11","verifier":"config:executors.script.gt1_landed_merge_repinned","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0}} diff --git a/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/evidence-report.md b/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/evidence-report.md index a915b672..62e53ee9 100644 --- a/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/evidence-report.md +++ b/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/evidence-report.md @@ -7,7 +7,7 @@ failed_evals: [] verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-09-04 --- @@ -253,3 +253,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 3 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 12 eval máy exit 0 diff --git a/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/run-log.jsonl b/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/run-log.jsonl index 2aee3d76..f29d4410 100644 --- a/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/run-log.jsonl +++ b/_acceptance/hang-rao-doc-nham-loi-thanh-khong-co-gi/run-log.jsonl @@ -43,3 +43,4 @@ {"ts": "2026-09-04T03:09:19Z", "kind": "eval", "run_id": "merge-repin-20260904T030830Z-rerun", "eval": "E6", "criterion": "AC-6", "verifier": "config:executors.script.hrdn_dupkey", "exit_code": 0, "sha": "792163491a11febaa0f5ff729f112442e3eecbef", "output": "chay lai sau lan ghim merge-repin-20260904T030830Z tren cay da tron: exit 0"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"792163491a11febaa0f5ff729f112442e3eecbef","suites_exit":[0,0,0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E6","criterion":"AC-6","verifier":"config:executors.script.hrdn_dupkey","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0}} diff --git a/_acceptance/kho-khoa-toan-ven/evidence-report.md b/_acceptance/kho-khoa-toan-ven/evidence-report.md index 72a464d1..8ec5f2b5 100644 --- a/_acceptance/kho-khoa-toan-ven/evidence-report.md +++ b/_acceptance/kho-khoa-toan-ven/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: machine-lane (owner chốt bỏ lớp hội đồng, 31/08) enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-08-31 --- @@ -288,3 +288,7 @@ máy chung cho cả đợt, 10 ô đo bị chạm, cả 10 chạy lại và exit KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 13 eval máy exit 0 diff --git a/_acceptance/kho-khoa-toan-ven/run-log.jsonl b/_acceptance/kho-khoa-toan-ven/run-log.jsonl index f58926fe..2883d49d 100644 --- a/_acceptance/kho-khoa-toan-ven/run-log.jsonl +++ b/_acceptance/kho-khoa-toan-ven/run-log.jsonl @@ -24,3 +24,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E11","criterion":"AC-11","verifier":"config:executors.script.kkt_teeth_all","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E13","criterion":"AC-12","verifier":"config:executors.test.unit_kkt_empty_key_put","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E12","criterion":"AC-11","verifier":"config:executors.test.unit_kkt_no_regression","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E13":0,"E12":0}} diff --git a/_acceptance/khong-noi-sai-ve-kho-khoa/evidence-report.md b/_acceptance/khong-noi-sai-ve-kho-khoa/evidence-report.md index d7702fa9..bab37d68 100644 --- a/_acceptance/khong-noi-sai-ve-kho-khoa/evidence-report.md +++ b/_acceptance/khong-noi-sai-ve-kho-khoa/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-09-04 --- @@ -242,3 +242,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 13 eval máy exit 0 diff --git a/_acceptance/khong-noi-sai-ve-kho-khoa/run-log.jsonl b/_acceptance/khong-noi-sai-ve-kho-khoa/run-log.jsonl index cc4e8f89..2be89d0c 100644 --- a/_acceptance/khong-noi-sai-ve-kho-khoa/run-log.jsonl +++ b/_acceptance/khong-noi-sai-ve-kho-khoa/run-log.jsonl @@ -65,3 +65,4 @@ {"ts":"2026-09-03T11:05:00Z","sha":"cb2fab21e079","round":3,"kind":"baseline","evals_hash":"8eb7448557153fd73eaf8d139caf1c9946f45d141fc646e148e5d41ddf38fab9","non_discriminating":[],"carried_from_round":null} {"ts":"2026-09-03T11:05:00Z","sha":"cb2fab21e079","round":3,"kind":"round-tally","verdict":"PASS","expected":20,"returned":20,"blocked":0} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"cb2fab21e07988883da528d72e5c5a62219ef058","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0}} diff --git a/_acceptance/local-cpu-plugins/evidence-report.md b/_acceptance/local-cpu-plugins/evidence-report.md index 776ea9f1..1a04517a 100644 --- a/_acceptance/local-cpu-plugins/evidence-report.md +++ b/_acceptance/local-cpu-plugins/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 5b94f33e53a74ea755bdf19331036d30050517c5 human_signoff: Manh 2026-08-07 --- @@ -475,3 +475,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-11, do chiến dịch kit 2.11.0 +run_id: repin-20260911T092040Z-63189 +sha: 5b94f33e53a74ea755bdf19331036d30050517c5 · suites: 9 lệnh exit 0 · evals: 25/25 eval máy đạt kỳ vọng diff --git a/_acceptance/local-cpu-plugins/run-log.jsonl b/_acceptance/local-cpu-plugins/run-log.jsonl index b3f83f2b..ff3e30c6 100644 --- a/_acceptance/local-cpu-plugins/run-log.jsonl +++ b/_acceptance/local-cpu-plugins/run-log.jsonl @@ -24,3 +24,4 @@ {"ts":"2026-08-07T01:49:45Z","round":2,"evalId":"E14","run_id":"local-cpu-plugins-E14-20260807T014944Z","exit_code":0,"cmd":"bash scripts/plugins/run-local-plugin-tests.sh oneflow-api-pyscenedetect tests/test_split.py::test_missing_ffprobe_fails_loudly_naming_ffprobe"} {"ts":"2026-08-07T01:53:33Z","round":2,"evalId":"E4","run_id":"local-cpu-plugins-E4-20260807T014740Z","exit_code":0,"cmd":"bash scripts/plugins/check-venv-isolation.sh"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"a4c6eca33542e78037b05273a280237194415004","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-11T09:20:40Z","kind":"repin","run_id":"repin-20260911T092040Z-63189","sha":"5b94f33e53a74ea755bdf19331036d30050517c5","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E24":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E22":0,"E23":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0,"E14":0,"E15":0,"E16":0,"E17":0,"E18":0,"E19":0,"E25":0,"E26":0,"E20":0}} diff --git a/_acceptance/measure-harness/evidence-report.md b/_acceptance/measure-harness/evidence-report.md index cf6571ea..9d9f36a7 100644 --- a/_acceptance/measure-harness/evidence-report.md +++ b/_acceptance/measure-harness/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -330,3 +330,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 4 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 19 eval máy exit 0 diff --git a/_acceptance/measure-harness/run-log.jsonl b/_acceptance/measure-harness/run-log.jsonl index a7aba4a6..b13cbe37 100644 --- a/_acceptance/measure-harness/run-log.jsonl +++ b/_acceptance/measure-harness/run-log.jsonl @@ -20,3 +20,4 @@ {"ts":"2026-08-28T04:30:00Z","kind":"repin","run_id":"repin-measure-harness-20260828T043000Z","sha":"bee578e120584402211a6c38577f324c040e995b","suites_exit":[0,0,0,0,0,0,0]} {"ts":"2026-08-28T05:30:00Z","kind":"repin","run_id":"repin-measure-harness-20260828T053000Z","sha":"8512c6e98c48ab3f4cab75dafa9493a0b1e36868","suites_exit":[0,0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"8512c6e98c48ab3f4cab75dafa9493a0b1e36868","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0,"E14":0,"E15":0,"E16":0,"E17":0,"E18":0,"E19":0}} diff --git a/_acceptance/noi-thuoc-tai-lieu-vao-ci/evidence-report.md b/_acceptance/noi-thuoc-tai-lieu-vao-ci/evidence-report.md index 45ac5004..16489cc2 100644 --- a/_acceptance/noi-thuoc-tai-lieu-vao-ci/evidence-report.md +++ b/_acceptance/noi-thuoc-tai-lieu-vao-ci/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: phiên VERIFY tươi, chạy TUẦN TỰ (CLASSIFIER-FALLBACK sau BLOCKED vòng 2) enforcement_mode: strict bypass_used: false -verified_commit: a5ed5e0c879727c4cdcbbb18d738e4da35265a0a +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-09-02 --- @@ -233,3 +233,7 @@ Một ghi chú về phép đo, vì nó suýt đọc thành hồi quy: lượt ch lệnh-hỏng; lúc đó cây không còn lành vì một hồ sơ vừa được mở ngoài kế hoạch đang băng. Gỡ hồ sơ ấy thì ô xanh. Ô đo không sai; cây sai, và ô đo nói đúng điều đó. + +### Re-pin lần 12 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 9 eval máy exit 0 diff --git a/_acceptance/noi-thuoc-tai-lieu-vao-ci/run-log.jsonl b/_acceptance/noi-thuoc-tai-lieu-vao-ci/run-log.jsonl index e2cdcb83..2240dd2c 100644 --- a/_acceptance/noi-thuoc-tai-lieu-vao-ci/run-log.jsonl +++ b/_acceptance/noi-thuoc-tai-lieu-vao-ci/run-log.jsonl @@ -75,3 +75,4 @@ {"ts":"2026-09-07T00:45:00Z","kind":"eval","run_id":"repin-uat-20260907T004500Z","eval":"E7","criterion":"AC-7","verifier":"config:executors.script.dkfo_docs_teeth","exit_code":0,"sha":"a5ed5e0c879727c4cdcbbb18d738e4da35265a0a","output":"exit 0"} {"ts":"2026-09-07T00:45:00Z","kind":"eval","run_id":"repin-uat-20260907T004500Z","eval":"E8","criterion":"AC-8","verifier":"config:executors.script.ntlc_resign_wave","exit_code":0,"sha":"a5ed5e0c879727c4cdcbbb18d738e4da35265a0a","output":"exit 0"} {"ts":"2026-09-07T00:45:00Z","kind":"eval","run_id":"repin-uat-20260907T004500Z","eval":"E9","criterion":"AC-9","verifier":"config:executors.script.ntlc_no_new_checkout","exit_code":0,"sha":"a5ed5e0c879727c4cdcbbb18d738e4da35265a0a","output":"exit 0"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0}} diff --git a/_acceptance/oneflow-plugin-prefix/evidence-report.md b/_acceptance/oneflow-plugin-prefix/evidence-report.md index 24430014..086a2928 100644 --- a/_acceptance/oneflow-plugin-prefix/evidence-report.md +++ b/_acceptance/oneflow-plugin-prefix/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -216,3 +216,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 11 eval máy exit 0 diff --git a/_acceptance/oneflow-plugin-prefix/run-log.jsonl b/_acceptance/oneflow-plugin-prefix/run-log.jsonl index 094a3a91..f15a0c2f 100644 --- a/_acceptance/oneflow-plugin-prefix/run-log.jsonl +++ b/_acceptance/oneflow-plugin-prefix/run-log.jsonl @@ -10,3 +10,4 @@ {"ts":"2026-08-07T01:30:20Z","round":1,"evalId":"E10","run_id":"oneflow-plugin-prefix-E10-20260807T013020Z","exit_code":0,"cmd":"cd sdk && PYTHONPATH=. uv run --no-project --with pytest --with tomli --with pydantic --with typing_extensions python -m pytest -q tests/test_scan_prefix.py"} {"ts":"2026-08-07T01:30:26Z","round":1,"evalId":"E11","run_id":"oneflow-plugin-prefix-E11-20260807T013026Z","exit_code":0,"cmd":"cd sdk && PYTHONPATH=. uv run --no-project --with pytest --with tomli --with pydantic --with typing_extensions python -m pytest -q"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"a788985b3b30c7072dcfd95bc65db1f83b940984","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0}} diff --git a/_acceptance/per-plugin-origin/evidence-report.md b/_acceptance/per-plugin-origin/evidence-report.md index 173a9909..a3608b02 100644 --- a/_acceptance/per-plugin-origin/evidence-report.md +++ b/_acceptance/per-plugin-origin/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -287,3 +287,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 12 eval máy exit 0 diff --git a/_acceptance/per-plugin-origin/run-log.jsonl b/_acceptance/per-plugin-origin/run-log.jsonl index 33076265..ce3b4c6d 100644 --- a/_acceptance/per-plugin-origin/run-log.jsonl +++ b/_acceptance/per-plugin-origin/run-log.jsonl @@ -11,3 +11,4 @@ {"ts":"2026-08-07T02:03:56Z","round":2,"evalId":"E12","run_id":"per-plugin-origin-E12-20260807T020356Z","exit_code":0,"cmd":"pnpm verify:plugins"} {"ts":"2026-08-07T02:04:05Z","round":2,"evalId":"E10","run_id":"per-plugin-origin-E10-20260807T020405Z","exit_code":0,"cmd":"pnpm build && pnpm typecheck"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"f7306bfa6c17c4e2ff656b66036b0d369c60648d","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0}} diff --git a/_acceptance/repin-khong-chay-lai-eval/evidence-report.md b/_acceptance/repin-khong-chay-lai-eval/evidence-report.md index e4a76adb..8e72a010 100644 --- a/_acceptance/repin-khong-chay-lai-eval/evidence-report.md +++ b/_acceptance/repin-khong-chay-lai-eval/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: phiên VERIFY tuần tự (CLASSIFIER-FALLBACK sau BLOCKED vòng 3) + 3 lớp soi chỉ-đọc + 1 lượt soi xác nhận đối kháng enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Phan Le Manh 2026-09-03 --- @@ -322,3 +322,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 6 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 14 eval máy exit 0 diff --git a/_acceptance/repin-khong-chay-lai-eval/run-log.jsonl b/_acceptance/repin-khong-chay-lai-eval/run-log.jsonl index 7081e0e8..820369fd 100644 --- a/_acceptance/repin-khong-chay-lai-eval/run-log.jsonl +++ b/_acceptance/repin-khong-chay-lai-eval/run-log.jsonl @@ -65,3 +65,4 @@ {"ts": "2026-09-04T03:09:19Z", "kind": "eval", "run_id": "merge-repin-20260904T030830Z-rerun", "eval": "E2", "criterion": "AC-2", "verifier": "config:executors.script.rkce_newlines_have_prev", "exit_code": 0, "sha": "792163491a11febaa0f5ff729f112442e3eecbef", "output": "chay lai sau lan ghim merge-repin-20260904T030830Z tren cay da tron: exit 0"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"792163491a11febaa0f5ff729f112442e3eecbef","suites_exit":[0,0,0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E2","criterion":"AC-2","verifier":"config:executors.script.rkce_newlines_have_prev","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0,"E14":0}} diff --git a/_acceptance/roadmap-drift-guard/evidence-report.md b/_acceptance/roadmap-drift-guard/evidence-report.md index da811103..74f7a69b 100644 --- a/_acceptance/roadmap-drift-guard/evidence-report.md +++ b/_acceptance/roadmap-drift-guard/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: a21840da44f3dc922c530d90d09666d8081f434a +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-27 --- @@ -417,3 +417,7 @@ Ký Cổng Đáng của `skill-1-footage-kho-clip` (A1) làm hai ca răng `kiem- mượn trạng thái chưa-ký từ cây thật thay vì tự dựng. Sửa cho chúng tự gỡ ký trong bản sao — một file dưới `scripts/roadmap/**`, nên mốc lần 5 (`be5426e`) hỏng theo glob. Mã của gói này không đổi. Cả mười ô đo chạy lại, cả mười exit 0; cây sạch trước và sau, phiên điều phối không ghi gì trong lúc đo. + +### Re-pin lần 7 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 10 eval máy exit 0 diff --git a/_acceptance/roadmap-drift-guard/run-log.jsonl b/_acceptance/roadmap-drift-guard/run-log.jsonl index 5e19cbcc..5cc27094 100644 --- a/_acceptance/roadmap-drift-guard/run-log.jsonl +++ b/_acceptance/roadmap-drift-guard/run-log.jsonl @@ -107,3 +107,4 @@ {"ts":"2026-09-05T14:00:00Z","kind":"eval","run_id":"repin-a1-20260905T140000Z","eval":"E8","criterion":"AC-8","verifier":"config:executors.script.roadmap_drift_green","exit_code":0,"sha":"a21840da44f3dc922c530d90d09666d8081f434a","output":"✅ docs/roadmap.md khớp với docs/adr/ và _acceptance/ — không có trôi."} {"ts":"2026-09-05T14:00:00Z","kind":"eval","run_id":"repin-a1-20260905T140000Z","eval":"E9","criterion":"AC-9","verifier":"config:executors.script.roadmap_teeth_supersede_source_single","exit_code":0,"sha":"a21840da44f3dc922c530d90d09666d8081f434a","output":" ✓ CASE supersede-source-single: PASS"} {"ts":"2026-09-05T14:00:00Z","kind":"eval","run_id":"repin-a1-20260905T140000Z","eval":"E11","criterion":"AC-4","verifier":"config:executors.script.roadmap_teeth_ledger_paired","exit_code":0,"sha":"a21840da44f3dc922c530d90d09666d8081f434a","output":" ✓ CASE ledger-paired: PASS"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E11":0}} diff --git a/_acceptance/scan-scope-diagnostics/evidence-report.md b/_acceptance/scan-scope-diagnostics/evidence-report.md index 6156f2c0..de6a7d81 100644 --- a/_acceptance/scan-scope-diagnostics/evidence-report.md +++ b/_acceptance/scan-scope-diagnostics/evidence-report.md @@ -6,7 +6,7 @@ failed_evals: [] verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-18 --- @@ -288,3 +288,7 @@ máy chung cho cả đợt, 1 ô đo bị chạm, cả 1 chạy lại và exit 0 KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 3 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 21 eval máy exit 0 diff --git a/_acceptance/scan-scope-diagnostics/run-log.jsonl b/_acceptance/scan-scope-diagnostics/run-log.jsonl index ca0e8855..b8d6f1ec 100644 --- a/_acceptance/scan-scope-diagnostics/run-log.jsonl +++ b/_acceptance/scan-scope-diagnostics/run-log.jsonl @@ -67,3 +67,4 @@ {"ts":"2026-08-19T00:49:53Z","kind":"repin","run_id":"repin-scan-scope-diagnostics-1","sha":"6b08f6a289b423eb63a2f422416da9138e1bf207","suites_exit":[0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"6b08f6a289b423eb63a2f422416da9138e1bf207","suites_exit":[0,0,0,0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E13b","criterion":"AC-13","verifier":"config:executors.script.diag_noise_real","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E6b":0,"E6c":0,"E18":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E13":0,"E13b":0,"E14":0,"E15":0,"E16":0,"E17":0}} diff --git a/_acceptance/scan-with-block-imports/evidence-report.md b/_acceptance/scan-with-block-imports/evidence-report.md index dadaad3e..fb216f03 100644 --- a/_acceptance/scan-with-block-imports/evidence-report.md +++ b/_acceptance/scan-with-block-imports/evidence-report.md @@ -8,7 +8,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh Phan 2026-08-18 --- @@ -285,3 +285,7 @@ máy chung cho cả đợt, 15 ô đo bị chạm, cả 15 chạy lại và exit KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 3 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 16 eval máy exit 0 diff --git a/_acceptance/scan-with-block-imports/run-log.jsonl b/_acceptance/scan-with-block-imports/run-log.jsonl index 869b8acd..971adcc6 100644 --- a/_acceptance/scan-with-block-imports/run-log.jsonl +++ b/_acceptance/scan-with-block-imports/run-log.jsonl @@ -80,3 +80,4 @@ {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E14b","criterion":"AC-14","verifier":"config:executors.script.check_overlay_discoverable_real","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E14","criterion":"AC-1","verifier":"config:executors.script.check_scope_walker_teeth","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} {"ts":"2026-09-05T10:15:00Z","kind":"eval","run_id":"repin-merge-20260905T101500Z","eval":"E15","criterion":"AC-7","verifier":"config:executors.script.check_reason_teeth","exit_code":0,"sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e"} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0,"E14b":0,"E13":0,"E14":0,"E15":0}} diff --git a/_acceptance/sdk-distribution-rename/evidence-report.md b/_acceptance/sdk-distribution-rename/evidence-report.md index ec213bc8..adaa5061 100644 --- a/_acceptance/sdk-distribution-rename/evidence-report.md +++ b/_acceptance/sdk-distribution-rename/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -252,3 +252,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 2 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 14 eval máy exit 0 diff --git a/_acceptance/sdk-distribution-rename/run-log.jsonl b/_acceptance/sdk-distribution-rename/run-log.jsonl index 0fd55c05..e5819c50 100644 --- a/_acceptance/sdk-distribution-rename/run-log.jsonl +++ b/_acceptance/sdk-distribution-rename/run-log.jsonl @@ -13,3 +13,4 @@ {"ts":"2026-08-07T01:34:40Z","round":1,"evalId":"E13","run_id":"sdk-distribution-rename-E13-20260807T013440Z","exit_code":0,"cmd":"pnpm lint:check"} {"ts":"2026-08-07T01:35:11Z","round":1,"evalId":"E12","run_id":"sdk-distribution-rename-E12-20260807T013511Z","exit_code":0,"cmd":"pnpm build && pnpm typecheck"} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"a788985b3b30c7072dcfd95bc65db1f83b940984","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E14":0,"E11":0,"E12":0,"E13":0}} diff --git a/_acceptance/task-metering/evidence-report.md b/_acceptance/task-metering/evidence-report.md index 9a1ff90b..d1d987ca 100644 --- a/_acceptance/task-metering/evidence-report.md +++ b/_acceptance/task-metering/evidence-report.md @@ -7,7 +7,7 @@ reason: verified_by: fresh-context verification subagent enforcement_mode: strict bypass_used: false -verified_commit: 96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e +verified_commit: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb human_signoff: Manh 2026-08-07 --- @@ -234,3 +234,7 @@ máy chung cho cả đợt, không ô đo nào bị chạm — chỉ dời mốc KHÔNG KẾT LUẬN ĐƯỢC (cửa sổ diff rỗng khi nhánh đứng ngay tại `main`; hoặc ô `ui-check` không chạy được ngoài luồng verify). Dời mốc khi ấy là khai rằng bằng chứng còn đúng trong khi chưa chứng minh được. + +### Re-pin lần 4 — 2026-09-10, do chiến dịch ghim lại theo mốc kit 2.10.0 (luật làn eval ADR 0014); năm hồ sơ có eval đỏ SẴN trên origin/main tách ra, chờ owner quyết +run_id: repin-20260910T015646Z-20533 +sha: 12a74f5f78a82e9b2acf00c7342d0ecb72859ebb · suites: 9 lệnh exit 0 · evals: 12 eval máy exit 0 diff --git a/_acceptance/task-metering/run-log.jsonl b/_acceptance/task-metering/run-log.jsonl index bc347c89..05384a8f 100644 --- a/_acceptance/task-metering/run-log.jsonl +++ b/_acceptance/task-metering/run-log.jsonl @@ -13,3 +13,4 @@ {"ts":"2026-08-28T04:30:00Z","kind":"repin","run_id":"repin-task-metering-20260828T043000Z","sha":"bee578e120584402211a6c38577f324c040e995b","suites_exit":[0,0,0,0,0]} {"ts":"2026-08-28T05:30:00Z","kind":"repin","run_id":"repin-task-metering-20260828T053000Z","sha":"8512c6e98c48ab3f4cab75dafa9493a0b1e36868","suites_exit":[0,0,0,0,0]} {"ts":"2026-09-05T10:15:00Z","kind":"repin","run_id":"repin-merge-20260905T101500Z","sha":"96ee9b89c428b5ce0d64c8f49ba29eb7bd65727e","prev_sha":"8512c6e98c48ab3f4cab75dafa9493a0b1e36868","suites_exit":[0,0,0,0,0,0,0,0]} +{"ts":"2026-09-10T01:56:46Z","kind":"repin","run_id":"repin-20260910T015646Z-20533","sha":"12a74f5f78a82e9b2acf00c7342d0ecb72859ebb","suites_exit":[0,0,0,0,0,0,0,0,0],"evals_exit":{"E1":0,"E2":0,"E3":0,"E4":0,"E5":0,"E6":0,"E7":0,"E8":0,"E9":0,"E10":0,"E11":0,"E12":0}} diff --git a/biome.json b/biome.json index 790db8be..80b56b8a 100644 --- a/biome.json +++ b/biome.json @@ -34,6 +34,7 @@ "!lib/md-section.cjs", "!lib/workspace-record.cjs", "!lib/eval-yaml.cjs", + "!lib/lop-nhin-thay.cjs", "!_acceptance" ] }, diff --git a/lib/eval-yaml.cjs b/lib/eval-yaml.cjs index ba30cc50..80cfe911 100644 --- a/lib/eval-yaml.cjs +++ b/lib/eval-yaml.cjs @@ -56,4 +56,60 @@ function parseEvals(text, fields, normalize) { return evals; } -module.exports = { parseEvals, BLOCK_RE }; + +// Cắt chú thích YAML — MỘT nguồn cho mọi bộ đọc dòng (surfaces, field của eval, +// frontmatter). Luật: `#` mở chú thích khi nó đứng ĐẦU chuỗi hoặc có khoảng +// trắng đứng trước; `x#y` là DỮ LIỆU, không phải chú thích. Trước hồ sơ +// gom-duc-ket-2-10-0 mỗi bộ đọc tự viết một regex (`[ \t]+#` ở lib/lint, +// `\s*#` ở thẻ) nên cùng một dòng `surfaces:` cho hai câu trả lời khác nhau. +const stripComment = s => String(s == null ? '' : s).replace(/(^|\s)#.*$/, '').trim(); + + +// Kỳ vọng mã thoát của một eval máy — MỘT nguồn cho mọi bộ đọc (s4-args, làn +// ghim lại, checkRepinEvals, evaluateEvidence). Vắng trường VÀ khai 0 tường +// minh cho CÙNG kết quả: «đã khai» không phải một trạng thái riêng, chỉ giá +// trị khác 0 mới là một giới hạn. +// +// EXPECTED_EXIT_BANNED phải BẰNG tập khoá của khối marker INFRA-EXIT-CODES +// trong feature-loop/workflows/acceptance-verify.js. Không require được sang +// đó: tệp này vendor sang repo tiêu thụ, tệp kia không. Ca EE8 giữ hai bên +// khớp, hai chiều. Vì sao cấm: normInfra đổi hai mã đó thành cannotRun TRƯỚC +// mọi phép so, nên khai chúng là hứa một điều máy không giữ được; và đúng hai +// mã đó là lãnh địa ô đã park `baseline-127-tin-hieu-phan-biet` (ADR 0016). +const EXPECTED_EXIT_BANNED = [97, 127]; +const EXPECTED_EXIT_EXECUTORS = ['test', 'script']; + +function expectedExits(text) { + const byId = new Map(); + const errs = []; + for (const e of parseEvals(text, ['executor', 'expected_exit'], stripComment)) { + const id = e.id; + const executor = String(e.executor || '').trim().toLowerCase(); + const raw = String(e.expected_exit == null ? '' : e.expected_exit).trim().replace(/^["']|["']$/g, ''); + // Khai 0 tường minh (kể cả "00") không phải một giới hạn — nó phải đi + // ĐÚNG đường vắng trường ở MỌI executor, kể cả executor không hợp lệ. + // Phép kiểm executor chỉ áp khi giá trị khai giải ra KHÁC 0. + if (raw === '' || (/^\d+$/.test(raw) && Number(raw) === 0)) { byId.set(id, 0); continue; } + if (!EXPECTED_EXIT_EXECUTORS.includes(executor)) { + errs.push(`eval ${id}: expected_exit khai trên executor "${executor}" — chỉ ${EXPECTED_EXIT_EXECUTORS.join('/')} chạy lệnh nên mới có mã thoát`); + byId.set(id, 0); continue; + } + if (!/^\d+$/.test(raw)) { + errs.push(`eval ${id}: expected_exit "${raw}" không phải số nguyên 0–255`); + byId.set(id, 0); continue; + } + const n = Number(raw); + if (!Number.isInteger(n) || n < 0 || n > 255) { + errs.push(`eval ${id}: expected_exit "${raw}" không phải số nguyên 0–255`); + byId.set(id, 0); continue; + } + if (EXPECTED_EXIT_BANNED.includes(n)) { + errs.push(`eval ${id}: expected_exit ${n} là mã hạ tầng (${EXPECTED_EXIT_BANNED.join(', ')}) — không khai được; hạ tầng hỏng đi đường cannotRun, không đi đường giới hạn đã khai`); + byId.set(id, 0); continue; + } + byId.set(id, n); + } + return { byId, errs }; +} + +module.exports = { parseEvals, BLOCK_RE, stripComment, expectedExits, EXPECTED_EXIT_BANNED, EXPECTED_EXIT_EXECUTORS }; diff --git a/lib/evidence-core.cjs b/lib/evidence-core.cjs index da1c176a..a474ac9c 100644 --- a/lib/evidence-core.cjs +++ b/lib/evidence-core.cjs @@ -38,6 +38,163 @@ function findAcceptanceConfig(fileDir) { return null; } +// Vị trí dấu nháy ĐÓNG của vỏ mở ở ký tự 0, hoặc -1 khi không có vỏ đóng hợp +// lệ. Vỏ kép: `\` escape ký tự kế. Vỏ đơn: `''` là một dấu nháy literal, không +// phải vỏ đóng. +function closingQuoteIndex(s) { + const q = s[0]; + if (q !== '"' && q !== "'") return -1; + for (let i = 1; i < s.length; i += 1) { + if (q === '"') { + if (s[i] === '\\') { i += 1; continue; } + if (s[i] === '"') return i; + } else { + if (s[i] !== "'") continue; + if (s[i + 1] === "'") { i += 1; continue; } // '' = nháy literal + return i; + } + } + return -1; +} + +// Cắt chú thích YAML trên MỘT scalar, CÓ NHẬN BIẾT VỎ NHÁY. +// +// Vì sao không dùng thẳng `replace(/\s+#.*$/, '')`: phép đó không biết gì về +// vỏ, nên một scalar HỢP LỆ mang ` #` bên trong vỏ bị xén giữa chừng; mảnh còn +// lại KHÔNG CÂN, `unquoteScalar` (đúng theo thiết kế) trả nguyên văn kèm dấu +// nháy MỞ, và `bash -c '"echo a'` thoát 2 — tái tạo đúng chuỗi xanh-giả bốn +// bước mà hồ sơ release-2-11-0 tồn tại để đóng, chỉ đổi nguồn gây +// nháy-không-cân từ NGƯỜI VIẾT sang CHÍNH BỘ GIẢI. S4 lượt 1 của hồ sơ đó bắt +// được; ca BG7 giữ chỗ này. +function stripYamlComment(raw) { + const s = String(raw == null ? '' : raw).trim(); + const end = closingQuoteIndex(s); + if (end >= 0) { + const sau = s.slice(end + 1); + if (/^\s*(#.*)?$/.test(sau)) return s.slice(0, end + 1); // vỏ trọn vẹn, phần sau chỉ là chú thích + } + // `(^|\s)` chứ không `\s+`: `s` đã `trim()`, nên giá trị CHỈ LÀ chú thích + // (`khoa: # TODO`) mở đầu bằng `#` và không có khoảng trắng nào đứng trước. + // Bản `\s+` trả nguyên chuỗi chú thích — truthy, qua lưới `if (!val) die`, và + // `bash -c '# TODO'` thoát 0 → PASS mà không chạy gì (lượt chấm 4 bắt). Cùng + // biểu thức với `stripComment` của lib/eval-yaml.cjs. + return s.replace(/(^|\s)#.*$/, '').trim(); +} + +// Tách một list inline `a, b` theo dấu phẩy Ở NGOÀI vỏ nháy. `split(',')` trần +// xẻ ngay giữa vỏ, cho ra hai mảnh không cân — cùng lớp lỗi với stripYamlComment. +function splitTopLevel(s) { + const out = []; let cur = ''; let q = null; let dauMuc = true; + for (let i = 0; i < s.length; i += 1) { + const ch = s[i]; + if (q) { + cur += ch; + if (q === '"' && ch === '\\') { if (i + 1 < s.length) { cur += s[i + 1]; i += 1; } continue; } + if (ch === q) { if (q === "'" && s[i + 1] === "'") { cur += s[i + 1]; i += 1; continue; } q = null; } + continue; + } + // Cùng luật với closingBracketIndex: nháy chỉ mở vỏ khi đứng ĐẦU một mục. + if (dauMuc && (ch === '"' || ch === "'")) { q = ch; cur += ch; dauMuc = false; continue; } + if (ch === ',') { out.push(cur); cur = ''; dauMuc = true; continue; } + cur += ch; + if (!/\s/.test(ch)) dauMuc = false; + } + out.push(cur); + return out; +} + +// Bóc vỏ nháy của MỘT scalar YAML một dòng — nguồn DUY NHẤT cho mọi đường đọc +// giá trị sẽ được THI HÀNH hoặc dùng làm chỉ thị/đường dẫn (resolveConfigKey · +// resolveConfigList · bốn chỗ trong feature-loop/scripts/s4-args.mjs). +// +// Vì sao không dùng `replace(/^["']|["']$/g, '')`: đó là phép thay thế CÓ NEO +// dạng lựa-chọn, gỡ nháy đầu và nháy cuối ĐỘC LẬP nhau, nên +// (a) một chuỗi chỉ TÌNH CỜ kết thúc bằng nháy mất luôn ký tự đó, và +// (b) vì nó chỉ cắt vỏ, nó không biết gì về escape BÊN TRONG vỏ. +// Cả hai đo được trên main d1d36479 (hồ sơ release-2-11-0): `pytest -q -k 'a or +// b'` giải ra thiếu dấu đóng → `bash -c` thoát 2 → luật kỳ-vọng-mã-thoát (ship +// 10/09, cấm [97,127] chứ KHÔNG cấm 2) đọc mã 2 của SHELL thành «giới hạn đã +// khai» của CÔNG CỤ → PASS. Xanh giả bốn bước, tái phát qua ba mốc liên tiếp. +// (Chuỗi tên trường viết dạng gạch nối có chủ ý: ca tĩnh SA-EE4 canh cho dạng +// snake_case của nó KHÔNG rò vào bất kỳ bộ đọc nào khác, kể cả trong chú thích.) +// `frontmatterField` cuối tệp này đã học đúng bài học ấy ở S4-r5 và tự vá; kit +// giải lớp MỘT LẦN rồi không lan sang bộ đọc kế bên — đó là lý do lần này đi +// bằng một hàm dùng chung thay vì lại sửa một chỗ. +// +// Hai biểu thức đòi nháy trong thân HỢP LỆ theo YAML (vỏ kép: nháy trong phải +// escape · vỏ đơn: nháy trong phải nhân đôi), nên `"a" && echo "b"` — nháy hai +// đầu mà KHÔNG phải một cặp vỏ — giữ NGUYÊN VĂN thay vì bị xẻ. Không đoán thay +// người viết là hành vi đúng cho một chuỗi sắp được thi hành. +// Giới hạn đã khai: nháy đơn nhân đôi KHÔNG được un-double (`'it''s'` → +// `it''s`, YAML nói `it's`) — chưa có ca thật nào trong 8 kho đo được. +function unquoteScalar(raw) { + const s = String(raw == null ? '' : raw); + if (/^"(?:[^"\\]|\\.)*"$/.test(s)) return s.slice(1, -1).replace(/\\(["\\])/g, '$1'); + if (/^'(?:[^']|'')*'$/.test(s)) return s.slice(1, -1); + return s; +} + +// Vị trí `]` ĐÓNG của một flow-sequence mở ở ký tự 0, bỏ qua mọi `]` nằm TRONG +// vỏ nháy. -1 khi không đóng. +function closingBracketIndex(s) { + if (s[0] !== '[') return -1; + let q = null; let dauMuc = true; // ngay sau `[` hoặc `,` (bỏ khoảng trắng) + for (let i = 1; i < s.length; i += 1) { + const ch = s[i]; + if (q) { + if (q === '"' && ch === '\\') { i += 1; continue; } + if (ch === q) { if (q === "'" && s[i + 1] === "'") { i += 1; continue; } q = null; } + continue; + } + // YAML: dấu nháy chỉ là CHỈ DẤU khi đứng ĐẦU một node. `[plain, ends']` là + // hợp lệ và nghĩa là ['plain', "ends'"] — coi dấu `'` giữa chừng là mở vỏ + // sẽ nuốt luôn `]` và cả biểu thức hoá vô nghĩa (bắt được ở ca BG4). + if (dauMuc && (ch === '"' || ch === "'")) { q = ch; dauMuc = false; continue; } + if (ch === ']') return i; + if (ch === ',') { dauMuc = true; continue; } + if (!/\s/.test(ch)) dauMuc = false; + } + return -1; +} + +// ─── MỘT CỔNG DUY NHẤT cho mọi giá trị YAML một dòng ────────────────────── +// +// `parseFlowValue` là bộ tách token duy nhất; MỌI bộ đọc của kit tiêu thụ nó +// thay vì tự viết một biểu thức nhận-biết-vỏ. Vì sao khuôn này chứ không phải +// vá từng chỗ: hồ sơ release-2-11-0 vá HAI lượt và cả hai lượt lại sinh lỗi +// CÙNG LỚP — lượt 1 «cắt chú thích/tách phẩy chạy TRƯỚC bộ bóc nháy», lượt 2 +// «bộ cắt chú thích không nhận ra flow-sequence nên rơi về mệnh đề trần». Mỗi +// lần nhận-biết-vỏ được gắn vào MỘT bước phẫu-thuật-chuỗi thì bước kế bên +// trong cùng ống dẫn lại thiếu, và hệ quả luôn giống nhau: mảnh không cân, +// dấu nháy MỞ lọt vào chuỗi giao cho `bash -c`, shell thoát 2, và luật mã +// thoát đã khai đọc số 2 đó thành «giới hạn của công cụ» → PASS. STOP-PATCHING +// nổ ở lượt 2; owner chọn ĐỔI KHUÔN (10/09). Tính đúng của bộ này KHÔNG phụ +// thuộc việc đếm đủ số đường đọc — đó là điều mà mọi bản vá theo-từng-chỗ +// không thể có. +// +// Trả về một trong hai: +// { kind: 'seq', items: string[], text: string } — flow-sequence `[...]` +// { kind: 'scalar', value: string, text: string } — mọi thứ còn lại +// `text` = phần giá trị SAU khi cắt chú thích, giữ nguyên vỏ — bên nào cần +// nguyên văn (vd resolveConfigKey trả chuỗi cho một khoá là danh sách) thì đọc +// nó, không tự cắt lại. +function parseFlowValue(raw) { + const s = String(raw == null ? '' : raw).trim(); + const end = closingBracketIndex(s); + if (end >= 0 && /^\s*(#.*)?$/.test(s.slice(end + 1))) { + const text = s.slice(0, end + 1); + // `value` CÓ MẶT cả ở nhánh seq (= nguyên văn `[...]`) để nó KHÔNG BAO GIỜ + // undefined. Lượt chấm 3 bắt: nhánh khối của resolveConfigList gọi `.value` + // trên một item là flow-sequence và đẩy `undefined` vào một mảng khai kiểu + // string[] — mà đó là nguồn của `feature_loop.suite_keys`. Bắt bên gọi phải + // NHỚ một biểu thức ba ngôi là đúng khuôn sai mà cổng chung sinh ra để bỏ: + // chỗ dễ quên phải nằm TRONG cổng, không nằm ở chín chỗ gọi. + return { kind: 'seq', text, value: text, items: splitTopLevel(s.slice(1, end)).map(x => unquoteScalar(stripYamlComment(x))).filter(Boolean) }; + } + const text = stripYamlComment(s); + return { kind: 'scalar', text, value: unquoteScalar(text) }; +} + function resolveConfigKey(configText, dottedKey) { // Indent-based walk for a 2-3 level dotted key (e.g. executors.test.api). // Returns the scalar value or null. No YAML lib — line-based on purpose. @@ -60,15 +217,8 @@ function resolveConfigKey(configText, dottedKey) { if (!m) continue; if (m[1] === parts[depth]) { if (depth === parts.length - 1) { - const rawVal = m[2].replace(/\s+#.*$/, '').trim(); - // A double-quoted YAML scalar carries escapes (`\"`, `\\`); the lane - // hands this string to `bash -c` verbatim, so leaving the backslashes - // in turns `--with "x"` into `--with \"x\"` and the command dies before - // it runs (measured 08/09: repin-lane suite 6 exit 2 in 0.0s). Unescape - // only for the double-quoted form; single-quoted YAML has no escapes. - const val = /^".*"$/.test(rawVal) - ? rawVal.slice(1, -1).replace(/\\(["\\])/g, '$1') - : rawVal.replace(/^'|'$/g, ''); + const pv = parseFlowValue(m[2]); + const val = pv.kind === 'seq' ? pv.text : pv.value; return val || null; // leaf must have a non-empty scalar } depth++; @@ -94,7 +244,7 @@ function resolveConfigList(configText, dottedKey) { if (leafIndent >= 0) { if (indent <= leafIndent) break; const m = line.trim().match(/^-\s+(.*)$/); - if (m) out.push(m[1].replace(/\s+#.*$/, '').trim().replace(/^["']|["']$/g, '')); + if (m) out.push(parseFlowValue(m[1]).value); continue; } if (indent < expectedIndent) { @@ -105,8 +255,10 @@ function resolveConfigList(configText, dottedKey) { if (!m) continue; if (m[1] === parts[depth]) { if (depth === parts.length - 1) { - const val = m[2].replace(/\s+#.*$/, '').trim(); - if (val.startsWith('[')) return val.replace(/^\[|\]$/g, '').split(',').map(s => s.trim().replace(/^["']|["']$/g, '')).filter(Boolean); + // `[` không đóng (hoặc đóng bên trong vỏ) → KHÔNG phải flow-sequence: + // rơi về nhánh khối, trả [] — fail-CLOSED. Với `suite_keys` thì s4-args + // chết có tên thay vì chạy một danh sách bịa. + if (parseFlowValue(m[2]).kind === 'seq') return parseFlowValue(m[2]).items; leafIndent = indent; continue; } depth++; @@ -196,16 +348,13 @@ function loadRepinRunIds(fileDir) { // NOTHING about the slug's own evals unless it re-ran them at that sha. Real // case (crm-onehub, 2026-09-07): a signed record whose premise an 88-commit // merge removed was re-pinned green and reached the main branch with CI green. -// From REPIN_EVALS_SINCE every lane that backs verified_commit must carry -// `evals_exit` = {evalId: exit} covering every test/script eval declared in -// the slug's evals.yaml, all 0 (ui-check/judgment cannot run in a machine -// lane — declared limit, see GUIDE §7.1). Lanes dated before the mark are -// suite-only history (~530 citations in the kit's own corpus alone, signed -// records are immutable): the readers report them, never block. A lane that -// DID record evals_exit is always judged, whatever its ts — it claims eval -// evidence, so the claim is checked. A lane with no parseable ts cannot claim -// to be history — fail-closed. -const REPIN_EVALS_SINCE = '2026-09-07T12:00:00Z'; +// Every lane that backs verified_commit must carry `evals_exit` = {evalId: +// exit} covering every test/script eval declared in the slug's evals.yaml, all +// 0 (ui-check/judgment cannot run in a machine lane — declared limit, see +// GUIDE §7.1). NO date mark, NO grandfather (owner, 2026-09-08): a suite-only +// lane never proved the pin, whenever it ran — old pins are honest debt, red +// until re-pinned with the eval lane; the kit's own debt is named in +// tests/scripts/mirror-sync-grandfather.mjs (two-way checked), not hidden here. const REPIN_MACHINE_EXECUTORS = ['test', 'script']; function loadEvalYaml() { @@ -223,47 +372,92 @@ function machineEvalIds(evalsText) { .map(e => e.id); } -function repinLaneIsHistory(entry) { - if (entry && Object.prototype.hasOwnProperty.call(entry, 'evals_exit')) return false; - const t = entry && typeof entry.ts === 'string' ? Date.parse(entry.ts) : NaN; - return Number.isFinite(t) && t < Date.parse(REPIN_EVALS_SINCE); -} - // entry: the parsed repin line that backs verified_commit (sha == vc); // evalsText: evals.yaml content, or null when the file is missing; slug for -// the message. Returns { history, note?, errs } — messages carry NO prefix so -// recheck ("REPIN x ") and pre-merge ("VIOLATION [slug]: ") print one text. -function checkRepinEvals(entry, evalsText, slug) { +// the message; reportText (NEW, optional) is the committed evidence-report.md +// text this lane is signing for. Returns { errs } — messages carry NO prefix +// so recheck ("REPIN x ") and pre-merge ("VIOLATION [slug]: ") print one text. +// +// Luật hai vế (owner, hồ sơ eval-khai-ma-thoat-mong-doi 2026-09-09): một mã +// thoát KHÁC 0 chỉ chống lưng được pin khi ĐỦ HAI VẾ — (a) evals.yaml đã KHAI +// đúng mã đó (đọc qua lib/eval-yaml.cjs#expectedExits — gọi hàm dùng chung, +// không tự đọc trường ở đây), VÀ +// (b) báo cáo ĐÃ KÝ (## Evidence, khối `- eval: `) đã ghi ĐÚNG mã đó +// trước khi làn này chạy — nếu không, mã khác 0 mới xuất hiện chính là tiền +// đề vừa mất, không phải giới hạn đã người ký nhận. Thiếu MỘT vế = fail-open +// (chỉ cần sửa dòng khai của hồ sơ đã ký là làn xanh lại). reportText VẮNG +// (bên gọi cũ chưa truyền, hoặc lib/eval-yaml.cjs không nạp được) đi thẳng +// nhánh fail-closed — coi như vế hai không kiểm được, đỏ như luật trước khi +// có luật hai vế (đường đọc-cũ an toàn cho repo tiêu thụ chưa chép tệp mới). +function checkRepinEvals(entry, evalsText, slug, reportText) { const id = entry.run_id; const sha = entry.sha; const ts = typeof entry.ts === 'string' ? entry.ts : '?'; - if (repinLaneIsHistory(entry)) { - return { history: true, errs: [], note: `re-pin lane "${id}" (ts ${ts}, before ${REPIN_EVALS_SINCE}) is suite-only — this slug's evals were NOT re-run at ${sha}; grandfathered, re-pin with the eval lane at the next campaign` }; - } const errs = []; if (evalsText == null) { errs.push(`re-pin lane "${id}" backs verified_commit ${sha} but _acceptance/${slug}/evals.yaml is missing — nothing to prove the pin against`); - return { history: false, errs }; + return { errs }; } const ex = entry.evals_exit; if (ex === undefined) { errs.push(`re-pin lane "${id}" (ts ${ts}) backs verified_commit ${sha} but recorded no evals_exit — a suite-only lane proves the repo's suites, not this slug's evals; run feature-loop/scripts/repin-lane.mjs (it re-runs evals.yaml's test/script evals at HEAD), do not hand-write the line`); - return { history: false, errs }; + return { errs }; } if (!ex || typeof ex !== 'object' || Array.isArray(ex)) { errs.push(`re-pin lane "${id}" evals_exit is not an object of {evalId: exit} — malformed lane line; run a NEW lane`); - return { history: false, errs }; + return { errs }; } const ids = machineEvalIds(evalsText); if (ids === null) { errs.push(`cannot list machine evals for re-pin lane "${id}": lib/eval-yaml.cjs is not vendored next to evidence-core.cjs — copy the full INIT-CI-COPY-LIST`); - return { history: false, errs }; + return { errs }; } const has = i => Object.prototype.hasOwnProperty.call(ex, i); const missing = ids.filter(i => !has(i)); - const red = ids.filter(i => has(i) && ex[i] !== 0); if (missing.length) errs.push(`re-pin lane "${id}" evals_exit lacks eval(s) ${missing.join(', ')} declared in evals.yaml (executor test/script) — the lane did not re-run them at ${sha}; run a NEW lane`); - if (red.length) errs.push(`re-pin lane "${id}" evals_exit has nonzero exit for ${red.map(i => `${i}=${JSON.stringify(ex[i])}`).join(', ')} — a red eval cannot back a pin; fix the eval and run a NEW lane`); - return { history: false, errs }; + const ey = loadEvalYaml(); + const expected = (ey && typeof ey.expectedExits === 'function') + ? ey.expectedExits(evalsText).byId + : new Map(); + const signed = reportText == null ? null : extractEvalBlockExits(reportText); + const red = []; + for (const i of ids) { + if (!has(i)) continue; + const got = ex[i]; + if (got === 0) continue; + const want = expected.get(i) || 0; + if (want === 0) { + red.push(`${i}=${JSON.stringify(got)} (chưa khai: evals.yaml không khai mã thoát mong đợi cho eval này)`); + continue; + } + if (got !== want) { + red.push(`${i}=${JSON.stringify(got)} (khai ${want}, làn trả ${got} — lệch mã đã khai)`); + continue; + } + if (signed == null) { + red.push(`${i}=${JSON.stringify(got)} (không đọc được báo cáo đã ký để đối chiếu — vế hai của luật không kiểm được)`); + continue; + } + if (signed.get(i) !== want) { + red.push(`${i}=${JSON.stringify(got)} (tiền đề vừa mất: báo cáo đã ký ghi ${signed.has(i) ? signed.get(i) : 'không ghi mã nào'}, làn nay trả ${got} — một mã khác 0 MỚI xuất hiện chưa ai ký nhận)`); + } + } + if (red.length) errs.push(`re-pin lane "${id}" evals_exit không đạt kỳ vọng đã khai cho ${red.join(', ')} — sửa rồi chạy làn MỚI`); + return { errs }; +} + +// evalsPath: absolute/relative path to a slug's evals.yaml. Returns the +// content of the evidence-report.md sitting next to it (same dir), or null +// when absent/unreadable. Callers of checkRepinEvals that only have the +// evals.yaml path (pre-merge-check.sh's inline reader) use this instead of +// reading the file themselves — one rule, one file-read, both live here so +// the two call sites (pre-merge-check.sh, recheck-evidence.cjs) cannot drift. +// recheck-evidence.cjs already holds the report text in memory (it IS the +// file being rechecked) and passes it straight through instead. +function readSignedReportFor(evalsPath) { + try { + const reportPath = String(evalsPath).replace(/evals\.yaml$/, 'evidence-report.md'); + return fs.existsSync(reportPath) ? fs.readFileSync(reportPath, 'utf8') : null; + } catch (_) { return null; } } // run_ids claimed INSIDE eval blocks (`- eval: ` + indented fields) — @@ -284,6 +478,112 @@ function extractEvalBlockRunIds(payload) { return ids; } +// MỘT biểu thức nhận diện một dòng mã thoát (bất kể trong hay ngoài khối +// eval). Một dòng ĐƯỢC TÍNH LÀ khai mã thoát của khối đang mở chỉ khi từ khoá +// là TOKEN ĐẦU TIÊN sau khoảng trắng đầu dòng — một dòng ghi chú tự do chỉ +// NHẮC tới cụm này giữa câu ("note: last run had exit_code: 9 (stale, +// ignore)") không thoả điều kiện đó nên không bao giờ bị đọc nhầm thành mã +// thoát THẬT của eval đang mở (S4, hồ sơ eval-khai-ma-thoat-mong-doi +// 2026-09-09: đúng phân kỳ này từng khiến một báo cáo PASS hợp lệ bị chặn +// nhầm vì một dòng ghi chú lẫn trong khối). Ngoài mọi khối eval thì không có +// gì để đối chiếu — bất kỳ dòng nào khớp biểu thức (dù từ khoá không đứng +// đầu) đều là một lời khai mã thoát lạc chỗ và bị tính là vi phạm. +// +// Cờ TOÀN CỤC (g) là bắt buộc: MỘT dòng có thể mang NHIỀU khớp (vd một dòng +// trường thật rồi một cụm mã thoát khác lẫn trong ngoặc/ghi chú cuối cùng +// dòng). Không có cờ g, `line.match()` chỉ trả khớp ĐẦU TIÊN mỗi dòng nên mọi +// khớp còn lại trên cùng dòng — dù mang mã KHÁC 0 — biến mất hoàn toàn khỏi +// cả `outside` lẫn `violations` (S4, hồ sơ eval-khai-ma-thoat-mong-doi +// 2026-09-09, lượt soi toàn nhánh: ba hình dạng lọt vì thiếu đúng cờ này). +const EXIT_LINE_RE = /(?:exit_code|verifier_exit_code|exit)\s*[:=]\s*(-?\d+)\b/gi; + +// MỘT lượt đi khối, MỘT biểu thức, HAI cách nhìn — trả về CẢ HAI thứ mà L1 +// CONSISTENCY và luật hai vế của re-pin cần, để chúng không còn tự dựng lối +// đi khối RIÊNG rồi trôi khỏi nhau (đó chính là lỗ mà hồ sơ +// eval-khai-ma-thoat-mong-doi 2026-09-09 phát hiện: L1 CONSISTENCY từng có +// vòng lặp thứ hai dùng biểu thức KHÔNG neo đầu dòng). Cùng lối đi khối với +// extractEvalBlockRunIds: `- eval: ` mở khối, dòng đầu tiên không thụt +// đóng khối. +// +// HAI đường, không ba (đảo lại một phép nới SAI đã yêu cầu ở vòng trước: một +// dòng ghi chú tự do chứa cụm mã thoát bên trong khối KHÔNG còn được tha — +// hợp đồng chỉ cho đúng MỘT ngoại lệ, dòng trường thật neo đầu dòng): +// byEval — Map DANH SÁCH mọi mã ghi trong khối của +// từng eval, theo đúng thứ tự xuất hiện: mỗi khớp EXIT_LINE_RE +// mà từ khoá neo ngay đầu phần không-trắng của dòng (token đầu +// dòng, sau khoảng trắng đầu dòng) được gom vào danh sách của +// khối đang mở. MỘT dòng chỉ có ĐÚNG MỘT vị trí neo đầu dòng +// (khớp đầu tiên của dòng nếu nó đứng ở đó) nên tối đa MỘT +// phần tử của danh sách tới từ mỗi dòng — đây là MỘT ngoại lệ +// duy nhất hợp đồng cho phép, lặp lại trên nhiều dòng của cùng +// khối thì gom thành danh sách thay vì để dòng SAU ghi đè dòng +// TRƯỚC (S4, eval-khai-ma-thoat-mong-doi 2026-09-09, lượt soi +// toàn nhánh: `Map.set` ghi đè từng khiến một mã khác 0 ở dòng +// đầu biến mất khi dòng sau trong cùng khối cũng neo đầu dòng). +// outside — mảng các mã thoát KHÁC 0 khớp EXIT_LINE_RE nằm ngoài mọi +// khối eval, theo đúng thứ tự xuất hiện (MỌI khớp trên một +// dòng, không chỉ khớp đầu tiên). +// violations — mảng {evalId, code, line} cho MỌI khớp EXIT_LINE_RE TRONG +// khối mang mã KHÁC 0 mà từ khoá KHÔNG neo đầu dòng — dấu gạch +// đầu dòng chen trước (" - exit_code: 9"), lệch thụt lề, hay +// nằm giữa một câu văn xuôi hoặc sau dòng trường thật trên +// CÙNG dòng ("exit_code: 0 (truoc do exit_code: 7)") đều CÙNG +// một hình dạng vi phạm, không còn phân biệt theo "trông giống +// trường thật" hay "trông giống ghi chú" — thứ duy nhất phân +// biệt là VỊ TRÍ neo, không phải nội dung xung quanh. Cùng bộ +// lọc "khác 0" như `outside`: L1 CONSISTENCY chỉ soi mã THẤT +// BẠI — một mã 0 lạc chỗ (vd "... exit=0 ...") không tố cáo +// điều gì nên không phải vi phạm (corpus thật, hồ sơ +// lenh-tran-tai-lieu-dau-tay, có đúng hình dạng này ở một ghi +// chú vô hại). +function walkEvalExits(payload) { + const byEval = new Map(); + const outside = []; + const violations = []; + let cur = null; + for (const line of String(payload).split('\n')) { + const open = line.match(/^\s*-\s+eval\s*[:=]\s*(.+?)\s*$/i); + if (open) { cur = open[1].replace(/\s+#.*$/, '').trim().replace(/^["']+|["']+$/g, '').trim(); continue; } + if (cur && !/^\s+\S/.test(line)) cur = null; + const leading = line.length - line.trimStart().length; + // MỌI khớp trên dòng, không chỉ khớp đầu — cờ g trên EXIT_LINE_RE cho + // phép matchAll đi hết dòng thay vì dừng ở khớp đầu tiên. + for (const m of line.matchAll(EXIT_LINE_RE)) { + const code = Number(m[1]); + if (cur) { + if (m.index === leading) { + if (!byEval.has(cur)) byEval.set(cur, []); + byEval.get(cur).push(code); // neo đầu dòng — GOM vào danh sách, không ghi đè + } else if (code !== 0) { + violations.push({ evalId: cur, code, line }); // mọi hình dạng khác, mã khác 0 — vi phạm + } + } else if (code !== 0) { + outside.push(code); + } + } + } + return { byEval, outside, violations }; +} + +// Mã thoát ghi TRONG khối của từng eval — MỘT giá trị mỗi eval (chữ ký + +// hành vi cũ, vì checkRepinEvals so sánh trực tiếp `signed.get(i) !== want`). +// walkEvalExits nay trả DANH SÁCH mã cho mỗi khối (một khối HIẾM khi nhưng CÓ +// THỂ mang nhiều dòng neo đầu dòng); rút gọn về một giá trị phải chọn AN TOÀN +// (fail-closed) chứ không phải "dòng cuối thắng" như bug cũ: ưu tiên mã KHÁC +// 0 ĐẦU TIÊN trong danh sách — một mã khác 0 gần như chắc chắn LỆCH mã đã +// khai (`want`) nên khiến checkRepinEvals đỏ đúng hướng; chỉ khi mọi mã trong +// khối đều là 0 mới trả 0. Dùng cho luật hai vế của re-pin và (gián tiếp, qua +// walkEvalExits) cho L1 CONSISTENCY. +function extractEvalBlockExits(payload) { + const byEvalLists = walkEvalExits(payload).byEval; + const out = new Map(); + for (const [evalId, codes] of byEvalLists) { + const nonZero = codes.find(c => c !== 0); + out.set(evalId, nonZero !== undefined ? nonZero : 0); + } + return out; +} + // Set of run_ids the machinery logged, or null when no log exists (older // flow — tolerated; pre-merge NOTEs it). Malformed lines are skipped. function loadRunLogIds(fileDir) { @@ -471,20 +771,71 @@ function evaluateEvidence(payload, opts) { const configText = opts.configText || null; const configPath = opts.configPath || null; - // L1 CONSISTENCY — a genuine PASS report never contains a failed eval, - // machine OR judgment. If anything failed, the verdict must be REJECT. - const NONZERO_EXIT_RE = /(exit_code|verifier_exit_code|exit)\s*[:=]\s*[1-9]\d*\b/i; const FAILED_JUDGMENT_RE = /verdict\s*[:=]\s*FAIL\b/i; + + // L1 CONSISTENCY — một PASS thật không chứa eval trượt. Ngoại lệ DUY NHẤT: + // mã khác 0 nằm TRONG khối của đúng eval đã khai đúng mã ấy, TRÊN MỘT dòng + // trường thật neo đầu dòng (giới hạn đã khai, không phải một lượt trượt). + // Mọi mã khác 0 còn lại — ngoài khối, lệch mã, của eval không khai, hoặc + // trong khối nhưng không neo đầu dòng (dù trông giống trường thật lệch + // định dạng hay lẫn trong văn xuôi) — vẫn là vi phạm. (Đảo lại một phép nới + // SAI đã yêu cầu ở vòng trước: hợp đồng không có rổ "ghi chú được tha".) + const declared = (() => { + if (!fileDir) return new Map(); + const ey = loadEvalYaml(); + if (!ey || typeof ey.expectedExits !== 'function') return new Map(); + try { + const txt = fs.readFileSync(path.join(fileDir, 'evals.yaml'), 'utf8'); + const r = ey.expectedExits(txt); + return r.errs.length ? new Map() : r.byId; // khai sai → không tha gì cả + } catch (_) { return new Map(); } + })(); + // MỘT lượt đi khối dùng chung (walkEvalExits — cũng là nguồn của + // extractEvalBlockExits) thay vì tự dựng lối đi khối RIÊNG ở đây: đó chính + // là lỗ đã trôi khỏi nhau trước khi vá (S4, eval-khai-ma-thoat-mong-doi + // 2026-09-09). `outside` đã lọc sẵn mã 0; `byEval` giữ DANH SÁCH mọi mã (kể + // cả 0) của mỗi khối nên ở đây tự lọc `code !== 0` trước khi xét vi phạm — + // MỘT khối chỉ được tha khi MỌI mã khác 0 trong danh sách của nó đều bằng + // đúng mã đã khai; một mã khác 0 nào KHÁC trong cùng khối (dòng trước bị + // dòng sau ghi đè ở bug cũ) vẫn là vi phạm độc lập. `violations` là MỌI + // khớp TRONG khối mà từ khoá không neo đầu dòng — fail-CLOSED, không được + // rơi mất, và không còn nhánh nào tha nó theo hình dạng. + const { byEval: blockExits, outside: outsideExits, violations: unanchoredExits } = walkEvalExits(payload); let consistencyFailure = null; - if (NONZERO_EXIT_RE.test(payload)) { - consistencyFailure = 'PASS report contains a failed eval (exit_code != 0) — the verdict must be REJECT'; - } else if (FAILED_JUDGMENT_RE.test(payload)) { - consistencyFailure = 'PASS report contains a failed judgment (verdict: FAIL) — the verdict must be REJECT'; + { + const viPham = []; + for (const code of outsideExits) { + viPham.push(`mã ${code} ngoài mọi khối eval`); + } + for (const { evalId, code, line } of unanchoredExits) { + viPham.push( + `eval ${evalId}: dòng "${line.trim()}" mang mã ${code} không neo đầu dòng trong khối — chỉ dòng trường thật neo đầu dòng (vd "exit_code: ${code}") mới được tính là mã thoát của khối; sửa lại đúng thụt lề nếu là trường thật, hoặc bỏ cụm mã thoát khỏi ghi chú/văn xuôi nếu không phải` + ); + } + for (const [evalId, codes] of blockExits) { + for (const code of codes) { + if (code === 0) continue; + if (declared.get(evalId) === code) continue; // giới hạn đã khai + // declared.has(evalId) — KHÔNG kèm điều kiện giá trị: một eval khai + // đúng giới hạn 0 vẫn PHẢI đọc ra "khai 0", không phải "chưa khai" + // (Phát hiện 2 — giá trị 0 là falsy nên phép kiểm cũ + // `declared.has(x) && declared.get(x)` đọc nhầm nó thành chưa khai). + viPham.push(`eval ${evalId} (mã ${code}${declared.has(evalId) ? `, khai ${declared.get(evalId)}` : ', chưa khai'})`); + } + } + if (viPham.length) { + consistencyFailure = `PASS report contains a failed eval (exit_code != 0) — the verdict must be REJECT: ${viPham.join('; ')}`; + } else if (FAILED_JUDGMENT_RE.test(payload)) { + consistencyFailure = 'PASS report contains a failed judgment (verdict: FAIL) — the verdict must be REJECT'; + } } // L1 SHAPE const HAS_RUN_ID = /run_id\s*[:=]\s*\S{4,}/i.test(payload); - const HAS_EXIT_ZERO = /(exit_code|verifier_exit_code|exit)\s*[:=]\s*0\b/i.test(payload); + // Một hồ sơ mà MỌI eval máy đều khai mã khác 0 không thể có dòng exit_code: 0 + // nào. Điều kiện hình dạng thoả bằng một dòng mã thoát ĐÚNG kỳ vọng đã khai. + const HAS_EXIT_ZERO = /(exit_code|verifier_exit_code|exit)\s*[:=]\s*0\b/i.test(payload) + || [...blockExits].some(([evalId, codes]) => codes.some(code => code !== 0 && declared.get(evalId) === code)); const HAS_VERIFIED_AT = /verified_at\s*[:=]\s*\d{4}-\d{2}-\d{2}/i.test(payload); const verifierValues = extractVerifierValues(payload); const HAS_VERIFIER = verifierValues.length > 0; @@ -619,6 +970,33 @@ function evaluateContractWrite(newPayload, oldPayload) { } } + // duong-lui-phai-song AC-6: «da-veto» có vết + T2 là một lối Cổng-1-ĐÃ-GHI — người đã + // phát ngôn trên hồ sơ máy-đi-trước; chặn nó ở đây là giết đúng nút dừng của làn V + // (gap-probe P0: hồ sơ machine-cleared × mo không ghi được da-veto). Vết vẫn bắt buộc + // (V09), T2-only vẫn giữ (V10). + // Lối này HẸP đúng bằng ca nó phục vụ (S4-r1 finding, lớp fail-open): chỉ hồ sơ ĐANG ở + // `verified`/`machine-cleared` với cửa veto ĐANG `mo` trong bản cũ mới được ghi da-veto + // mà không có approved_by — hồ sơ mới/draft, hay `approved`/`signed-off` (không thuộc + // làn V), vẫn theo luật cũ: kèm da-veto vào không mua được Cổng 1. + let vetoRecorded = false; + if (v.present && v.state === 'da-veto') { + const oldV = oldPayload == null ? { present: false } : vetoGateState(oldPayload); + // laneStatus đọc bản CŨ (và bản mới vẫn phải trong làn): lối này mở cho hồ sơ ĐANG + // ở làn V, KHÔNG phải cho lượt ghi tự đặt mình vào làn V. Bản đầu đọc mỗi `status` + // mới, nên `draft` + `mo` nhảy thẳng sang `machine-cleared` + `da-veto` với + // approved_by rỗng và TẮT cả hai răng dưới (mốc 2.10.0 lượt chấm 1 — chú thích ở + // trên đã hứa «trong bản cũ» từ đầu, chỉ mã là đi lệch). Ca V14/V15 giữ chiều đỏ, + // V16 giữ đối chứng dương cho đúng lối verified → machine-cleared của làn V. + const trongLan = (st) => st === 'verified' || st === 'machine-cleared'; + const laneStatus = trongLan(oldStatus) && trongLan(status); + if (!v.stamped) failures.push(`veto_state: da-veto but veto_opened_at is ${v.openedAt ? `unreadable ("${v.openedAt}")` : 'missing'} — a veto without a timestamp is a silent gate skip. Set veto_opened_at: .`); + else if (v.tier === 'T3') failures.push(`veto_state: da-veto on a T3 contract — the V lane (and its veto) is T2-only; T3 always needs approved_by.`); + // Bản cũ đang `mo` (người vừa veto) HOẶC đã `da-veto` (ghi lại hồ sơ đang veto: thêm Known + // limits, sửa lý do, resume lượt bị ngắt) — cả hai đều là Cổng 1 đã có phát ngôn của người + // (S4-r4 finding: hồ sơ đã veto bị chặn mọi lượt ghi với lý do sai «Gate 1 chưa duyệt»). + else if (laneStatus && oldV.present && (oldV.state === 'mo' || oldV.state === 'da-veto')) vetoRecorded = true; + } + // `machine-cleared` = qua Cổng Bằng chứng KHÔNG có chữ ký người — đó CHÍNH là điều làn V // chỉ cho phép ở T2. Răng T2-only phải đứng ở tầng GHI, không chỉ ở lưới trước-merge: T3 // là «Cổng 2 luôn dừng chờ người», và hai tầng cưỡng chế lệch nhau cho cùng một luật là @@ -633,7 +1011,7 @@ function evaluateContractWrite(newPayload, oldPayload) { failures.push(`status: machine-cleared on a ${hangMoi || '(empty)'} contract — «machine-cleared» means Gate 2 passed WITHOUT a human signature, and that is T2-ONLY. T3 touches enforcement core / data / breaking API, so Gate 2 ALWAYS stops for a human: use verified, then /acceptance-gate:signoff to reach signed-off.`); } - if (!approvedBy && !gate1Skipped && !vOpen) { + if (!approvedBy && !gate1Skipped && !vOpen && !vetoRecorded) { if (status === 'approved' || status === 'signed-off' || status === 'machine-cleared') { failures.push(`status: ${status} with empty approved_by — Gate 1 approval not recorded. Fill approved_by (+ approved_at); only when the user explicitly skips Gate 1, record gate1_skipped: true (audited, pre-merge NOTEs it).`); } @@ -656,16 +1034,21 @@ function machineClearedSignoffConflict(contractTxt, evidenceTxt) { return `chữ ký người trên hồ sơ máy-thông — ký thì status phải sang signed-off (human_signoff="${sig}", status=machine-cleared). /signoff đổi status cùng lượt ghi chữ ký.`; } + module.exports = { PASS_FAMILY, machineClearedSignoffConflict, findAcceptanceConfig, + unquoteScalar, + stripYamlComment, + splitTopLevel, + parseFlowValue, resolveConfigKey, resolveConfigList, - REPIN_EVALS_SINCE, REPIN_MACHINE_EXECUTORS, machineEvalIds, checkRepinEvals, + readSignedReportFor, frontmatterField, extractRunIds, loadRunLogIds, diff --git a/lib/lop-nhin-thay.cjs b/lib/lop-nhin-thay.cjs new file mode 100644 index 00000000..5c306a13 --- /dev/null +++ b/lib/lop-nhin-thay.cjs @@ -0,0 +1,101 @@ +// lop-nhin-thay.cjs — LUẬT DUY NHẤT trả lời «hợp đồng này có MẶT NGƯỜI NHÌN không» và «đã có +// bằng chứng lớp nhìn-thấy (ui-observed) chưa». +// +// Vì sao một chỗ: bốn bộ đọc (lint W8 · thẻ Cổng Phạm vi · thẻ Cổng Bằng chứng · pre-merge NOTE) +// và vị từ «có người dùng cuối» của nguong-o-co-hoi.cjs cùng hỏi một câu. Từ vựng `surfaces` đã +// trôi một lần (web / web-ui ngoài enum, mỗi bộ đọc một regex) — hồ sơ lop-bang-chung-nhin-thay +// (D4) gom về đây. Ai thêm bên đọc thứ năm thì GỌI hàm này, đừng chép regex. +// +// Neo máy của nghĩa vụ ở bản khai (lint W8 · thẻ Cổng Phạm vi · NOTE pre-merge) là +// `executor: ui-check`. Răng của FRAME là thẻ Cổng Bằng chứng: nó đọc block của eval ui-check +// trong evidence-report (đạt = exit_code 0 + screenshot:). Hook write-time KHÔNG đòi screenshot +// trên block ui-check — nó chỉ kiểm observed: khi block ĐÃ có screenshot: (evidence-core +// evaluateObserved). `layer: ui-observed` là NHÃN KHAI để luật ghép cặp đọc đối xứng với +// backend-effect; nhãn đặt trên executor khác ui-check là lạc chỗ (D1). +// +// Hàm THUẦN nhận chuỗi; chỉ classify() và CLI đọc đĩa — bên gọi quyết định đọc ở đâu. +'use strict'; +const fs = require('fs'); +const path = require('path'); +const evalYaml = require('./eval-yaml.cjs'); + +// Enum PHẢI BẰNG chú thích dòng `surfaces:` của khối CONTRACT-FRONTMATTER-TEMPLATE +// (ca LNT1 round-trip khuôn ↔ lib — đổi một bên là ca đỏ nêu giá trị). +const SURFACE_ENUM = ['api', 'cli', 'sdk', 'ui', 'mobile', 'docs', 'ci', 'config']; +const SURFACE_ALIAS = { web: 'ui', 'web-ui': 'ui' }; +// Tiền tố entry descope — SKILL chép nguyên văn, thẻ/lint/pre-merge so bằng startsWith. +const UI_OBSERVED_DESCOPE = 'bỏ ui-observed — '; + +function tokensOf(surfaces) { + const s = evalYaml.stripComment(String(surfaces == null ? '' : surfaces).replace(/^\s*surfaces:\s*/i, '')); + return s.replace(/[\[\]"']/g, '').split(',').map(t => t.trim().toLowerCase()).filter(Boolean); +} +const canon = t => SURFACE_ALIAS[t] || t; +const laMatNguoiNhin = surfaces => tokensOf(surfaces).some(t => canon(t) === 'ui'); +const tokenLa = surfaces => tokensOf(surfaces).filter(t => !SURFACE_ENUM.includes(t) && !SURFACE_ALIAS[t]); + +const ex = e => String(e && e.executor || '').trim().toLowerCase(); +const ly = e => String(e && e.layer || '').trim().toLowerCase(); +const uiCheckIds = evals => (Array.isArray(evals) ? evals : []).filter(e => ex(e) === 'ui-check').map(e => e.id); +const coUiObserved = evals => uiCheckIds(evals).length > 0; +const nhanLacCho = evals => (Array.isArray(evals) ? evals : []).filter(e => ly(e) === 'ui-observed' && ex(e) !== 'ui-check').map(e => e.id); + +// Cùng nếp eval-coverage-lint: giá trị trong quote giữ nguyên (kể cả #), ngoài quote thì +// " # …" là comment. +function fieldVal(raw) { + const s = String(raw).trim(); + const q = s[0]; + if (q === '"' || q === "'") { const end = s.indexOf(q, 1); if (end > 0) return s.slice(1, end); } + return evalYaml.stripComment(s); +} +const parseEvalsText = text => evalYaml.parseEvals(text, ['criterion', 'executor', 'layer'], fieldVal); + +function descopeId(ledgerText) { + for (const line of String(ledgerText == null ? '' : ledgerText).split('\n')) { + if (!line.trim()) continue; + try { + const j = JSON.parse(line); + if (j && j.type === 'descope' && String(j.decision || '').startsWith(UI_OBSERVED_DESCOPE)) return j.id || null; + } catch (_) { /* dòng hỏng: bỏ qua, bên đọc khác đã đếm */ } + } + return null; +} + +function frontLine(text, key) { + const m = String(text == null ? '' : text).match(/^---\r?\n([\s\S]*?)\r?\n---/); + const fm = m ? m[1] : ''; + const l = fm.split('\n').find(x => x.startsWith(key + ':')); + return l ? evalYaml.stripComment(l.slice(key.length + 1)) : ''; +} + +function classify(dir) { + const rd = f => { try { return fs.readFileSync(path.join(dir, f), 'utf8'); } catch (_) { return null; } }; + const c = rd('contract.md'); + if (c == null) return { applicable: false, reason: 'no-contract' }; + const surfaces = frontLine(c, 'surfaces'); + const approved_at = frontLine(c, 'approved_at') || '-'; + const applicable = laMatNguoiNhin(surfaces); + const e = rd('evals.yaml'); + if (e == null) return { applicable, reason: 'no-evals', surfaces, approved_at, tokenLa: tokenLa(surfaces) }; + const evals = parseEvalsText(e); + return { + applicable, reason: '', surfaces, approved_at, + declared: uiCheckIds(evals).length, + lacCho: nhanLacCho(evals), + descoped: descopeId(rd('decisions.jsonl')), + tokenLa: tokenLa(surfaces), + }; +} + +module.exports = { SURFACE_ENUM, SURFACE_ALIAS, UI_OBSERVED_DESCOPE, tokensOf, laMatNguoiNhin, tokenLa, uiCheckIds, coUiObserved, nhanLacCho, fieldVal, parseEvalsText, descopeId, frontLine, classify }; + +// CLI cho bash (pre-merge): `node lib/lop-nhin-thay.cjs classify ` → MỘT dòng +// `applicable\tdeclared\tdescoped_id\tapproved_at` (mẫu lib/gap-probe.cjs classify). +if (require.main === module) { + const [cmd, dir] = process.argv.slice(2); + if (cmd !== 'classify' || !dir) { process.stderr.write('usage: lop-nhin-thay.cjs classify \n'); process.exit(2); } + const r = classify(dir); + if (r.reason === 'no-contract') process.exit(3); + if (r.reason === 'no-evals') { process.stdout.write(`n-a\t-\t-\t${r.approved_at}\n`); process.exit(0); } + process.stdout.write(`${r.applicable ? 1 : 0}\t${r.declared}\t${r.descoped || '-'}\t${r.approved_at}\n`); +} diff --git a/scripts/pre-merge-check.sh b/scripts/pre-merge-check.sh index 9cee15f1..b8a4be9f 100755 --- a/scripts/pre-merge-check.sh +++ b/scripts/pre-merge-check.sh @@ -365,8 +365,8 @@ xanh_sach_check() { # const fs=require("fs"); const t=fs.readFileSync(process.argv[2],"utf8"); const h=process.argv[3]; - const has=t.split("\n").some(l=>/^#{1,6}\s+/.test(l) - && l.replace(/^#{1,6}\s+/,"").trim().toLowerCase()===h.toLowerCase()); + const has=t.split("\n").some(l=>/^#{2,6}\s+/.test(l) + && l.replace(/^#{2,6}\s+/,"").trim().toLowerCase()===h.toLowerCase()); if(!has){process.stdout.write("__VANG__");process.exit(0);} process.stdout.write(section(t,h).join("\n").trim()?"__CO__":""); ' "$ROOT/lib/md-section.cjs" "$report" "$_sec" 2>/dev/null || printf '__LOI__')" @@ -464,11 +464,39 @@ t1_escape_not_enforced() { echo "NOTE: rủi ro khi tắt — nếu một thay đổi chạm code quan trọng lọt vào lần chạy này, nó sẽ KHÔNG bị chặn vì thiếu hồ sơ nghiệm thu. Các luật khác vẫn chạy đủ (phản biện context sạch, chữ ký người, bằng chứng hết hạn). Muốn bật lại: bỏ cờ --no-t1-escape." } +# ── `**/` là KHÔNG-hoặc-nhiều thư mục (glob-hai-sao-khop-goc-kho, 2.9.0) ────── +# `case` của bash đòi `**/` phải có ít nhất một `/`, nên `**/*.md` bỏ sót +# AGENTS.md ở gốc kho (CRM 07/09: 4 hồ sơ stale/ngày vì commit thuần tài liệu). +# Sinh mọi biến thể của glob với từng đoạn `**/` được GIỮ hoặc BỎ — chỉ tách tại +# chuỗi ba ký tự `**/`, KHÔNG tại `**` (docs/** phải đi qua nguyên vẹn, HS10). +# `*` vẫn vượt `/` như trước — lời khai `*.md`/`docs/**` ở mọi consumer không +# đổi nghĩa. Biến thể rỗng (glob chỉ là `**/`) bị bộ khớp bỏ qua, không khớp-mọi-thứ. +glob_variants() { # <đã-xử-lý> — in mỗi biến thể một dòng + case "$2" in + *'**/'*) + local pre="${2%%\*\*/*}" post="${2#*\*\*/}" + glob_variants "$1$pre" "$post" # GLOB-DOUBLESTAR-ZERO-DIRS + glob_variants "$1$pre**/" "$post" + ;; + *) printf '%s\n' "$1$2" ;; + esac +} match_globs() { # — 0 iff any glob matches while IFS= read -r g; do [ -n "$g" ] || continue # unquoted $g on purpose: case PATTERN matching (globs never fs-expand here) case "$1" in $g) return 0 ;; esac + # Glob có `**/` → thử thêm mọi biến thể giữ/bỏ từng đoạn (glob_variants ở + # trên). Thuần CỘNG: dòng khớp cũ vẫn chạy trước, không đổi nghĩa glob nào + # không chứa `**/` (HS10) — và DV5 (chỉ-thêm) giữ được nguyên vẹn. + case "$g" in *'**/'*) + while IFS= read -r v; do + [ -n "$v" ] || continue + case "$1" in $v) return 0 ;; esac + done </dev/null && pwd)/lib/lop-nhin-thay.cjs" + if { [ "$DIFF_READY" -eq 0 ] || slug_in_diff "$slug" || [ "$RECHECK_ALL" -eq 1 ]; } && [ -f "${dir}evals.yaml" ]; then + # Ba nguyên nhân KHÔNG-kiểm-được từng nấp sau một câu gộp: người đọc NOTE không + # biết phải copy lib, cài node, hay đi sửa lib đang lỗi (nợ C1 Ngoài-5). + lnt_line=""; lnt_why="" + if ! command -v node >/dev/null 2>&1; then + lnt_why="thiếu node; cài node để cổng đọc được lib" + elif [ ! -f "$LNT_LIB" ]; then + lnt_why="thiếu lib/lop-nhin-thay.cjs (mang cổng vào repo phải copy CẢ lib/)" + else + lnt_line="$(node "$LNT_LIB" classify "$dir" 2>/dev/null)"; lnt_rc=$? + # exit 3 = hồ sơ không có contract.md (không phải lỗi lib) — im lặng như trước. + if [ "$lnt_rc" -ne 0 ] && [ "$lnt_rc" -ne 3 ]; then lnt_why="lib lỗi (exit $lnt_rc)"; lnt_line=""; fi + fi + if [ -n "$lnt_why" ]; then + echo "NOTE [$slug]: lớp nhìn-thấy không kiểm được — ${lnt_why}; NOTE này không chặn." + elif [ -n "$lnt_line" ]; then + lnt_app="$(printf '%s' "$lnt_line" | cut -f1)"; lnt_decl="$(printf '%s' "$lnt_line" | cut -f2)" + lnt_desc="$(printf '%s' "$lnt_line" | cut -f3)"; lnt_appr="$(printf '%s' "$lnt_line" | cut -f4)" + if [ "$lnt_app" = "1" ] && [ "$lnt_decl" = "0" ]; then + if [ "$lnt_desc" != "-" ]; then + echo "NOTE [$slug]: mặt người nhìn (surfaces ui/web) nhưng không eval ui-check — đã BỎ có tên theo ledger $lnt_desc (approved_at $lnt_appr); người ký Cổng Bằng chứng đọc tên ca máy, không nhìn frame. Ngưỡng siết: 2 hợp đồng ký không frame trong một mốc phát hành." + else + echo "NOTE [$slug]: mặt người nhìn (surfaces ui/web) nhưng không eval ui-check nào — bằng chứng lớp mã thay lớp nhìn-thấy (approved_at $lnt_appr). Thêm ≥1 ui-check (layer: ui-observed) theo hợp đồng, hoặc ghi entry descope có tên. Ngưỡng siết: 2 hợp đồng ký không frame trong một mốc phát hành." + fi + fi + fi + fi + # Counter scope NẰM NGOÀI khối luật bên dưới và cố ý khác lexical (off không # nháy kép): tiêm vô hiệu khối thì counter vẫn đếm, sổ lệch, chokepoint bắt. [ "$GAP_PROBE_MODE" != off ] && slug_in_diff "$slug" && GP_SCOPE_N=$((GP_SCOPE_N+1)) @@ -1287,6 +1355,7 @@ XLACS # while its provenance reads empty (would otherwise let a bypassed PASS slip). verdict="$(front_field "$report" verdict)" signoff="$(front_field "$report" human_signoff)" + LAN_V=0 # DLPS-LAN-V-MOT-DUONG: 1 khi hồ sơ làn V xanh-sạch đi tiếp KHÔNG chữ ký (đổi khuôn, owner 08/09) # ── machine-cleared × chữ ký người = hai sự thật cãi nhau (hồ sơ ra-co-ten, AC-15) ── # Ký thì status phải sang signed-off; để chữ ký nằm trên hồ sơ máy-thông là mọi bên đọc # nói hai chuyện về cùng một hồ sơ. @@ -1329,11 +1398,20 @@ XLACS # Đường xanh-sạch KHÔNG có chữ ký để kiểm tiếp — các chốt dưới (giữ-chỗ, # provenance commit chữ ký) đều nói về một chuỗi không tồn tại ở đây. echo "NOTE [$slug]: xanh-sạch — máy đi tiếp, KHÔNG mời ký (verdict PASS · 0 UNCERTAIN · không bypass · Known limits rỗng · Ngoài hợp đồng rỗng · hạng T2). Cửa veto vẫn mở." - continue + # DLPS-LAN-V-MOT-DUONG (duong-lui-phai-song, đổi khuôn — owner 08/09/2026): KHÔNG `continue`. + # Làn V rơi xuống CÙNG chuỗi kiểm với hồ sơ có chữ ký — hoá cũ · pin ma · re-pin + # provenance · làn eval · soi lại — đúng chữ «soi MỌI hồ sơ ở MỌI lượt» (ADR 0014). + # Ba vòng S4 của hồ sơ này đều bắt cùng lớp fail-open ở chính chỗ `continue` cũ: hồ sơ + # máy-đi-trước là loại KHÔNG có người đọc lại, nên không được là loại duy nhất thoát lưới. + # Các chốt chỉ nói về chữ ký (giữ-chỗ · chiều ghi chữ ký) tự bỏ qua vì $signoff rỗng / + # LAN_V=1; dòng OK ở cuối gọi đúng tên làn. + LAN_V=1 fi + if [ "$LAN_V" != 1 ]; then echo "NOTE [$slug]: không đủ điều kiện xanh-sạch để đi tiếp không ký — $clean_why" echo "VIOLATION [$slug]: verdict PASS but human_signoff is empty (Gate 2 pending)" violations=$((violations+1)); continue + fi fi # THỨ TỰ CÓ RĂNG: chốt rỗng ngay trên chạy TRƯỚC. Gộp hai chốt cho gọn sẽ làm # chuỗi rỗng không khớp mẫu lưới-đen nào rồi rơi ra `clean` — hồi quy fail-open @@ -1384,6 +1462,7 @@ XLACS # Phạm vi: CHỈ hồ sơ nằm trong diff PR — dùng ĐÚNG hàm slug_in_diff mà luật # staleness/gap-probe dùng. Không thu phạm vi thì mọi hồ sơ sử liệu đều in # một dòng mỗi lần chạy (đo thật: 20+ dòng), đúng lớp loãng-tín-hiệu. + if [ "$LAN_V" != 1 ]; then # DLPS-LAN-V-MOT-DUONG: làn V không có chữ ký → không có chiều ghi để nói if [ -n "$BASE" ] && slug_in_diff "$slug" && command -v git >/dev/null 2>&1 && git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then rel_report="$(cd "$ROOT" 2>/dev/null && git ls-files --full-name -- "${report#"$ROOT"/}" 2>/dev/null | head -1)" [ -n "$rel_report" ] || rel_report="${report#"$ROOT"/}" @@ -1394,6 +1473,7 @@ XLACS echo "NOTE [$slug]: chữ ký mới trong diff — $signoff — provenance ở forge: người bấm merge xác nhận đây là quyết định của người" fi fi + fi # đóng guard DLPS-LAN-V-MOT-DUONG # Stale-evidence check: the PASS certifies the tree at verified_commit. Any # non-gate file changed since then (committed or working tree) means the code # being merged is NOT the code that was verified — re-verify, don't ride old @@ -1605,8 +1685,11 @@ REPINIDS # xanh (crm-onehub 07/09). MỘT nguồn luật: checkRepinEvals trong # lib/evidence-core.cjs (bên đọc thứ hai là recheck-evidence.cjs); nó liệt # kê eval máy qua lib/eval-yaml.cjs, nên cả hai phải được chép theo - # INIT-CI-COPY-LIST. Làn trước mốc REPIN_EVALS_SINCE là sử liệu suite-only: - # NOTE, không chặn. Thiếu node/lib → khai NOT ENFORCED, không im lặng. + # INIT-CI-COPY-LIST. KHÔNG mốc ngày, KHÔNG phạm vi diff (owner 08/09/2026, + # hai lần): làn suite-only đời nào, hồ sơ nào trong kho, cũng là VIOLATION ở + # MỌI lượt chạy — pin chưa chứng không được nằm im chỉ vì PR không chạm nó; + # cách sửa duy nhất là ghim lại bằng làn eval. Thiếu node/lib → khai NOT + # ENFORCED, không im lặng. if [ -n "$vc" ]; then if command -v node >/dev/null 2>&1 && [ -f "$HERE/../lib/evidence-core.cjs" ]; then repin_evals_out="$(REPIN_IDS="$repin_ids" node -e ' @@ -1623,7 +1706,7 @@ REPINIDS let bad = 0; for (const id of ids) { const e = repins.get(id); if (!e || e.sha !== vc) continue; - const r = core.checkRepinEvals(e, evalsText, slug); + const r = core.checkRepinEvals(e, evalsText, slug, core.readSignedReportFor(evalsPath)); if (r.note) process.stdout.write(`NOTE [${slug}]: ${r.note}\n`); for (const x of r.errs) { bad = 1; process.stdout.write(`VIOLATION [${slug}]: ${x}\n`); } } @@ -1699,12 +1782,18 @@ NETIDS printf '%s\n' "$recheck_out" | sed 's/^/ /' if [ "$RECHECK_MODE" = strict ]; then violations=$((violations+1)); continue; fi elif [ "$rc" -ne 0 ]; then + if [ "$RECHECK_MODE" = strict ]; then echo "VIOLATION [$slug]: evidence re-check KHÔNG CHẠY ĐƯỢC (exit $rc) — recheck: strict coi cổng câm là cổng hỏng; sửa: vendor lib/ cạnh scripts/, đọc được evidence-report.md"; violations=$((violations+1)); continue; fi echo "NOTE [$slug]: evidence re-check unavailable (exit $rc) — ${recheck_out:-skipped}" fi else + if [ "$RECHECK_MODE" = strict ]; then + if [ ! -f "$RECHECK" ]; then rc_duong="recheck-evidence.cjs vắng"; else rc_duong="node vắng"; fi + echo "VIOLATION [$slug]: evidence re-check KHÔNG CHẠY ĐƯỢC ($rc_duong) — recheck: strict coi cổng câm là cổng hỏng; vendor scripts/recheck-evidence.cjs + lib/ và cài node"; violations=$((violations+1)); continue + fi echo "NOTE [$slug]: evidence re-check not vendored (recheck-evidence.cjs/node missing) — committed-evidence bar NOT enforced" fi fi + if [ "$LAN_V" = 1 ]; then echo "OK [$slug]: $verdict — làn V, máy đi tiếp không chữ ký (đã qua cùng chuỗi kiểm: hoá cũ · pin · làn eval · soi lại)"; continue; fi echo "OK [$slug]: $verdict, signed off by $signoff" done diff --git a/scripts/recheck-evidence.cjs b/scripts/recheck-evidence.cjs index ecdb861c..c1366868 100644 --- a/scripts/recheck-evidence.cjs +++ b/scripts/recheck-evidence.cjs @@ -93,14 +93,14 @@ if (!core.determineEnforce(payload)) process.exit(0); // The lane that backs verified_commit must have re-run THIS slug's // test/script evals at that sha (evals_exit). One rule source: // core.checkRepinEvals — pre-merge prints the same words under its own - // label; history lanes (before REPIN_EVALS_SINCE) only NOTE there. + // label. No date mark, no grandfather (owner, 2026-09-08). if (vc) { const evalsPath = path.join(dir, 'evals.yaml'); const evalsText = fs.existsSync(evalsPath) ? fs.readFileSync(evalsPath, 'utf8') : null; for (const id of new Set(cited)) { const e = repins.get(id); if (!e || e.sha !== vc) continue; - for (const x of core.checkRepinEvals(e, evalsText, slug).errs) errs.push(`REPIN x ${x}`); + for (const x of core.checkRepinEvals(e, evalsText, slug, payload).errs) errs.push(`REPIN x ${x}`); } } }