G2-1A Time Concept Ledger Delta — READY_FOR_AUDIT
G2-1A Time Concept Ledger Delta — READY_FOR_AUDIT
Ngày: 2026-07-07. Nhiệm vụ: G2-1A — render concept-delta đúng schema thật cho drift "3 giá trị thời gian" (phần tổng phút cộng dồn). Chỉ read-only PG + ghi artifact audit trong mcp-writes. 0 ghi PG, 0 copy vào /opt/incomex/dot/sql, 0 append manifest, 0 apply.
Gate: GO_OPEN_G2_LEDGER_TIME_CONCEPT_DELTA received — yes. Owner phát lệnh nguyên văn trong phiên khi được hỏi trực tiếp (đúng kỷ luật G1-2B: lượt nhận prompt chỉ chứa chuỗi gate trong phần mô tả đã HOLD 0 hành động trước, không tự suy GO).
1. Verdict
READY_FOR_AUDIT
2. Scope
Ledger-only. Schema-aware (information_schema là nguồn cuối cùng). No UI source patch, no rescan, no shadow edit. Không tạo field.tong_thoigian_nhaptay (defer).
3. G1 sealed baseline check
Đối chiếu g1-final-proof-2026-07-07.md + sealed baseline, SELECT read-only trước khi render — PASS toàn bộ:
- concept = 13; usage total = 31; current = 30; current distinct slot_key = 30; non-current = 1 (chỉ id 11); 0 slot vi phạm 1-current.
- current match_status = matched 27 / candidate 2 / review 1.
- id 24/25/30 vẫn keep_pending, không dòng nào khác decided.
- G1 target: id 11 history + id 31 current (field.so_phut, matched) đúng như sealed.
- CHƯA có
field.tong_phut_congdon; CHƯA cófield.tong_thoigian_nhaptay(0 rows).
Re-check sau render: 13/31/30, 0 concept mới, 3 decided, id 13 vẫn current → PG không bị ghi trong suốt G2-1A.
4. Live schema of 2 tables
Đọc information_schema.columns (đủ data_type, is_nullable, column_default, is_generated, generation_expression, is_identity) — 17 + 23 = 40 cột.
public.sua_re_khai_niem_nhap (concept):
| Cột | Type | Nullable | Default | Ghi chú |
|---|---|---|---|---|
| id | bigint | NO | — | IDENTITY ALWAYS — không insert |
| concept_key | text | NO | — | NOT NULL không default, unique |
| ten | text | NO | — | NOT NULL không default |
| concept_kind | text | NO | — | NOT NULL không default (không có trong danh sách dự kiến của đề — schema thật thắng) |
| mo_ta | text | NO | — | NOT NULL không default — xác nhận nghi vấn của đề |
| ranh_gioi | text | YES | — | cột boundary thật |
| aliases | jsonb | NO | '[]'::jsonb |
|
| match_policy | text | NO | 'auto' |
|
| status | text | NO | 'draft' |
có default → muốn active phải set tường minh |
| note, first_seen_ui_id/raw_label/scan_id, first_seen_usage_id, contract_ref, promoted_at | — | YES | — | |
| date_created | timestamptz | NO | now() |
không insert |
KHÔNG có cột canonical_label, KHÔNG có boundary, KHÔNG có near_concepts ở bảng concept — SQL không dùng.
public.sua_re_ui_khai_niem_nhap (usage):
| Cột | Type | Nullable | Default | Ghi chú |
|---|---|---|---|---|
| id | bigint | NO | — | IDENTITY ALWAYS |
| item_key, slot_key, ui_id, scan_id, raw_label, purpose, location_anchor, dedupe_key | text | NO | — | NOT NULL không default — INSERT phải điền đủ 8 cột này |
| ui_file, location | text | YES | — | |
| scan_at | timestamptz | NO | now() |
không insert |
| is_current | boolean | NO | true |
|
| anchor_quality | text | NO | 'strong' |
|
| concept_id, owner_concept_id | bigint | YES | — | |
| near_concepts | jsonb | NO | '[]'::jsonb |
|
| match_status | text | YES | — | GENERATED ALWAYS: CASE concept_id NOT NULL→'matched'; dedupe_key LIKE 'review.%'→'review'; LIKE 'candidate.%'→'candidate'; ELSE 'pending' — không được INSERT/UPDATE |
| owner_decision, decision_note, decision_by, decision_at | — | YES | — | |
| date_created | timestamptz | NO | now() |
không insert |
5. Current time-related concepts
field.so_phut (id=5, full row):
- ten:
Số phút thực hiện; concept_kind:field; status: active; match_policy: auto; aliases["min","phút","thời gian thực hiện"]; note/first_seen_*/contract_ref/promoted_at NULL. - mo_ta:
Thời lượng ước tính của MỘT task, đơn vị phút.→ ĐÃ hẹp đúng nghĩa từng task — KHÔNG sửa mo_ta (đúng kỳ vọng phản biện). - ranh_gioi:
KHÔNG phải tổng phút của quy trình (giá trị TÍNH từ các task, không phải khái niệm riêng).→ cái sai chính nằm ở đây (đúng kỳ vọng phản biện): câu "không phải khái niệm riêng" chặn tổng phút cộng dồn thành concept riêng, trong khi usage id=13 (tổng phút) đang phải trỏ nhờ field.so_phut.
6. Current time-related usage
Filter: concept_key='field.so_phut' OR raw_label/purpose ILIKE %phút%/%thời lượng%/%tổng% OR location/anchor ILIKE %qv-tot% → 5 dòng:
| id | cur | slot_key (rút gọn) | scan_id | raw_label | dedupe_key | concept | status | decision | classification |
|---|---|---|---|---|---|---|---|---|---|
| 7 | ✔ | …items[].n | scan_0 | Tên việc (task) | task | task | matched | — | KHÔNG phải giá trị thời gian (lọt filter do chữ "phút" trong purpose) — không đụng |
| 11 | ✘ | …items[].min | scan_0 | Số phút của task | field.so_phut | field.so_phut | matched | — | task_duration_minutes (history G1-5) — giữ nguyên |
| 12 | ✔ | …text_marker:Số phút | scan_0 | Cột Số phút (ma trận qv) | field.so_phut | field.so_phut | matched | — | task_duration_minutes (cột render phút mỗi task) — giữ field.so_phut |
| 13 | ✔ | …code_marker:qv-tot | scan_0 | Tổng phút (dòng tổng) | field.so_phut | field.so_phut | matched | NULL | computed_total_task_minutes — TARGET remap |
| 31 | ✔ | …items[].min | scan_g1_5_demo_001 | Thời lượng task (phút) | field.so_phut | field.so_phut | matched | — | task_duration_minutes (slot hiện hành) — giữ field.so_phut |
- manual_total_process_duration: KHÔNG có usage nào → chỉ backlog, không tạo concept/usage trong G2-1A.
- id=13 là dòng computed_total duy nhất → không HOLD_TARGET_NOT_UNIQUE.
7. Target id=13
Điều kiện target: id=13 ✓; is_current=true ✓; match_status=matched ✓; concept_key=field.so_phut ✓; owner_decision IS NULL ✓; raw_label "Tổng phút (dòng tổng)" + purpose "Tổng thời lượng cả quy trình — giá trị TÍNH từ các task." + location_anchor code_marker:qv-tot thể hiện tổng phút cộng dồn ✓; không phải task duration ✓; không phải 24/25/30 ✓.
Full pre-state (lưu để render guard):
- item_key
master-list-quy-trinh-v1::code_marker:qv-tot::scan_0; slot_keymaster-list-quy-trinh-v1::code_marker:qv-tot; ui_idmaster-list-quy-trinh-v1; ui_filemaster-list.js; scan_idscan_0; scan_at = date_created = 2026-07-07 08:18:04+00; is_current true; raw_labelTổng phút (dòng tổng); purposeTổng thời lượng cả quy trình — giá trị TÍNH từ các task.; locationmaster-list.js · qv-tot; location_anchorcode_marker:qv-tot; anchor_quality strong; dedupe_keyfield.so_phut; concept_id 5; owner_concept_id NULL; near_concepts[]; match_status matched; owner_decision/decision_note/decision_by/decision_at NULL.
Pre-check bổ sung: item_key mới …::scan_g2_1_time_concept_001 và scan_id mới chưa tồn tại (SELECT = 0 rows).
8. Proposed delta
- create
field.tong_phut_congdon— kind field, ten "Tổng phút cộng dồn", mo_ta "Tổng thời lượng tính toán bằng cách cộng thời lượng các task trong một nhiệm vụ/quy trình, đơn vị phút.", ranh_gioi "Đây là giá trị tính toán ở cấp nhiệm vụ/quy trình; không phải thời lượng của từng task và không phải tổng thời gian quy trình nhập tay.", aliases 5 mục, status active tường minh, match_policy để default 'auto'. - update ranh_gioi
field.so_phut→ "Thời lượng của MỘT task riêng lẻ, đơn vị phút. Không dùng cho tổng phút cộng dồn từ nhiều task, và không dùng cho tổng thời gian quy trình nhập tay." — guard nguyên văn mo_ta + ranh_gioi cũ; không sửa mo_ta. - remap id=13 bằng SR-SUA — UPDATE id=13 current=false (10 guard) + INSERT dòng mới cùng slot_key, scan_id
scan_g2_1_time_concept_001, dedupe_key đổi thànhfield.tong_phut_congdon(dedupe_key cũ là concept key), concept_id qua subquery, giữ nguyên raw_label/purpose/location/anchor/near_concepts, 4 cột decision NULL, không insert match_status/date_created/scan_at. - defer
field.tong_thoigian_nhaptay— chưa có usage; chỉ backlog, bài riêng.
9. Change-scope
- Path:
/opt/incomex/docs/mcp-writes/sua-re/change-scope/g2-1-time-concept-delta.jsonl - sha256:
b7133a7d82296be3cd311a36b6f31dc14f0c9432081ae2086d63c14a378cb39f(4398 B, xác nhận local shasum + VPS sha256sum) - 4 object JSONL hợp lệ: 1
meta+ 3 action đúng danh sách cho phép (create_concept,update_boundary,remap_usage). Không có patch_ui_source / rescan / create field.tong_thoigian_nhaptay / modify id 24/25/30. - JSONL mô tả quyết định, không phải nguồn apply tự động.
- Thư mục
sua-re/change-scopemới tạo (chown 10001:10001, chmod 2775 — pattern G1).
10. Golden SQL
- Path:
/opt/incomex/docs/mcp-writes/sua-re/golden/concept-delta-time-values-g2-1.golden.sql - sha256:
23ced9a4cc0e6eeffa8c73233d824584aed9a82849bb50d9d1278dcb5e0478c0(6440 B, xác nhận 2 phía) - Đúng 4 statement write theo thứ tự: INSERT concept → UPDATE ranh_gioi → UPDATE usage 13 current=false → INSERT usage mới. Kỳ vọng output:
INSERT 0 1/UPDATE 1/UPDATE 1/INSERT 0 1. - Không BEGIN/COMMIT (gate psql -1 tự bọc). Không ON CONFLICT, không DDL, không DELETE, không ghi match_status (chỉ đọc trong WHERE guard), không nhắc id 24/25/30, không tạo concept type-3.
- Fail-closed: unique
concept_keychặn concept trùng; uniqueitem_key+ux_sruk_slot_currentchặn INSERT usage nếu statement (3) không hạ current cũ → transaction abort. - CHƯA copy vào
/opt/incomex/dot/sql/sua-re/(ls xác nhận chỉ 4 file G1), CHƯA append manifest (vẫn 8 dòng, 0 dòng g2), CHƯA apply (PG counts nguyên 13/31/30).
11. Self-check
| # | Mục | Kết quả |
|---|---|---|
| 1 | Đã đọc information_schema 2 bảng (40 cột, đủ nullable/default/generated/identity) | PASS |
| 2 | SQL không dùng cột không tồn tại (không canonical_label/boundary/near_concepts ở concept) | PASS |
| 3 | SQL điền đủ NOT NULL không default (concept 4 cột; usage 8 cột) | PASS |
| 4 | Concept insert có mo_ta (NOT NULL bắt buộc) | PASS |
| 5 | status='active' tường minh (default 'draft'; so_phut active) | PASS |
| 6 | Boundary update dùng đúng cột thật ranh_gioi |
PASS |
| 7 | Không sửa mo_ta (đã đúng nghĩa task; chỉ dùng trong WHERE guard) | PASS |
| 8 | SR-SUA: UPDATE old current=false trước, INSERT new current=true sau | PASS |
| 9 | item_key mới = slot_key ‖ '::' ‖ scan_g2_1_time_concept_001; pre-check 0 rows | PASS |
| 10 | Không INSERT/UPDATE match_status | PASS |
| 11 | Không copy SQL sang apply path | PASS |
| 12 | Không append manifest (8 dòng nguyên) | PASS |
| 13 | Không apply (0 dot-pg-atomic-apply; PG nguyên) | PASS |
| 14 | Không đụng/nhắc id 24/25/30 trong SQL | PASS |
| 15 | Không UI patch, không sửa shadow/preview | PASS |
| 16 | Không tạo concept type-3 (tong_thoigian_nhaptay chỉ xuất hiện trong text ranh giới + backlog defer) | PASS |
| 17 | G1 baseline còn nguyên (check trước render + re-check sau render) | PASS |
17/17 PASS.
12. Owner decisions needed before G2-1B
Owner cần chốt tường minh 4 điểm trước khi mở G2-1B (copy apply path + manifest + apply qua gate):
- Đồng ý tạo
field.tong_phut_congdon(ten/mo_ta/ranh_gioi/aliases như mục 8.1)? - Đồng ý text ranh_gioi mới của
field.so_phut(mục 8.2)? - Đồng ý remap usage id=13 bằng SR-SUA (id=13 thành history, dòng mới current trỏ concept mới)?
- Đồng ý defer
field.tong_thoigian_nhaptaysang bài riêng?
13. Caveat
- Shadow/preview files không phải UI source thật; G2-1A không đọc/không sửa chúng (dữ liệu lấy từ PG + KB).
- Chưa có scan/re-scan pipeline — scan_id
scan_g2_1_time_concept_001là scan-id thủ công cho delta ledger, như khuôn G1-5. - G2-1A chỉ ledger — dòng tổng phút trên UI thật không đổi gì; đây là sửa sổ khái niệm.
- Schema thật (information_schema) là nguồn cuối cùng — mọi cột trong SQL đã đối chiếu schema đọc 2026-07-07; nếu schema đổi trước G2-1B, phải re-check.
- Guard UPDATE (statement 2/3) không tự abort khi UPDATE 0 (transaction vẫn commit các statement khác) — verifier G2-1B bắt buộc đối chiếu 4 dòng affected-count với kỳ vọng
INSERT 0 1 / UPDATE 1 / UPDATE 1 / INSERT 0 1; INSERT (1)/(4) đã fail-closed bằng unique constraint +ux_sruk_slot_current. - Sau khi G2-1B apply thành công, sealed baseline G1 (concept 13/usage 31) sẽ lỗi thời theo thiết kế — phải tạo sealed baseline mới (đã ghi trong g1-final-proof mục 8).