Archived
E04 修到零被拒线,harness 补七刀:跨进程租约与广播桥、原子写、引用墙、对话区按序号排
活动侧(E04 2.1.0 → 2.1.9,I01 1.2.2): - 覆盖闭合成为机检:基座新增 distinct 读数,「计划盖住的客户数 = 候选行数」钉进 S3 收步 / S4 哨兵 / 放行 L2;人加的候选客户不再被整单无视 - 「关键人待识别」占位句式全链退役:查无联系人先发数据录入卡收人;契约新增 refersTo, 计划/回执的 contact_code 只许引用真实存在的联系人(安装期核引用目标) - 台账更新确认摆全落库面:客户档案/联系人档案两张落库预览(touched: 数据源, 正式现值 + 草稿叠加),可补改、可加行(自增主键由基座续号);姓名升必填 - 更新明细:update_key 位置键 + 「同一处只留一条」L2;依据写人话不带机器键; 标题旁不摆单号;判据与文案不夹字段名;行标识去掉单标识那一段 - 回执骨架 = 计划行数钉进 S3 收步与 S4 哨兵;重做分支不许删计划凑数 - 阶段刻度对齐文档 7 步;起单样例预填满 基座侧: - 两个后端连同一个库:task-claim 跨进程租约(迁移 0030)+ Postgres LISTEN/NOTIFY 广播桥;对话区按任务内记忆序号排,不按墙上时钟;并卡「刚说过话」按记忆序列判紧邻 - 多行 write 整批先验后写(dryRun),被拒 = 一行都没落 - 决策卡意见与本单草稿字面比对,归属以观察进轨迹(note-anchors) - 括号栈补「补闭括号」两形(少一个 } / 行对象没关直接跟下一行) - 件上加行:空着的自增主键直进续号,不从别的行借号;未落下的行点名回给前端 - 人答复落库那一刻就把 runtime 翻 running(task.wake),两块同帧变脸 - 试跑单可落真库(land_master,迁移 0031,默认开);数据域按活动分组; JSON 列不再是 [object Object];按钮键感 + 在办进度条 + 防抖 - 报价链 A1–A7 从系统卸载(只卸不删源码),种子只装 E04/I01 契约变更(api-report 已刷新):FieldDeclaration.distinct / refersTo, objectDeclaration.file,landMaster,unkeyed,assetFiles,ledgerByActivityRoute。 1700 测 / typecheck / lint / depcruise / api:check 绿。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEJX8Z7CHejvwmDQyPQuBX
This commit is contained in:
@@ -40,7 +40,7 @@ export const manifest: ActivityManifest = {
|
||||
identity: {
|
||||
activityId: ACTIVITY_ID,
|
||||
name: 'E04 · 关系覆盖与关键人经营',
|
||||
packageVersion: '2.0.9',
|
||||
packageVersion: '2.1.9',
|
||||
category: '客户关系经营',
|
||||
sdkVersion: '0.1.0-m5',
|
||||
checksum: 'dev-checksum-crm-relationship-coverage',
|
||||
@@ -185,6 +185,18 @@ export const manifest: ActivityManifest = {
|
||||
level: 'L2',
|
||||
predicate: `${D}_plan_rows > 0 and ${D}_plan_missing = 0`,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* **覆盖闭合**(2026-08-24 柴浩实测补):人核对后的候选清单是后续每一步的输入契约 ——
|
||||
* 他加的那家客户,计划里必须有它。两边都是基座数:计划里有几家不同客户
|
||||
* (`distinct`,声明在 plan.customer_code 上)= 候选清单几行(增删后现数)。
|
||||
* S3 的收步判据与 S4 的入场哨兵同一句 —— 这里是第二道墙,防的是绕过收步的路。
|
||||
*/
|
||||
key: 'plan-covers-scope',
|
||||
label: '每家确认纳入的候选客户都进了经营计划(含人核对时新增的,一家不落)',
|
||||
level: 'L2',
|
||||
predicate: `${D}_plan_distinct_customer_code = ${D}_candidate_rows`,
|
||||
},
|
||||
{
|
||||
key: 'receipt-matches-plan',
|
||||
label: '每条计划都收到执行回执,且完成状态、结果摘要、关键人变动均已填写',
|
||||
@@ -197,6 +209,13 @@ export const manifest: ActivityManifest = {
|
||||
level: 'L2',
|
||||
predicate: `${D}_ledger_update_rows > 0 and ${D}_ledger_update_missing = 0`,
|
||||
},
|
||||
{
|
||||
/* 2026-08-24:重做后过期的旧明细不许留 —— 同一处字段只能有一条更新 */
|
||||
key: 'no-duplicate-update',
|
||||
label: '同一处字段只留一条更新(重做后过期的旧记录已撤掉)',
|
||||
level: 'L2',
|
||||
predicate: `${D}_ledger_update_distinct_update_key = ${D}_ledger_update_rows`,
|
||||
},
|
||||
{
|
||||
key: 'no-missed-update',
|
||||
label: "每条「已完成」的执行回执至少有一条对应的台账更新(没有漏更)",
|
||||
@@ -218,6 +237,8 @@ export const manifest: ActivityManifest = {
|
||||
{ key: 'no-guess-contact', statement: '决策链节点对应哪位联系人不确定时不得臆断 —— 匹配不上就留空,那就是缺口' },
|
||||
{ key: 'no-skip-evidence', statement: '台账更新明细每条都要有回执依据,不得凭空推算写入主数据' },
|
||||
{ key: 'no-external-write', statement: '放行前不得触达外部系统 —— 触达世界的动作集中在放行那一刻' },
|
||||
/* 2026-08-24:模型给缺口节点自造过顺延引用码 + 占位人名 —— 计划里「有人」必须真的有人 */
|
||||
{ key: 'no-phantom-contact', statement: '计划与回执只许引用 customer.contact 已有的联系人编码与真人姓名;不得自造编码或以占位称呼顶格 —— 查无联系人先以数据录入卡收人' },
|
||||
],
|
||||
authorization: {
|
||||
discretion: [],
|
||||
@@ -263,9 +284,16 @@ export const manifest: ActivityManifest = {
|
||||
* 说明书让录入卡落什么,声明里就得有什么(物理列平台基线本就有,声明是权责面)。
|
||||
* 与 A1 的 name 声明并存(add-column 合并,同名同型不冲突)。
|
||||
*/
|
||||
{ name: 'name', type: 'text', primaryKey: false, masked: false, label: '客户名称' },
|
||||
{ name: 'industry', type: 'text', primaryKey: false, masked: false, label: '所属行业' },
|
||||
{ name: 'region', type: 'text', primaryKey: false, masked: false, label: '区域' },
|
||||
/*
|
||||
* name 必填(2026-08-24 柴浩实测:新客户档案落库连名字都是空的 —— 候选行里
|
||||
* 明明写着,模型没抄)。`customer_profile_missing` 本就在 S6 收步与放行哨兵里,
|
||||
* 标上它,「无名档案」从此进不了正式表;代价是碰过的客户行要把 name 照现值带上
|
||||
* (剧本写死)。industry/region 标建议填:AI 从来件与背景说明推得出就填,
|
||||
* 推不出留橘胶囊给人 —— 台账更新确认屏上现在改得了。
|
||||
*/
|
||||
{ name: 'name', type: 'text', primaryKey: false, masked: false, required: true, label: '客户名称' },
|
||||
{ name: 'industry', type: 'text', primaryKey: false, masked: false, expect: true, label: '所属行业' },
|
||||
{ name: 'region', type: 'text', primaryKey: false, masked: false, expect: true, label: '区域' },
|
||||
/*
|
||||
* L-02 文档明列的字段,权威维护者是尚未建成的 T02(客户建档评估) —— 平时
|
||||
* E04 不写它;唯一的例外是"新客户建立合作"这一刻,E04 代替不存在的 T02
|
||||
@@ -296,8 +324,14 @@ export const manifest: ActivityManifest = {
|
||||
* (静默退化成留空,不报错)。
|
||||
*/
|
||||
{ name: 'contact_code', type: 'text', primaryKey: true, masked: false, auto: true, label: '联系人编码' },
|
||||
/* 建档卡的联系人段会写的三列 —— 同上,声明即授权面;email 照平台口径标脱敏 */
|
||||
{ name: 'name', type: 'text', primaryKey: false, masked: false, label: '姓名' },
|
||||
/*
|
||||
* 建档卡的联系人段会写的三列 —— 同上,声明即授权面;email 照平台口径标脱敏。
|
||||
* name 必填(2026-08-24 柴浩实测:早前一轮模型替「计划要经营的岗位」凭空建了
|
||||
* 两条无名联系人档,人名职务全空、却标着关键人/亲密度3 —— 那不是联系人,是把
|
||||
* 计划里的节点冒充成了人)。`customer_contact_missing` 本就在收步与放行哨兵里,
|
||||
* 标上它,无名建档从此进不了正式表;代价是碰过的联系人行把 name 照现值带上。
|
||||
*/
|
||||
{ name: 'name', type: 'text', primaryKey: false, masked: false, required: true, label: '姓名' },
|
||||
{ name: 'title', type: 'text', primaryKey: false, masked: false, label: '职务' },
|
||||
{ name: 'email', type: 'text', primaryKey: false, masked: true, label: '邮箱' },
|
||||
{ name: 'role', type: 'text', primaryKey: false, masked: false, expect: true, label: '角色' },
|
||||
@@ -346,8 +380,21 @@ export const manifest: ActivityManifest = {
|
||||
label: '关键人经营计划',
|
||||
fields: [
|
||||
{ name: 'round_ref', type: 'text', primaryKey: true, masked: false, label: '覆盖轮次编号' },
|
||||
{ name: 'contact_code', type: 'text', primaryKey: true, masked: false, label: '联系人编码' },
|
||||
{ name: 'customer_code', type: 'text', primaryKey: false, masked: false, required: true, label: '客户编码' },
|
||||
/*
|
||||
* `refersTo` —— 计划只许指向真实存在的联系人(2026-08-24,措辞治不了的结构治):
|
||||
* 模型三次给缺口节点自造顺延引用码 + 占位人名,反例描述/说明书纪律/禁令
|
||||
* 全拦不住;现在基座在写入那一刻查 customer.contact(正式 + 本单草稿),
|
||||
* 查无此码当场拒并指路(先发数据录入卡收人)。receipt 同款。
|
||||
*/
|
||||
{ name: 'contact_code', type: 'text', primaryKey: true, masked: false, refersTo: 'customer.contact.contact_code', label: '联系人编码' },
|
||||
/*
|
||||
* `distinct: true` —— 基座数「计划里有几家不同客户」(`crm_coverage_plan_distinct_customer_code`)。
|
||||
* 它是覆盖闭合判据的落点(2026-08-24 柴浩实测:人在覆盖范围确认卡上加了一家客户,
|
||||
* 行落进了台账,而计划/回执/收口把它从头无视到尾 —— 收步与放行只数「计划有没有行」,
|
||||
* 「盖没盖住每一家候选」没有任何一个基座数说得出来)。计划行数 ≠ 客户数
|
||||
* (一家客户几位关键人就几行),所以必须另数这一个。
|
||||
*/
|
||||
{ name: 'customer_code', type: 'text', primaryKey: false, masked: false, required: true, distinct: true, label: '客户编码' },
|
||||
{ name: 'customer_name', type: 'text', primaryKey: false, masked: false, expect: true, label: '客户名称' },
|
||||
{ name: 'contact_name', type: 'text', primaryKey: false, masked: false, expect: true, label: '联系人姓名' },
|
||||
{ name: 'action', type: 'text', primaryKey: false, masked: false, required: true, label: '建议动作' },
|
||||
@@ -385,7 +432,7 @@ export const manifest: ActivityManifest = {
|
||||
label: '经营计划执行回执',
|
||||
fields: [
|
||||
{ name: 'round_ref', type: 'text', primaryKey: true, masked: false, label: '覆盖轮次编号' },
|
||||
{ name: 'contact_code', type: 'text', primaryKey: true, masked: false, label: '联系人编码(与计划一一对应)' },
|
||||
{ name: 'contact_code', type: 'text', primaryKey: true, masked: false, refersTo: 'customer.contact.contact_code', label: '联系人编码(与计划一一对应)' },
|
||||
{ name: 'customer_code', type: 'text', primaryKey: false, masked: false, expect: true, label: '客户编码' },
|
||||
/* 目标件的「对象」列长「AvtoKom · 产品 VP」—— 客户名与人名都要在,S3 从计划抄 */
|
||||
{ name: 'customer_name', type: 'text', primaryKey: false, masked: false, label: '客户名称(承继自计划,只读展示)' },
|
||||
@@ -430,7 +477,15 @@ export const manifest: ActivityManifest = {
|
||||
{ name: 'field_label', type: 'text', primaryKey: false, masked: false, required: true, label: '字段(人读列名)' },
|
||||
{ name: 'before_value', type: 'text', primaryKey: false, masked: false, required: true, label: '更新前(无值写"(无)")' },
|
||||
{ name: 'after_value', type: 'text', primaryKey: false, masked: false, required: true, label: '更新后' },
|
||||
{ name: 'evidence_ref', type: 'text', primaryKey: false, masked: false, required: true, label: '依据(引用具体回执事实)' },
|
||||
{ name: 'evidence_ref', type: 'text', primaryKey: false, masked: false, required: true, label: '依据(用人话引用回执事实)' },
|
||||
/*
|
||||
* 更新位置键(2026-08-24 用户:「重做后老的变更记录应该删除」):主键是序号,
|
||||
* 同一处字段(同一张表·同一客户·同一联系人·同一字段)重做时若新开一行,旧行就留在
|
||||
* 明细里骗人 —— SQ-0031 的覆盖度一度同时挂着 50→50 与 50→100 两条。
|
||||
* 这一列由模型按「台账地址|客户编码|联系人编码|字段」拼,`distinct` 让基座数
|
||||
* 「有几处不同位置」;判据钉 distinct = rows —— 同一处只留一条。
|
||||
*/
|
||||
{ name: 'update_key', type: 'text', primaryKey: false, masked: false, required: true, distinct: true, label: '更新位置键(台账地址|客户|联系人|字段)' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user