Commit Graph
91 Commits
Author SHA1 Message Date
ChaiHaoandClaude Opus 5 545103af1b A6 三个去向改选择组,「恰选一口」全链打通 —— 整条流第一次真正跑完
G4 是整条流最后的断点:三个去向写成了必交口里的 outcome 字段 + selective: [],
而引擎只在选择组恰发一口时才注入 outcome —— 结构上永远没有判据。

## 四层贯通

① 契约:验收工单加 `portChoice`(组名 + 可选出口)。draft 是 Omit 透传,human-tool 零改动。
② A6 声明:outcome 移出必交口,三个去向成选择组(won/revise/lost 各一口带人读说明)。
   契约 0.2.0、包版 0.7.0。G4 三条边一行没改 —— outcome 由放行选口注入落地事实。
③ 引擎:验收发卡时从活动契约现读选择组上卡(组是契约的事实,不在步的卡面里声明)。
④ 前端 AcceptForm:选择组渲染为必选单选,不选「通过」不亮;选中的口随放行回传。

## 「恰选一口」拦在收单,不拦在落地 —— 拦错位置实测翻过车

第一版把 validateSelection 放进 release.land:回传是**同步收单**(200 = 收到裁决),
落地在推进器里**异步**跑 —— 拦晚了就是「工单已答完、任务卡死、推进器循环报错」(实测)。
改到 checkWorkOrderReply(与「驳回必附意见」同族的收单规矩):工单投影自带 portChoice,
放行回传缺口/口不在组内 → 400 同步拒收,工单还活着,人补选就是。
land 里的 validateSelection 留作兜底 —— 这条从 contracts 导出以来从未被执行的不变量,
现在两个岗位都有了。

## 实测四连

  不选口通过 → 400「放行前先选『议价结果』」,工单未被吃掉
  选 won    → end_won released,流 completed —— **整条流第一次真正跑完**
  选 revise → A4#2 重开新实例(A4#1 留痕不动)
  选 lost   → A7 情报归档 → end_arch released,流 completed
  全程 route-dead-end 事件 0 条

typecheck ✓ lint ✓ depcruise ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 16:37:59 +08:00
ChaiHaoandClaude Opus 5 894769e2ca 流程包详情整页 UI 梳理:一套图纸语言,贴边清零
量了一遍页面,问题四处,全修:

① **属性卡是混进来的第二种风格**(治理台圆角卡),同格栅其它三块都是图纸风。
   改为图纸卡:外壳同纸同影同角,题头入族 ——
   「流程包 · 版本」「流程图 · 顺序」「异常 · 看板」「节点 · 属性」四张两字·两字对仗;
   题头右侧 = 状态字 + 保存芯片(与「新建」「编辑」同款);
   内部小卡与节点条也入图纸语言(方角细线、mono 小字距题头),等高 250、超高内滚。

② **属性卡内部三处贴死**(题头↕0节点条↕0属性格↕0按钮):
   内容区统一 12px 呼吸;保存从底部挪进题头,不用滚到底找按钮。

③ **异常板被 stretch 拉到 916px**,三条异常配一片空白:改为高度随内容
   (实测 916 → 150),行顶仍与属性卡对齐。

④ 2px 的 margin hack 删了,row2 两卡顶严格同线(840 = 840)。

typecheck ✓ lint ✓ depcruise ✓ api:check ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 16:10:57 +08:00
ChaiHaoandClaude Opus 5 ba5f65e685 画图不检查,激活才查完整 —— 保存 bug 的根治 + 异常看板
你存不了图的根因:保存跑闭合校验,而画图必然经过不完整的中间态
(节点没接完边、活动没安装)—— 画到一半就 412 卡死。实测同一份图:
改前 412 拒存;改后存为未生效的新版,报告随行。

## 模型改成三段

  画图 = 只创建节点和边,图上真正生效可编辑的只有**名字**(双击不再出岗位一栏;
        边上的字是辅助阅读的注记;岗位/判据/映射这些**闭环要素在节点属性里决定**;
        分配到人是运营的事,设计侧不碰)
  保存 = 不检查、不生效:恒存为新版本号,谁也伤不着 —— 因此不设确认卡,直接存;
        任何版本都可编辑(在旧版上改 = 以旧版为底另起一版)
  激活 = 完整性闸:不闭合 412 拦下并点名缺什么;过了即独占生效

## 异常看板(左,与版本卡同列同风)

画图不拦,看板替你盯着:逐条列这一版缺什么,**点一条定位到那个节点的属性**;
零异常时给空占位说「可以激活」。版本行的「激活」按钮按闭合灰显 ——
不闭合点不了,亮了才能上线。实测:v4 两条异常全列出、激活灰;闭合的 v2/v1 亮。

## 顺手修一个画布盲区

packageToGraph 以手绘存证为呈现真相,**语义里有、存证里没有的节点画布看不见**:
异常看板指着一个图上不存在的节点,点了也定位不到(实测:API 直存的包新增节点后
picker 里根本没有它)。补画:缺席节点按 60px 一档排在图纸下缘 —— 位置丑没关系,
看得见才能修。实测点异常 → 选中 A8 → 五张属性小卡弹出。

## 布局照你定的

row2 = 异常看板(1/3,与版本卡对齐)+ 节点属性卡(2/3,与流程图同宽);
属性卡内部小卡**等高 250px**,输入/输出超高的内容自己滚(实测五张全 250)。

种子改为保存后显式激活;NotClosedError 文案「不得保存」→「不得激活」。

typecheck ✓ lint ✓ depcruise ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 15:52:45 +08:00
ChaiHaoandClaude Opus 5 2a89e9feda 版本卡题头与图题**同一组几何数** —— 标题、按钮、底线三线全平
上一版只对了底线,标题被顶在高盒子的上沿,与右图题差 16px(用户点破);
「3 版」计数也多余,去掉。

改法不是再补一个差值,是**逐段照抄右边的几何**:图题距纸顶 30 / 题行高 19 /
题底到 hero 框顶 16(实测),左题头同为 30+19+16 —— 于是三样对齐都不是碰巧:
  标题行  y 286 = 286
  按钮    y 286 = 286
  底边界线 322 ≈ 321(1px 边框宽)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 15:19:02 +08:00
ChaiHaoandClaude Opus 5 1bb74a9a2d 版本卡三处对细节:题头成对 · 按钮同款 · 底线与图框平齐
① 题头成对:左卡「流程包 · 版本」对右图「流程图 · 顺序」—— 同字型同字距,
   左右两卡说同一句话的两半。
② 「新建」按钮换成图上「编辑」芯片(dc2-addbtn)完全同款 —— 计算样式逐项比对
   (背景/边框/颜色/字号/圆角/内距)全同:一对动作一种长相。
③ 题头栏的底边界线与右图 hero 框的上边对齐:补 23px 对齐量,
   实测两线同落 y=321,差 0 —— 两卡横线一条平线。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 15:16:38 +08:00
ChaiHaoandClaude Opus 5 fd5ff1606f 拆掉画布的灰壳 —— 白图纸自己就是那张卡,一行一层
用户点破:右侧流程图看着是「两个层叠风格」—— 因为 .g-canvas 自己是一张灰卡
(#e9edf2 底 + 边框 + 14px 圆角),里面再垫白图纸;而左侧版本卡是单层白纸。
同一行两种叠法,像两套风格摞着。

拆掉灰壳:.g-canvas 只做布局(透明、无框),白图纸(process-doc)flex 撑满列高,
自己就是那张卡 —— 与版本卡同纸同影同角。实测:壳背景 transparent、边框 none,
白纸与版本卡顶对齐(256=256)、等高(572=572)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 15:11:44 +08:00
ChaiHaoandClaude Opus 5 28adab83b0 版本卡改图纸风 —— 与右侧流程图同一套视觉语言
版本卡原是治理台的圆角卡,跟旁边的图(flow-canvas 的图纸风)是两套语言。
改成同一张图纸的构件:

  · 白纸同影同角(10px 圆角、同一串投影,与 g-canvas 里的 process-doc 逐项相同)
  · 题头 mono 小字距大写:「VER — 版本记录」对图的「FIG — xx流程」
  · 行是细线方框(方角,同图例 legend 的画法),左侧 3px 色条:
    钢青 = 普通版,黄铜 + 米色底 = 生效版 —— 一眼可辨
  · 「新建版本 / 激活 / 停用」按钮同为细线方框小件,黄铜色标激活类动作
  · 卡尾说明也落 mono 小字,像图纸的备注栏

实测(计算样式逐项比对):背景 #fff=#fff、圆角 10px=10px、投影同串、
题头字体/字号/字距(SF Mono / 9.5px / 1.33px)全同,与图等高不变。

typecheck ✓ lint ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 15:00:24 +08:00
ChaiHaoandClaude Opus 5 ff114a2246 流程详情:版本卡与图平齐 + 显式「新建版本」+ 节点属性成卡
三处走查反馈:

① 版本列改成**固定高度卡片,与右侧的图等高**(grid stretch):
   头部 = 标题 + 版本数 + 「新建版本」;中段版本行,多了在卡内滚,不把页面撑长;
   卡尾一句常驻说明(恰一个生效;在途按启动版本跑完)。实测两侧 591px 对 591px,顶对齐。

② 版本从此有**显式的新建入口** —— 之前只能靠改图保存来隐式长版本。
   「新建版本」= 以当前看的版本为底克隆一版(服务端定版号并即刻生效)。
   与「激活」分工明确:激活只是切生效指针,不长版本;新建才长 ——
   把旧版本的画法复活成最新版、或在现状上另起一版接着画,都走这儿。
   画布有未保存改动时确认卡会明说「克隆不带未保存的改动」。
   实测:以 v3 为底建 v4 → v4 生效、v3 自动停用、列表实时刷新。

③ 节点属性从裸块改成**卡片**(与页面其它卡同一形制),标题右侧带状态
   (只读 / 有改动待保存 / 点节点就地填写)。

typecheck ✓ lint ✓ depcruise ✓ api:check ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 14:50:08 +08:00
ChaiHaoandClaude Opus 5 710946e729 流程包台面重做:版本收进包内部,启停是运行时开关
按你定的六条做:

## ① 台面三页签:总览 · 流程包 · 触发器
「调起规则」改名触发器(键不动,深链不断)。

## ② 版本收在流程内部,不平铺台面
货架一流程一卡:名字 + 标识 + 「生效 vN / 已下线」+ 版本数。
从前一版本一张卡,三个版本占三格 —— 版本是流程的内部事,不该摊在台面上。

## ③ 详情页布局照你说的排
左 1/3 版本列表(恰一个生效,点谁看谁的图),右 2/3 流程图;
图下是节点属性(点画布或点节点条,就地填);再往下才是声明式契约细节
(边映射校验 · 调用接口 · 触发器)。属性区从右侧窄栏挪到图下整行。

## ④ 新建流程
「新建流程」→ 填名称与标识 → 建出一张「开始 → 结束」的最小图,v1 即刻生效,直接进详情。
最小图天然过闭合校验 —— 不闭合存不进来这条闸对新建同样成立。
标识收紧为小写字母开头、只许小写/数字/连字符(它进 URL 和触发器规则)。

## ⑤ 历史包袱文案清掉
「工作流不设负责人,责任只落在节点上:此处不声明岗位,起单时就解析不出任务负责人」
→「这个节点还没指定岗位 —— 不指定,起单时就不知道任务该派给谁」。
同类:「未声明 · 发布前须补齐」→「未指定 —— 保存前选一个岗位」;
「发布前须先安装并过跨包契约相容核对」→「先去活动库安装;保存时会核对契约相容」;
边映射页的「边不闭合不得发布」→「不得保存」。

## ⑥ 版本可激活/停用,一次只能激活一个,切换不动在途
运行时模型从「最新版生效」改为**显式生效指针**:
  · `setPackageState` 激活即独占(同流其余版本一并停用)
  · 停用生效版 = 整条流下线,新起单被拒(报「无生效版本 —— 去流程包里激活一个」)
  · 起单取生效版;在途工作流按启动时钉住的版本号读定义,启停对它们零影响
  · 保存新版仍即刻生效(旧生效版自动停用)—— 回退就是把生效切回旧版,不用改图
store 的 setPackageState 把列上与 definition(jsonb)里的两份 state 一起改(教训同 0012);
迁移 0013 把存量多版同 active 归一为「每条流只留最高版生效」。

实测:激活 v1 → v3 自动停用,新起单钉 v1;停用 v1(零生效)→ 起单 500 且明说原因;
在途 v1 工作流照跑;恢复激活 v3。UI:切版看图、只读提示、启停确认卡、新建一条龙全通。

typecheck ✓ lint ✓ depcruise 376 模块 ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 14:35:54 +08:00
ChaiHaoandClaude Opus 5 a9e9c7babd 设计中心加联调测试台:造入站邮件(带附件)投通道,看真结果
你要的「模拟输入邮件+附件触发起单」。后端**本来就齐了** ——
`ingestMailRoute` 契约里早有 attachments,出参也早就回归属解析与三级消费结果。
所以这是纯前端加一个区:设计中心新增 `testbed`,一个页签「入站邮件」。

走的是与真通道**同一条**入站链路(通道归一 → 归属解析 → 统一事件流 → 三级消费)。
邮件通道是外界,模拟通道是 README 明许的;系统内部机制这里一行都不 mock ——
命中判定、起单、消息兜底全是真的。

## 这一屏回答三个问题

投出去之后就摆三样:归属判到谁(哪一级命中 / 无主的原因 / 默认认领岗位)、
谁接了(任务监听 vs 触发器各命中几个)、没人接落哪儿(消息兜底)。

还有一格**起单前置自检**:投之前就告诉你会不会命中,不用投完了猜。
判据与真实配置同源 —— 通道 id、主题关键词、两个归属键正则,四条逐条给绿灯或说差什么。
预填的样例是一键能起单的那一封;把它改坏,自检立刻指出差哪条。

附件如实说明「只走**登记**」:名字/类型/大小/存证指针进事件信封,内容不解析 ——
解析 Excel/PDF 是活动的事,活动还没实现。不含糊过去。

## 顺手修一个会静默分裂数据的 bug

通道的归属键正则 `RFQ-[A-Z0-9]+` 不含连字符,`RFQ-2607-501` 只抽到 `RFQ-2607` 就停。
而这个键会成为「受理结论」那一行的**主键** —— 截断了,同一单的数据就静默分裂成两行,
网关读到哪一行全看运气。改成分段续接 `RFQ-[A-Z0-9]+(?:-[A-Z0-9]+)*`,
实测 `RFQ-2607-501` / `RFQ-ABC123` 都整个吃下。

## 我自己踩的两个

① 出参类型手搓,`level`/`kind`/`position`/`rationale` **四个字段名全是编的** ——
页面上就摆出两个永远显示「—」的格子。改为直接用契约类型:归属解析真实是按 `outcome`
判别的联合(owned 给 rule+taskId,unowned 给 reason+可选 fallbackPosition)。
为此给契约补了 `IngestMailOutput` 导出(加法)。
② JSX 正文里写 markdown 的 `**` 会显示成字面星号,换 `<b>`。这坑本轮踩过第二次。
另补两个缺失图标(flask-conical / split),不补就是空 SVG。

## 实测

界面上点「投递这封信」→ 归属判**无主 · 三级都没对上 · 默认认领岗位 运营**
(对新询价完全正确:没有在途任务可归)→ 触发器命中 1 个 → 起单。
起单入参 `customerCode: C014` / `rfqRef: RFQ-2607-501` 都抽对了。

一个值得记的观察:事件起单**没有「来源人」**,所以不装载工作组,A1 的 BD 岗位解析到
真正的 BD(冯兵),任务落他工位而不是我的 —— 这是对的,不是 bug。
要在自己工位上看,用「人工登记起单」那条路(登记人即来源)。

typecheck ✓ lint ✓ depcruise 376 模块 ✓ 498 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 14:02:00 +08:00
ChaiHaoandClaude Opus 5 b2f5f69d6a 流程包去掉发布机制 —— 严格检查 + 保存即生效,生效由运行时决定
用户要的是运行时机制:新建 + 编辑,存下去就生效,旧任务走完旧版本,
新任务调用时才加载新编排。所以「草稿 → 发布」两态整套去掉。

## 闸从「发布」挪到「保存」

`savePackage` 现在先跑闭合校验,不闭合抛 `NotClosedError`(路由 412 带报告)——
**一个字节都不落库**。存进来的每一版都能起单,所以不需要「已发布」这个标记。
`publish` 用例、路由、`publishPackage` 存储方法一并删掉。

实测:把进 A6 的边映射清空后保存 → 412,逐条点名「边 e-g3-a6 未完成载荷映射;
节点「报价议价」的必填字段未映射:rows」。

## 保存恒新增版本号,服务端说了算

这不是可选项,是「旧任务走完旧版本」的前提:工作流按 (包id, 版本) 去读定义,
就地覆盖 v1 就等于改掉所有在途 v1 任务正在读的编排 —— 它们会中途换了规则却毫不知情。

版本号由用例层算(当前最大 + 1),**不采信入参**。实测:入参故意填 version: 999,
落的是 v2。store 层因此改成**只插不改**:撞键宁可让唯一约束报错,也不静默覆盖。

起单取版从「最新已发布」改为「最新一版」(retired 除外);触发器的 requiredInputs 同口径。
实测:改完描述存成 v2 后,新起的单用 v2,早先那单仍挂 v1。

## 迁移:旧状态值不归一就是一读就炸

状态枚举从 draft/published/retired 收成 active/retired。列上和 definition 这个 jsonb 里
各存着一份 state,两处都要改 —— 不改,`processPackageSchema.parse` 读一行就抛。
这不是开发期小麻烦,任何已部署实例都会中招。加了迁移 0012。

## 界面:恒为 0 的假指标撤掉,不换个说法留着

- 编排面板:「已发布/草稿」芯片 → 「生效中/历史版本」(真正的区别是哪一版会被新起单取到);
  发布按钮撤掉,保存按钮改成「保存并生效(存为 vN)」并在确认卡里说清影响面
- 历史版本只读,但就地指路:「去 v(N-1) 改(生效中)」,不让人自己找
- 蓝图面:「草稿 N · 未闭合 M」两个计数在新机制下**结构上恒为 0**(不闭合存不进来),
  换成「共 N 个版本,保存即生效」
- 驾驶舱:「未闭合草稿」卡整张撤掉 —— 同理恒为 0。天然的第三张是「死路」
  (route-dead-end 事件),但那需要一条按事件类型聚合的路由,没有之前不摆(同死信卡的规矩)

## 顺手修:种子的幂等判断本来是坏的

比对用 `JSON.stringify` 认键序,而 jsonb 从 PG 读回来键是重排过的 —— 永远判不等,
每播一次种就多存一版一模一样的定义(实测一口气堆到 v3)。改成递归按键名排序后比对。
连播三次,只第一次存。

## 契约变更(破坏性,一步到位)

`publish` 删除、`NotPublishableError` → `NotClosedError`、`publishable` → `closed`、
状态枚举收窄。按规矩破坏性变更该走三步弃用 —— 这里一步改完,因为:
① depcruise 反查下游全在仓内(374 模块无违规),同批改完;
② 要弃用的是一个**产品决定不再存在**的机制,留弃用窗口没有意义。
CONTRACT.md 已同步,快照单独说明。

typecheck ✓ lint ✓ depcruise 374 模块 ✓ 495 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 12:49:24 +08:00
ChaiHaoandClaude Opus 5 9802550ae8 审批 / 消息 / 纪要 / 汇报补上助理栏 —— 那不是空态,是整栏没渲染
`.workspace` 是**三列**网格(侧栏 · 工作区 · 助理栏 440px)。这四个模块只渲染了
两栏,右边就空出一条 **234px 的白带** —— 里面什么都没有,不是「空态没写好」,
是这一栏根本没画。实测四面皆然。

那一栏该摆什么,按 OS 4.1 定:「对话流 / 视图区」是**工作台-任务**的交互结构、
是回环输入的唯一入口。这四个要素各有自己的形态 —— 审批是通过/驳回附依据、
消息是就地答(MessageDesk 自己那条 NoteBand 早写着「不开放任务对话流」)、
纪要靠人记、汇报是确认即提交 —— 都不经对话流。

所以**不摆能打字的输入框**:那是在许诺聊得起来。只如实说这一栏是什么、
这一面该怎么用、想说话该去哪儿。共用件 `AssistantAside`,色调 `muted`
(通路不在这儿,灰着就不许诺),章也不打彩色渐变 —— 亮着像在待命。
四句文案各说各的事,不是同一句复制四遍:

  审批 拍板不用先商量 —— 看依据就够了,想先问一句就去那一单的任务里说
  消息 这儿不用聊     —— 就地答完即可,作答只及卡面,不用跑进别人的任务
  纪要 会得你自己开   —— 你写下来最准,写完登记起单责任才落到人
  汇报 不用你写一个字 —— 按任务日志自动聚合,要数字好看得回任务里干活

顺带治了题头被截:一行摆四件(章 · 任务助理 · Agent · 说明句),对话区压到
212px 时说明句只剩 29px,被省略号截成「汇…」,一个字都读不出来。改为按**本栏宽度**
容器查询,挤了就让说明句换到第二行拿整行说完。任务面的「盯着这单推进 · 有事随时说」
以前也是截的,这下一并读全了。容器上下文落在 `.jc-tch` 不是 `.session-chat` ——
后者带拖拽调宽的负偏移柄,不给它加 containment。

补 3 个缺失图标(gavel / pencil-line / chart-column)—— 不补就是空 SVG,这坑踩过。

typecheck ✓ lint ✓ depcruise 374 模块 ✓ api:check ✓ 490 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 11:27:52 +08:00
ChaiHaoandClaude Opus 5 f7b6a3a107 空态分出第三种空 —— 「没接通」不许诺,别让人白等
上一版补占位时漏了一件:占位分**两种**空,我只做了一种。

「沟通记录」的注释写着「明说没接,不伪装成暂无数据」,正文却写「与客户、供应商的
邮件和消息都会归到这里」—— 注释和文案自相矛盾。按单归档的投影根本没做,`outbound_mail`
至今只有 channel 建表和 reset-runs 碰过,**任何界面都读不到**。所以在那一屏等下去
永远不会有内容,而文案在请人等。

改成如实说:「往来记录还没接通」。并给 EmptyState 加第三色调,让三种空长得不一样:

  ok     办完了、清空了 —— 这是好事(待批清空、无未读)
  brand  还没发生,但通路是通的 —— 等着就会有(还没有任务、还没有成果)
  muted  通路还没接 —— 等下去也不会有。灰环灰图标,视觉上就不许诺

`muted` 是新加的真色调(不是我编的类名 —— union 与 CSS 一并落地)。
文案也不把人指去「消息」面:那里同样读不到外部邮件,指过去是第二个谎。

顺手把十处空态过了一遍:其余 brand 都名副其实(起单、聚合、纪要、成果的装配都通),
只有沟通记录这一处在许诺。债务簿该条对账。

tsc ✓ eslint ✓ depcruise ✓ 481 测试 ✓

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 10:32:23 +08:00
ChaiHaoandClaude Opus 5 c59e73754b 工作台空占位补齐 —— 有内容渲染内容,没内容才落空态
任务面原来缺两处占位:中栏是一行裸文字,对话区在没选中任务时**整栏不渲染**。
补齐后三栏恒在:中栏落设计空态「手上没有任务」,对话区给全壳(题头 +
空态 + 禁用输入条),空着也看得出这是干什么的地方。

但真起一单之后暴露了更重的问题:占位在**说谎**。待处理角标写着 1,正文却
说「手上没有待办」—— 因为 ChatStream(643 行)与 WorkOrderReport(449 行)
早就写好、也从 @features/desk-task 导出了,却没有一处在用。占位不是缺内容,
是内容没接上。三处接回真渲染:

  待处理  → WorkOrderReport(工单正文、编号、派发时间、数据与分析)
  工作日志 → .jc-log 行,按归侧四类各一色(机器/人类/裁决/等世界)
  工作成果 → .jc-file 行,点开进 FileViewer;打开时右槽换「返回」
  对话区  → ChatStream,三个回传(说一句 / 答卡 / 答工单)在这里收口

顺带治了窄对话区的抗压:工作区优先保「五按钮 + 翻页」,对话区在 1280 下被
压到 212px,卡头标题 `flex:1` 没设 `min-width:0`,一挤就逐字折断成竖排单字。
降级顺序改成「状态芯片换行下沉、标题始终整词可读」—— 截断能让布局不崩,
但读的人不知道这是什么卡。不改任何一栏尺寸。

五闸:tsc ✓ eslint ✓ depcruise 373 模块 ✓ api:check 公开契约无变化 ✓ 481 测试 ✓
走查后清了运行数据(仓库自带 reset-runs,配置原样留着),换业务化主题重起一单。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 10:25:19 +08:00
ChaiHaoandClaude Fable 5 5619d86ce4 编排层③:活动装入/换版入口 —— 开发完能装进来,不必跑种子
此前活动只能靠 seed 装入,治理台没有任何入口 —— 这是「逐个开发活动」的拦路石。
补 POST /api/gov/activities(无代码通道:交清单 + .js 产物,都是数据),
两审在服务端跑;不过审按发布门同样的式样回 412 + ApiError.detail 带审计结论
(直接回业务体的话类型化客户端拿不到详情)。活动库给「装入 / 换版」卡:选文件或粘贴两份。
实测:0.1.0 → 0.2.0 版本并存;声明未注册的工具即 412 并点名到工具。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 10:01:25 +08:00
ChaiHaoandClaude Fable 5 9de641459e 编排层①:改图入口下沉画布 + 活动契约面全链打通
① 已发布包就地给「起草新版本并去编辑」,不用去页头找;
② 修一个我自己引入的 bug:卡点还原把审批点的「退回调整」牌子当成边,凭空造出 e-A5-A4 ——
   卡点只认亲、不新建(旧包有这条边才认);实测编辑器往返 16 边 14 节点无损;
③ 活动契约面接进治理台:列表出参带必填入参/输出口/声明依赖,活动详情摆成一屏,
   导出依赖文件一并带上 —— 开发一个活动要照着的东西,现在有一处能看全。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 03:02:44 +08:00
ChaiHaoandClaude Fable 5 af789f546c UI④:元素盘点击落子真能落 —— 原型里这条路是坏的
事件流实测:click → drag.init → create.start → create.move → **create.rejected**。
create.move 要有 hover 目标才算 canExecute,而 click 到达时鼠标早已抬起,
拖拽在同一个调用栈里就被拒 —— 工具提示写着「点击后点画布落子」,一颗子也落不下。
点击这条路改为直接 modeling.createShape 到空位(撞车往下让、一列满换列);
拖拽那条路不动。实测:落子 32→33、追加自动连线 33→34、撤销回退干净。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:49:50 +08:00
ChaiHaoandClaude Fable 5 5a8589046b UI③:LLM 工具改为大模型驱动的系统内通用工具 —— 不是模型实例
五件真实存在的:案例决断(loop-turn)/ 步内生成(flow-step)/ 叙述性小结 /
蒸馏归纳 / 连通探针,各标算谁的账。模型实例退成尾注:模型是发动机,这些是装在上面的件。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:36:57 +08:00
ChaiHaoandClaude Fable 5 ec0b78c550 UI②:数据对象全用中文名 —— label 随物化落 PG 注释,全链读回
此前 label 在建表那一步就丢了,治理台只剩 project__intake_record 这种键给人看。
用表/列注释而非另建元数据表:名字与表同生共死,不会对不上。
设计台/运营台/对象详情/触发器下拉一律中文名在前、键在后。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:33:09 +08:00
ChaiHaoandClaude Fable 5 188637cf26 UI①:修卡片被压扁剪裁 —— 工作面是滚动 flex 列,子块一律不压缩
内部是 grid 的块(.g-entries)会被按很小的 min-content 算,整张卡压扁,
内容再被 .g-card 的 overflow:hidden 剪掉 —— 卡里只剩个头。两台全页审计已清零。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:27:43 +08:00
ChaiHaoandClaude Fable 5 10990a1efa MVP底座⑧:数据域四域大卡 —— 项目/客户/情报/供应商
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:05:28 +08:00
ChaiHaoandClaude Fable 5 21b66567bd MVP底座⑦:活动库卡片化 —— 六槽位卡
卡上只报查得到的事实(范式/分类/包版本/资产生效版/上架):
清单里没有「实现到没到位」的可靠依据,不在卡上编一个章 —— 槽位状态记在 debt.md。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:04:11 +08:00
ChaiHaoandClaude Fable 5 06b9cbde04 MVP底座⑥:工具箱四段卡片 —— 功能/LLM/人类/接入
三类工具并列不是编排,是「一件事能交给谁办」的全集:交给系统、交给模型、交给人。
导入表单走两审同门(端点真调);MCP 如实标未连接,不摆点不动的按钮。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 02:02:00 +08:00
ChaiHaoandClaude Fable 5 0fe5222f79 MVP底座④:统一报价 1:1 流程包单实例 —— 四域物化,种子整体切换
14 语义节点/16 边:A5 是内置审批点(驳回走 reject 声明 reopen A4),
G2 的两条互斥分支显式汇合于 G2J —— 隐式合并过不了闭合校验(实测)。
顺手修 graph-to-pkg:卡点带 to 时还原成语义边,否则回边画成卡点一存盘就没了。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 01:49:49 +08:00
ChaiHaoandClaude Fable 5 3edd133230 MVP底座①:数据四域命名 —— 项目/客户/情报/供应商
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 22:39:49 +08:00
ChaiHaoandClaude Fable 5 34e207c3e8 三面拆分⑫:UI 打磨 —— 补 10 枚缺失图标,蓝图改因果链,台账收成一个模块
图标注册表缺 arrow-left-right/columns/table/tag 等 10 名,用到即渲染成空 SVG —— 补齐;
蓝图四库改真箭头相连的因果链节点卡(卡即入口,删重复的入库段);
驾驶舱终态分布改五色堆叠条;运营数据收成左轨一枚「台账」,域下沉为 2-3 字短名页签
(受理→寻源→定价→议价→替代→共享,按流程序),进模块自动落首域。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 22:02:49 +08:00
ChaiHaoandClaude Fable 5 4a19690389 三面拆分⑪:收口 —— 走查通过,删掉与蓝图重复的需处置页签,文档对账
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:32:38 +08:00
ChaiHaoandClaude Fable 5 6f36f8340a 三面拆分⑩:工作组管理落员工区 —— ADR-011 欠账清账
建组/改组:逐岗位选人,留空即回落四策略。绑定先于策略,起单时快照进工作流;
实测改绑定后新起单的 work_group 快照即含新成员表,在途不受影响。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:28:30 +08:00
ChaiHaoandClaude Fable 5 a93f03f464 三面拆分⑨:台账动态位入运营,数据域瘦身为纯定义面
设计侧只见结构(列/主键),运营侧按域列行数与行浏览 —— 改 schema 与查行数据
是两种心智,摞一屏行数会把结构挤到看不见。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:22:12 +08:00
ChaiHaoandClaude Fable 5 6bb4675893 三面拆分⑦⑧:触发器一分为二 —— 规则定义入设计·流程包,起单开关入运营·任务
定义面可改名/改目标包/改三类规则/改起单装配;编辑期的装配行走本地状态,
存盘才解析 —— 派生自已解析 mapping 的话,刚添加的空行会被当场滤掉,人打不出第一个字。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:19:42 +08:00
ChaiHaoandClaude Fable 5 19108af6fa 三面拆分⑤:企业蓝图首页 —— 四库因果链与待补清单(闭合/缺活动/无调起)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:11:09 +08:00
ChaiHaoandClaude Fable 5 9fce0fdaa0 三面拆分④:驾驶舱首页 —— 度量改接 report 真八指标,纠正率/DMN 不再恒为 0
治理台原先调 memory 的五指标版,还把 submissions/corrections/judgements
硬塞 0 —— 仪表在说谎。八指标本就在 report 里算好,这里接上,与工作台汇报同源同口径。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:08:42 +08:00
ChaiHaoandClaude Fable 5 bb6760d7a4 三面拆分③:壳参数化两台,台账随域动态生成,顶栏互跳按权亮灯
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 21:00:25 +08:00
ChaiHaoandClaude Fable 5 cbae9b1284 三面拆分②:三章标签与入口路由,/gov 深链整链改写
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 20:53:43 +08:00
ChaiHaoandClaude Fable 5 e578b5bc34 三面拆分①:surface 配置与区表 —— 归属/亮灯/旧链改写皆纯函数先测后写
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 20:50:32 +08:00
ChaiHaoandClaude Fable 5 ac85ecf2ea 基线:鉴权会话+工作组+工作台三区修复+编排工作区+产品设计文档
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 20:43:35 +08:00
ChaiHaoandClaude Opus 5 ac2fecd005 汇报流:活动按步序位置推视图,容器沙箱渲染
「flow:按**步序位置**推送声明的模版」(AM 07)。原先这条链只有写面没有读面,
活动的 viewTemplates 是一行占位字符串,工作台视图区永远只显示一份硬编码概览。

补齐整条链:
  · 步声明新增 `view`:这一步呈现哪张模版 —— 推什么由声明给定,不由临场决定。
  · 新增模版填数的纯函数(interaction/domain):`data-slot` 取值、`data-rows` 逐条展开。
    **填数只做取值与转义**,没有表达式、没有分支、没有循环 —— 一旦模版能算,
    它就成了代码,容器的「无脚本执行权」也就形同虚设。填充**消费槽位**,
    交出去的是干净 HTML,不是带模板属性的半成品。
  · interaction 补读面 `viewOf`;desk 路由把推送的 HTML 交给前端;
    ViewRegion 经 `@ui` 的 ViewContainer(sandbox="" 的 iframe)渲染 —— feature 不碰 innerHTML。
  · A1 写了三张真模版(事态全景 / 打标判据 / 成果预览),内联自带样式
    (沙箱页面不继承工作台 CSS),按步序位置挂在 S3 / S5 / S6 上。

沿路两处修:
① 取值路径遇到**本身带点号的键**(台账地址 `域.对象`)会被拆成两级、永远取不到。
   改为整键优先、找不到再下行;`view-render` 与 `step-sequence` 两处同修。
② 「本单交付」不能画成台账全表:任务视图是正式版 + 我的草稿的合并结果,
   直接拿来列会把**别单**放行过的记录一并列出。本单自己写下的行单独放在
   `mine:域.对象` 下(整键,取值不歧义)。

另:视图推送失败原先静默吞掉 —— 会让「视图区一直空着」变成查不出原因的怪事;
改为留痕(仍不影响步序推进,呈现是投影)。

实测:一封 RFQ 入站 → 放行前那一屏列出本单交付 LM358DR / TI / 12000 / 8.2 / 10周,
以及 Type A「直接快答」的分类结论与四项打标判据。

gates: tsc / eslint / depcruise(321 模块)/ api-report / 423 测试 全绿

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 10:47:20 +08:00
ChaiHaoandClaude Opus 5 3b9587563a M6(4/n): 工作台五要素齐活 —— 审批 / 消息 / 纪要 / 汇报
四个 desk-* feature 自 workbench 原型 ModuleWorkspace.tsx 平移(jc-* 类名原样),
共用件落 shared/desk/module-kit;mock 数据换成服务端投影:
  · desk-approval:审批点卡到审批人工位;依据快照、驳回走向(声明式)、驳回必附意见
  · desk-message:通知 + 跨任务征答**就地作答**;卡面表单由 card.ts schema 驱动,
    与后端回传校验同 schema;跨人卡不占任务清单,不开放任务对话流
  · desk-minute:纪要维护 + 决议登记起单;正文可续、决议只增
  · desk-report:四周期草案 + 度量八指标 + 确认即提交
左轨角标常驻(待批 / 未读),责任面要一眼看见什么在等我。

修一个真 bug:process.start 从不校验流程包的 callInterface,
先插工作流再由 task.start 撞活动契约 —— 失败就留下一条永远推不动的在途单。
改为**先校验后建单**(CallInterfaceViolationError),一条工作流都不留;
路由回 400 并带上缺哪个字段。已清掉这次触发出的两条孤儿单。

判据 ⑩ 纪要一环跑通:决议 → 登记触发 → 工作流 → A1 落到 BD 冯兵,
登记人即来源已记在单上;同一决议重复登记被 412 挡下。

gates: tsc / eslint / depcruise(316 模块)/ api-report / 380 测试 全绿

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 03:53:36 +08:00
ChaiHaoandClaude Opus 5 a9cd6d10c7 M6(2/n): 治理台九功能 + SSE 订阅层 + 读/治分权
治理台按 §9.1 拆成九个 gov-* feature,共用件落 shared/gov:
  · 外壳(左轨/顶栏/面包屑/页签/整页下钻)自原型 Governance.tsx 平移,
    DOM 与 g-* 类名原样;路由状态即应用状态,区/页签/下钻栈全编码进 hash 可深链
  · 编排画布 diagram-js 画布件 1:1 平移(flow-layout/flow-node-paint/FlowDiagram),
    新增 pkg-to-graph 把 ProcessPackage 转成画布图模型;统一报价 v1 全图 12 节点 15 边渲染通过
  · 后端补四路由:审批单 / 工作流下钻 / 通道实例 / 度量仪表

SSE 订阅层(§9.2):app 层单一连接,按信封目标失效缓存;
组件不再自行轮询(去掉 refetchInterval)。广播只说「哪个目标动了」,不带业务载荷,
且在投递已落库已送达之后才发 —— 不是第二条投递链路。

两处实质修正:
  · 治理路由一律要 govern → 读路由改要 read。客体三类 × 动作三种的分法就是为此:
    BD 有 task:read 能看在途、动不了控制事件;一律 govern 等于把三种动作压成一种
  · 控制事件/恢复/改派原记为 engine-transition(归机器产出)→ 新增 control 条目种类,
    归人裁决侧。归侧是按动作类型的纯推导,所以「谁干的」必须体现在 kind 上;
    否则人的叫停会被算进自主率的机器分子

判据 ⑩ 治理台一半跑通:在途监控 / 叫停 / 恢复,治理动作留痕可查。
无权查看不再画成空清单,按岗位说明缺哪一项。

gates: tsc / eslint / depcruise(286 模块)/ api-report / 360 测试 全绿

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 03:28:40 +08:00
JCAI Main AgentandClaude Opus 5 3cfaa04098 M6(1/n): 工作台任务要素 —— 原型 1:1 平移的第一屏
样式整文件搬(README 平移规则 1):app.css 2767 行 + proto.vendor.css +
theme.css + console.css 原样搬,设计令牌与全部 jc-* / g-* 类名不动。

前端(按 §9 重排,渲染输出 1:1):
- shared/:Ico / ScrollArea / useChatWidth 自原型搬,去掉 "use client" 等 Next 专有件;
  失效的 react-hooks disable 指令按 §17 清掉(不改渲染)
- shared/typed-fetch.ts:服务端交互唯一通道,路由契约来自 @contracts/api;
  不引 Hono RPC 客户端(那要求前端 import 后端类型,违反 §5.1)
- app/query.ts:TanStack Query;缓存失效由订阅层驱动,组件不轮询
- features/desk-task:任务列表(一条 = 一个活动的一次运行,不是一整条工作流)/
  标题区 + 工作区四页签 / 对话区(气泡二元制 + 卡族 + **composer 锁**)
- @ui:ViewContainer 用**沙箱 iframe(sandbox 不含 allow-scripts)** —— 结构上无脚本执行权,
  不依赖净化算法的完备性;ViewBlocks 渲染十一种视图块
  feature 不得自行 dangerouslySetInnerHTML,eslint 有规则守着

后端:工作台路由 /api/desk/*(任务清单 / 任务详情 / 工单回传 / 自由输入 / 消息);
回传与后端校验**同 schema**;任务详情是服务端投影 —— 前端零过程状态,刷新即重建

已验证(真机):任务卡「A1 RFQ需求分析 · 序位 1/7 · awaiting-event」、
预算 2/40 步、1 张工单(LLM 步失败后转人兜底那张)、7 行带归侧标签的任务日志

358 个测试通过,门禁五道全绿;web 构建通过

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 02:45:42 +08:00
JCAI Main AgentandClaude Opus 5 7cd664af3a M0: 工作区骨架 + 五道门禁 + 环境自举
- pnpm workspaces / tsconfig 双工程(node · web)/ 路径别名(§11.1)
- eslint flat(§11.3 + §12.5 可机检项)/ dependency-cruiser 基线八条 + JCAI 增补(§11.4)
- tools/module-tiers.json + gen-depcruise-tiers.ts 生成 tier-order 逐层规则
- tools/api-report.mjs 契约快照只留契约面(ADR-005)
- docker-compose(PG16)+ db/init 四 schema;种子数据五岗位五员工冻结为常量
- docs/debt.md · docs/adr/ADR-005

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 00:18:58 +08:00