Commit Graph
155 Commits
Author SHA1 Message Date
ChaiHaoandClaude Opus 5 ade0fa5a94 A2-A7 全部补齐到验收线;顺手把几处「门拦住却不给路」的坑填了
活动:A2 选型 / A3 寻源 / A4 定价 / A6 议价 / A7 归档五件各补成真活动包 ——
契约宽进(input.required 空,归一在活动内)、台账必填声明(含行级 requiredWhen)、
入场哨兵与 L1/L2 判据一律读基座数、两份件(在办可编辑 + 办结静态快照)、
三案例常备、包内自测。e2e 各三案例 released、行动被拒 0、发口正确、提交闸每单真拦。

基座(共享面,改一处影响所有活动,故每处都带回归):
· 重发判断走在站上场之前 —— 人答完那步常已收掉,readyToWork 先抛「不能再往它上面挂活」,
  于是「重发已答过的卡 = 无事发生」这条唯一活路在最需要时够不着,A1 基线当场熔断;
· 决策卡补幂等兜底(与执行工单同一把尺):头两次无事发生,第三次起才算被拒;
· 输出没成形先就地重问一次,原话进工作日志、不再摆上卡面;
· 工具调用读数 tool_<名>_calls —— 「机检只读基座数」这条纪律第一次覆盖到工具;
· 执行卡 steps/standard 补进出参 schema(从前能到卡面全靠厂商 JSON 模式宽松);
· 件的就地更新改逐节点 morph,保存先把新值镜像进只读那份 —— 不闪、不等回声。

A1(基线,全程守住):措辞三档对齐(必填/建议/选填)、禁止拿历史价当客户目标价、
卡骨架从步骤剧本搬进说明书(压成一拍连做时剧本没摊开,会发出没有指导书的裸卡)。

契约两处**新增可选字段**(非破坏):FieldDeclaration.requiredWhen、工单 finalHtml;
api-report 同批更新。docs/adr 与 docs/archive 的 13 份文件在工作树里不见了,
本次予以恢复而非提交删除。

门禁:typecheck / lint / depcruise / test(1366)全绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:28:31 +08:00
ChaiHaoandClaude Opus 5 85466e815f 活动开发规范第三版(按四轴重组)+ HTML报告生成规范单独成册
给「任务活动开发 agent」沉淀的两份操作手册,基准是用户验收过的 A1(quote-intake@42,
三条形状不同的案例 released、被拒 0)。

活动开发规范.md 第三版,按四条轴重组:
· 解耦机制 —— 活动与系统之间只有安装通道;三份声明=三个授权面;
  边界纪律「别替下游产出」(随令牌流向下游的只有验收过的成果);
· Harness 契约 —— 台账三写一撤与字段四标记(required/expect/tally/auto)、
  基座读数全表与机检纪律(三次违反史逐条记账)、一路的门与闸
  (起单宽进/提交闸两端/提交门/放行门哨兵/熔断)、拒回话术三分、五类卡、
  phases/三色日志/一轮一句、放行落地;
· Loop —— 局面组成、行动十四型全表、串纪律、人工激活与 start
  (「话说的范围要盖住门拦的范围」)、doneWhen 自动收步;
· 活动怎么写 —— 清单六区(ledgers/editableAtRelease/判据措辞/内部一致性不上卡)、
  建模十纪律(哨兵 ifPart、阶段全覆盖补进)、剧本 steps 六字段与 doneWhen 三坑、
  guide 写作十条(一单一卡、卡骨架照抄、纯文本)、三常备案例与验收口径。
排障速查表并入这一轮全部新账(14 行新增)。

HTML报告生成规范.md 初版(用户点名单独成册,并强调报告与表单的关系):
· 一份 HTML 三个身份:件(看)/表单(改)/归档件(存)—— 同一份,分开必分叉;
· 报告与卡的关系立成硬规矩:逐行数据归件、整单级归卡;编辑在件、提交在卡;
  同一个数管三处(件上红带/卡上闸/放行门 L1 同源);保存链路与三条实测教训;
· 绑定语言全表、不算不判(按值上色/按条数分宽/按数开关)、编辑态四件套
  (闸/孪生件/增删行/缺项红带)、PRD 平移法、浏览器走查清单、陷阱表。

CLAUDE.md 文档权威地图指向两份新版。五道门禁全绿(975 passed)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
2026-08-02 15:30:40 +08:00
ChaiHaoandClaude Opus 5 ec47fd46a0 现状快照记上这一轮最后两条,日期改到 2026-08-02
「话说的范围要盖住门拦的范围」那一条(模型漏 start 的根因)与 A1 三案例常备,
是这一轮唯二还没进快照的。快照抬头还写着 07-30,而里面已经记到 08-02。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
2026-08-02 15:15:04 +08:00
ChaiHaoandClaude Opus 5 a9e66ceb39 话说的范围要盖住门拦的范围;报告上把缺哪几格红字直说
三件,都是「说的和做的不是同一件事」这一类的又一次现形。

**为什么模型会漏掉 start** —— 提示词那条规矩写窄了。
原文:「标了「须你启动」的项要先 start **再调工具**」——只说了调工具;
而拦截那一侧(`readyToWork`)管的是 tool / ask / human / decide / entry / finish 一整片。
模型那一拍要发的是 `human`(派工单),照字面读这条规矩管不着它,于是漏了 start,
撞上「S3_confirm 标了人工激活,要先 start 再干活」白烧一拍。
**话窄一格,模型就正好漏在那一格上。** 现在写全:动它之前先 start,发卡与 finish 都算;
只有 write 例外(它的 itemId 只是记账,挂不上照写)。

**目标价左对齐** —— 右对齐是给要竖着相加的那种数用的;这张表一行一个料、彼此不相加,
右对齐只让它跟自己的表头分了家:标题贴左、数贴右,中间空一条,眼睛来回找。
等宽字体留着(位数对齐仍有用),对齐跟表头走。

**报告上把缺哪几格红字直说** —— 从前只在空格子里摆一枚小小的「必填」胶囊,
九行料摊开就淹在表里;而人打开这一屏就是来填的。现在表上方一条红带,
点名还差几格、差在哪一行的哪一列。两个数由基座现算(`_missing` / `_missing_keys`),
与提交闸、放行门 L1 同一个数;**模版不算也不判** —— 「一格不缺就别出这条带」
交给样式表(`data-class-of` → `v-0` 那档 display:none)。
浏览器验过两态:缺 1 格时 v-1 显示,从件上补齐后重渲变 v-0 自动收起。

五道门禁全绿(975 passed)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
2026-08-02 15:04:33 +08:00
ChaiHaoandClaude Opus 5 3cf9f10b86 进度条补回漏掉的那一格;删掉一条已经不存在的路
用户送来一条实测日志:中间被拒四次,卡片进度条也走得不对。两处都不是模型跑偏。

**进度条漏了一格** —— `INTAKE_PHASES` 里没有 `S3_confirm`(它是 08-01 才补回成一项的):
计划项六个、名单里五个。于是 S2 一收,前两格全过,条当场跳到「判定去向」;
而人这会儿正对着受理需求审定那张卡 —— **他手上办的那件事在条上没有格子**,
条却已经走过去了。那不是走快了一格,是它在说一件没发生的事。
补成四格(定位客户 / 归一受理 / 交你审定 / 判定去向)+ 基座统一加的放行收口;
包内自测钉死「除放行外每一项恰好属于一个阶段」「一项不进两个阶段」。

**那四次拒回是一条已经不存在的路** —— 说明书里还留着「人交回来还缺必填,就再发一张卡」。
提交闸上线后那条路没有了:缺必填根本按不下提交。模型照它办,每次都撞在
「这件事刚问过,人也答过了」上,白烧四拍。改成「这张卡一单只发一次」。
同批把提交闸补到**服务端**(收下回传之前把住):说明书向模型承诺
「卡回来时必填一定是齐的」,那句承诺只有服务端拦得住才算数。

A1 三案例复跑:9 拍 / 10 拍 / 14 拍,前两个**被拒 0**(修前是 12 拍被拒 1),
进度条五格逐格走对。五道门禁全绿(975 passed)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
2026-08-02 14:13:24 +08:00
ChaiHaoandClaude Opus 5 259192f736 人手改的那一手真正落得下去;界面不撒谎那几处补齐
手改是**兜 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
2026-08-02 13:41:44 +08:00
ChaiHaoandClaude Opus 5 94f1c7a4ef 活动开发规范:立「HTML 报告模版活动持有,一单一模版贯穿始终」为硬规矩
用户强调补进规范(§9.3 整节重立,三条硬规矩):
  ① **关键表单逐张配 HTML 报告模版** —— 模版是活动自己持有的资产
    (assets.viewTemplates,随包版本冻结),不是系统临场生成;执行与验收都要配,
    人办工单看到的是已排好版的报告(AI 拟值已填、basedOn 的过程成果嵌在正文里),
    不是一堆裸字段;
  ② **从待处理工单到工作成果报告是同一张模版**:在办 = 报告 + 指导/判据;
    办结后指导与判据卸下,只剩报告原样进「工作成果」归档。不许两张模版 ——
    迟早长歪,人回头对不上账(语义出处:PRD ViewRegion 头注);
  ③ 一个局面一张模版,不在一张模版里堆条件分支。

同步三处:§4.2 assets 区硬规矩栏、§9.2 执行事项行、§11.2 自测清单
(关键表单逐张有模版、执行/验收都配、待处理与成果同模版)。

纯文档改动,五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 03:22:25 +08:00
ChaiHaoandClaude Opus 5 1d2d5ebb53 归档过时文档,立仓库根 CLAUDE.md 记最新状态
**归档四份**(docs/archive/,每份头部带归档说明与现行去向,另配 archive/README.md 索引):
  · MVP规格包-README.md(原 docs/README.md)—— 从零实现的启动包,MVP 已建成,
    启动提示词与里程碑纪律不再是现行指引;代码注释「README《归一化对照表》」等引用
    的各节原文保留,查历史语境仍来这里;
  · PROGRESS.md —— M0-M6 全部完成后停止维护,「下一步」多数已做完或被后续决策取代;
  · plan-2026-07-27-{mvp-foundation,three-surfaces}.md —— 两份已执行完毕的实施计划
    (三面形态此后又有演进:运营撤数据区、触发器与大模型独立成区)。
  语义源三份 html(操作系统/活动模型/MVP示例)不归档 —— 仍是 OS/AM 条款的出处,
  只是 flow 相关章节读作历史记述。

**新立 CLAUDE.md**(仓库根,每会话装载):现状快照(三面一体 · 编排层测死 · 范式退役
一律案例模型 · 无模型密钥时三套 e2e 跳过 · 下一件大事 = 按活动开发规范第 12 章销账)、
文档权威地图(活文档/语义源/前端权威/归档)、八条铁规矩(五闸以退出码验 · 契约四步 ·
§12.5 禁止清单 · mock 只在外界 · 密钥只从环境 · 试跑用 AI 账号测完清数据 ·
安装恒新增改必升版 · 界面不撒谎)、常用命令与结构速查。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 03:15:00 +08:00
ChaiHaoandClaude Opus 5 d1ddf5f481 活动开发规范:给 AI 开发活动查阅的一份现状如实、差距列账的规范
用户要开始实现活动和工具调用逻辑,先把「活动怎么开发」写死成 docs/活动开发规范.md。
四条产品语义(本轮问答确认):
  ① 活动只读世界,一切写(台账/发邮件)必须经人类验收才落地;
  ② 活动间数据无强制类型,活动有启动 Schema —— 机械检查为门(required 缺项发补全卡)
    + Agent 案内随时可补;
  ③ 工具调用完全声明式 —— 未注册转人类执行卡+作业指导书(指导段写在工具声明里),
    未授权报错不转人;
  ④ 评价卡暂不做。
另补:工作台视图逻辑以 PRD 目录为语义权威(统一建模:AI Loop 自主、阶段可重复、
过程成果逐个验收;工作事项两类执行/验收、决策在对话区、三类同级唤醒事件、气泡二元制)。

写法纪律:**现状与目标分开说** —— 已就位的机制带 file:line(三路并行探查 + 关键行
逐条回源复核),产品要求但代码未到的标 ⚠️ 并汇总第 12 章待实现清单(11 条主账)。

**编排层确认满足**语义②:起单宽进、flatScope 零类型铺平、节点入参全铺下游自取、
出口载荷从落地事实推导、闭合只查结构+装载 —— 各有代码与测试证据,已写进第 5 章。

探查顺带钉出的两条要账(debt.md 已记,指向规范第 12 章):
  · 写类动作意向登记后**永不执行**(submitForRelease 无调用方,意向永停 drafted);
  · 工具未命中现状是抛错+拒装,转人链路整条待建。

本轮只出文档,不改一行代码。五闸绿(纯文档,跑闸当回归保险)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 02:56:36 +08:00
ChaiHaoandClaude Opus 5 61ee63e6dd 模型卡改矮:图标一列 + 文字一栏对齐,图标恒蓝
· **矮**:132 → 96px。状态不再是横穿整卡的填色带,收成一行小字 + 一枚钮;
    段距、字号、图标各降一档。
  · **对齐**:名字 / 厂商型号 / 状态**同一条竖线起头**,与图标并成一块 ——
    从前名字与型号缩进 48px、状态条却横到卡边,三条线各走各的。
  · **图标恒蓝**(与全站主色同一支 #3370ff,不再靛紫):它是**身份**不是状态 ——
    能不能用由状态行说;先前未绑定就把图标灰掉,结果两条全灰、整片死气。
    「去配置」改实心蓝:那是这张卡上唯一该点的东西。

交互复核:⋯ 菜单仍落在卡内(短卡下 top 跟着上移)、去配置开抽屉、Esc 关得掉。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 02:09:14 +08:00
ChaiHaoandClaude Opus 5 da8ac8f9bc 模型实例卡重做:名字不截、密钥不撒谎、不可用就别摆统计;只留 flash 与 pro 两条
三条毛病一次改净:

**① 名字被截断**。用途名是活动里声明的那个名,看不全等于没显示 —— 卡面改成
   40px 图标 + **名字独占一行、折行也不截**(overflow-wrap: anywhere),
   厂商与型号退到第二行小字。

**② 「已绑定」是谎**。种子从前塞一个 `sk-placeholder` 冒充密钥,卡上写着「已绑定」,
   一自检就是 `api key ... is invalid`;抽屉里那格也照「是不是新建」写占位,
   于是没钥匙的实例也显示「已绑定 · 留空保持原值」。现在:
     · 种子**读不到环境密钥就不绑**,如实显示未绑定;
     · 抽屉的占位与判词改看 `keyBound` —— 没绑就写「还没有密钥 —— 不填这条实例调不动」。
   **界面撒谎比缺功能更坏**:缺功能人会去补,撒谎的人会照着假状态做决定。

**③ 不可用还摆一排统计**。没密钥连调都调不起来,「系统用途/端点」那些格没有意义 ——
   未绑定时卡上只剩一句判词 +「去配置」;绑好了才谈端点与「测试」。
   系统用途从卡面撤了(用户:不要管是不是系统用途,两条都能用)。

**只留两条实例**:`deepseek-v4-flash` 与 `deepseek-v4-pro`,都不预设系统用途。
配套两件:
  · `pickSystemUse` 加**回落** —— 没人勾就取第一条能用的(启用且已绑密钥);
    从前非勾不可,没勾那天系统叙述整条哑掉,那是配置疏忽不该变成功能缺失(补了三条测试);
  · 六个活动包里声明的用途名 `quote-extractor` 改指 `deepseek-v4-flash`,各升一个补丁版。

顺带补 `DELETE /api/gov/llm/:id`(卡上 ⋯ 菜单):还有活动声明着这个用途名就拒(409)——
删了那些活动一调模型就是「用途名未绑定」,而人当时以为只是清一条没用的记录。
实测:用它把库里遗留的 quote-extractor 删掉,现在库里就是那两条,卡上如实写「未绑定密钥 · 不可用」。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 01:53:42 +08:00
ChaiHaoandClaude Opus 5 fffb46eae7 修抽屉两处真故障:详情页里被压成 129px、portal 后令牌全失效变透明
用户报「点开连输入框都看不见」,我前两轮量的是货架那条路 —— 那条本来就是好的。
**走详情页进去才踩得到**,两处叠在一起:

① **抽屉被钉进详情卡里**。`.g-drawer` 是 `position: fixed`,而详情页容器 `.g-detail`
   带着入场动画的 `transform` —— **带 transform 的祖先会成为 fixed 的包含块**,
   于是 `inset: 0` 解析成那张卡的盒子:实测面板矩形 520×**129**,头尾一挤,
   中间的输入框整片没了。改走 `createPortal` 挂到 body,与 DOM 位置解绑。

② **portal 之后面板变透明**。整套令牌(--card / --cline / --ink …)定义在 `.gov-root` 上,
   挂到 body 就出了那个作用域:实测 `background-color: rgba(0, 0, 0, 0)` ——
   顶栏与页面内容从抽屉里透出来,字叠字。修法是把 `gov-root` 类跟着portal 一起挂,
   并给面板背景与边框留了字面兜底值。

顺带:z-index 60 → 120(压过顶栏,先前顶栏那一条压在抽屉标题上)。

实测两条路都验:详情页与货架各开一次,面板均为 (760, 0, 520, 577)、背景 rgb(255,255,255)、
四个输入框全在屏内;详情页测试连接照旧只测不存(判词是厂商原话),Esc 与遮罩关得掉。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 01:36:44 +08:00
ChaiHaoandClaude Opus 5 51567d3b3b 接入模型抽屉:输入框一屏装得下 —— 供应商收成一行小签,身份两栏并排
上一版量出来是真看不见:视口 577 高、抽屉身只有 442px,而「模型」落在 y=557、
「用途名」落在 y=649 —— **定义这条实例是什么的两个字段全在折线以下**,点开只看得见
供应商牌子和端点。病根是把最不决定性的东西摆得最大:5 枚 146px 宽的大牌子一个人吃掉 118px。

重排(按决定性从大到小,且一屏装得下):
  · 供应商 → **一行小签**(圆角 chip,默认端点挂 title),118px → 30px;
  · 身份 → **用途名 + 模型两栏并排**(短字段不该各占一整行);
  · 连接 → 端点 + 密钥 + 测试连接;
  · 开关收进末段,说明并进同一行。
  段距 16→13、头尾 padding 各收 3–4px,长句说明砍短。

实测同一视口:四个输入框底边 258 / 258 / 366 / 450,**全部落在可视区(≤520)**;
「测试连接」487 也在;编辑态整屏不用滚(scrollHeight ≤ clientHeight)。
保存往返、密钥留空保持原值、Esc 与遮罩关闭,全部复核过。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 01:22:57 +08:00
ChaiHaoandClaude Opus 5 f9318b1ae9 接入模型改成右侧抽屉:先挑供应商、再填连接、当场测连通(且只测不存)
上一版是把字段倒在地上:整页宽的内联卡、输入框拉到 1100px、动作钮掉出屏幕。
照模型接入面的通行做法重排 —— 520px 右侧抽屉,头固定 / 身滚动 / 底动作栏常驻:

  ① **供应商**:一排可点的牌子,挑中即预填它的默认端点(没有默认的标「端点自填」);
  ② **连接**:API 端点 + API Key(密码框带显示切换),下面就是「测试连接」;
  ③ **型号与用途**:模型(厂商侧型号名)+ 用途名(活动里声明的那个)+ 两枚开关。
  遮罩点击与 Esc 都关得掉 —— 抽屉盖住整屏,不给键盘出路是把人关在里面。

**默认端点从服务端取**(新 `GET /api/gov/llm/providers`):前端不自带一份 URL 表 ——
那种表迟早与 provider 档案漂移,而漂移那天没人会发现(端点错了只表现为「连不上」)。

**「测试连接」只测不存**(新 `POST /api/gov/llm/probe` + `llm.probeDraft`):
拿表单上正填的四元真发一次最小调用,一个字节不落库;密钥留空则取该实例已存的密文,
改端点、换型号不必重打钥匙。上一版是「先存再试」—— 人只想知道钥匙对不对,
结果端点被改了、实例被建了,点取消也收不回来。实测:改错端点后测试,
库里 instances 逐字节未变(测过 before/after 全等)。

顺带补 `eye-off` 图标。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 01:10:49 +08:00
ChaiHaoandClaude Opus 5 21aea48c6c 大模型区能配了:四元绑定就地改 + 连通自检,不再是只读橱窗
后端的 upsert 与 probe 一直在(`POST /api/gov/llm` · `/api/gov/llm/:id/probe`),
只是**界面从来没用过**:进去只看得见「密钥已绑定」,却没有一处能绑 —— 那不叫配置面。

现在:
  · **实例卡**能配:名 / Provider / Base URL / Model / API-Key / 启用 / 系统用途,
    列表卡上一枚笔就地开表单,详情页也有同一张表(同一个组件,不写两份);
  · **API-Key 只写不读**(OS 7.3 凭证隔离):服务端永不回显,所以留空 = 保持原值,
    不是清空 —— 实测改型号后 `apiKeyBound` 仍为 true,密钥没被空表单洗掉;
  · **Base URL 留空取该 Provider 的默认端点**;`openai-compatible` 没有默认,
    前端先拦一道(服务端也拦)—— 不填就是连不上,别等自检才知道;
  · **连通自检**:真发一次最小调用,通了报延迟,不通把**厂商原话**摆在卡里,
    不改写成一句「连不上」—— 「密钥无效」和「端点不通」是两件要分头修的事。
    实测种子里的 key 是占位串,自检当场说清:`Your api key: ****lder is invalid`。
  · 幽灵卡新建实例(LLM 没有删除路由,所以本轮只验证了改,没造多余实例)。

卡片沿用刚定稿的管理系统风(着色图标 + 状态胶囊 + 计量块);端点那格占两格宽,
主机名不截断。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 00:43:49 +08:00
ChaiHaoandClaude Opus 5 9b286ae4ba 流程卡与活动卡按管理系统风重做:着色图标 · 状态胶囊 · 计量块
上一稿的两段式卡(头行 + 竖线分格)信息没错,视觉是素坯 —— 没有身份色、
没有状态语义色、数字排一排像表格,整片看过去是灰的。按管理后台的规格重做:

  · **头行**:40px 着色图标定身份(流程靛 · 活动青 · 审批琥珀)+ 名/标识 +
    **状态胶囊**(圆点 + 词:生效/上架走绿,下线/停用是灰,下线的图标同步转灰);
  · **计量块**:浅底圆角小块、数上名下 —— 边闭合不全那格整块点红,不只字红;
  · 活动卡的业务分类并进副标行(`rfq-intake · 统一报价`)—— 分类是唯一的一维,
    不值一枚独立签;
  · 卡 12px 圆角软影,悬停抬升;幽灵卡同尺寸虚线位。
  · 计量字号 14px、卡最小宽 288 —— 「14/14」实测不再截断(scrollWidth 核过)。

中途试过一版「图纸风」(流程画几何缩略、活动画芯片、审批画比较器),
用户明确不要:**这是管理系统,不做电路隐喻** —— 图形三件连同珊格纸整体撤除,
只留这一套管理系统语言。

交互不变:整卡可点、⋯ 菜单(编辑/删除)、就地改名、幽灵卡新建/装入,全部复核过。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 00:25:42 +08:00
ChaiHaoandClaude Opus 5 1fd215cf40 范式退役:活动只剩一种、只跑 Loop;审批活动可管;活动库重做
用户定的两件,一并落地。

**一、活动不再分 flow 和 loop —— 彻底退役 flow**
  · `flow-engine` 模块整个删除(runner 379 行 + step-sequence 184 行 + 测试);
  · `paradigm` 从清单身份、`activity_package`/`task` 两张表、任务卡与活动库一并退场;
    `businessModel` 不再是判别联合 —— 只有案例模型(CMMN + 说明书 + DMN)一形;
  · task 的引擎分派从「按 paradigm 取两个之一」收成**唯一的引擎**;
  · `activities/` 四个 flow 活动(A1 受理 / A4 定价 / A6 议价 / A7 归档)各写了一份
    案例模型:阶段照原来的步分,触达世界的项一律 manualActivationRule,
    能算的交 DMN(A1 的三分类 P-03、A4 的 P-01/P-02)不交 Agent;
  · 六个占位槽位的骨架从「机器步落台账 + 一张验收单」改成案例骨架,包版本 0.8.0 → 0.9.0。

**代价写在明处,不假装没有**:`turn-runner` 每一拍都要 `agent.decide` ——
环境里没有模型 key,案例活动一步也走不动。三套端到端(统一报价 / 新建流程包 / 测试台
Trace)整套跳过,文件头写明恢复条件:①有可用模型 ②走法改写成按 Enabled 集推进。
**不许把断言改松让它变绿** —— 绿得不诚实比红着更坏。debt.md 已记。

**二、审批活动可管**(新能力)
  · `sys.approval_template`:审批点**可复用的那一半** —— 审批人看哪几项、按什么名字看、
    怎么催、说什么话。谁来审不在里面(与活动点同口径,运营时轮值);驳回回哪个节点
    也不在里面(那是每张图自己的事,留在节点上);
  · 三条路由 + 引用反查:还被审批点引着就不许删(409),删了那些节点会**静默**退回旧行为;
  · 运行时 `basisOf`:引了模板就按模板筛与改名,没引即旧行为(载荷全摊开)。
    模板改了只影响新发出的审批单 —— 在途单的依据在发出那一刻已定形。

**三、活动库重做**:一区两格 —— 「活动(装进来的)」与「审批活动(配出来的)」,
都用流程卡那套两段式卡片(头 + 四格数据板),幽灵卡当入口(装入活动 / 新建审批活动);
「标准/案例」那一维随范式一起撤,业务分类成了唯一的一维,以行内小签呈现。

迁移 0020:两张表 drop paradigm、建 approval_template。已在开发库跑过并重播种。
实测(丁子乔账号):建「定价审批」模板 → 流程包 A5 属性里选得到 → 引用反查计数正确。
四闸绿(api:check 随本提交)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 23:53:51 +08:00
ChaiHaoandClaude Opus 5 18c3e3fd09 测试台:抽键预检屏与收件箱格一并撤,台面改两栏对开
**抽键预检读数屏删了**。宽进之后它已经不是闸,只是一屏会亮会灭的字 ——
抽得出抽不出,进了活动由受理补全单说了算,不必在门口先演一遍。
镜像服务端正则的那份前端实现(`preflight`)随之退场:一套规则两处实现,
本就是迟早对不上的账。

**收件箱那一格删了**。投给哪个信箱是通道配置的事,不是造这封信的人该操心的 ——
契约里 `mail.to` 放宽为可空,空地址由服务端取在用的邮件通道(与线上真来一封信同一条路)。
信头从三行收成两行:发件人 / 主题 → 正文 → 附件签条。

**台面重排**:从「左读数屏 + 右两段」改成 **两栏对开** —— 左造信(01)、右派人(02),
起单条横跨两栏吸在底边,像仪器前面板压在桌沿上。被测流不再占一整栏:它是一次性的
决定,改成顶部一行卡片,且只在多于一条生效流时才出(没得选的选择器是纯占位)。

实测(丁子乔账号):不写收件箱照样起单成功,起后「停止仿真」连根销毁,
任务 0 / 工作流 0,试跑数据未留。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 22:51:09 +08:00
ChaiHaoandClaude Opus 5 e5cfca638f 运营中心撤掉「数据」区;流程包首页重排:卡有层次、⋯ 管编辑与删除、新建变幽灵卡
**运营 · 数据(活动记忆四层)整个撤掉** —— 记忆的放行口还没成形,摆一个空区不如
不摆;真要做时随「数据资产」一并重开。区表、面归属、shell 映射、KnowledgeHome /
MemPage、活动详情里那枚入口一并清干净;旧深链 `#/gov/memory/layers` 落运营首页
(测试跟着改口径,不留死链)。运营中心自此六区。

**流程包首页**:
  · 「编排要素:四种」这枚计数删了 —— 网关早废,它是句没人用的口号;
  · 卡片重做。从前是「头 + 芯片行 + 一大片空 + 脚注」,158 高全靠留白撑;
    现在两段:头(图标 · 名 · 标识 · 生效版 · ⋯)+ **数据板**(活动/审批/边闭合/版本
    四格等宽、竖线分隔)。段段有内容、段间有线,高矮由内容说了算 —— 实测 111 高;
  · 卡上 **⋯ 菜单**:编辑(就地改名,落在卡面那一版上)/ 删除(整条流,菜单原地翻成
    确认,不另弹窗);
  · **新建按钮变幽灵卡**:虚线卡住在货架末位,与真卡同宽同高(111/111)。

删整条流是新能力:`DELETE /api/gov/process/:id` + `process.deleteFlow`。
生效版这道闸不设(明示动作,不是手滑),在途单那道照设(PinnedVersionError → 409);
**「还有调起规则指着它」由路由层反查** —— process 是 L7,不该知道 trigger 的存在。

实测(丁子乔账号):改名往返、删除被 2 条调起规则如实挡回、幽灵卡建 `tmp-drop`
再删掉整条流,库里回到只剩 unified-quote v4,试跑数据已清。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 22:38:52 +08:00
ChaiHaoandClaude Opus 5 f631b5b8bb 版本号自己定:点编辑,整列版本进编辑态,取消/保存收尾
用户的目的是**自己改版本号**,不是让系统替他递增;顺带把上一轮那些
指示性交互全撤了 —— 这软件给专业业务设计人员用,不需要「点我改」的提示条。

界面:
  · 顶栏 编辑 → 取消 / 保存(与流程图卡「编辑 → 保存」同一套手势);
  · 行内两个字段:号(自己编)与名(各版不同),行尾 删除;
  · 改动攒在草稿里,按保存一趟落库;取消原样退出;
  · **删掉**:改名指示条、「点我改」虚下划线、`删掉 v4`/`激活 v4` 这类复述钮名的浮字。
    只留下禁用态那一句(生效版先停用 / 还不闭合),那不是指示,是钮为什么点不动。

后端 —— 号从「系统递增」放开为「设计人员自己编」,两道闸是数据本身要求的:
  · 撞号拒(VersionTakenError,409);
  · 在途钉版拒改号(那些单正按这个号找定义,搬号等于抽它们脚下的地板);
  · 已完结的单**跟着改指**:号在三处(包的列、definition、workflow.packageVersion)
    一起改 —— 号只是这一版的名牌,搬号连引用一起搬,留痕仍指同一份定义。
    先前写成「跑过单就不许改号」,实测等于任何试跑过的包永远编不了号,是过闸。
  · 名不设闸:标签不参与流转,在途钉版也能改;改名只动这一版(推翻前一日的
    「及于整条流」)—— 各版本正是靠名字互相区分,全同名等于没名字。

路由 POST /api/gov/process/:id/:version/edit 取代 …/:id/rename(单一消费者是本仓前端);
CONTRACT.md 与产品设计.md 同步,api-report 快照随本次提交。

实测(丁子乔账号,测后已 reset-runs 清运行数据):v4→v2→v4 往返,列表、画布图签、
库里三处同步;在途单存在时改号如实报 409 并原样退回。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 22:15:19 +08:00
ChaiHaoandClaude Opus 5 05c0a57cad 四枚头钮真正同款:保存撤掉强调色,按钮字体不再被画布纸面改写
量出来两处差异,都不是错觉:
  · 「保存 v4」挂着 t-go —— 棕字(138,95,28)米边(217,201,164),另外三枚是
    墨字(58,68,82)灰边(216,222,230)。**撤掉 t-go**:可不可存由禁用态说,
    不靠换色抢戏;t-go 留给版本行的「激活」那种真·主动作。
  · 中卡那枚「编辑」字体族是 PingFang 栈,另外三枚是 Inter 栈 —— 因为
    `.g-ver-act` 用 `var(--sans)`,而画布纸面 `.process-doc` 把 --sans 换成了
    中文正文栈(那是给图上的字用的)。立 **--ui-sans** 令牌(控件专用、同栈但
    不被局部作用域改写),按钮改用它 —— 骑在纸上的按钮属于界面,不该跟着换脸。

实测四枚:字色 58,68,82 · 边色 216,222,230 · 字体 Inter · 高 26 —— 完全一致;
保存在可用态 opacity 1、禁用态 .45,是同一枚钮的两个状态,不是两种风格。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 21:18:32 +08:00
ChaiHaoandClaude Opus 5 cae4dbcb76 三卡头线对齐 · 题字调大 · 四钮各归其位 —— 两个「编辑」分工划清
· **头线对齐**:左右卡的头底线与中卡的**图框上边**同一水平(308/308/308)——
    中卡题下不再另画一条线,画布顶边就是它的分割线(几何:14 纸内距 + 26 题行 + 12)。
  · **题字**:9.5px → 11px,疏排大写照旧。
  · **四钮全部住标题栏右端**、同一族(图纸方钮 26 高):
      版本 → 新建 · 编辑    流程图 → 编辑    节点 · 属性 → 保存 v4
    左卡那条独立动作条(.g-veracts)整条撤掉。
  · **两个「编辑」划清**(用户定「标题栏的编辑只作用于版本记录」):
      · 版本卡的编辑 = **版本记录**:开着才出改名条、行尾钮换成删除;不碰画布。
      · 流程图卡的编辑 = 手绘画布;编辑态升为工作区级的做法就此回退 ——
        FlowFigureBlock 收回内部 state(canEdit 回来),两者互不相干。
    停用/激活照旧长在版本行尾(那是某一版的运行时开关)。

实测:头线 308/308/308;头钮 左[新建·编辑] 中[编辑] 右[保存 v4];
点版本卡「编辑」→ 行钮变删除 + 出改名条,画布进手绘 = false;点「完成」还原。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 21:11:51 +08:00
ChaiHaoandClaude Opus 5 89ea6e609c 版本栏动作再分工:启停回到版本行上,新建·编辑·改名住顶条,编辑态行钮换删除
· 顶条只放**建改类**(作用于整条流/工作区):新建 · 编辑 · 改名。
    「编辑」从图卡题行迁来 —— 编辑态升成**工作区级受控状态**
    (FlowFigureBlock 的 editing 提升为受控 props):版本行的按钮语义都跟着它变,
    这不是图卡的私事。编辑中顶条示「编辑中」,收尾走画布里的 保存绘图/取消。
  · 停用/激活是**某一版**的运行时开关 —— 回到每条版本行的行尾
    (矮一号的小钮,行不发胖;行本身照旧点击切版,小钮拦冒泡)。
  · **编辑态下行钮换成删除**:正在改定义的人,手边该是版本管理,不是启停开关;
    生效版照旧禁删(先停用)。

实测:顶条 新建·编辑·改名;平时行钮 停用/激活;点编辑 → 画布进手绘、行钮变删除
(生效版灰);取消 → 行钮变回停用。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 19:29:11 +08:00
ChaiHaoandClaude Opus 5 af2d00a107 编排工作区三卡统一:按键一族 · 标题一规 · 顶部留白一档
量出来的病根:三张头三种几何(左 30px 顶距 / 中 0 / 右 13px),按钮两种血统 ——
而且 .g-ver-act 在 CSS 里有**两份定义互相覆盖**(图纸方钮版 + 圆角芯片版),
按钮忽方忽圆的怪样就是它。

  · 按钮:立**唯一规格** —— 图纸方钮,26 高、白底细线、无圆角;主动作 t-go 黄铜、
    危动作 t-bad 赤。中卡「编辑」(原 dc2-addbtn 蓝芯片)与右卡「保存 v4」
    (原 g-ver-new 蓝芯片)全部换族;g-ver-new 与两份旧定义连 CSS 一起清掉。
  · 标题:三条头同一几何 —— 14/16/11 内距 + mono 大写题 + 底缘细线;
    头行内容一律 26 高(= 一枚方钮),没按钮的头也不塌。
    实测三条头底线 308/308/308,按钮顶 270/270,完全同线。
  · 留白:头下内容起点一律 12px(版本列表 / 图框 / 属性明细)。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 19:18:53 +08:00
ChaiHaoandClaude Opus 5 4cd14d7849 版本栏与节点属性再调:比例 · 四钮同款同排 · 「实现」改成看得出能点的真选择器
· 比例:左栏 196–224 → 228–268(版本行整行排满),右栏 320–1.25fr → 264–1fr(节点属性收窄)。
  · 四枚按键(新建 · 激活/停用 · 改名 · 删除)**同款同排**收进顶部动作条 ——
    新建不再另作一枚蓝芯片挂在头上;白字不换行,右端 v 号去掉(选中行自己亮着)。
    右栏头顺带收掉闲置提示「点节点就地填写」(空态文案已交代),只留脏态。
  · 「实现」下拉从无框文字改成**真控件**:有边、有底、有箭头、焦点有落点 ——
    无框下拉在窄轨里读成一行普通文字,人不知道能点,这是可用性缺陷不是审美偏好。
    实测:7 个选项、换选即入脏态,保存路径原样。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 19:05:16 +08:00
ChaiHaoandClaude Opus 5 541b1c816e 版本栏三改:显示完整 · 动作统一住顶部 · 「实现」明确为链接自活动库
· 栏宽 132 → 196–224:一版一行排满「v4 生效 10 节点 · 14 边」,不再挤成三行。
  · 激活/停用 · 改名 · 删除收成**顶部动作条**(右端注明作用对象 v几,
    换版看,条上的钮跟着换语义);行里只剩事实,不在行内展开小钮。
    改名输入就地在动作条下方展开,不再吊在卡底。
  · 「实现」行改口:标签「实现 · 链接自活动库」,空选项写
    「从活动库链接一个活动 —— 未链接,激活会被拦」—— 节点不含实现,
    链接才算装载,这层语义直接写在控件上。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 18:48:25 +08:00
ChaiHaoandClaude Opus 5 9c947950ce 测试台与节点属性三改:拆盒 · 收色 · 让三件实物说话
上一轮的病根认下来:暗侧是「盒子摞盒子」—— bed/panel/panel2 三层深蓝几乎同色,
每节各带一条填色题头栏,纸信缩在盒子里像张明信片;磷光、琥珀、青蓝、暖纸四个
色温体系打架。节点属性那条竖格线逐行断裂,类型切换是个外来的灰块。

**测试台 · 拆盒**:台面上只留三件「实物」——纸信(暖白)、抽键读数屏(纯黑凹屏)、
起单钮(磷光);其余全部退成台面排版:
  · 左右两栏不再是描边圆角盒,一道竖细线分栏;节题从填色横栏改成
    疏排大写 + 底缘细线 —— 是标题,不是盒盖。
  · 被测流选中态只亮一道磷光左棱 + 提亮文字,撤掉整块青染 —— 色彩留给读数屏。
  · 读数屏撑满栏宽、值放大;「必填」从描框小徽退成缀在键名后的小字 ——
    屏上的字越少越像屏。
  · 纸信撑满右栏成为主角:内距 22px、主题 14px 半粗、正文行高 2;
    纸上聚焦一律墨色加深 —— 琥珀与磷光都留给机器侧,纸只有纸的颜色。
  · 起单条撤掉渐变毛玻璃,平铺台面 + 一道细线。

**节点属性**:335px 窄轨里逐行断裂的竖格线比没有更乱 —— 改标签在上、值在下的
叠排,行距放足,图签味交给 mono 大写与行线;类型切换从灰色分段控件改成
**两枚迷你节点皮肤**:选活动点就是一小块画布蓝,选审批点就是一小块琥珀 ——
切换器长成它代表的东西。

教训一并修:上一轮一段 CSS 替换因原文不匹配**静默没吃上**(没加 assert),
截图看着旧样还以为改了 —— 这轮逐条 grep 验证每段都落了。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 18:27:00 +08:00
ChaiHaoandClaude Opus 5 f8f208e945 两处 UI 重做:节点属性 = 图签 + 画布同款节点芯片;邮件输入 = 台面上的一张纸信
**流程包 · 节点属性**:泛用表单换成**图签**(title block)——
  · 卡顶一枚从画布上「拎下来」的节点芯片:活动蓝 E8F1FB/4E7DAF、审批琥珀
    FBF0DC/B98432,左上角标同画布 —— 属性改的是哪一件,一眼对上,不用回图上找。
  · 字段收成图签行:76px 标签格(mono 竖签 + 格线)+ 值格,行间细实线 ——
    表格,不是表单;值格输入无框,格子本身就是边界。
  · 出边收成路由小表:带题一行(共用提示住右角:活动点「条件读本节点的输出字段」/
    审批点「条件读审批裁决 verdict」),每行 E号 → 去向 + 去向节点名,条件在值位;
    从前三条重复的长提示删成一条,空条件的语义进 placeholder(留空 = 默认兜底)。

**测试台 · 邮件输入**:表单换成**一张纸信压在暗台面上** —— 整台仪器里唯一的浅色面,
把「机器说 mono、信是外界」推到视觉结论:
  · 暖白纸面(FBFAF6)+ 纸边细线 + 投影浮起;信上全是无衬线,标签是小号暖灰。
  · 解剖照邮件写:信头三行(发件人 / 收件箱▾ / 主题加粗)→ 正文(纸上的一片空,
    不描边不描线 —— 写信不是填表,resize 手柄也摘了)→ 附件签条(虚线隔开,
    纸质小签 + 「加一个 BOM」虚框钮)。
  · 聚焦色在纸上转琥珀(纸是暖的,磷光绿留给机器侧)。
  实测:改坏主题 → 预检 0/2,改回 → 2/2 —— 灯对纸上的字照样实时。

旧 .tb-ml / .g-att 两组样式退役。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 18:11:44 +08:00
ChaiHaoandClaude Opus 5 6cff6ab34c 删掉节点的「说明」字段 —— 它填得进、存得下,却从来画不出来
`sub` 声称是「画布上的第二行小字」,但画笔里那支只在 `variant !== 'business'`
(步骤图)才走,而全仓的调用点一律是 business:这个字段写了、存了、
一次也没显示过。属性面上那句提示是句假话。

整条清:属性面的一行 · `ProcessNode.sub`(契约) · `FlowNode.sub` ·
图↔包两处映射 · 画笔里那支画不出来的分支(连同它带来的「两种画法」分叉,
现在节点框里就一行活动名) · 节点宽度算法里 `node.sub || node.ghost` 的宽框判据
(sub 没了,只剩 ghost 决定宽窄)。

存量数据不受影响:库里没有一条带 sub 的定义(查过),schema 非严格,
真有旧值也只是解析时被剥掉。

五闸绿;契约快照随本提交入库(去一个可选字段,加法的反面,无下游)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 17:48:12 +08:00
ChaiHaoandClaude Opus 5 28623cd1cb 节点属性平铺 —— 不分类,也不写数据契约声明
分类卡(身份与命名 / 数据接口 / 类型与责任 / 链接活动实现 / 出边)全撤:
节点本来只决定这么几件事,分成五张小卡反而把四五个字段摊成半屏。
现在是一列字段直排,字段间一条细线断句:
  节点 ID(只读)· 名称 · 说明 · 节点类型 · 链接实现 · 出边条件(每条一格)。

「数据接口 · 声明」整节删掉 —— 数据契约**归活动自己**,编排面不复述它。
链好实现后只留一枚直达钮:「去活动库看 X 的契约」。

顺带清掉两条一直漏网的说教横幅(前一轮 ⓘ 清扫时因为文案里夹了 <b> 没匹配上):
「编排不带岗位 ——…」与「审批点是系统内置要素 ——…」。前者的意思已收进
「节点类型」那行的提示,后者本就是常识性交代,不必占一整块。

CSS 里 .g-props/.g-propcol/.g-eprops/.g-prop* 与 .g-dif* 两组样式随之退役,
换成一条 .g-nodeform。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 17:29:11 +08:00
ChaiHaoandClaude Opus 5 5414e99778 清掉「节点决定数据契约」的三处遗留 —— 编排面从此一个字段都不碰
讨论定的界线:节点只决定四件(身份 · 类型 · 链接哪个活动 · 出边条件),
数据契约全归活动自己(它的 manifest,随活动升版),流程包的 callInterface 是
「这条流被调用时的签名」另算。照此清三处化石:

  ① `ProcessNode.in/out` —— schema 上还留着「这个节点**声明**吃什么、吐什么」,
     注释还写着「闭合校验以**边映射**为准」;边映射上一轮已退役,这两行是上个模型的化石。
     连同图↔包的两处映射一并撤。
  ② 手绘编辑器属性卡的 **进 / 出 / 查 / 执行** 四行 —— 其中「查」(use)与「执行」(owner)
     连 ProcessNode 都没有,填了保存就丢:写了不生效的输入框。
     同卡里**网关**与**卡点**两支也一并删(两种要素早已从模型里去掉,分支不可达,
     而且正是网关那支在写 owner)。
  ③ 只读图双击卡的 **执行** 行、`onEditNode` 的 owner 形参、画笔里的**责任人角标** ——
     编排不带岗位,图上不该画它。上一轮图例注释说「图上早已不画责任人角标」其实说错了:
     画笔一直画着,只是没人写得进 owner;这次真的撤了,注释也改对。

连带:`FlowNode` 的 owner/in/out/use 四个字段退役;岗位选择器 support.tsx 成了孤儿
(depcruise no-orphans 当场逮住)—— 编排不带岗位,它没有归宿,删。

四闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 16:44:30 +08:00
ChaiHaoandClaude Opus 5 c9ac058bdf 三面拆分⑯:流程包详情改三栏 · 字段只声明 · 版本可删可改名
**字段只声明,不做任何要求**(用户定):编排层不再碰字段 ——
  · 激活闸只剩两面:结构闭合(dangling-node / multi-default-edge)与活动装载
    (unknown-activity);字段类的检查(同名不同型、容忍分支被必填依赖)全部退役。
  · 节点属性卡的「数据接口」从「推来源」改成**纯声明**:照活动契约列出吃什么、吐什么,
    不标必填、不推来源、不提补全 —— 缺了怎么补是**活动内实现**的事,不在这一层现形。
  · 字段类型支持数组:统一写成 `T[]`(如 `any[]`),出口口的字段也带上类型
    (原来只有字段名)。实测 A2 的 benchmark 口显示「rows any[] · needSourcing boolean」。

**详情页改三栏**:左窄轨版本(132px) | 中流程图 | 右节点属性。
  · 版本条一版一行(v几 · 状态 · 点/边计数),动作只在**看着的那一版**上展开 ——
    窄栏放不下每行一排钮,也不该让人误点别版。
  · 删掉「激活 · 双判据」整卡:没选节点时,属性栏就地列出还差哪几条(点一条定位过去);
    两面都齐时盖一枚小检验章,不再占一整张卡。
  · 删掉节点拣选行 —— 直接在图上点节点。
  · 属性卡用包壳绝对定位:行高由中栏的图定,属性长了在卡内滚,不把图拉长
    (实测卡高 467、明细内容 1039、可滚,图框不受影响)。窄轨里属性小卡改单列竖排。
  · 顺带校正:上一轮那条「图框下沿对齐左列底栏顶线」的 20px 留白,
    三栏改版后左栏已无底栏,没有对齐对象了 —— 改回四边等距(18px)。

**版本可删可改名**(新):
  · 删:生效版不可删(先停用,ActiveVersionError → 409)、在途钉版不可删
    (那些单要按它跑完,PinnedVersionError → 409);删掉正看的那版会落到剩下的最新版,
    一版不剩就回货架。
  · 改名:名字是**这条流的身份**,一次改及于所有版本 —— 版本列表上只显示 v1/v2…,
    若只改一版的名,列表上什么也看不见,人会以为没生效。
  · 5 条单测守两道闸与改名口径;实测走查:改名落库 → 改回;生效版删 409、停用版删 200。

process CONTRACT.md 与产品设计.md 同步。五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 16:14:54 +08:00
ChaiHaoandClaude Opus 5 f03f23f2ca 编排页两处收口:图框下沿对齐左列底栏;边不再是可编辑对象
**对齐**:图框下边原本停在纸面内距上方,与左列版本卡底栏的顶线差 16px,
两条本该连成一线的横线错开。改法不是拿魔数把图框往下推 ——
纸面改成 flex 列、图框 flex:1 吃满(被栅格拉高时跟着长,不会又浮回上面),
下方留出**恰好一条底栏的高度**:20 = 38(底栏净高) − 18(纸面下内距)。
底栏那侧加 min-height:38 锁住基线,两边注释互指。实测差 0。

**边不再是可编辑对象**:上一轮边已瘦成「顺序 + 条件」,再给它一张属性卡、
一条 E1…E14 拣选行、一套与节点互斥的选中态,就是为一个条件养一整套机制。
按 Mastra 的语义,分支本来就归**发起它的那一步**管
(`.branch([[条件, 下一步], …])` 挂在上一步上)—— 于是:
  · 删掉边属性卡、边拣选行、selEdge 选中态;
  · 节点属性卡新增「出边 · 往哪走」:列出本节点的每条出边(E号 → 去向)与条件,
    单出边显示「无条件直连」,留空即默认兜底;
  · 审批点的提示单写一版 —— 它的判据是**系统注入**的 verdict,不是自己的输出字段;
  · 点画布上的线不再打开边卡,而是选中发起它的那个节点。

顺带清掉三处失真文案:头注与「节点 ID」提示里的「边映射」、空态里的
「边填传递契约(条件 + 映射)」。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 15:13:55 +08:00
ChaiHaoandClaude Opus 5 4cbfea5b46 流程图图例收进图框下沿 —— 删掉「责任」那两格
图例本来是画布下面一个带边框、带钢青左线、带灰底的独立盒子,读起来像图之外
又摆了一块内容。工程图的图例画在图框**里**,不另起一张纸 —— 挪进 .hero,
做成与顶部图签(.cap)对称的一条框内小字:细线横贯整框(负外边距抵掉框内距),
左右 16px 与图签的字对齐同一竖线,mono 9.5px 同一记法。展示态与编辑态共用。

「责任 · 右上角标 责任人」删了:编排**不带岗位**(负责人是运营时分配的),
图上早就不画责任人角标 —— 图例里留着是指着一件不存在的东西。

顺带两处对账:
  · 图签右格原本写「蓝 = 活动点 · 琥珀 = 审批点 · 线标 = 边号」——
    图例进框后这就是同一框内说两遍(蓝/琥珀本来就由图例的图标自己带);
    改成说这张图**是什么**:「顺序与条件 —— 数据按字段名流动」,
    边号那句并进图例的「顺序流 · 线标即边号」。
  · oneLiner 的兜底文案还写着「活动 · 网关 · 顺序流」—— 网关早已去节点化,改掉。

图例小图标从 vertical-align + translateY(-1px) 的手抬改成 flex 居中(行已是 inline-flex)。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 14:44:26 +08:00
ChaiHaoandClaude Opus 5 03eb666ac2 三面拆分⑮:对齐 Mastra 数据流 —— 边只表达顺序,数据按输入/输出字段名流动
用户定的机制对齐:Mastra 的边不传数据,所有约束力靠输入/输出字段(schema 咬合)完成。
照此把「边映射」整个退役:

  · 契约:edge 去 mapping,审批 reject 去 mapping —— 边只剩 顺序 + 条件(读上游
    输出字段)+ 标签/回边。fieldMapping 只留给触发器的起单装配(系统边界)。
    存量包无需迁移:zod 解析时把旧 jsonb 里的 mapping 静默剥掉,图照常有效。
  · 运行时:assemble(边装配)→ flatScope(铺平作用域)——
    起单入参垫底 ← 沿途各输出口字段依次盖上 ← 刚发射的载荷(Mastra 语义:
    下一步的 input 首先是上一步的 output)。下游按自己的契约取字段;
    「__」前缀是运行时自留地,不入业务作用域。审批驳回重开、失败改道同一条路。
  · 闭合校验:边未映射/必填未映射/容忍依赖三条映射类检查退役
    (宽进之下必填有没有着落是运行时补全单的事,不拦激活);
    激活闸只留一条硬伤 —— **同名不同型**:名字即管道,名同型异必坏,
    容忍依赖改按名判。改名映射不存在:名不对改契约,不是加映射。
  · 种子:A2 的入参 material 更名 pn(它就是 PN;上游 A1 发的名就得是它收的名),
    契约 0.3.0、槽位 0.8.0;流程种子边全部去映射。
  · 前端:边属性卡砍掉「映射 · 载荷装配」整节,只剩 E号/方向/条件/标签;
    节点属性卡新增「数据接口 · 按字段名流动」——每个输入字段标出运行时从哪来
    (起单入参 / 上游 X / 补全单),输出口列出发什么名;沿边回溯推导,设计期看得见。
    画布保存与依赖文件导出同步去映射。

E2E 顺带把宽进接进真流:快速归档流的 A3 要 outcome 而流里没人产 ——
测试如实走补全路(等人 → 答卡 outcome=won → 开跑 → completed)。
实测走查:A2 节点卡上 pn←上游A1、rfqRef←起单入参、scenario←补全单,推导全对。

五闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 14:25:27 +08:00
ChaiHaoandClaude Opus 5 8d50ceda6a 三面拆分⑭:宽进收敛 —— 起单不卡缺项,进活动受理归一,信息不全派补全单
用户定的逻辑:「调用活动,输入数据可以不定或者为空;进入活动后受理归一,
信息不全派补全单。」把收敛点从门口挪进活动 —— 三道门口闸全撤:

  · 触发装配:缺必填**不再入死信**(AssemblyResult 的 missing 改 partial,带上已装配的);
    装到多少带多少照样起单。死信只留给真错误(勾了确认没指定人这类配置错误)。
  · process.start:撤掉调用接口缺项闸 —— 从前缺一个字段整条流都起不来,
    现实是客户来信本来就常缺客户码,拦在门外等于要求外界替系统把信息备齐。
  · task.start(替代旧 AM 12.1「缺项不得启动」):缺必填的任务落成「等人」,
    缺的字段做成**补全卡**(elicitation,标签取 schema 的 title)发到负责人的
    任务对话流,并武装 human 监听(IntakeDesk 端口;不占活动的人卡预算)。
    答复只收契约声明过的键,合并进 data;齐了或答「没法填」才转 running 开跑;
    答一半就就缺的部分再派一张卡。等人期间谱一步不走、不扣步数。

  · 测试台预检改成**信息**不是闸:灯灭不拦起单,文案直说
    「抽不出的键由受理补全单找人收齐」。

5 条受理归一单测 + 全链实测:投一封只写「想问下工控板价格」的信(零键)→
流照起 → A1 落负责人工位、等人、补全卡在对话流 → 答卡(customerCode/rfqRef)→
任务醒、合并、谱跑 3 步到验收。修一处接线错误:监听 deadline 要 ISO-8601
时长(P2D)不是时刻,传错整个补全监听静默没装上。

trigger/task/process 三份 CONTRACT.md 与产品设计.md 同步(宽进纪律成文)。
五闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 13:46:13 +08:00
ChaiHaoandClaude Opus 5 f9b2c07731 三面拆分⑬:触发确认链路 + 运营中心「工作流」区 —— 设计只管设计,运营管细节
**触发确认链路**(用户口述五步的第 4/5 步):
  接收邮件 → 分类识别 → 命中 RFQ 事件 → ④(可选,运营勾)系统消息到指定人
  工作台(带邮件内容)→ ⑤ 工作台点「确认起单」,流程才起。
  · 命中不等于必起:勾了「需人工确认」,装配好的入参存成待确认单
    (sys.trigger_pending,migration 0019),ConfirmDesk 端口把带来件内容的
    系统消息送指定人(eventRef 挂票号,消息列表就地贴确认状态与那枚钮)。
  · 先认领后起单:consumed_at 空才认得到 —— 两人同时点、一人点两次,都只起一条流;
    起单失败退回认领,不留死票。确认人记进 source.by,留痕可查。
  · 登记触发不走确认(登记那一下本身就是人在确认);勾了没指定人 = 配置错误入死信。
  · 4 条单测 + 全链实测:投信 → triggersHit=1 且零直起 → AI 工作台收到确认消息
    → 确认起单 → 二次确认幂等回同一流号 → source.by = AI。

**运营中心重排**(区名即运行时:工作流是流程包的运行时,任务是活动的运行时):
  · 新「工作流」区:在途看板(从任务区迁入)+ 运行配置 —— 每包的触发器
    起单开关 / 确认打勾 / 确认人,和节点负责人(sys.node_owner)。
  · 负责人三层:显式指派 > 运营配置 > 轮值 —— 合并点在 process.start,
    复用既有派发链一行不改。
  · 任务区瘦身成活动运行时(任务/审批/需处置);知识库区改名「数据」
    (与设计中心的知识库解开同名);系统区只剩通道实例。
  · 设计中心触发器详情页摘掉启停按钮 —— 设计只管设计,启停/确认全在运营。
  · 旧深链有改嫁:tasks/board → runs/board,tasks/trg → runs/conf。

reset-runs 补 sys.trigger_pending(待确认单是运行痕 —— 和上回漏 trace_span 同类洞)。
邮件分类 Agent(第 ② 步)现由抽键正则 + S-FEEL 代位,升级路径记进 debt.md。
产品设计.md 运营章、trigger/process 两份 CONTRACT.md 同步。

五闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 13:09:16 +08:00
ChaiHaoandClaude Opus 5 70b261d067 测试台重制:浅色桌面上的一台仪器 —— 抽键预检读数屏是戏眼
产品:
  · 抽键预检(新):通道的抽键正则**实时**跑在正打的字上 —— 键名/抽到的值/一盏灯,
    该抽的必填全亮,起单钮才「上膛」发光。从前的头号困惑是投出去才知道
    「抽不出客户码」,现在打字就知道。契约把 extract 规则原文回给治理台
    (正则不是密钥),前端镜像服务端 extractFields 的取料与取值;服务端仍是唯一裁判。
  · 收件箱改成通道下拉 —— 投给哪个信箱决定用哪套抽键规则,手打地址错一位,
    预检整屏熄灯还不知道为什么。
  · 「全派 AI」一键(测试一律用 AI 账号,把项目规矩做成一枚钮)+「全部轮值」清空。
  · 双层页头砍成一层:区壳的英雄头留着,屏内改成一根「仪器顶条」——
    一盏灯 + 状态词,装配态与观测态共用同一根骨架,起单前后面对的是同一台机器。
  · 观测态删掉两枚手动「刷新」(2s 自动轮询早就在),唯一动作是珊瑚红的停止仿真。

视觉:
  · 概念:页面是浅色桌面,测试台是桌上**一台有边有圆角的暗色仪器**——
    不是把纸刷黑(上一版的问题:半迁移的暗色,TRACE 里十几处浅色时代的硬编码
    在深底上要么刺眼要么隐形,如 k-node #161b22 深底深条完全不可见)。
  · 三色律:磷光绿 = 机器活着(灯/命中/上膛);琥珀 = 人(指派/审批/等人/人卡);
    珊瑚红 = 坏(异常/销毁)。其余全是冷灰蓝结构色,集中在一组变量上。
  · 机器说 mono,那封信说无衬线 —— 它是外界唯一伸进仪器的东西。
  · 指派轨:节点挂在一条竖轨上,活动是圆点、审批是琥珀菱形,插了人点亮琥珀。
  · 呼吸灯尊重 prefers-reduced-motion;焦点环全部磷光可见。

实测走查:改坏主题 → 灯灭/计数 0/2/钮退膛/状态行说因;重置样例 → 全派 AI →
起单 → 观测态(呼吸灯+TRACE 示波记录+派工带)→ 停止 → 库里零残留。

四闸绿;契约快照随本提交入库(listChannels 增 extract,加法)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 11:12:22 +08:00
ChaiHaoandClaude Opus 5 72f90f293b 测试台改仪表台:启动输入换成一封信;卡片化触发器与大模型;清掉 ⓘ 说教条
**测试台**
  · 启动输入不再是「调用参数」表 —— 这条流真实的起法就是客户来信,
    界面上就该是一封信(发件人 / 收件人 / 主题 / 正文 / BOM 附件)。
    服务端拿**真通道的抽键正则** + **真触发器的装配映射**推出调用入参:
    测试台自己不解析邮件,否则试通的是测试台而不是这条流。
    抽不出必填就如实报「哪个字段没命中、通道的正则要什么」,不静默起空单。
  · 一屏两大块:左选流,右两节 —— 01 输入配置、02 节点指派。
  · 起单钮只剩一枚(原来页头一枚、RUN 卡里一枚)。
  · 改暗色仪表台:调色板集中在 .g-tb/.g-rig 的一组变量上,
    TRACE 那张树 + 甘特的结构一行没动,只是纸变成了面板。

**触发器 / 大模型** 列表改卡片:一条规则、一个实例都要一眼看全
(何时起 · 起哪条流 · 开没开 / 谁家的 · 什么型号 · 密钥绑没绑)。
触发器卡是 div 不是 button —— 卡里还坐着「改规则」那枚真按钮。

**同类卡等高**:底栏钉在卡底、说明恒占两行、卡头一行截断。
实测同一货架内 13 张工具卡、6 张活动卡、3 张模型卡各自完全等高。

**删掉 19 条 ⓘ 说教横幅**(「只列有生效版的包…」那一类)。
留下的是三种:确认带里的影响说明(点了动作才出现,是决策依据)、
warn/ok 的真反馈、以及「X 不存在」这类空态。

删掉入站邮件演练整屏 —— 它验的那两步已经并进测试台的起单路径了。

新增一条接缝测试:通道抽出来的键叫 keys.customerCode,触发器映射也得照这名字取;
哪头改了名字单还是能起,只是入参悄悄变空、流走到 G1 才莫名其妙地停。

四闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 10:42:01 +08:00
ChaiHaoandClaude Opus 5 331fd25922 知识库补图标 —— 顺带堵掉「图标名写错静默留白」这个洞
左轨那一格是空的:ZONES 给知识库写的 `library` 在 Ico 字典里根本没有,
而 Ico 查不到名字时返回一个**空 svg** —— 图标掉了不报错、不留痕,
八格有图标一格没有,看上去像布局塌了。是用户指出来才发现的。

三件事:
  · 补 library 字形(书脊排在架上,与运营侧知识库的 layers 明显不同形)
  · 查无此名时画一枚虚线空框(字体界的「豆腐块」),不画空气 —— 缺图标得看得见
  · 导出 hasIco,加一条测试逐格对 ZONES / ZM / TABS 的图标名,
    并自证查名管用(不在册的要答不在,否则前三条是空转)
    全库 92 个手写图标名扫过一遍,现在零缺

顺手改掉知识库占位卡的语气:原来用 Clear(绿对勾),读着像给「还没建」打了勾;
换成中性 Note + 三行未建清单。

四闸绿(api:check 未动契约)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 09:02:10 +08:00
ChaiHaoandClaude Opus 5 8cb00d1ff6 三面拆分⑫:设计台九区一级目录 —— 一区一内容,测试台收成单例仿真
设计中心从「蓝图 + 四库」摊成九区,顺序即设计的次序:
蓝图 → 触发器 → 流程包 → 活动库 → 工具箱 → 数据域 → 知识库 → 大模型 → 测试台。
触发器与大模型从「并进流程包 / 塞在系统区」里拿出来独立成区 —— 前者与流程包平级
(不入包结构、不随包版本),后者是设计者天天要碰的东西;知识库先立个诚实的空占位。

一区一内容,于是区内页签栏整条删掉(壳层在只剩一格时收起):
  · 流程包:总览的三枚计数并进货架顶端
  · 测试台:入站邮件演练移到触发器区就地验(它验的正是那一区定的规则)
  · 大模型:从系统区拆出,系统区只剩通道实例

测试台一次只跑一条流。起单前先销毁上一单,刷新页面能认回在跑的那一单,
「停止仿真」把工作流连同它派出的任务、工单、实例、留痕一并拔掉 ——
不留半单挂在别人工作台上。实测:起单 → 1 单落到 AI 工作台 → 停止 → 库里零残留。

功能工具补中文名(migration 0018,读回退到逻辑名),治理台一律主显示中文名。
顺带清掉几处说教式文案(「这些是工具,不是模型 —— 模型是它们跑在上面的发动机…」那类)。

五闸:typecheck / lint / depcruise / test 绿;api:check 快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 04:35:36 +08:00
ChaiHaoandClaude Fable 5 ffb71def4b 修:工作台列表不实时刷新、办完的活不进「已完成」—— 两个 bug 叠在一起
用户实测报的。查下来是两处各自独立、叠在一起才显形的缺陷:

**① SSE 订阅层的 queryKey 与实际键对不上(推送白推)**
TanStack 的失效按**前缀**匹配,而工作台的键都以 `desk` 打头
(`['desk','tasks']` / `['desk','task',id]` / `['desk','messages']`);
订阅层却手写着 `['tasks']` / `['task',id]` / `['messages']` —— 一条也匹配不到。
推送照发、画面纹丝不动。修:订阅层一律取自 `queryKeys`,不写字面量;
`['approvals']` 也收进 queryKeys(app-shell 原来手写)。

**② 推进器推完不广播(压根没推送)**
只有派发器(事件投递)广播;而任务从在办走到终态是**推进器**推的 ——
于是「办完的活不会自己挪到已完成」。修:推进器在 runtime/terminal 真变了时
广播 task + workflow(比对本轮前后,不变不发,免得每两秒给在线浏览器发噪声)。

实测(全程用 AI 测试账号,不碰真人工作台):起单 → 以 AI 身份答验收单 →
浏览器停在工作台,探针记到**任务列表自动重取 1 次**(修复前 0 次),
SSE 三条 touch 齐到(task / task-advanced / workflow)。测完清运行数据。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 03:46:37 +08:00
ChaiHaoandClaude Fable 5 e962bb526b 清运行数据 + reset-runs 补 trace_span:试跑一律用 AI 账号,不碰真人工作台
用户纠正:我在验证测试台时把节点指派给了他本人(Chaihao),七条测试单堆进了
他的工作台 —— 而我自己就有 AI 测试账号。真实员工的工作台是他干活的地方,
不是试验场;混进去的测试单还要他自己分辨、自己清。

- 清掉全部运行数据(reset-runs:50 张表,配置与组织原样保留)——
  柴浩名下任务 0、工单 0;流程包/员工/活动配置一条没动
- **reset-runs 补上 sys.trace_span**:span 是运行痕,与工作流同生共死;
  漏清它,清完运行数据后观测面还挂着 62 条孤儿 span(实测)
- 规矩记进记忆:试跑指派一律给 AI 账号,测完主动清运行数据

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 03:33:44 +08:00
ChaiHaoandClaude Fable 5 d98cdddca3 修:点了通过却以 exhausted 收场 —— 放行落地失败是终态,不是可重试的中间态
用户实测报的:任务起起来了,点通过就卡住,测试台也看不到日志。查下来是一条真事故:

**机理**(证据链完整):`land()` 抛错(草稿与正式版并发冲突)→ 异常穿到推进器 →
推进器写一行 stderr 就 break;而这一拍**已经把 runtime 落回 running、已经扣了
一步预算** —— 两秒后又来一次,空转到 steps 触顶。实测:3 步的活跑了 40 步,
终态 `exhausted`,而真正的原因只在服务端 stderr 里刷屏
(`草稿与正式版并发冲突:2 处字段已被他单改动` 刷了几十行),
任务记忆、界面、trace 上一个字都没有 —— 这正是「看不到日志」。

冲突检测本身**是对的**(多单并发写同一行,基线过期即冲突,不该静默覆盖);
坏的是失败处理。三处修:

① **落地失败落终态**:`land` 抛错 → 就地 `blocked` + 原因写进任务记忆(人读得到),
   推进器再也不会来推它 —— 空转到预算耗尽那条路断了
② **失败在时间轴上标红**:非放行终态的节点 span 走 `fail()` 并带原因,
   不再收成一条无害的「已结束」(从前失败的单在观测面上与走完的单长得一模一样)
③ 顺带修:`listInstances` 没读回 `assignee_id`(写了不读等于没写)—— 上一提交已含

实测复核(真库 + HTTP 全链):正常路径 A1 四步 released、流转到 A4(修复前是 40 步
exhausted);单测三例锁死失败路径(blocked 终态 / 只调一次 land / 不误伤正常路)。
五闸全过,测试台六例端到端照旧绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 03:27:43 +08:00
ChaiHaoandClaude Fable 5 48bc664c7e 仿真测试台(界面):装配一次试跑 → 起单 → 全链 TRACE 看穿(frontend-design 专项)
测试台从「只能造一封邮件」升级成仿真试跑台,两种试法同屏切换:

**装配态**:选生效版流程包 → 按 callInterface.input 现生成参数表单(必填标出)→
节点指派表(每个活动点/审批点选账号,留空即轮值)→ 起单试跑;
起不来把后端判词原样上屏(如「must have required property 'rfqRef'」)。

**观测态**:WF 工作流图签 · DSK 任务落到了谁的工作台(明说测试台不代答)·
**TRC 全链 TRACE(签名元素)** · NOD 节点实例。
TRACE 做成一张走查记录纸:左半 span 树(细线方角枝线),右半同轴甘特(方格纸底纹)。
三处判断值得留:
- 轴的右端**只认已知时刻,不认 now** —— 按 now 收口会被不收尾的工作流 span 拉到
  十几秒,真干活的两三毫秒压成发丝;而根 span 常常一辈子不收尾,拉到「此刻」
  等于替它编了个结束时间
- 未收尾的段用剖面线 + 箭头(图纸的「未完待续」画法)
- 包络(流/节点自己不干活)画尺寸线而非实心条 —— 实心会盖过真正干活的那几笔
颜色只花在动作三色(工具石青 / 模型靛 / 人黄铜),结构走灰阶。

顺带修:区头 desc 是纯文本渲染,里面的 markdown `**` 会原样露星号 ——
六处全清;测试台页签名改「联调试跑」(它现在不止入站邮件)。

实测:真起单三次,指派两处都落地(TRACE 的 attributes.assigneeId 与节点实例
受理人一致);浏览器核对装配态与观测态。五闸全过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 02:46:31 +08:00
ChaiHaoandClaude Fable 5 5fc6dfdfe1 仿真测试台(后端):节点指派 + 全链 Trace —— 起单定向到指定账号,真实任务落工作台
用户定的形态:测试台是**后端检测活动与流程**的,真实任务照旧到工作台
(不然指定账号干嘛)—— 所以测试台只管「起单 + 看穿」,人那一环还是真的。

**节点指派**(迁移 0016 workflow.assignments):
- StartWorkflowInput 增 `assignments {节点id → 员工id}`;分派改三级取人:
  ①节点指派(点名的人在岗就是他)②员工组轮值 ③全员轮值 —— 指派是加法不是替换,
  点名的人不在岗退回轮值(单不能没人接);事件里如实记 `(节点指派)`
- **顺带修一个真 bug**:`node_instance.assignee_id` 写了但 `listInstances` 从没读回来
  (审批箱收件、员工面链条、治理列表全按它认人 —— 写了不读等于没写)

**全链 Trace**(新模块 trace,L2;迁移 0017 sys.trace_span):
- span 由 **Mastra Observability 组件**产出(执行不经 Mastra 图,所以手动打点),
  一开就落库、一收就补 —— 观测面不该比被观测的事晚(不走 exporter 的批量异步路)
- 打点覆盖:工作流 root → 节点(记着派给了谁)→ 活动内每次工具调用 / 模型调用 / 人卡
- **root span 挂在 `runtime.begin`**:那是「单已建好、还没进第一个节点」那一刻 ——
  挂在 start 返回之后就晚了,起单同步走到第一个节点,节点 span 会先出生、另起孤树(实测)
- 观测尽力而为:写 span 失败吞掉,不掀翻业务
- 三样东西各管各的:trace(机器读时间轴)/ 任务记忆(人读留痕)/
  **工作区报告(活动自持的 HTML)** —— 谁也不替代谁

路由:`POST /api/gov/testbed/run`(带指派起单)、`GET /api/gov/workflows/:id/trace`。

端到端六例(真库):指派生效 / 任务真落到被指派人手上并由他答单 / 下游节点同样生效 /
全链 span 逐层挂得上且耗时齐备 / 一条流一个 traceId / 不指派照旧轮值。五闸全过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 01:43:49 +08:00
ChaiHaoandClaude Fable 5 9df2294f6e Mastra 胶合层:FlowRuntime 的第二实现 —— run ↔ 实例,发号权留在主工程
编译器只管推图,胶合层管一单一单的账(createMastraRuntime):

- **发号权在主工程**:实例号 nextInstanceNumber 算、sys.node_instance 落笔;
  Mastra 不发实例号也不发任务号(spike 实测)
- **run ↔ 实例**:runId = <workflowId>#<seq>,重开 = 新 run(seq+1),旧 run 冻结;
  当前 run 的入口记在 vars.__runEntry —— 重开后从回边目标那份变体起步
- **迟到 / 重复回调不甩给 Mastra**:先在实例表定位、确认是当前 open 的那个,
  不是就发 stale-callback 丢弃(spike 实测:错投的 resume 会打坏 run,
  嵌套下甚至不可恢复)
- **失败走向不进 Mastra**:改道/升审批/容忍都当「从目标节点重新入场」,
  起一个以它为入口的新 run —— 绕开 .parallel() 那套「任一失败即整体失败」
- **状态仍是聚合投影**:refreshState 读 sys.node_instance,不读 Mastra 快照
  (run 只有 running/suspended/success/failed,没有「收敛未到终点=abnormal」)
- MastraRunner 是 Mastra 侧的最小口子(startRun/resumeRun),换版本只改它

四闸过。**尚欠**:MastraRunner 的真实现(Mastra 实例 + PostgresStore 挂
mastra schema)与接线开关 —— 编译器与胶合层都有单测但没在真库上跑过整条流,
转正前自持实现仍是唯一在跑的路径;已如实记进 debt M5-1。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 00:19:37 +08:00
ChaiHaoandClaude Fable 5 0ba3a80e13 Mastra 编译器落地:流程包 → workflow(路线 B)—— 回边成出口,变体各带入口
按 spike 实测结论(spike/mastra-reopen/FINDINGS.md)落地 M5-1 的编译器:

- **回边不连回去**,落成回边出口步骤:本 run 到此为止,把
  `{reopen, reopenedBy, reopenTarget, payload}` 写进 result,胶合层起新 run。
  1 run = 1 实例,与「重开产生新实例、旧实例留痕不动」一一对应
- **每个回边目标各编译一份「以它为入口」的变体**(`<包id>@<节点id>`)——
  新 run 只能从入口起步;种子 unified-quote 编出 `@start` 与 `@A4` 两份
- 条件出边 → `.branch()` + **XOR 收口步**:Mastra 把未命中的分支键也放进输出
  (值 undefined),收口步过滤并断言恰一条 —— 「恰取一条」运行时照旧成立;
  条件谓词排掉「前面已命中」的情形(Mastra 求值非短路),无条件边作兜底,
  连兜底都没有时留一条「全不中 → 死路诊断」的出路
- 活动点/审批点 → 「起任务 → suspend()」,副作用写在 `if (!resumeData)` 里
  (实测 resume 时 execute 从头重跑,不这么写会起两次任务、旧的成孤儿)
- 编译期全验:悬空边、正向边成环(未标 reopen)当场报 —— 编译只走到得了的边,
  悬空边会落在递归碰不到的角落(实测:多默认边情形下 E9 压根没被编译)
- Mastra 泛型桥接收在两个薄工厂里,不把类型逃逸撒满文件

测试:编译器四例(变体/无回边/成环/悬空)+ app 层一例(种子真图编得出来);
五闸全过。胶合层(FlowRuntime 的 Mastra 实现)与 CONTRACT/debt 对账随后。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 00:15:07 +08:00
ChaiHaoandClaude Fable 5 ce59e4e1e4 spike:回边 reopen 的 Mastra 表达 —— 结论走路线 B(新 run = 新实例)
隔离验证(spike/mastra-reopen,@mastra/core@1.53.0,不属主工程、不受产线闸约束),
两条候选各写可跑原型 + 6 探针 + 2 反例,三场景全通。**结论有运行输出支撑**。

推荐**路线 B**(回跳 = 结束本 run,胶合层用同一份定义起新 run),两条决定性理由:
① 语义对齐:1 run = 1 实例 —— 新 runId / 新任务 ID / 旧快照冻结全是引擎自带;
   路线 A(dowhile)里第二轮 A4 是同一 step 的重跑,**引擎会覆盖第 1 轮记录**
   (实测:第 2 轮开始时内层快照 context 里 A5 那一格直接消失),与
   「重开产生新实例、旧实例留痕不动」正面冲突;
② 健壮性:误 resume(迟到/重复回调 —— 我们的活动终态本就来自不受控的外部调用链)
   在 A 下把整条 run 打成**不可恢复的 failed**(补正确 resume 也救不回),
   在 B 下只是抛异常、run 毫发无伤。

其余实测事实(FINDINGS.md 全文):dowhile 内 suspend/resume 可用但**定位不到轮次**
(forEachIndex 对 dowhile 是哑参;不存在的 resumeLabel 会静默命中当前挂起 step);
.branch() 条件在源步终态后一次性全求值、拿得到 requestContext;
.branch() 输出含未命中的 undefined 键(收口步必须允许);
step 的 execute 在 resume 时从头重跑(副作用必须写在 if(!resumeData) 里)。

FINDINGS.md 第 6 节给出了走 B 的编译器七件事,下一步照它落地。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 00:04:35 +08:00
ChaiHaoandClaude Fable 5 9845516a61 文档:编排层 Mastra 化四阶段状态对账 —— 解耦已达成,编译器待 spike 结论
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 23:57:50 +08:00