forked from ChaiHao/BPOS-MVP
人手改的那一手真正落得下去;界面不撒谎那几处补齐
手改是**兜 AI 的错**的那一手 —— 这一轮把它从「摆在那儿但落不了地」做成真的: 件上就地改 · 保存**按地址收**,不看当下那张卡:载荷从前借道工单的 `blocks[i]` 取列名, 于是熔断卡(没有 blocks)在屏上时,人补的那一格一个字都送不出去 —— 而他要补的恰恰是把这一单卡住的那个必填格。授权面改由活动清单的台账声明把关。 · **能增删行**:错不止「这一格填错了」,还有「这一行不该在」与「漏了一行」。 删挂记号不当场抹掉(看得见、可后悔),且**删要说出来**(`drops`)—— 「没回传就是删了」会把一次不完整的回传变成一次删表。 · **必填没填按不下提交**:与放行门 L1 同一个数同一套算法;闸上摆出差在哪一行哪一格。 · 只写真改了的那几行 —— 改一格却留「修订 4 行」的痕,那句话是假的。 判据与门 · 裁量判据带谓词时**谓词说了算**:「选填缺口已补齐」基座数得出来, 人填好的目标价它照样判「客户未提供」的毛病由此消掉。 · 验收卡判据**读时现算** —— 人在成果件上补一格,判据跟着变。 · 放行门认「**办完了没有**」不认「有人写过」:从前写个 `false` 就把门推开, 于是一单没打标就进了放行门。三个数全由基座现数。 · 拒回把「活没干完」说成「数或行对不上」的毛病:判据点名的表一行都没写时直说那一步没办。 **指向两扇打不开的门,比不指还糟。** 界面不撒谎 · 日志只有三色:负责人绿 · 智能体蓝 · 系统灰(归侧五种是度量的分法,不是给人看的)。 · 验收收口答两件事:落了什么(按**交付物**点名,一份成果的几张表并成一行)、 往哪儿去(转出哪一口、带过去哪些字段);一个口都没发就直说到此为止。 · 签完到收尾之间那一段有自己的话「字已签下,正在落地」—— 中间态本来就该说出来,只是要说对。 · 消息不再被内部事件刷屏:只有从通道进来的件才谈得上「无人认领」。 · 建客户公司与联系人**一次确认落两行**;联系人编码自增不问人;卡面摆表的人读名。 A1 三案例端到端全 released:全 A 类直通 12 拍 / 客户点名跳一条 10 拍 / 新客户缺必填 14 拍。 五道门禁全绿(971 passed)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
-- 工具未命中转人(2026-07-30,§6.2):**人是工具的一种实现**。
|
||||
-- 系统里没有这件工具(无契约,或有契约无实现)时,不报错、不空转 —— 开一张执行卡请人做,
|
||||
-- 人填回的表单值就是这次调用的出参,下一拍 invoke 直接取到。
|
||||
|
||||
-- 面向人的作业指导段:与面向 AI 的 description 分开写,随包版本冻结。
|
||||
alter table sys.tool add column guide jsonb;
|
||||
|
||||
create table sys.tool_handoff (
|
||||
id text primary key,
|
||||
task_id text not null,
|
||||
tool text not null,
|
||||
-- 内容地址(工具 + 入参指纹):同一次调用只问人一次,重问拿同一份答案。
|
||||
-- 没有它,Loop 每拍都会为同一件事再发一张卡。
|
||||
call_key text not null,
|
||||
input jsonb not null,
|
||||
work_order_id text not null,
|
||||
state text not null default 'pending',
|
||||
-- 人填回的值 = 工具出参
|
||||
output jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
answered_at timestamptz
|
||||
);
|
||||
create unique index tool_handoff_call_key on sys.tool_handoff (task_id, call_key);
|
||||
create index tool_handoff_order_idx on sys.tool_handoff (work_order_id);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- 任务起单来源(2026-07-30):这一单是从哪儿起的 —— 流程节点 / 登记直起 / **设计台试跑**。
|
||||
-- 试跑单必须认得出来:「仿真不是生产,试跑留下的东西不该在库里、在别人工作台上过夜」,
|
||||
-- 而工作流那侧靠 source->>'ref' = 'testbed' 认,任务这侧从前没有对应的记号 ——
|
||||
-- 于是「试跑一个活动」(不挂工作流)起出来的单与登记直起单长得一模一样,拔不掉也认不出。
|
||||
alter table sys.task add column origin text;
|
||||
create index task_origin_idx on sys.task (origin) where origin is not null;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- 试跑日志(2026-07-30):**运行数据不过夜,观测记录要留下**。
|
||||
--
|
||||
-- 「停止仿真 = 连根拔掉」这条不变 —— 试跑起的是真任务,不该在别人工作台上过夜。
|
||||
-- 但拔掉的同时把这一单的**观测快照**存下来:逐拍轨迹、写下的台账草稿、发过的卡、
|
||||
-- 预算读数与终态。开发活动是反复试的活,「上一版跑了几拍、卡在哪一步」正是
|
||||
-- 要拿来比对的东西;拔干净等于每改一次就把上一次的账一并烧了。
|
||||
--
|
||||
-- 存的是**快照不是外键**:原任务早已不存在,这里的 task_id 只作编号回溯。
|
||||
create table sys.testbed_run (
|
||||
id text primary key,
|
||||
-- 两种试法:activity(单活动)/ package(整条流程包)
|
||||
kind text not null,
|
||||
subject text not null,
|
||||
-- 试的是谁:activityId 或 packageId
|
||||
target text not null,
|
||||
task_id text,
|
||||
workflow_id text,
|
||||
-- 终态名;null = 人中途停的(那也是一次值得留的账)
|
||||
terminal text,
|
||||
reason text,
|
||||
used jsonb not null default '{}'::jsonb,
|
||||
caps jsonb not null default '{}'::jsonb,
|
||||
trail jsonb not null default '[]'::jsonb,
|
||||
drafts jsonb not null default '[]'::jsonb,
|
||||
cards jsonb not null default '[]'::jsonb,
|
||||
started_at timestamptz,
|
||||
archived_at timestamptz not null default now()
|
||||
);
|
||||
create index testbed_run_time_idx on sys.testbed_run (archived_at desc);
|
||||
@@ -0,0 +1,16 @@
|
||||
-- 上传件 —— 附件要能真正进活动,文件本身就得留着。
|
||||
--
|
||||
-- 存两样:**原字节**(留得住才叫「真实的文件」,人回头点得开)与**读出来的文本**
|
||||
-- (活动那一侧读得懂的只有文字)。读不出文本的类型 text 留空、note 说明为什么。
|
||||
create table sys.upload (
|
||||
id text primary key,
|
||||
name text not null,
|
||||
content_type text not null,
|
||||
size integer not null,
|
||||
bytes bytea not null,
|
||||
text text,
|
||||
note text not null default '',
|
||||
uploaded_by text,
|
||||
uploaded_at timestamptz not null default now()
|
||||
);
|
||||
create index upload_time_idx on sys.upload (uploaded_at desc);
|
||||
@@ -0,0 +1,20 @@
|
||||
-- 沟通记录 —— 一单往来的**原件存档**。
|
||||
--
|
||||
-- 「跟客户、供应商往来的邮件和消息按单归档」这件事,从前只有一屏诚实的空态:
|
||||
-- 数据在 channel / event 里确有,按单的投影一直没做。现在有了落点。
|
||||
--
|
||||
-- 进来的那一封(direction='in')是**开案的那份料** —— 活动的入参就是它;
|
||||
-- 出去的(direction='out')是放行后系统真发出去的件。两向同表,按时刻排。
|
||||
create table sys.task_comm (
|
||||
id text primary key,
|
||||
task_id text not null,
|
||||
at timestamptz not null default now(),
|
||||
direction text not null, -- 'in' | 'out'
|
||||
channel text not null, -- 'mail' | 'im' | 'phone' | …
|
||||
party text not null default '',-- 对方(邮箱 / 账号 / 号码)
|
||||
subject text not null default '',
|
||||
body text not null default '',
|
||||
attachments jsonb not null default '[]'::jsonb,
|
||||
note text not null default ''
|
||||
);
|
||||
create index task_comm_task_idx on sys.task_comm (task_id, at);
|
||||
@@ -0,0 +1,22 @@
|
||||
-- 台账对象的**性质**落成一等事实(2026-07-31)。
|
||||
--
|
||||
-- 起因是一次自找的性能退化:治理台「数据域」那一屏要按性质(单据/主数据/派生)分区,
|
||||
-- 而性质只写在活动清单里 —— 于是路由每次请求都去把 12 个活动的清单捞回来重建一遍。
|
||||
-- `manifestOf` 是 `select *`:拉该活动**所有版本**的清单加产物,再整份 zod parse。
|
||||
-- 光 quote-intake 一个就是 26 个版本、798 kB,一次请求约 1.5 MB JSON ——
|
||||
-- 热连接 73ms,并发八次就掉到 350ms,而慢请求占住浏览器连接,点别的页跟着排队。
|
||||
--
|
||||
-- 物化的东西就该记在物化侧:表建出来的那一刻性质就定了,不必每次去清单里问。
|
||||
-- 与人读名同一个道理 —— 那个落在表注释上,这个落在这张小表上
|
||||
-- (性质不是列属性,注释挂不上,故单立一张)。
|
||||
--
|
||||
-- `__` 前缀:与 `ledger.__draft` 同一约定,`listObjects` 按前缀把它排除在数据对象之外。
|
||||
create table if not exists ledger.__object_meta (
|
||||
domain text not null,
|
||||
object text not null,
|
||||
kind text not null default 'record',
|
||||
case_key text,
|
||||
primary key (domain, object)
|
||||
);
|
||||
|
||||
comment on table ledger.__object_meta is '台账对象性质:record 单据 / master 主数据 / derived 派生';
|
||||
@@ -0,0 +1,11 @@
|
||||
-- 沟通记录的**未读**(2026-07-31 用户定)。
|
||||
--
|
||||
-- 一封客户来件落进沟通记录之后,人是"看没看过"这件事从前没人记 ——
|
||||
-- 于是这一屏永远一个样:新到的信和三天前的信长得一模一样,人只能靠时间戳自己比。
|
||||
--
|
||||
-- `read_at` 为空 = 未读。**不由打开页面自动清**:自动清等于替人宣布"你看过了",
|
||||
-- 而他可能只是路过那个页签。用户定的口径是**按钮说了算** ——
|
||||
-- 标记已读/未读都由人按,气泡计数跟着那一下走。
|
||||
alter table sys.task_comm add column if not exists read_at timestamptz;
|
||||
|
||||
comment on column sys.task_comm.read_at is '读过的时刻;空 = 未读(只由人按按钮改,不随打开页面自动清)';
|
||||
@@ -0,0 +1,11 @@
|
||||
-- 记住**这一帧用的是哪张模版**(2026-08-01)。
|
||||
--
|
||||
-- 件是**投影**,而从前只存渲染好的 HTML —— 那一帧就成了快照。
|
||||
-- 人在件上改完几格按保存,只读那份跟着变了(那是他自己敲的),
|
||||
-- 而由数据算出来的东西(类徽 A/B/C、分布条、结论横幅那条去向)全停在渲染那一刻:
|
||||
-- 屏上一半新一半旧。**那不是没更新,是界面在撒谎。**
|
||||
--
|
||||
-- 存下模版名,才重得出来:数据一变,同一张模版用新数据再渲一遍(见 `views.repush`)。
|
||||
alter table sys.task_view add column if not exists template text;
|
||||
|
||||
comment on column sys.task_view.template is '这一帧用的模版名 —— 数据变了要按同一张重渲(件是投影,不是快照)';
|
||||
@@ -148,6 +148,62 @@
|
||||
"when": 1785130115173,
|
||||
"tag": "0020_paradigm_retired",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"version": "7",
|
||||
"when": 1785130116173,
|
||||
"tag": "0021_tool_handoff",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"version": "7",
|
||||
"when": 1785130117173,
|
||||
"tag": "0022_task_origin",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"version": "7",
|
||||
"when": 1785130118173,
|
||||
"tag": "0023_testbed_log",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"version": "7",
|
||||
"when": 1785130118174,
|
||||
"tag": "0024_upload",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"version": "7",
|
||||
"when": 1785130118175,
|
||||
"tag": "0025_task_comm",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"version": "7",
|
||||
"when": 1785130119175,
|
||||
"tag": "0026_object_meta",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"version": "7",
|
||||
"when": 1785130120175,
|
||||
"tag": "0027_comm_read",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"version": "7",
|
||||
"when": 1785130120176,
|
||||
"tag": "0028_view_template",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user