 xcsandClaude Opus 5
|
588d5c2dd4
|
fix: 配方只认 liveStep;保存不再无端叫醒任务;prune 不在人填的时候撤行
**I6 · 配方只认 `liveStep`**:`current` 有一条兜底(`liveStep ?? 在场的第一个有剧本的项`),
它不过滤 `settledIds`。当初这只影响提示词内容;配方接进来之后它驱动**副作用** ——
再写一遍台账、再 prune 一遍,carded 为假时甚至再发一张卡。兜底继续只服务提示词。
同处 `settledIds` 改取 sweep 之后的 `stateRuntime`(`liveStepOf` 吃的是 sweep 之后的
`stateEnabled`,两边得同一份局面)。
**注**:这一形状(既已收掉又在场)我没能在当前 lifecycle 里构造出可达来路 ——
`publishEnabled` 把 Completed/Terminated 挡在 entries 与 inProgress 之外,
`reenter` 又是就地改状态、不留旧实例。用例用的是 `live-step.ts` 注释描述的那种局面
(同 id 两份实例),守的是不变式;详见最终报告。
**F1 · `afterSave` 只在有未答的卡时才 `wake`**:`wake` 对 awaiting-event / awaiting-human
一律拨成 running,推进器随即推一拍并**记一步预算**。而现有九个活动包一个 auto 都没有:
人每按一次保存就白烧一步、界面闪一次「AI 正在推进这单」;任务本来 awaiting-human
(等人裁决)时被叫醒,那一拍结束还会把它写成 awaiting-event —— 从「等人办事」降级成
「等外部回音」,而等的明明还是人。**这是界面撒谎。**「保存即铺格」的场景恰恰都有卡在场。
用既有的 `humanTool.pendingCards`,不新造。`wake` 失败不再 `.catch(() => false)` 静默 ——
它是「保存即铺格」的唯一触发器,吞掉等于人按了保存、格子没出现、系统一个字不说。
**F3 · `prune` 不在人填的时候撤行**:人在件上「加一行」加出来的行,配方的数据源里当然没有 ——
编辑中途把它悄悄撤掉是最不能接受的一种静默数据丢失。有卡在等人(quiet)那几拍只铺不撤;
同一张表既被 prune 又列在该步 `humanWrites` 里,装包报 warn;规范 §4.6 纪律补两条
(prune 的表不该是人能加行的表 · card 之后那几笔要等人交回之后那一拍才跑)。
I6 2 测(做过变异验证)· F1 5 测 · F3 2+1 测。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 08:42:06 +08:00 |
|
 xcsandClaude Opus 5
|
fcf1822233
|
fix(app): 配方的 analyze 走 traced 网关并回账用量 —— 一条问模型不花钱的路
装配层从前传的是裸 `deps.modelGateway`:`createModelGateway` 自己不做
`addConsumption`,计量全靠调用方给的 `onUsage` —— agent 那两条路都接了,
只有 analyze 漏了。后果两条:配方里 analyze 烧的 token 一个数都不计入活动预算
(预算这道闸对它形同虚设);时间轴上也不产生模型 span,「这一单问了几次模型」
看不见它。而 spec §5.2 白纸黑字写着「用量计入预算」。
现 `createAnalyzeGateway(tracedGateway, onAgentUsage)`,网关内**两次** generate
(含重问那一次)的用量各记一笔 —— 失败的调用不是免费的。记账不吞异常:
记不上账等于预算失效,宁可当场停下由配方留痕交人。
debt.md 里那半句「它烧 token、计预算」当时是假的,改老实。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 08:18:10 +08:00 |
|
 xcsandClaude Opus 5
|
bd26756da9
|
docs(adr): ADR-014 §3.2/§4/§5/§11 对齐落地代码 —— 三动词改五动词,拍内次序补全
评审指出 ADR-014 被标「已实现」后,正文 §3.2/§4/§5 仍是实施前的三动词提案,
与真实 schema(auto-recipe.ts)和 turn-runner.ts 的拍内次序对不上,会误导
下一个直接翻开这份 ADR 的读者(W05 重写实现者)。逐条对代码核过后分两档改:
§3.2 动词表与 §5 拍内次序按代码改对(含之前遗漏的「有卡未答就静默重跑配方」
那道前置门);§4 的两个例子不逐行改,改成开头一段按语指出三处已知出入
(workOrder→as、view 挪到 PlanStep、self/joinRows 未实现)。顺带把 §11
待定的前两条标成已定并指回销账位置。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 07:42:27 +08:00 |
|
 xcsandClaude Opus 5
|
6cbac3220c
|
docs(spec): W05 重写设计 §5.9 改口 —— analyze 那一笔也归系统灰,不是 AI 蓝
这份 spec 是下一份计划(W05 重写)的权威,留一句已知错的话在里面,
下一个实现者会照它做、再花一轮改回来 —— 这一轮的教训正是「三段各自正确、
合起来仍然不对」。顺带记下病根:kind: 'result' 不进工作日志骨架、internal
又被 machinery() 再滤一道,配方留痕能不能被看见没有机制保证,靠的是手工选对。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 07:27:11 +08:00 |
|
 xcsandClaude Opus 5
|
dba6071772
|
docs: 确定性步骤落地 —— 规范 §4.6、ADR-014 转已实现、两笔欠账
ADR-014 §8 的两条禁令(不 submit、不发决策卡)撤掉并写明理由:
那是假设还有 agent 在场时的保守话,全程无 agent 的活动没有别人来干这两件事。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 07:24:13 +08:00 |
|
 xcsandClaude Opus 5
|
6f721ffc6d
|
fix(interaction): data-options 收尾防重改认显式标记,不再靠「有没有 selected 这个词」
评审复现了一个真泄漏:selectCurrent 用 /\bselected\b/.test(block) 当「行内那一遍
处理过没有」的代理 —— 而一行被正确处理过、且合法地落在「没有选中项」上(值不在
选项里,或这一格还没填),跟「压根没被处理过」在字面上是同一个样子。renderView
收尾那一遍拿外层作用域重新处理这块,若外层恰好有个同名裸键命中某个选项,就会把
它错误地渗进这一行 —— 界面撒谎:显示一个这一行数据里根本不存在的选中态。
改记一个跟内容无关的标记属性 data-sel-scoped:处理完(不管有没有真标出 selected)
都打上,下一遍见到标记就跳过;renderView 收尾前把它整个剥掉,不留进交给沙箱的成品。
顺带治了评审点的 Minor #1:旧写法还会被 <option> 显示文字里恰好出现的 "selected"
误判(枚举标签写成 "Selected Value" 那种)。
三条新用例:行内下拉值不在选项里 / 新加的空行,均验证不再被外层同名值渗透
(RED 证实了泄漏确实发生过);行外独立下拉仍正确标好 selected(防重归防重,
不能把本该工作的那条也防没了)。
docs/HTML报告生成规范.md 补一句:data-options 与 data-slot 不能共存,后者会被
fillOptions 摘掉不起作用(评审 Minor #2)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 06:21:26 +08:00 |
|
 xcsandClaude Opus 5
|
81fb8179c2
|
feat(interaction): data-options —— 下拉的选项从台账现读
芯片类型是人在件上现造的,写死在模版里等于「只能选出包那天就有的那几种」。
与 data-rows 同一层机制:只取值不判断,选中哪一个仍由 selectCurrent 按行内的值定。
空选项一律留着 ——「还没选」得说得出来。
brief 给的实现有两处会让测试落空,已按 TDD 修正并留痕在代码注释里:
①产出的 <select> 若留着 data-slot,renderTemplate 的 SLOT 规则会把整段 <option>
当文本槽冲掉(<select>2</select>)—— fillOptions 需要把 data-slot 一并摘掉;
②selectCurrent 只在 renderRows 的逐行流程里被调用,不在任何 data-rows 里的下拉
永远等不到人给它标 selected —— renderView 收尾再兜底调一遍(用外层作用域),
已经被行内定过的整块原样放过(靠判断块内是否已有 selected,不靠字符串层面
分不清的「是不是在行里」)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 06:03:45 +08:00 |
|
 xcsandClaude Opus 5
|
80e9b01f84
|
docs(plan): R8 —— 全 auto 的步要能声明「没有 guide」,并进 Task 9
Task 7 的评审挖出来的:manifest.ts 的 guide 是 z.string().min(1)(必填非空),
而全 auto 的步按设计就没有 guide —— 引擎正是按 guide.trim() === '' 分半 auto 与全 auto。
照现在的 schema,第二份计划里四步全 auto 的活动会在装包那一刻被拒。
改成 superRefine:声明了 auto 才允许 guide 为空;没有 auto 的照旧拦
——「作者忘了写做法」是个老错,那道门要留着。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 04:42:54 +08:00 |
|
 xcsandClaude Opus 5
|
04234d2fda
|
docs(plan): 发车前扫描的三条裁定入计划(R1 测试桩前移 / R2 去类型逃逸 / R3 推帧改条件)
R1:TurnRunnerDeps 加 analyze 会让 turn-runner 测试脚手架的 deps 字面量少一个必填属性,
typecheck 在 Task 4 提交时就红 —— 桩前移到 Task 4,Task 7 那一步退化成验证。
R2:auto-source 的 matches() 在生产域代码里用了 as never,形参直接标 AutoExpr。
R3:showView 第二参不可选,传 undefined 编不过 —— 改成「声明了画面才推」。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 03:00:08 +08:00 |
|
 xcsandClaude Opus 5
|
b9951483bc
|
docs: ADR-014 确定性步骤 + W05 重写设计 spec + 实施计划(第一份:平台机制)
spec 定死八条:配方驱动零工具 · 六张台账 + P-06 按结论入账 · 四态 AI 定等级规则算 ·
保存即铺格 · 类型不一致硬拦 · 审核卡只有确认 · 只做真用得到的那几式。
计划十三个任务,机制先在纯函数与假端口上钉死,再去接真活动。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
|
2026-08-29 02:56:39 +08:00 |
|
 xcsandClaude Opus 5
|
a370616f01
|
CLAUDE.md 与 debt:humanWrites 那条入快照;记下更大的一条 —— 确定性步骤没有落点
用户同时点出(未做):**存在性核对 + 派数据工单是确定性流程,根本不该交给模型** ——
W05 的「逐个料号查库 → 不在库就铺骨架、发数据工单」是纯规则,却写成了模型的 guide,
因为一个计划项的做法只有一个落点(模型的 guide):纯工具只读、判定表不写台账也不发卡、
`doneWhen` 只收步、哨兵只开门,**没有一个机制能整段承接**「读台账 + 写草稿 + 发人卡」。
引擎三样能力全有(`taskView` / `draftWrite` / `issueExecution`),缺的只是声明面。
代价已经付过两次:08-27 原 PN 不在库却判「在库」;08-28 模型把原 PN 的规格书抄到候选头上。
真治法:剧本加 `auto` 步(声明「这一步引擎按规则做,不问模型」)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 12:38:26 +08:00 |
|
 xcsandClaude Opus 5
|
2cef6f7489
|
feat(contracts): PlanStep.humanWrites —— 人填的表模型不许写;还欠一张卡的那一步不摆 doneWhen
柴浩实测单 6ddcecf8(连撞五拍熔断):P-10 资料记录的标题 / 版本 / 链接与台账里 `LM2596S-5.0` 那一行
**逐字相同** —— 不是幻觉,是「手边有一行看着对的就拿来用」(那一步 reads 摊开了 `parts.document`,
视野里唯一一份真资料就是原 PN 的)。行找对了、料找错了,而这份假证据会直接喂进差异比对当「硬约束有证据支持」。
三层合谋:①把 P-08 的回卡认成 P-10 的(P-10 的卡从没发过);②08-27 给这一步加的 doneWhen 把
「资料必填不缺」摆成目标、后面还跟「成立了就 finish」,**与同一份提示词里「唯一合法的动作是先发那一张卡」
直接打架**;③它顺手把 `exists_status` 改成 created,按剧本发卡名单自己空了 —— 一个合法动作都不剩。
止血两刀:
①**`PlanStep.humanWrites`**(契约,可选字段、老活动一个字不用改):声明的台账 `write` 当场拒并指路
「去发那张卡,值由人填」;`drop` 不拦(写错了得撤得掉)。判法认点名的项,点不出退回当下在办的那一步
(压拍时骨架写在上一步名下正好放行)。**只声明「模型永远没有来源」的表** —— 有附件时该预填的
(P-08 的参数值从 datasheet 抽)别声明,那是它的活。
②**还欠一张卡的那一步不摆 doneWhen** —— 判据同时是摆在模型眼前的目标,而它此刻只许发卡。
W05@1.6.5 声明 `humanWrites: ['parts.document']` 并从 writes 去掉。4 测(墙 / 放行 / drop / 声明)。
**一个闲着的模型 + 一个它够得着的判据 = 它一定会去凑那个判据。**
契约变更四步:depcruise 反查下游绿、loop-engine CONTRACT.md 同步、api-report 随本提交入库、
可选字段非破坏性。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 12:38:26 +08:00 |
|
 xcsandClaude Opus 5
|
e1d8d86b16
|
合并 origin/mvp-foundation:运营中心收口(四区建设中占位 · L2 文案与收口)+ 治理台告警钮暂隐(shanqin 两条)
CI / ci (push) Failing after 10s
主支这边一条:实例时间线第 9 步的结果跟第 8 步走(已放行的单不再永远停在 pending);
远端两条是队友的前端:运营中心四区(驾驶舱 / 工作流 / 台账 / 系统)摆建设中占位、
L2「启动活动」改「创建活动」、沙箱区块隐藏、行内终止撤掉收口 L3、负责人小签隐藏、
文案定名活动列表 / 活动号;治理台顶栏告警钮暂隐(SHOW_ALERTS 开关,计数逻辑保留)。
两边文件零重叠(后端 activity-ops + API 文档 vs 前端 gov-shell / panel + 需求文档),自动合并无冲突。
五道门禁绿:2260 测试通过、23 跳过(无模型密钥 / 无真信箱的惯常项)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 10:51:08 +08:00 |
|
 xcsandClaude Opus 5
|
c1137fb09a
|
fix(ops): 实例时间线第 9 步的结果跟第 8 步走 —— 已放行的单不再永远停在 pending
放行那一步(T_release,人工激活)**没有自己的收步事件** —— 人签字后 `submit` 直接把整单落终态,
计划项本身从没被 finish 过。于是一单已 `released` 的详情里第 9 步永远是 `pending`,
而它前面拟落账那一步早就 `done`:同一张单上两句话互相打脸。
`followRes` 纯函数在服务端交出详情之前把第 9 步的 `res` 与 `at` 跟上第 8 步(2026-08-28 用户定,`at` 也跟);
**用时不编** —— 那一步没有自己的起止痕;两步有一步不在(别的活动步数不同)就什么都不动。
《API文档-活动模块》§ 时间线补一行口径。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 10:50:16 +08:00 |
|
shanqin
|
fff2e6ec2d
|
治理台顶栏告警钮暂隐(SHOW_ALERTS 开关,计数逻辑保留)
CI / ci (push) Failing after 11s
|
2026-08-28 10:47:33 +08:00 |
|
shanqin
|
21d41f5859
|
运营中心收口:四区(驾驶舱/工作流/台账/系统)摆建设中占位;L2「启动活动」改「创建活动」、沙箱区块隐藏、行内终止撤掉收口 L3、负责人小签隐藏;文案定名活动列表/活动号
CI / ci (push) Failing after 12s
|
2026-08-28 10:39:13 +08:00 |
|
 xcsandClaude Fable 5
|
88f2149d12
|
差异比对三刀:客户约束不再一票否决 · 入参由基座从台账取 · 「下限~上限」一律读成范围
①**两颗一模一样的输入电压范围判成 MISMATCH**(用户送来 0bddd862):客户写「45V 以内」→ requirement `>= 45`,
而原 PN 与候选上限都是 40V;`judgePair` 只看候选过不过客户线、不看原 PN 自己过不过 ——
需求边界与在用料的差距记在了候选头上,硬约束 MISMATCH → 整颗不推荐。差异评估比的是「换上去会不会比现在差」:
候选与原 PN 相等 / 盖住、且客户线原 PN 也过不去 → 仍按比对结果判(MATCH,风险中),备注点名
「需求边界,请回头核对需求」;候选更窄且过不了线仍 MISMATCH(3 形有测)。
②**入参由基座从台账取,模型只报料号与客户约束**(用户:「这个做差异评估比对的 harness 肯定有问题」):
同一单痕里模型念出「输入上限 32V 低于客户 40V」—— 那是 S3 剧本示例的原话、不是这单的数;
工具入参只存哈希,喂了哪几对值事后查不到;写回时还把工具的 `equal` 改成 `less`。两头都靠模型抄、两头都没有基座核。
改三层:工具运行时把 `taskId / activityId` 交给处理器(`ToolHandler` 入参加两个可选键);
`compare-parameters` 给 `originalInternalPn + candidates[].candidateInternalPn(+ requirements)`,
参数行从 `parts.parameter`、封装 / 生命周期从 `parts.profile`、证据引用从 `parts.document` 由工具现读任务视图
(本单草稿也算),出参每项带原值与证据,写盘照抄;老形状(自带 pairs)照接,试运行走它;
container 用 `compareParametersWith(ledger)` 顶掉静态名单那份;≤800 字的工具入参整份进 `result` 痕(审得了才谈得上认真)。
**基座能读到的事实,不让模型转述给工具。**
③**「下限~上限」一律是范围**(用户:「4.5~40 / -40~+85 这种我怕模型搞不清楚」):实测解析器真有洞 ——
单位写进值里(`4.5V~40V` / `-40℃~+85℃`)被读成单个数,Unicode 减号、`…`、`≥45 / 40 以内` 读成文本。
分隔符认 ~ ~ - – — … 至 到 to、单位可夹在值里、单边界读成半开范围;出参每项 `readAs:{original,candidate}`
写明「范围 4.5~40 / 定值 5 / 下界 ≥ 45 / 文本」—— 比对依据可见,模型照它写影响、不自己重新解释值;
契约描述与 S3 / P-08 剧本明写读法(示例用中性数 1~10,不用真数据里的 4.5~40 —— 模型会把示例当这单的值)。
工具 1.0.0 → 1.3.0(注册一名一行、upsert 换版本,handler 在进程内按名绑,装完稳定版重建即生效);
W05 包 1.6.2 → 1.6.4:S3 第一拍只报料号与约束、示例只留占位形,第三拍 compare_result 照抄,S4 重比只改 requirements。
13 工具测 + 包内 89。在途单要人在审核卡上「重做」并写明意见才会重比。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 01:13:07 +08:00 |
|
 xcsandClaude Fable 5
|
282584d26e
|
feat(web): 工作台任务界面给 SSE 配 10 秒兜底轮询 —— 只此一处,由壳层起停
`app/fallback-poll.ts`:任务界面开着时每 10 秒把 `desk` 下**在用的**查询(清单 / 这一单 / 角标,
`type:'active'`)各重取一次,推送漏了画面最多旧 10 秒。**不取消在途**(`cancelRefetch:false` ——
慢接口不被兜底打成永远取不回)、页签藏起不打、回前台先补一趟;壳层 `useEffect` 起停,
切模块 / 卸载即 `stop()`(定时器与可见性监听一起摘)。`doc` 可注入,4 测钉死
(周期 / 停止 / 可见性 / 在途去重,第四条做过变异验证)。
`queryKeys.desk` 新增作整支前缀,订阅层的裸 `['desk']` 改用它。
编码规范 §9.2「组件禁止自行轮询」照旧,补一句:兜底只此一处、由壳层起停。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-28 01:13:07 +08:00 |
|
 xcsandClaude Fable 5
|
f77c6325fe
|
合并 origin/mvp-foundation:活动模块接真接口 + 员工模块界面改版 + 启动抽屉「责任人」+ 身份菜单直链运营中心(shanqin 三条)
CI / ci (push) Failing after 11s
主支这边:W05 1.4.1–1.4.7 七条 + 刚合进来的 feat/activity-ops-w05(运营中心活动模块接口 L1/L2/L3、
W05 在途修订、同日 harness/工作台修);远端三条是队友的前端:活动模块 L1/L2/L3 接真接口(顺手按接口文档
补了 api/activity-ops.ts 契约)、员工模块界面改版、启动抽屉固定参数「责任人」、工作台身份菜单直链 /ops。
冲突三处,全是两边各写了一版同一样东西:
① `packages/contracts/src/activity-ops.ts` / `api/activity-ops.ts`(add/add):取后端那版 —— 队友是照
《API文档-活动模块》补的,43 个导出同名、路由 12 条全同,只差 launchOptionSchema / INSTANCE_REASON_KINDS /
STEP_RESULTS 三个名字;队友前端对着后端契约原样编译通过。
② `docs/API文档-活动模块.md`:取后端按契约回写的那份(已含 §5 责任人 ownerId、combo 语义、关键台账看板一节、
候选料号改单选);队友那侧是回写前的旧稿。
设计端活动库两条路由改名 `/api/gov/activity-packages` 让位随 feat 分支进来,队友契约与治理台同名路由撞车那 7 条
路由注册表测试(远端主支自己红)就此消解;api-report 按合并树重刷。
五道门禁绿:2240 测试通过、23 跳过(无模型密钥 / 无真信箱的惯常项)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 23:22:57 +08:00 |
|
 xcsandClaude Fable 5
|
7b85a79323
|
harness 与工作台同日修:数据工单确认即入库 · 叫了人不再自动推进(两道结构闸)· 审核卡 = 终局验收卡结构 · 验收清单人点达标 · 迟到守卫不丢放行裁决 · 画面跟着这一拍发出去的卡走 · 成果详情只翻页 · 占位居中 · 进度条
human-tool / ledger / loop-engine / release / task / interaction 六模块与 app 层(desk 路由、engines、consumers、
data-order-landing、case-stamp、reset-runs、seed-activities、容器与 server 装配),web 的 desk-task
(ViewRegion / chat-bubbles / review-face)与 app.css、ui-kit 图标;契约 card / manifest;
迁移 0034_task_seq 与迁移日志;api-report 快照;CLAUDE.md 快照、debt、活动开发规范、HTML 报告规范同步。
逐条口径见 CLAUDE.md 快照(2026-08-27 下午至晚)。另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 23:20:16 +08:00 |
|
 xcsandClaude Fable 5
|
909b1fe4b7
|
W05 在途修订:差异评估结论审核件一个候选一张表 · 关键台账数据看板件(ledger-board)· S1 清单不再把人刚填的参数摆成缺口
活动包 `part-substitution-assessment`(case-model / manifest / report / target-style / badge / ledger-board 与两份包内测试)、
目标件「验收工单-01-差异评估结论审核」、`docs/ss02-act-05` 关键台账数据两份、端到端测试记录、e2e 脚本。
逐条口径见同批 CLAUDE.md 快照。2026-08-27 另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 23:20:15 +08:00 |
|
 xcsandClaude Fable 5
|
0923fbfe4d
|
feat(ops): 运营中心 · 活动模块接口落地 —— L1/L2/L3 十一条(全 ops)+ 设计端活动库两条改名让位
`apps/api/src/app/activity-ops/*`(service / store / instance-state / instance-steps / launch-params /
summaries / view-html / view-scope)+ `routes/activities.ts`;契约 `activity-ops.ts` / `api/activity-ops.ts`
(与队友按文档补的那版 43 个导出同名,多 INSTANCE_REASON_KINDS / STEP_RESULTS / launchOptionSchema);
迁移 0035_activity_ops;《API文档-活动模块》按契约回写。
设计端活动库 GET/POST `/api/gov/activities` 改名 `/api/gov/activity-packages`,`/api/gov/activities/*`
整个让给运营端(前端 import 路由对象,零改动);activity-registry CONTRACT.md 与路由总表同步。
2026-08-27 另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖,以合并提交为验证单位。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 23:20:15 +08:00 |
|
shanqin
|
7f32a7e450
|
活动模块接真接口 + 员工模块界面改版
CI / ci (push) Failing after 11s
- contracts 补建 activity-ops(schema + 11 条路由);L1/L2/L3 全真接口对接(清单/详情/实例/启动抽屉/沙箱)
- 启动抽屉:参数表服务端下发、幂等键防重、400 逐格报错;combo「新增」提为候选第一项
- 终止/禁用/激活轻气泡反馈闭环:在途留场转忙碌、成功自闭合并刷新、失败原因留气泡可重试
- L3 实例详情 7 秒轮询(待执行/进行中),终态自动停
- 员工模块四页改版:目录行+首字圆块、权限三槽点位、组织树/空态、成员详情 hero+角色开关;卡内容区内边距补齐
|
2026-08-27 22:52:29 +08:00 |
|
shanqin
|
27d2fe6bb4
|
进度暂存:启动抽屉加固定参数「责任人」(名册下拉、默认当前登录人);接口文档 §5 加 ownerId 固定字段;需求文档记 2026-08-27 两条决策
CI / ci (push) Failing after 10s
|
2026-08-27 15:04:18 +08:00 |
|
 xcsandClaude Fable 5
|
b98ec75a89
|
数据工单由剧本声明、引擎决定 —— 不靠模型抄卡骨架(W05 1.4.3)
用户:「右边 AI 聊天框里这个数据工单怎么又显示的执行工单?」查实:说明书骨架里
`"variant":"data"` 与 `gateLedgers` 并排写着,模型抄卡时 gateLedgers 抄到了、variant 丢了
(看着像元数据)。靠模型抄一个标记本来就靠不住。
改成与 `view` 同一条道理:这一步派的是什么单,写剧本时就定死 ——
- 契约 `PlanStep.cardVariant: 'data'`;活动在 S0d_p08_master / S0d_p10_document 两步上声明;
- `cards.issue` 入参多一项可选 `itemId`(turn-runner 从 human 动作带下来;引擎自发的验收/兜底卡没有项);
- 组装层按 itemId 查剧本,`stepVariant ?? 卡上写的` —— 模型写不写都一样。
在跑那一单的卡已就地补上 variant(payload),刷新即见「数据工单」。
2102 测 / typecheck / lint / depcruise 绿;api-report 已刷;两处 CONTRACT.md 同步。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 13:51:14 +08:00 |
|
 xcsandClaude Fable 5
|
51c87af583
|
数据工单有了自己的面孔;件上四处样式对齐;缺库不再问人;5173 反代改回本机
用户在工作台上连报六条(2026-08-27):
- 对话区把数据工单摆成「执行工单」→ 契约 ExecutionWorkOrder.variant:'data'(引擎侧与执行工单无异,
只换面孔),归一层从卡上带下来,web 新增 DataForm(同一套办法、另一副面孔:色/图标/「数据工单」/「确认写入」),
办结卡与治理台人类工具目录同步;活动的两张数据工单卡骨架标 variant:"data"。
- 表显示不全不能右滑 → 目标件把 overflow-x:auto 写在 .tbl-wrap,平台包装是 .jc-tbl-wrap,谁都没管到;补一条。
- 表头只留中文 → 三张数据工单表去英文列名与 .thd 小字。
- 编辑态内部料号「只读字 + 输入框」并排 → 目标件 #tbl1 .jc-vcell{display:inline}(id 特异度)盖过
table.on 的隐藏规则,表 1 每格其实都并排,PN 那格恰好有字;用 id 特异度覆盖回去。
- input 与 select 没对齐 → 徽标从前包 .ro 编辑态留着、压在下拉框头上把那格顶低 13px,改成随只读格一起藏;
input/select 钉同一高度。
- 第一步「派数据工单还是放弃候选」不该问人 → 决策卡退役(覆盖规格「候选 ≥2 可放弃」那一条,用户定),
查无记录一律自动派;剧本/说明书/测试/e2e 同步(e2e 新增 expectAsks.max 断言「不该问的没问」)。
顺带:5173 的 /api 反代默认指向一条公网隧道(150.158.83.131:46100 → nps → npc → 本机 :8787),
浏览器每次请求先出公网再绕回来;默认改回本机,要远端的显式给 API_PROXY_TARGET。
静态渲染实证:900px 宽的框里横向能滑 200px;编辑态同一行 3 input + 1 select 全部 32px 同一 y;
只读 PN 格 display:none。活动包 1.4.0;2097 测 / typecheck / lint / depcruise 绿。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 12:36:13 +08:00 |
|
 xcsandClaude Fable 5
|
3171d8a864
|
合并 feat/org-directory:成员目录(Keycloak 读写面穿透)+ 治理台成员/组织/权限三页 + 广播桥回弹修复 + 稳定版脚本 + W05 目标件
CI / ci (push) Failing after 11s
分支四条(2026-08-26 做的,一直留在工作树没入库,今天补提交):
① feat(org) 成员目录 —— KeycloakDirectory 端口与适配器、org-directory 契约/路由、sync-roster CLI、
personName 姓在前、Staff.kind 按账号名现判;前端员工屏重做成成员 / 组织 / 权限三页签;
② fix(app) 广播桥「转发进来的不再 NOTIFY 回去」—— 两台后端互桥回弹 19 万条广播那次的修复,代码此前没入库;
③ chore stable.sh + .stable/ 入 ignore + vite preview 宿主白名单;
④ docs(w05) 目标件五份 HTML 与三份说明、实施计划、三张图。
冲突六处,全在 org 后端「姓在前」上 —— 主支(0c029b6,shanqin)与分支同日各做了一版:
主支拼「姓 名」留空格,分支 personName 汉字直拼(「柴浩」)、非汉字留空格(「Admin Amy」),
且分支那版是超集(服务账号识别、名册同步走同一把尺)。取分支版:port.ts / claims.ts /
keycloak-token-verifier.ts / keycloak-admin-roster.ts 及其测试按分支;主支那条 claims 测试
(「亲 删」→ 姓在前)保留,期望从「删 亲」改为「删亲」。api-report 重生成。
五道门禁绿:2096 测试通过、23 跳过(无模型密钥 / 无真信箱的惯常项)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 11:49:05 +08:00 |
|
 xcsandClaude Fable 5
|
8556432dba
|
feat(org): 成员目录 —— Keycloak 读写面穿透、治理台成员/组织/权限三页、姓在前 personName、Staff.kind
后端:`KeycloakDirectory` 端口(users / groups / roles 读写;写直接穿透 Keycloak —— 这里建的人立刻能登录、
删的人立刻消失,停用与收权之后 logout 踢掉会话)、`keycloak-directory.ts` + `keycloak-admin-http.ts` 适配器、
org-directory 契约与 /api/gov 路由、`sync-roster` CLI(ops 路由够不着时整册照过来),
容器按 provisioning 服务账号有无决定注不注入(没配就如实说不可用)。
`personName` 姓在前:汉字直拼「柴浩」、否则留一个空格「Admin Amy」,token 与名册同步两条路同一把尺;
`staffKindOf` 按 Keycloak 固定前缀 service-account- 认服务账号,员工那一屏不摆它(`Staff.kind` 不落库,按账号名现判)。
前端:员工那一屏重做成成员 / 组织 / 权限三页签(member-page 下钻),页签栏右端一句话说清这一格管什么。
契约变更:contracts org.ts / api/http.ts / api/org-directory.ts;api-report 已刷新;org CONTRACT.md 与 ADR-012 同步。
2026-08-26 做的,一直留在工作树没入库。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 11:44:36 +08:00 |
|
 xcsandClaude Fable 5
|
bd86dd6088
|
docs(w05): 差异评估的目标件五份 HTML + 三份说明 + 实施计划;三张图
活动包 views/target-style.ts / report.ts 与两份 W05 文档都指着 docs/SS02-ACT-WORK-05-html ——
模版「逐字节搬自目标件」的那份目标件此前没入库。docs/img/cy 三张 png 现无引用,随批入库。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 11:44:35 +08:00 |
|
 xcsandClaude Fable 5
|
6a69acfc69
|
合并 feat/act-work-05:第三个活动 ACT-WORK-05 差异评估(part-substitution-assessment@1.3.6)+ 脚本 e2e 逼出的平台侧改动
主支这边(d133d6c,PR #1/#2)是活动模块 L2/L3 前端(实例详情页、启动参数抽屉、禁用规则重定、
二次确认气泡、沙箱占位页)、工作台撤顶栏、姓名展示改姓在前(token claims 与名册同步);
分支这边 21 条:差异评估活动包(九个计划项、4 域 7 张主数据表、五张目标件平移的模版、
两枚纯函数工具、五案例 e2e 五例全 released 被拒 0)与平台侧 gateLedgers / answeredCardFact /
emptyGate / 早收只记观察 / 工具入参 null 归一 / 拒回不摆 S-FEEL 函数名,CLAUDE.md 快照跟上。
两边改的文件零重叠,自动合并无冲突。合并树上补三笔本该随各自提交入库的东西:
① api-report 两份快照 —— `org/port.d.ts`(主支加 given_name / family_name 时没刷)与
`api/workbench.d.ts`(分支加 gateLedgers 时刷出来的文件没一起提交);
② pnpm-lock 补 `activities/part-substitution-assessment` 的 importer 条目(新 workspace 包,
与当年 mail 模块同一回事;`--frozen-lockfile --offline` 装过核对一致);
③ org CONTRACT.md 补一笔 `VerifiedClaims` 增两个可选散件的影响半径。
五道门禁绿:2040 测试通过、23 跳过(无模型密钥 / 无真信箱的惯常项)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
|
2026-08-27 11:37:29 +08:00 |
|
shanqin
|
723d379dbd
|
进度暂存:禁用规则重定(任何时刻可禁用,只拦新启动)+ 启动参数加 combo 控件(选择+新增,库里没有不拦启动、启动后派数据工单);新增《API文档-活动模块》(L1/L2/L3 九条路由,供后端编写)
|
2026-08-27 11:15:21 +08:00 |
|
 xcsandClaude Fable 5
|
6f7513aa58
|
W05 收口:五例在收紧断言下全 released · 全被拒 0(活动 1.2.9 → 1.3.6)
第 7–12 轮逼出七条(T–Z),两条是脚本自己的、五条是活动的,其中一条上结构:
- W 参数名写成英文 key,与库里中文行不是同一行 → 27 条里 14 条 UNKNOWN。措辞两遍 +
乘法对账都拦不住单颗料那一路(5 = 5×1 恒成立),改自指 refersTo:param_name
只能用台账里已经在用的名字,一颗料时也咬得住。
- V/Z 数据工单那一项的两个方向:建完第一颗就收掉(再给第二颗发卡撞「已办完」)、
铺完骨架就标 created 直接 finish(撞「从没发过卡」)—— 顺序写死:骨架 → 发卡 →
拍结束 → 人交回 → 才标 created;absent 没清零不许 finish。
- T P-10 也要「发卡前骨架先有行」;X 第二颗缺库也要先问。
- 脚本:U 一例翻车不拖垮整套;Y 按闸的指示「加一行」;断言收紧 —— 点名的行整例跑完
仍没出现 = 失败,决策卡按「问的是哪件事」数(第 9 轮逮到一次假绿)。
流程上两条纪律(用户当场纠正):只跑受影响的那一例,改了平台共享面才全跑;先说计划再动手。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 11:13:53 +08:00 |
|
shanqin
|
d03fed97d2
|
进度暂存:L2 启动活动按钮接功能 —— 参数抽屉(LaunchDrawer)按规格渲染,占位参数表每活动一份,提交落「待执行」演示行;需求文档记 2026-08-27 决策
|
2026-08-27 10:31:50 +08:00 |
|
 xcsandClaude Opus 5
|
df18882322
|
脚本 e2e 逼出的八条:闸看错了表 · 拒回喂指针 · 零行骗过闸与哨兵 · 早收不该算撞墙
凭证到位后 `w05` 五案例连跑六轮,逼出八条**浏览器走查逮不到**的缺陷 ——
脚本每张卡都先空手交一次、每个岔路口都按序代答,人手点的时候永远不会去试
「空着交上去会怎样」。末轮:跑到的四例全部 released,三例被拒 0
(第五例停在大模型账户余额不足,不是代码问题)。
平台侧(六条):
- L 数据工单的提交闸没牙 —— 卡没绑表就回落到必交付物,而数据工单要人补的是
`parts.*` 主数据,不在交付物名单里:闸盯着一堆无关的表、一格不缺,空手交卷一路放行。
契约新增 `ExecutionWorkOrder.gateLedgers`(这张卡该拦哪几张表,发卡的人说了算),
`gateAddressesOf` 变三级取一:绑的表 > 卡自报 > 交付物。
- M `finish` 撞 doneWhen 为假的拒回只谈「行与列」,而缺的是一次**工具调用**;
现在摆出判据原文 + 那几个名字此刻的读数,`tool_*_calls` 读到 0 的单独点名(`unmetWhy`)。
- N 人点了决策卡,模型每拍再发一张,连拒五拍熔断。把「他选的是 approve」写进拒回**没用** ——
下一拍它又从头翻一次会滚走的窗口。改结构:`answeredCardFact` 把
「这张卡已答过 → 他选的是什么」做成每拍都在的事实行。
- O 模型传 `requirement: null`,工具 `null.trim()` 当场崩(边界上一律经 `text()` 归一)。
- P 拒回里的 `count=(没写过)` 是 S-FEEL 函数名被当成台账名 —— 假线索模型会去追。
- Q/S 零行 = 零缺,闸与哨兵一起放过空手交卷的数据工单(`emptyGate`:卡自报的表一行都没有
= 没完成);「早收」头一次只落观察、第二次起才算被拒(与「重发已答过的卡」同一把尺)。
活动侧(1.2.7 → 1.2.9):三张执行工单各自声明 `gateLedgers`;说明书③补「发卡前骨架必须先有行」、
⑤补这张卡的前提(一颗 absent 都不剩);哨兵 `parts_profile_rows >= created` 逐颗对账;
S0_bind 写明发录入卡那一拍别抢写需求行。
e2e 脚本加 `JCAI_E2E_BEARER` 直供旁路(服务账号 client_credentials 仍是正路)。
门禁 typecheck / lint / depcruise / test(2091)全绿;api:check 的差异仍只在 org/* 与 api/*
(工作树里先前那批鉴权改动),card.d.ts 是本轮的纯新增字段。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 09:31:35 +08:00 |
|
 xcsandClaude Opus 5
|
eb80876554
|
走查逼出的六条:发卡前清单要有行 · 在库要拿得出依据 · 数据工单只建缺的那颗 · 录入卡自带 basis
ACT-WORK-05 差异评估的浏览器全流程走查(六轮六条路径,全部 released),
逐条治了实跑里现形的缺陷。活动包 1.2.2 → 1.2.6:
- H(1.2.3):模型压拍把执行工单发了、清单一行没写,人对着空表 ——
「先写清单再发卡」只在剧本里,压过拍就只有说明书还在;规矩搬进说明书。
- I(1.2.4,结构治):原 PN 根本不在库,模型两颗都判「在库」,硬阻塞整条路被跳过。
剧本已写到头 → pn_check 加 found_pn_ref(refersTo + requiredWhen):
判在库就必须填一个基座查得到的料号,查无此值当场拒、填不出则收不了步。
这是「机检只读基座数」第六次现形,前五次都是计数,这次是存在性。
- J(1.2.5):数据工单派给了在库的那颗,缺的那颗没人建 ——
剧本把「建哪几颗」和「要不要问人」写在同一串分岔里,从没写过「found 的不建」;拆成两问。
- K(1.2.6):数据录入卡的参考信息栏摆着引擎内部家具(九个计划项全名)——
entryCard.basis 契约里可选,活动没声明,基座就兜了内部事实;卡骨架补三行人话。
包内自测 56 → 61 条;门禁 typecheck / lint / depcruise / test(2071)全绿
(api:check 的差异全在 org/* 与 api/*,是工作树里先前那批鉴权改动,本轮未添)。
docs/ACT-WORK-05-端到端测试记录.md:六轮走查的逐轮结论与 A–K 十一条发现总表。
docs/debt.md:四条平台欠账(disable 无路可走 · 前一项不收后一项的件推不出来 ·
拒回数不出缺的是工具调用 · 零行台账的提交闸无牙)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 04:29:40 +08:00 |
|
 xcsandClaude Fable 5
|
7d743635eb
|
docs(w05): 数据域字段说明 —— ACT-WORK-05 差异评估十张台账
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
|
2026-08-27 00:10:28 +08:00 |
|
shanqin
|
8139948c28
|
活动模块二次确认瘦身成轻气泡(2026-08-26 用户定):只问一句+确认/取消,不摆影响三必答;本地 PopAsk 组件替代共享 AskBand,L2 禁用/激活与 L3 终止同用
|
2026-08-26 20:41:47 +08:00 |
|
shanqin
|
023d3157a0
|
实例不可删除、不可编辑(2026-08-26 用户定):L3 撤掉编辑/删除入口,只留进行中的终止活动;需求稿同步关闭两条待确认
|
2026-08-26 19:59:46 +08:00 |
|
shanqin
|
99f021f964
|
活动模块 L3 实例详情页:过程时间线为主角的主从布局;终止/编辑/删除收在最深层;L2 查看详情接入
|
2026-08-26 15:39:19 +08:00 |
|
 xcsandClaude Fable 5
|
a681ffe9f7
|
合并 feat/keycloak-auth:统一鉴权中心后端(ADR-012)+ 邮件收发模块(ADR-013)+ CI/CD 入库
CI / ci (push) Failing after 10s
主支这边(f01286a)是前端接 Keycloak(keycloak-js / PKCE / Bearer / 60 秒票据)、
活动模块运营态模版、数据域与工作台改版、/me 个人中心;分支这边 66 条:后端资源服务器
与角色→端、邮件收发(IMAP/SMTP · 企业微信邮件 API)、CI/CD 四件与两份文档、
pnpm-lock 补 mail 模块 importer。
冲突两处(packages/contracts/src/org.ts · api/workbench.ts):前端对着后端文档先行补的
principalSchema / meRoute / authTicketRoute(注释里自己写着「apps/api 仍是旧后端,契约暂留」)
缺 RouteContract 必填的 access,SURFACES/surfaceSchema 也已在 api/http.ts —— 取分支(后端)
这一份;前端代码对它原样编译通过(staff.email / roles 本就在 staffSchema 里)。
pnpm-lock 自动合并,--frozen-lockfile 核对一致。
五道门禁绿:1945 测试通过、23 跳过(无模型密钥 / 无真信箱的惯常项);
合并树与先前验证过的那棵树(9e9ba38)逐字节一致。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01712YeSo5fTfkCSPZHBiniq
|
2026-08-26 14:34:19 +08:00 |
|
 xcsandClaude Fable 5
|
f52edd5383
|
CI/CD 四件与两份文档入库 —— debt.md 早已写「已接」而文件一直没跟踪
.gitea/workflows/ci.yml · tools/ci.mjs · tools/cd.mjs · docs/部署.md:推主干跑五道门禁 +
从空库起的集成测试 + 三份构建,全绿后部署到 runner 那台机(机密一律 secrets.*,机器相关
一律 vars.*,文件里不写死)。debt.md 在 9848e2f 就点名了这几个文件,远端却从未有过 .gitea。
docs/keycloak-backend-guide.md:ADR-012 引为出处的后端接入手册(只有 clientId 与「有/没有」,
无密钥)。docs/数据域字段说明-E04-I01.md:设计中心数据域那一屏的字段说明。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01712YeSo5fTfkCSPZHBiniq
|
2026-08-26 14:34:19 +08:00 |
|
shanqin
|
f01286a89d
|
接入统一鉴权中心(Keycloak,ADR-012);活动模块 L1/L2 运营态模版(历史活动列表+检索+沙箱);数据域与工作台界面改版;个人中心 /me
|
2026-08-26 13:29:36 +08:00 |
|
xcs
|
0f1e53d114
|
文档:两份前端文档按真环境核对 —— clientId 实测为 task-dispatcher,示例换成实测响应
设计阶段写的两份对外文档,Task 12 只按契约核过,没按真环境核过。这次跑通之后逐条对:
① clientId 写的是「建议 api-gateway」——实际这个 realm 里 api-gateway 的 mapper 对我们不适用,
本部署是 task-dispatcher(两个前端 client 都已挂好指向它的 audience mapper,实测确认);
② e2e 账号写的是 bpos-e2e,实际用的是 task-dispatcher 的服务账号,且它只有 service+user
两个角色 → 只进得了工作台,要跑测试台得另配;
③ 「ends 为空」原本像个假想边界,实际 service 角色就是——没配进「角色→端」表的角色一律不加端;
④ §8 的响应示例从「按契约构造」换成实测响应(/api/me 的 JIT 建档结果、403 的真 message、
aud 不对时的 401、票据的真形状);
⑤ 两处「核对状态」改写:前置已就位、整条链真环境验过,并写明仍未实测的那一件——用真人 token 走一遍。
|
2026-08-26 10:55:58 +08:00 |
|
 xcsandClaude Fable 5
|
f70de44338
|
终审残余两处:换 address 就是换信箱;错误话的出口也剥 NUL
复审的两条范围外观察,都落在这一轮刚动过的那两段里,一并收掉:
① 收侧判据看不见 address —— `imapSettingsOf` 用的是 `login ?? address`,而 login **常常空着**,
这时候真正决定「登到哪个信箱」的就是 address。上一刀把发信三键排除掉之后,
换 address 判据为假:旧游标的 UID 说的是原来那个箱子,而 UID 是按信箱编号的。
判据改认**实际登录名**:login 填了就比 login(这时 address 只是发信落款,换它不动收信),
空着就比 address。wecom 不参与 —— 它的 address 由探测回填,比它会在回填那一刻误清游标。
② 治毒信的那道门自己会被同一个字符毒死 —— 降级存档把解析失败的原因写进正文与
`last_poll_error`,而那串原因常常来自那封信自己的字节。`errorText` 出口一律剥 NUL:
所有落库的错误话都从这一个出口出去,分散到每个调用点去剥,总会漏掉下一个新调用点。
两条测试都验过 RED→GREEN(拿掉修复各自变红,旁边的既有用例不受影响)。
顺带:`mail/CONTRACT.md` 两处点名的 `createFakeMailProvider` 全仓不存在(未定义、未导出、无调用方)——
契约文档摆一个不存在的出口,照它接线的人会去 import 一个没有的东西;改成实情。
debt 补 ⑳-㉔(IMAP 每轮重登录与腾讯频率限制 / wecom -1 无退避 / pollDue 每 tick 刷日志 /
notes 不设上限 / claimForResend 推 created_at 使该列不再是创建时刻)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 04:07:08 +08:00 |
|
 xcsandClaude Fable 5
|
816389a185
|
邮件收发终审修复轮:token 按凭证指纹、毒信有退路、只改发信设置不丢信、重发先抢、列表不搬原件、save 不盖运行列、重锚出声、脏游标不炸页、线程口径归一
全分支终审(跨任务视角)逮出的十条 P0 + 八条 P1,一次修完。每条都配了测试。
P0-1 企业微信 token 缓存改按**凭证指纹**(sha256(corpId,corpSecret),secret 不进 Map 的键):
按 account.id 存有两条真实串号路径 —— 草稿探测共用 'draft'(探完 A 公司再探 B 公司会命中 A 的
token,回的是 A 的应用邮箱地址,凭证填错的 B 也显示成功);已存账号换了凭证 id 不变,
下一轮轮询继续拿旧 token 拉旧 corp 的收件箱,分发给新账号绑的通道(窗口 ≤ 7200s)。
P0-2 一封「毒信」不许卡死整条路:①domain 的 buildInboundRecord 把落 text/jsonb 的字段一律剥 NUL
(PG 拒收它,MIME 解出二进制垃圾时真会出现);②单封失败先落**降级骨架**(原件原样存、
主题从原始字节扒、正文写明失败原因)→ 落成了就推进游标并把「第 N 封(providerRef)解析失败,
已降级存档」写进 last_poll_error;骨架也落不下才停在这一封,那时 error **点名是哪一封**。
降级行不自动分发(正文是失败原因,不是客户的话)。
P0-3 cursorReset 只比**收侧**键(imapHost/imapPort/imapTls/login/folder;corpId/apiBase):
从前比全部 settings,把 465 改成 587 也会清游标 → IMAP 重锚 → 上次游标到重锚之间的来信永远不拉。
P0-4 复用旧行重发**先抢**(OutboundStore.claimForResend,一条条件更新;真 store 与内存件同款):
两个后端连同一个库,两台同时重放同一次放行都判「超时可复用」→ 两封真邮件,破掉「同键不发两封」。
P0-5 列表与只要元信息的读**不取 raw**(一封上限 16MB × 200 行);rawAvailable 由 `raw is not null`
投影,不靠取回字节再判;只有「下载原件」走全列的 get()。InboundRecord 新增 rawAvailable。
P0-6 账号 save() 只写**配置列**:运行列(cursor/last_polled_at/last_poll_error/last_inbound_at/
polling_until)只经 savePoll/claimPolling/releasePolling 改 —— 整行 upsert 会把另一台正持着的租约
与刚推进的游标盖回读那一刻的快照(08-24 loop_state 整份覆盖同款指纹)。清游标改为显式单写那一列。
P0-7 UIDVALIDITY 变化不再静默:provider 回 note,用例落进 last_poll_error(「已重锚在当下;
期间来信未拉取」)—— 丢了一段信而账号页一片绿是界面撒谎。
P0-8 parseCursor 连取值范围一起查(非负安全整数 + 界内:UID ≤ 0xFFFFFFFF、秒 ≤ Date 上限)——
1e13 正是安全整数,乘 1000 出界,一行脏游标能让 listAccounts 整页 500。debt ⑨ 划线销账。
P0-9 线程口径归一:threadIdOf 改成**取根**(references[0] ?? inReplyTo,ADR-013 决策 3),
mail-wiring 调它、不再内联一份。原测试改断言,不删。
P0-10 文档说老实话:mail.send 工具路发出的信**不登记 outbound_ref**(recordOutbound 的唯一调用方
channel.sendMail 在 src 里零调用方)—— API 文档 §4 与 ADR-013 决策 6 各补一段,根治记 debt。
P1:imap anchor 的 Math.min(...uids) 改 reduce(十万级 UID 会栈溢出)· wecom 翻页加页数上限
(服务端一直回 has_more:1 会死循环)· MAIL_TOOL 导出并对**真契约**断言(原 v1/v2 是手抄夹具、
自证,且 v1 版本号写错)· reset-runs 清运行数据时把邮箱账号的游标与拉取状态一并清(留着游标而信没了,
wecom 十分钟重叠窗会把最近的信当新信再投一次)· due.test 的 leaseMsFor(30) 断言改写死 300_000(原为自证)·
cursor.test 删掉指向评审报告的注释 · 设计稿稿头标注三处已被 ADR-013 取代 · ADR-013 补记 wecom
compose_send 不带 inReplyTo/references(它发出的信在对方那里不串线程)。
契约变更(§12.4):port.ts 的 InboundStore 加 getMeta、OutboundStore 加 claimForResend、
savePoll 的 cursor 允许显式 null、MailProvider.pull 回参可带 note —— 实现方只有本模块 adapter 与
__tests__/fakes.ts 的内存件(两边语义一致,已同改),CONTRACT.md 已同步,api-report 已刷新。
测试:1922 → 1942(mail 模块 102 → 113,含真 PG 的 save 不盖运行列 / 不搬原件 / 两条真连接抢同一行)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 03:47:48 +08:00 |
|
 xcsandClaude Fable 5
|
18ca6dacfe
|
文档修复:补齐入站线程取根、企业微信游标整窗语义、发信幂等第三支(未超时 sending 不发)—— controller 评审逐条核实后落笔
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 02:57:44 +08:00 |
|
 xcsandClaude Fable 5
|
e862a5279b
|
文档:ADR-013 邮件收发、API 文档与前端对接说明(两形账号 / 四个动作 / 投递状态 / 腾讯侧前置)、总表 15 条、欠账十五笔、CLAUDE 快照
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 02:38:12 +08:00 |
|
 xcsandClaude Fable 5
|
ab30ce56c5
|
计划修:入站线程取根不取最近一跳,附件缺 uploadRef 不静默丢
评审逐跳走了一遍:我方出站登记的 threadId 恒是这一串的首封,而归属解析①级是精确等值。
入站若取 In-Reply-To(最近一跳),跑一个来回就漂 —— 我方 M1 → 客户回 M1(命中)→ 我方再回
(实际 M2、仍记在 M1 名下)→ 客户回 M2 → 库里从没记过 M2 ⇒ ①级落空,退到③地址+时间窗。
取 references[0](根)才稳定;客户端只给 In-Reply-To 时退回它。
同批:app 层丢掉没给 uploadRef 的附件却照回 queued:true —— 模块自己那一层是硬的(抛 MailSendInvalidError),
app 层比它松,活动说「带上 q.pdf」而信发了附件没了、没人吭声。翻成 invalid。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 02:16:41 +08:00 |
|
 xcsandClaude Fable 5
|
58358210e2
|
计划再修:游标推进与 more 必须同一个判据 —— 「页翻完」不等于「新信吃完」
上一次修的是「多页时截断不许推进游标」,但漏了一形:最后一页可能同时 has_more:0
且新信多过本轮预算(LIST_PAGE 是 100,与 perTick 的 50 无关)—— 那时 exhausted 为真、
游标照推,而 wanted 截掉的那几封从此永久丢(重叠窗只兜 10 分钟)。
评审的话说得准:more 的判据是对的,cursor 的不是,两者本该是同一个。
改成 `const more = !exhausted || fresh.length > wanted.length; cursor: more ? cursor : 推进`。
补两条测试:单页 has_more:0 但新信超预算(游标不许动)、-1 连击到边界不再重试。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 02:05:39 +08:00 |
|
 xcsandClaude Fable 5
|
f04c64926b
|
计划修死企业微信那条路的游标丢信:截断时不许把游标推到窗口上沿,且滤重要在截断之前
Task 9 的评审点过「批末无条件覆盖游标、没有单调性护栏」,当时两个适配器还没落地、判不了实情。
照原计划的 wecom pull 读下来是两个真缺陷,都只在积压超过一轮预算(50 封)时现形:
① 被 limit 截断时仍把游标推到窗口上沿 —— 没读到的那几封从此跳过去了;
重叠窗只兜 10 分钟,兜不住一次积压(停机重启、首次回填)。
② 滤重(known)发生在截断**之后** —— 一个窗口里若前 50 条恰好都已入库,这一轮交出 0 封,
而引擎见空批即收工、游标又没动,下一轮还是这 0 封,永远吃不到后面的新信。
改法:滤重提到分页循环里(每页先滤再数够不够),游标只在把窗口翻完时才推进,
截断时原样退回 —— 已入库的下一轮被 known 滤掉,每轮照旧往前吃一批,不卡也不丢。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
|
2026-08-26 01:42:10 +08:00 |
|