 xcsandClaude Fable 5
|
fba82c71dc
|
mail 用例测试:拉取 / 去重 / 逐封游标 / 失败停位 / 分发三态 / 重新投递 / 附件原件
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 01:38:01 +08:00 |
|
 xcsandClaude Fable 5
|
78e36ab73c
|
修复轮1:凭证解不开时明文经 SyntaxError 泄进 last_poll_error;同键在飞的那封会被当失败行重发;发成功不清上一次的错误话;卡死的 dispatching 给人手一条路
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 01:29:24 +08:00 |
|
 xcsandClaude Fable 5
|
79fd25e1c1
|
mail 测试夹具:内存 store 排序与真 store 严格同序,补两处差异注释
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 01:11:48 +08:00 |
|
 xcsandClaude Fable 5
|
1328aeb142
|
mail 用例:账号建改删与探测(草稿探测可借库里密文;wecom 探到地址回填);收发用例同份落地待测
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 01:08:48 +08:00 |
|
 xcsandClaude Fable 5
|
b9a4af9a2a
|
mail adapter:postal-mime 解析器(GBK 字头 / 群组地址 / References 拆串 / 附件字节)+ 测试夹具
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:59:40 +08:00 |
|
 xcsandClaude Fable 5
|
d65579c0d8
|
修复轮1:mail 账号列表排序键还原为 name(与 channel/llm 惯例一致),测试改断言集合而非顺序
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:53:28 +08:00 |
|
 xcsandClaude Fable 5
|
5f1e64b4d4
|
迁移 0033:邮箱账号 / 入站 / 投递 / 出站四张表;mail store 与跨进程租约(两连接对抢 20 轮每轮一个赢)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:49:24 +08:00 |
|
 xcsandClaude Fable 5
|
8d7e56aa92
|
mail domain:发信校验与选账号(from 不静默回落)、分发状态机、账号记录与视图(密文进不了视图)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:28:02 +08:00 |
|
 xcsandClaude Fable 5
|
6748ef01b7
|
mail domain:解析结果 → 入站记录 / 视图,附件与原件按上限分存留注,厂商原话脱敏三形
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:26:08 +08:00 |
|
 xcsandClaude Fable 5
|
83f65b2785
|
mail 模块骨架:契约 / 端口 / 领域错误 / 游标两形 / 到期与租约(ADR-013)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 00:11:14 +08:00 |
|
 xcsandClaude Opus 5
|
5facf6b745
|
名册同步补三道下限保护;同名让位;停用判定走在 JIT 写之前
**C2:一次同步能把所有人停用,而停用之后没有界面能救回来。**
「本地有、远端无 → 停」是有意的,但没有下限:①`listUsers()` 因任何原因回了空数组
(realm 配错但存在、代理 200 空体、view-users 被改窄)→ 全表 disabled;②更可能的是
**Admin 的 `GET /users` 不返回服务账号用户**(手册 §14.5 为此单列一条接口)——
e2e 与试跑的 AI 账号是首登 JIT 建的,本地在册、远端查无此人,**第一次点「同步名册」
就把它停了,再同步多少次都回不来**。而恢复动作 `POST /api/gov/staff/sync` 要 ops,
ops 要一个 active 的 principal:全员停用之后这条路自己把自己锁死,只剩去库里手改 state。
三道闸(两个触发面分别被后两条挡住,第一条是最后的网):
- `diffRoster`:`remote` 为空时不产出「缺席即停」—— 远端一个人都没有,更像取数出了问题;
- `diffRoster`:`testAccounts` 豁免「缺席即停」(新入参,必填 —— 只有装配层知道哪几个是
服务账号),判据用既有的 `isTestAccount`(不分大小写、忽略空白);
- `syncRoster`:落 setState 之前用**同步后的活跃员工角色集**(新纯函数 `activeRolesAfter`)
跑一遍 `assertNotLockedOut`,不过就整体拒绝、一条都不写;路由映射 409(与
setRoleAccess 那两条同款,`syncStaffRoute` 从前没有这个 catch)。
`AccessLockoutError` / `assertNotLockedOut` 收可选 message —— 两个来路拒绝的理由不同,
给人的下一步也不同(这条指向「先核对 provisioning 指的是不是同一个 realm」)。
**I3:JIT 与同步撞 `account` 唯一索引 → 500,且此人从此登不进。**
Keycloak 里删了人再建一个同名的(或用户名被让渡),新 sub 走 insert 就撞
`staff_account_key`,`server.ts` 的 onError 把 PG 原文原样回给调用方。
处置选的是**先查后让位**(不是捕异常):走到 insert 就说明按 sub 找不到他,本地那条同名的
必然是另一个 sub 的 stale 行 —— 把它的账号让位成 `账号#retired-<旧 sub 前 8 位>` 再插,
留一条 stderr;不删那一行(它身上可能还挂着在途工作)。`StaffRepository.findByAccount`
为此回到端口上(退役的是 OrgService 上的那个同名出口,不是仓储这一口)。
同步逐条落库改为**单条失败不停在半路**:失败的人点名进 `RosterSyncOutcome.failed`
(契约变更,api-report 已刷新),三个计数改成**真落下的条数** —— 半途失败的同步
不许报成一排绿数字。
顺手两条:
- `authenticate` 的 JIT 写挪到停用判定之后 —— 一个已停用的账号只要还攥着有效 token,
从前每 60 秒就能驱动一次 updateIdentity 写库;「第一次见到的人要建档」原样保留。
- `keycloak-admin-roster` 自己又写了一遍 dedup+sort+滤噪声 → 改用 `normalizeRoles`。
两处对「同一次归一」的理解一分叉,`identityChanged` 的逐字比对就会天天判「变了」。
测:roster-diff +8(两道下限保护 + activeRolesAfter 四种局面)、org-service +5
(整体拒绝且一条 setState 都没落 · 远端空着不停人 · 服务账号缺席不停 · 单条失败点名且
不停在半路 · 停用账号驱动不了 JIT 写)、同名让位 1(内存仓储照搬了唯一索引这条约束)。
文档:org/CONTRACT.md 不变量与影响半径、API 文档 §0(HEAD / 409)· §3(三道保护 + failed)· §7。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015kAzS35kMnZNt4YGgJXtfw
|
2026-08-25 19:42:19 +08:00 |
|
xcs
|
7978c6faca
|
文档修订:评审四处 —— 「约100」改实数59(governance-ops 45 + governance 14)、ADR 引用改实际文件名、CONTRACT.md depcruise 措辞改准
评审指出「约 100 处守卫」是把行数(每处两行)误当处数,实测切换前 governance-ops.ts 45 处
+ governance.ts 14 处 = 59,其余路由文件 0 处;ADR-012 与 CLAUDE.md 各改一处。
ADR-012「后果」段引用的《前端接入手册》仓内不存在,改成实际路径
docs/前端对接说明-统一鉴权中心.md。org/CONTRACT.md「depcruise 已反查确认」改成
「depcruise 全量校验通过」——这一轮跑的是全量校验,不是针对性反查,原措辞强于事实。
|
2026-08-25 18:39:45 +08:00 |
|
xcs
|
aa18701130
|
文档:ADR-012 统一鉴权中心;编码规范鉴权定调改为资源服务器 + 权限只到端;org CONTRACT.md 重写;debt 鉴权段;CLAUDE.md 铁规矩 5/6
|
2026-08-25 18:32:23 +08:00 |
|
 xcsandClaude Opus 5
|
dd31b91829
|
统一鉴权中心接入(ADR-012):org 重写为 Keycloak 身份 + 角色→端;中间件按路由归属统一判;口令/会话/岗位授权退役;迁移 0032
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015kAzS35kMnZNt4YGgJXtfw
|
2026-08-25 17:40:55 +08:00 |
|
xcs
|
4d55ac465d
|
org adapter:Keycloak Admin API 拉名册(provisioning 服务账号,分页 100,只读 view-users)
用 master realm 的 provisioning 服务账号(client_credentials)取管理 token(闭包缓存、
提前 60 秒过期),分页拉全 realm 用户(默认 max=100,必须分页),逐人查
role-mappings/realm/composite 取实际生效的 realm 角色并滤噪声(复用 isNoiseRole)。
非 2xx 一律抛带状态码的错,不吞;secret 不落任何留痕。
|
2026-08-25 16:32:47 +08:00 |
|
xcs
|
43917b559a
|
org adapter:改正 explainJoseError 注释里的继承关系描述(评审 Important)
「JWTExpired 是 JWTClaimValidationFailed 的子类」是错的 —— jose 5.10.0 里两者都
直接继承 JOSEError,implements 只是 TS 结构化类型声明,运行时不建立继承。
判在前的真实理由是让「已过期」这条更具体的话先命中,不是靠父子关系兜底 ——
错误的继承说法会给日后「简化掉」判断顺序的人一个不存在的依据。仅改注释,
两条 instanceof 分支的顺序与内容一字未动,10/10 测试原样通过。
|
2026-08-25 16:28:18 +08:00 |
|
xcs
|
cb143d6413
|
org adapter:jose 验签 —— RS256 写死、校 iss/aud、30s 容差、错误译人话(ADR-012;新依赖 jose,用户已批)
四项校验顺序即安全要点:algorithms 写死 RS256(绝不读 token header 的 alg,否则
alg:none 可绕过)、issuer、audience、clockTolerance 30 秒;jose 的错误经
explainJoseError 翻成人话后包成 TokenRejectedError,排错省时间。测试用
createLocalJWKSet 造本地 JWKS 当 Keycloak 替身,不联网,验签逻辑本身走同一个
jwtVerify。zod 的 .optional() 与本仓 exactOptionalPropertyTypes 有摩擦,
按 claims.ts::identityOf 已有的手法(undefined 就不带键)加了 toVerifiedClaims
做收窄,详见 task-3-report.md。
|
2026-08-25 16:21:17 +08:00 |
|
xcs
|
5108d7a580
|
org domain:claims 归一、角色→端与锁死不变量、名册差异、测试账号策略(ADR-012,纯函数)
为统一鉴权中心(Keycloak)落地铺地基:五个零 IO 的纯函数文件,后续 org 用例
重写(Task 8)直接复用。本任务只加不删 —— 旧的岗位授权 / 口令会话 / 停用检查
原样保留,现役 org-service 仍在用它们。
- claims.ts:token claims → Identity,滤掉三种 Keycloak 家具角色
- ends.ts:角色 → 端的并集,并守住「改完之后至少一人能进运营中心」这条锁死不变量
- roster-diff.ts:与 Keycloak 名册的插/改/停/复活差异(远端说了算)
- test-account.ts:测试账号判定与独立工作组构造(ADR-011 语义原样搬)
- in-flight.ts:停用前置检查要看的在途工作(与旧 disable-check.ts 并存一轮)
contract.ts / port.ts / index.ts / seed-data.ts 均为文件末尾追加,契约变更已
经 pnpm api:check --update 刷新快照。
|
2026-08-25 16:09:10 +08:00 |
|
 xcsandClaude Opus 5
|
a5c8d4786d
|
契约:三个端与路由归属(access 必填)、Principal / 角色→端 / 名册同步 schema、退役路由标 @deprecated(ADR-012)
- packages/contracts/src/api/http.ts:新增 SURFACES / surfaceSchema / Surface / SURFACE_LABEL /
RouteAccess;RouteContract.access 必填;API_ERROR_CODES 增 'gone'。
- packages/contracts/src/org.ts:staffSchema 补 email? / roles(realm 角色快照);新增
principalSchema/Principal、roleAccessSchema/RoleAccess、rosterSyncOutcomeSchema/RosterSyncOutcome、
inFlightWorkSchema/InFlightWork;旧岗位授权(grant* / governanceFunction*)与 sessionSchema/Session
全部标 @deprecated 留一轮(web 编译不受影响,下个迭代删)。
- workbench.ts / governance.ts / ingest.ts:每条既有路由补 access(按所属端/两端共用/退役 public);
新增 meRoute、authTicketRoute(access:'any')与 syncStaffRoute、setStaffPositionRoute、
staffInFlightRoute、listRoleAccessRoute、setRoleAccessRoute、deleteRoleAccessRoute(access:'ops')。
- apps/api 的 org-service.ts 两处 staff.insert 补 roles: [](staffSchema 新必填字段,该文件下个
迭代会整份替换,这里只是让本次 typecheck 过)。
- 新增 packages/contracts/src/__tests__/route-access.test.ts:95 条路由的 access 归属断言。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015kAzS35kMnZNt4YGgJXtfw
|
2026-08-25 15:54:20 +08:00 |
|
xcs
|
d788140548
|
工作成果里摆着别单的资料:「这一单产出的」认本单碰过的行
放行存档(archiveAssetFiles)与在办列单(assetFilesOf)取行都用 taskView(where:{}) ——
那是「正式版全表 + 本单草稿」的合并视图,而资料常落在主数据上,整表里躺着别单放行过的行。
抽 assetRowsOf 两处同用,touched 为必填入参;e2e 补份数断言。
顺手清两笔:wake.test.ts 的 as unknown as(lint 红)、wake 契约的 api-report 快照(api:check 红)。
|
2026-08-25 15:38:10 +08:00 |
|
 xcsandClaude Fable 5
|
f3397a60ef
|
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
|
2026-08-25 01:23:30 +08:00 |
|
 xcsandClaude Opus 5
|
0aa2fc11b0
|
资料文件真产出来了;E04/I01 补到验收线,顺手填了几个「墙拦住却不给路」的坑
**资料文件全链**(用户:审核资料这一步要真产出 word/excel/md/html,前端能渲、点资料名能开)
接手时这一步一个文件都产不出来 —— S3 剧本白纸黑字写着「file_ref 本 MVP 阶段可留空」。
文件是台账那一行的投影,不另存一份:
· 声明 `file:{titleColumn,bodyColumn,formatColumn}`,它同时是授权面(没声明就点不开)
· 现造真字节 —— docx/xlsx 是自己打的 OOXML 包(zip-write:store+CRC32,零依赖)
· 读回来渲 —— 解的就是造出来那份字节,渲得出来才证明文件是真的
· 件上 `data-file-of` → 工作区二级界面(Word 纸面/Excel 网格/渲好的 md/沙箱 html)+ 下载原件
放行落地前把每一份冻进 `sys.task_asset_file`(迁移 0029):归档件点开的必须是签字那一刻
那一份,而资料落在主数据上、试跑单不落正式表 —— 不存这一份,收工后一个都点不开。
工作成果里「产出的资料」自成一摞。Markdown 富文本渲染顺带销账(仍零依赖)。
**Harness**
· 画面按「这一拍办完之后」在办的那一步挑 —— 从前拿拍首的局面决定拍尾的事:
收掉 S4、发出 S5 的卡,而屏上还摆着 S4 的只读件,人无处可填(墙要配路第四次现形)
· 验收「重做」真能退回重做,且打回后台账没动就不许再提交(软硬两段,不锁死单子)
· 立监听的授权面是清单声明;发卡的授权面是调人预算,不是计划项
· 读工具同参重调有兜底;空转写身后还有行动就不废串;finish 的 doneWhen 按写完后的草稿算
**界面**
· 翻件与翻页各归各位(从前二选一,多卡多页时页翻不动);没得翻写「—」不写 0/0
· 工作成果详情能翻份;表宽超出能横滑(E04/I01 抄版式时把 overflow-x 抄丢了)
· 查看面灰底滚过一屏变白 —— 两条独立的路都治了(沙箱内不同色 / 弹性子项不长个)
· 测试台「取不到」不再当成「还活着」
**活动**
E04 关系覆盖、I01 品牌内容各自补到验收线:判据全读基座数、判据指向的东西摆上卡面、
样例满载且名字 ≤14 字;提交前要裁的判据搬进说明书(模型会压拍,压过之后只有说明书还在)。
验收:e2e i01 4/4、e04 3/3 全部 released,资料在办中渲得出、放行后存了档点得开;
门禁 typecheck/lint/depcruise/1628 测全绿。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEJX8Z7CHejvwmDQyPQuBX
|
2026-08-24 10:26:45 +08:00 |
|
 ChaiHaoandClaude Opus 5
|
70e83d0b09
|
工作日志:一行摆首句,展开就把话说完
从前一条只有一行标题,而人真想回看的东西全躺在留痕里没露过面 ——
凭什么算这一步办完了、那一笔落下哪几行、被拒到底拒在哪儿、发的是哪种卡送到哪儿。
现在每条可展开,细节由 detailOf 摘成**一句句人话**(不摆 execution 这类内部名);
摘不出就是空数组,前端据此不给展开钮 —— 点开是空抽屉比不给还糟。
不摆二级条目(用户定):细节不是「键:值」两栏 —— 那是把留痕的字段名搬到人面前,
人还得自己在脑子里连成句子。每句自带主语与语境,单拎出来也读得通。
连带修一处文档与实现不符:「一轮一句」的口径说埋头办事那几拍的交代「留进工作日志」,
而实现把 internal 整类滤掉了,那几句哪儿都看不到。现在带交代的放行,
章写「交代进展」、记在 AI 名下;排障用的内部痕照旧不摆。
两种交代统一「首句上行、全文进抽屉」,一句话说完的不重复摆;截了才加省略号。
契约:任务详情的日志行新增可选 detail(字符串数组),api-report 同批更新。
门禁:typecheck / lint / depcruise / test(1378)全绿;浏览器实测折叠行高 34-36px 齐平、
展开无键值两栏残留。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-03 13:10:46 +08:00 |
|
 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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
f96eff906a
|
工具总线 + Agent 开环:声明式工具、人类工具与 LLM 五件系统内化(Mastra tool 形状)
用户定:Agent 调用工具一律**声明式**;人类工具与 LLM 工具要系统内化;
工具总线基于 Mastra tool 设计。
**声明面**(`toolbox/internal/domain/tool-bus.ts`,纯逻辑零框架):
`compileToolBus(声明 × 目录) → 一张清单` —— 编译期定死这一单能调什么,
清单之外结构上调不到(白名单在缝里再把一次关);缺件/停用如实报不静默。
三路同一形状:
· `function` 功能工具:按活动白名单查目录,带出效应(read/write)
· `human` **人类工具**(系统内化、零声明即得):调人 = 发工单 + 立监听听人 ——
这是 Harness 给的能力,不进目录、不需白名单,每个活动天然可以调人
· `llm` **LLM 五件**(系统内化):extract/classify/summarize/judge/rewrite,
各有入参出参契约、经模型网关一缝;**仅当活动声明了模型用途名才上总线**
(没声明却会问模型 = 越权,用量也无从归因);提示词归系统,活动改不了
**装配面**(`app/tool-bus.ts`,Mastra `createTool`):清单 → 可调用工具,
JSON Schema 现译 zod(模型照它填参,填错当场被拦);三路各穿各的缝:
写类工具**过程中一律不落地**,只登记动作意向(骗 Agent 说已执行是最坏选项);
调人把卡号记进 trace,引擎据此把这一拍挂起。
**Agent 开环**(`app/mastra-agent-runner.ts`,M5-2 第二实现,用户选的路线):
Mastra `Agent` + 工具总线,拍内自主连环调工具,拍末交回结构化结论。
放开的是工具循环不是规矩:写类不落地、终局唯放行、调人即挂起(新增
`AgentAction.asked` 型 —— 卡已由总线发出,引擎只收尾,不重复发卡)、
用量按 usage 计入预算。`JCAI_AGENT_OPEN_LOOP=1` 开启,缺省仍是单拍版。
`ModelGateway.resolve` 新增:名 → 四元(密钥当场解出,只给 app 层装配用)。
代价如实记 debt M5-2:开环下模型**逐轮**调用不经录制回放(tool-calling 往返
`generate` 的 text-in/text-out 承载不了)—— 凭证隔离与工具调用一缝完整。
测试:tool-bus 六例(白名单/缺件/停用/人类工具恒在/LLM 按声明/五件契约);
四闸(typecheck/lint/depcruise/test)全过;spike 目录排除出 lint(验证性原型)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 23:46:12 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
7c609e852c
|
Mastra 化阶段1:抽 FlowRuntime 端口 —— 编排层执行面成为可替换切面,解耦完全成形
目标(用户定):完全实现编排层与活动解耦。解耦线(TaskGateway 起活动 / 终态回报)
本就存在;缺的是 CONTRACT M5-1 那句「Mastra 编译器作可替换 adapter、usecase 不动」
的端口 —— 勘察坐实它此前不存在,状态机直接写在 usecase 里揉着五端口副作用编排。
- port.ts 立 FlowRuntime 端口:begin / onTaskTerminal / applyFailure /
onApprovalVerdict / refreshState / terminate —— 执行面的全部
- 状态机整体迁入 internal/runtime/self-hosted-runtime.ts(逐字搬迁,行为零变化):
enter(调度+组轮值分派+实例落 assignee)、advanceFrom(条件出边选路+死路诊断+
分支不连坐)、失败走向四选一、审批裁决(边优先、声明兜底)、三态聚合投影、终止级联
- process-service 573→248 行薄壳:定义生命周期(保存/激活/校验)+ 起单前置
(取生效版/入参校验/工作组快照/建单留痕)+ 五方法委托;
ProcessServiceDeps.runtime 可注入 —— Mastra 编译产物从这里换入,路由/接线零动
- index 出口 FlowRuntime 型;CONTRACT.md 记切面与已核实的语义冲突清单
(reopen 无原语待 spike / parallel 失败连坐须 step 内自吞 / abnormal 三态 /
node_instance 投影必留);debt M5-1 → 切面已立
等价性护栏:process 49 单测 + 八例端到端真库,提取前后原样全绿 —— 行为零变化实证。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 23:12:04 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
1917320584
|
Mastra 化前置:loop 三修 —— 提交放行发真验收卡、事件只记不跑、轨迹喂回叙事面
勘察(两路 code-explorer)坐实 loop 范式三处真缺口,本轮先修(用户拍板),
与 Mastra 化解耦、按外科手术做(活动内 MVP 期高内聚不过度抽象):
① 提交放行走不到 released:submit/判齐只返回 submitted,task 层当 running
处理,任务原地重跑到预算耗尽(exhausted 而非 released)。
修:提交 = 发**验收卡**挂起等裁决(raiseAcceptance 唯一出口:发卡、立监听、
在途验收入状态信封 sys.loop_state.pending,迁移 0015);判齐重入不发第二张卡;
裁决 pass → finished released(选口随放行带回),reject → finished 不放行。
TurnOutcome 增 finished/released/selectedPorts,engines 接线透传。
② onEvent 双拍:自跑一整拍后 deliver 的 tick 再跑一拍 —— 每次人卡回传多耗
一次不计 steps/activeMs 预算的模型决策。修:onEvent **只记不跑**
(登记 occur / 收验收裁决入信封,存快照即返),推进统一归 tick,预算一个口径。
③ Agent 每拍失忆:memory.window 定义了但零调用,任务自身轨迹从不喂回 prompt。
修:叙事面新增【本任务最近轨迹】段,窗口大小取活动声明的
manifest.declarations.harness.memoryWindow(活动侧唯一记忆配置,不再硬编码)。
测试:turn-runner-acceptance 八例;全量绿,五闸退出码过;loop CONTRACT.md 同步。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 23:02:41 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
f145bde875
|
三面拆分⑲:审批点卸岗位 —— 负责人一律运营时分配,绑员工组,实例记 assignee
模型(用户定):审批点不绑岗位;节点负责人是运营时分配的,绑定到员工组。
- 契约:approval 节点删 approver(功能属性只剩驳回走向/催办/委托消息);
CLOSURE_VIOLATION_KINDS 删 missing-owner-position(岗位不入编排,无岗可核);
治理审批列表删 approverPosition 字段
- 运行时统一口径(活动点=审批点):工作流绑了员工组按组轮值(组员并集最闲者先),
没绑组全员轮值;staffId 稳定排序保证确定性,组员全不在岗退回全员。
ADR-011「绑定先于策略」随岗位退场 —— 工作组快照的成员集合成为轮值池
- 实例记 assignee(迁移 0014 node_instance.assignee_id):分派结果是流转事实 ——
审批箱收件(i.assigneeId === me)、裁决权(同一判据)、员工面链条报实际承接人、
治理台审批列表报人,全部按它认,不再有岗位比对
- closure 卸 positions 入参;desk/desk-approval/governance-ops 三路由改口;
web 属性卡删「审批岗位」选择与警示、positions 管线拆除;种子 A5 卸 PM;
导出依赖文件审批段只留编排语义
测试:closure 25、save-package 6、seed 8、graph-to-pkg 5、端到端八例真库全绿;
五闸退出码全过。库:迁移 + v4 就地同步(唯一生效版)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 21:24:41 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
a10a7b2855
|
三面拆分⑰:编辑即其身 —— 保存写回本版,新版本只出自「新建」
用户问:为什么编辑一个版本、保存就自动多一个副本?那不是我要的。
旧机制「保存恒新增版本号」改为:
- savePackage:pkg.version 已存在 → **就地写回该版**(号不变、状态不变);
`asNew: true`(新建按钮)或新流程首版才铸新版本号(服务端算,不生效)
- 底线三道,一道不少:
① **在途钉版不可变** —— 该版有未完结工作流(按 (包,版本) 钉定义)→ 409,
一字不落库;「就地覆盖会改掉在途正在读的编排」由这道闸守,不再靠只插不改一刀切
② **生效版必须始终可运行** —— 写回生效版跑闭合闸,不闭合 412 带整份报告;
未生效版画图不检查、随手存
③ **陈旧编辑不复活** —— 流程存在而版本号已被清理 → 409(实测:停在已删旧版上的
标签页发来保存,把老内容静默复活成了新版本;StaleVersionError 拦死)
- store:新增 updatePackageDefinition(只许命中现存版本)+ countPinnedInFlight
- 前端:保存按钮「保存 v{n}」;新建走 asNew;文案全线「新建才长版本」
- 测试:save-package.test 六例(写回/钉版/热改闭合/asNew/防复活/首版);
过程中揪出双 API 进程并存(旧进程霸端口跑旧代码)——已重启归一
实测:改名保存 → 版本列表仍唯一 v4 生效中,名字已写回;八例端到端全绿;
五闸退出码全过(api:check 提交后转绿)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 20:11:41 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
7f0d25c337
|
三面拆分⑭:纯编排第三轮 —— 活动卸岗位、卡点废除全真边、边号 E1–En 图上可选
活动契约不带负责人岗位(用户定):
- schema:活动节点删 owner(审批点的 approver 是「卡到人的工位」的功能语义,保留)
- 运行时:活动任务默认**全员轮值**(在岗候选并集、最闲者先、staffId 稳定排序,
owner-resolved 事件岗位记「(全员轮值)」);运营分派机制落地后让位 —— 债已记
- closure:活动点不核岗位,missing-owner-position 只出自审批点
- 员工面链条:活动点报**实际承接人**(实例→任务→人),没起的如实报「轮值待派」;
NodeInstance 公开 taskId/approvalId(店面读回,与端口型合流)
- 画布/导出依赖文件/属性卡全线摘岗位;属性卡活动点明说「分派归运营」
卡点画法废除,顺序流一律真边(用户定):
- 种子图重画:四条回跳/直达(E4 直接定价、E6 选型后定价、E10 不通过、E12 有异议)
全部画成折线真边,车道分层零交叉(顶 y30 / y190 / y230 / 缝隙对开 / 底 y380);
卡点节点删净,图=恰 10 语义节点 + 14 真边一一对应(测试守着)
- graph-to-pkg 卡点认亲机制删除;pkg-to-graph 直接按 from→to 认亲
- 元素盘删卡点件;图例、属性卡卡点分支、kindLabel/kindTone 随删
边号 E1、E2…(用户定):
- 语义边 id 即边号:种子 E1–E14;合并器铸号(旧边保号、新边取下一空号,回归测试守着)
- 画布线标带号(`E3 直接寻源`,无注记的边也标 `E1`);拣选条以边号立牌,
**条件不再上按钮** —— 条件/映射只住属性面
- 边在图上可选中:FlowDiagram 连线加宽透明命中垫(边可点时注解层提到形状层上),
点线即切属性卡到该边(实测 E4 命中)
测试:closure 28、advance-order 6、graph-to-pkg 5(新增铸号例)、seed 8、
端到端八例真库全绿(全员轮值下照跑);五闸退出码验过。
库:purge 后重种,唯一 unified-quote@v1 生效(双面判据齐)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 19:02:07 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
281f4ef084
|
三面拆分⑬:流程包纯编排化 —— 编排与传递契约归包,实现方式归库,激活看双判据
模型(用户定):流程包只决定活动编排 + 活动传递的契约,不决定活动的实现方式;
节点只分活动点与审批点;图只定名称与顺序,属性在卡上填,链接好实现即可运行;
激活 = ①Mastra 式图编排闭合完善 + ②活动装载,两面判据。
schema(库经外科手术清空,无历史包袱,网关彻底出局):
- contracts:删 gateway 节点变体 / GATEWAY_KINDS / GATEWAY_KIND_LABEL /
'gateway-deprecated' 违规项 —— 节点四种:start/end(结构件)+ activity/approval
- routing:joinReady 整个删除(多入边即异或汇合,没有「等回齐」;AND 待并行组);
selectEdges 精简;closure 删 checkGateway;process-service 删汇合等待与网关直传,
节点一律只收装配后载荷(verdict/outcome 判据由系统注入,不走映射)
编排面(画布 = 名称 + 顺序,其余在属性卡):
- 元素盘五件:活动点(单一,不再分标准/案例 —— 那是实现方式)/审批点/起止/卡点
- 属性卡:节点类型二分(活动点/审批点);新增「链接活动实现」选择器(装载面,
FlowNode.act 经 merge 成为语义 activityId);范式/版本降为只读装载信息
- 边属性可填:条件(S-FEEL)+ 映射(上游输出口/起单载荷/常量三种来源;
workflow-var/expression 归系统隐性,不进设计者面)—— FlowEdge.condition/mapping
工作副本,pkg-to-graph 回填、graph-to-pkg 合并,清空条件即变默认兜底边
- 异常看板 → 激活双判据看板:图编排(结构+属性+契约)与活动装载(unknown-activity)
分面亮灯,两面清零激活才亮
- pkg-to-graph 去 paradigms 绿化与网关分支;图例/文案全线「活动点/审批点」
测试:closure 27(joinReady 两组 describe 随机制摘除)、advance-order 按真图形状重写
(去 as never 捏造的网关节点)、graph-to-pkg 9(新增 act 合并 + 边契约合并/清空用例)、
seed 8、端到端八例真库全绿;五闸退出码验过(api:check 提交后转绿)。
库:purge 后重种,唯一 unified-quote@v1 生效(10 节点 14 边,双面判据齐)。
债:M5-5 清账(兼容路径连 schema 一起摘);M5-4(并行组)仍挂。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 18:29:32 +08:00 |
|
 ChaiHaoandClaude Fable 5
|
6854524784
|
三面拆分⑫:网关去节点化 —— 分支即条件出边,汇合即多入边异或
模型(与 Mastra .branch 同构,条件挂在步与步之间):
- routing.selectEdges:多出边一律异或,不分节点种类 —— 条件命中优先(按声明序),
无条件边作默认兜底,恰取一条;单出边直通保留(历史并行网关的遗留通道)
- closure:含网关即 gateway-deprecated(历史版本仅可读、不可激活);
「隐式合并」禁令删除(多入边=异或汇合,上游互斥无歧义);
新规:多出边节点的无条件边至多一条,超出报 multi-default-edge
- contracts:CLOSURE_VIOLATION_KINDS 去 gateway-unbalanced/join-ambiguous-source,
进 multi-default-edge/gateway-deprecated(下游零引用,api-report 随行)
种子(按用户要求:只留一条流一个版本,图/节点/边全部对账):
- MVP_PACKAGE 重写:10 节点 14 边零网关 —— G1/G2 展开为 A1 的三条出边
(选型/直接寻源/默认直接定价)+ A2 的两条,G2J/G3 整颗删除,
A5 审批点的两个去向就是自己的两条 verdict 条件出边(驳回边与 reject 声明字字对齐)
- 手绘图:顶车道 y30 补画 A1→A3「直接寻源」—— 画布保存只认画出来的边,
不画这条语义边会在首次存盘被静默丢掉(新增图边对账测试卡死这类漏画);
「供应商底价表」标注钉进 y190 车道空档,不再被卡点压住
- 开发库外科手术:清运行数据 + 删 v1–v4,重种为唯一生效版 v1(闭合过闸)
UI 与文案同步:
- 元素盘/追加盘不再有网关件(画布仍认得历史图);图例删「判断/并行网关」「菱形=网关」
- 新建流程补激活一跳(保存不生效模型下,不激活「建出来就能起单」就是谎言)
- 总览四种编排要素、「画图不检查,激活才查完整」贯穿 blueprint/memory/process 文案
测试:closure 43 通过(gateway-deprecated + multi-default-edge 两用例),
seed-mvp-flow 8 通过(含图边对账),端到端八例真库全绿(网关从不建实例,断言原样存活);
五闸 typecheck/lint/depcruise/api:check/test 全过(退出码验)。
债:M5-4 AND 并行待「并行组」声明(Mastra .parallel);M5-5 网关运行时兼容三处,
含网关在途流清零后随 schema 一并摘除。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
|
2026-07-28 17:56:20 +08:00 |
|
 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
|
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
|
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 |
|