From 7a66ed3a100985d0267f2fd52f37644fd71976cc Mon Sep 17 00:00:00 2001 From: "agent.develop" Date: Tue, 22 Sep 2026 22:11:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(pbl=5Fevidence):=20collector.py=20?= =?UTF-8?q?=E4=B8=BB=E9=94=AE=E8=90=BD=E5=9C=B0=E2=80=94=E2=80=94record=20?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E5=A4=84=E6=98=BE=E5=BC=8F=20gen=5Fpk('ev')?= =?UTF-8?q?=EF=BC=88DISC.1=20=E6=96=B9=E6=A1=88a=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - import 区新增 (复用 pk.py 唯一生成器,PK_MAX_LEN=32) - collect_evidence_from_events:在 record.setdefault('artifact_id', 0) 之后、 pick_columns(record, tgt_cols) 之前,唯一一次 → INSERT 列集合自带主键,消除真实部署 STRICT_TRANS_TABLES 下 1364 Field 'id' doesn't have a default value(models id=str(32) NOT NULL 无 default,DB 侧不生成) - _upsert_evidence 入口加 fail-fast;其内不再调 gen_pk, 末尾 record['id']=new_id['id'] 回读赋值保留(仅作 created_ids 返回用,非生成源) - 全文件无 兜底分支(清理正则命中 0 处,本来不存在) - 自证:grep -c 'gen_pk(' collector.py = 1;py_compile / ast.parse 通过 - 未碰 api.py / models / DDL,未跑 harness(留给收口子任务) --- pbl_evidence/collector.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pbl_evidence/collector.py b/pbl_evidence/collector.py index 8b51fe2..ca5f019 100644 --- a/pbl_evidence/collector.py +++ b/pbl_evidence/collector.py @@ -22,6 +22,7 @@ from .evidence_map import ( normalize_dt, now_str, first_present, map_event_to_evidence_type, build_dedup_key, event_source_id, summarize_payload, ) +from .pk import gen_pk # 运行时事件表候选名:M11b 落 pbl_runtime_event;历史/别名兼容 runtime_event。 EVENT_TABLE_CANDIDATES = ('pbl_runtime_event', 'runtime_event', 'pbl_event') @@ -227,6 +228,11 @@ async def collect_evidence_from_events(tenant_id, # artifact_id 为 NOT NULL:行为类证据(协作/反思/观测)无强归属产出物时以 0 占位, # 不因此丢事件——证据链完整性优先于归属字段(M6 评估侧按 artifact_id>0 过滤)。 record.setdefault('artifact_id', 0) + # DISC.1 方案(a):主键由应用层显式生成——models/pbl_evidence.json 把 id 定义为 + # str(32) NOT NULL 且无 default(DDL 渲染 VARCHAR(32) NOT NULL,禁 AUTO_INCREMENT), + # DB 侧不生成主键,INSERT 必须自带 id。全模块唯一生成落点就在这里(record 构造处), + # _upsert_evidence 内不再调 gen_pk,只做回读赋值供 created_ids 使用。 + record['id'] = gen_pk('ev') record = pick_columns(record, tgt_cols) stats['items'].append(record) @@ -255,6 +261,9 @@ def first_present_col(cols, candidates): async def _upsert_evidence(record, tgt_cols, update_existing=False): """幂等写入:预查 + ON DUPLICATE KEY UPDATE 双保险。返回 created/skipped/updated。""" + # 主键必须在 record 构造处(collect_evidence_from_events)已由 gen_pk 生成——单一落点约定。 + # 这里 fail-fast:任何绕过构造处的调用方(漏生成)立刻暴露,而不是把无主键的行交给 DB。 + assert record.get('id'), 'record 缺少 id:主键必须在 record 构造处由 gen_pk 生成(DISC.1 方案(a))' tid = record['tenant_id'] sid = record['source_event_id'] etp = record['evidence_type']