[CLAUDE] Contract: chặn mọi đường tạo HĐ ngoài KHKK — YC-040 (106)=(b), chuỗi NCC→KHKK→HĐ khép kín
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 10m0s

Owner chốt: "(b) Chặn HẾT 7 loại — mọi HĐ đều phải từ KHKK -> Tao nghĩ nên như vậy trước đã."

BE: ContractCreationGate (1 chỗ, AllowedDirectTypes rỗng — nới = thêm loại, không sửa handler)
chặn 409 ở 2/3 write-site: POST /contracts (tạo tự do) + POST /purchase-evaluations/{id}/
create-contract (PE→HĐ 1-click nhảy cóc KHKK, di tích Phase 6). Bridge KHKK giữ nguyên
(write-site duy nhất). Gate đứng TRƯỚC mọi load — không lộ tồn tại dữ liệu. Seeder demo
là write-site miễn-trừ có khai (flag-gated).

FE ×2 app (8 lối): menu Create per-loại ẩn (Layout, policy Ct_*_Create giữ DB) · nút
"Tạo HĐ mới"/"Thêm mới" → "Tạo từ KHKK" trỏ /khkk/list (MyContracts + Dashboard +
ContractCreatePage) · ?mode=new → EmptyState chỉ đường KHKK · nút PE→HĐ ẩn (PeDetailTabs).
ContractCreatePage + PeDetailTabs giữ SHA-mirror 2 app.

Tests 697 pass + 6 skip / 0 fail (total 703): +4 gate mới (quét-trọn-enum fail-closed +
chặn-trước-NotFound + đổi message ApplicableType); 6 test multi-winner PE→HĐ chuyển
Skip-có-khai (spec di sản Mig 58, mở lại khi owner nới gate). Reviewer PASS_WITH_FIXES,
6/6 issue vá trong lượt (kể cả 3 chuỗi EmptyState/ListPanel còn mời tạo trực tiếp).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-14 19:39:28 +07:00
parent 93a19a01f2
commit 55a01643ae
20 changed files with 219 additions and 75 deletions

View File

@ -11,9 +11,9 @@
},
"_tick_invariant_note": "Tick invariant (hub dede7ec5 Delta-1, verbatim): moi LAN-CHOT +1; mot cap dung-noi tang DUNG +1, khong +2, khong +0. SE form = tick-at-entry-gate idempotent-per-label (hub Delta-2 recovery-gate +1 = permitted form) - NET +1/session-label EQUIV hub +1/cap on CLOSED pairs; an OPEN pair is transiently +0 until its entry gate fires (hub blessed, 9a35405b block-1 phep dung-noi). Guard song-con = label-convention (session-start 2.1.8: new conversation = new S\u003cnn\u003e label, NEVER reuse). history[] is append-unbounded BY DESIGN =\u003e absence of a marker = never-happened (safe semantics); IF a FIFO cap is ever added, eviction MUST be handled explicitly (absence-vi-bi-day != absence-vi-chua-xay-ra - log-BOUNDED design-note dede7ec5).",
"_seed_honesty": "Seeded UNTICKED on purpose. counter=0 and last_ticked_* = null mean \u0027no tick has ever happened\u0027, which is the truth at S121 - the ritual that performs the tick lands in W3. Seeding a fake first tick here would make the very first cadence reading a lie, and H24 exists to catch exactly that kind of invented number.",
"counter": 70,
"last_ticked_session": "S196",
"last_ticked_head": "e255c778215a90014533a9f33c19d09acc42e4bf",
"counter": 71,
"last_ticked_session": "S197",
"last_ticked_head": "a01147e9dfabda342abee48e34d920b1457ec064",
"last_ticked_at": "2026-08-14",
"last_audit": {
"light_at_counter": 66,
@ -362,6 +362,11 @@
"at": "2026-08-14",
"session": "S196",
"event": "squash-benign (session-counter-tick.ps1 M2, contract fail_loud_on_regress trigger-2 BENIGN branch): counter 69->70, session S195->S196, head e470bdd->e255c77. last_ticked_head e470bdd object EXISTS (cat-file=commit) but NOT reachable (merge-base --is-ancestor exit!=0), counter not regressed => a closeout squash lifted the ticked wal:/session commit out of history (expected drift, not tamper). Trace appended, continue, no owner alarm. Written atomically (temp + Move-Item -Force)."
},
{
"at": "2026-08-14",
"session": "S197",
"event": "CLEAN tick (session-counter-tick.ps1 M2): counter 70->71, session S196->S197, head e255c77->a01147e. Classify-before-tick: no regression (n=197 >= stored n=196); last_ticked_head reachable (merge-base --is-ancestor exit 0). 4 fields updated, 1 history entry appended, written atomically (temp + Move-Item -Force)."
}
]
}

View File

@ -31,7 +31,9 @@
| item-id | source | detected | reinjected | attempt | remeasured | status |
|---|---|---|---|---|---|---|
| _(chưa có floor-rot nào được reinject — ledger khởi-tạo trống S95, 2026-07-01)_ | | | | | | |
| CG-1 `front-end-reviewer-style` (floor-rot sub-class **clobber-rot** — mất H1 + LUẬT LÕI owner) | `.claude/agent-memory/front-end-reviewer-style/MEMORY.md` | S195 | S195 (UNION `e470bddf^`, commit `24566a50`) | 1 | **S197** (lead đo TƯƠI cùng lượt: `wc -c` = **5.913 B ≥ ngưỡng 5.800** + H1 dòng-1 còn; khớp `harness-eval` I1 bản PIN) | **resolved** |
> 🧊 *Dòng trên = dòng THẬT đầu tiên của bảng (@S197, thi hành `harness-refine` A1). Placeholder cũ "(chưa có floor-rot nào được reinject — ledger khởi-tạo trống S95)" đứng ở đây S95→S197 và từ @S195 đã TỰ MÂU THUẪN với prose `:100` (attempt=1) — `harness-audit` N2 @S197 bắt; lật trong CÙNG lượt ghi để lượt đóng nợ không đẻ neo thối mới. CHỐT-DỪNG giữ nguyên: tick sau nếu file <5.800 B hoặc mất H1 ⇒ ESCALATE, CẤM attempt-2.*
---