Archived
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
This commit is contained in:
@@ -108,6 +108,7 @@
|
||||
|---|---|---|
|
||||
| `data-slot="键"` | 任意元素 | 取值填为文本。数值整数原样、小数截 4 位;数组给长度 |
|
||||
| `data-rows="mine:域.对象"` | 行容器(tbody 等) | 按本单草稿行逐行复制内部结构;行内 `data-slot` 相对该行取值;序号交 CSS 计数器 |
|
||||
| `data-by="子列"` / `data-by="子列=父列"` | 与 `data-rows` 同元素(**嵌套**在另一个行模版里) | 只留子列值 = 外层那一行父列值的行 —— 「一个候选一张表」(外层按候选复制 `<section>`,里层只列它名下的明细);也能当查表用(`<span data-rows="parts.profile" data-by="internal_pn=candidate_internal_pn">` 从整表里挑这一颗料那一行摆品牌)。父值缺席一行不留。行模版可以嵌套:里层先按本行展开,再填本行标量;**外层容器的标签名不得在行模版内部再出现**(用 `<article>` 包 `<section>`) |
|
||||
| `data-blank` | 与 `data-slot` 同元素 | 空值**真空**(不写「无」)—— 空格子的胶囊、占位交给 CSS `:empty::after` |
|
||||
| `data-class-of="键"` | 任意元素 | 把值消毒成 `v-<小写值>` 追加进 class(数值就是 `v-0`/`v-1`/…)。**判断留在样式表** |
|
||||
| `data-col="台账列名"` | 可改格子(与 `data-slot` 同元素) | 渲染时多渲一个孪生 `<input class="jc-cell">`;写的是**台账列名**不是表头文字(表头改说法不该让写回错位) |
|
||||
@@ -140,6 +141,34 @@ routeTo / routeWhy` = 引擎注入的案情与算出的去向。
|
||||
数值列**与表头同侧左对齐**(右对齐是给要竖着相加的数用的;一行一个料、彼此不相加的表,
|
||||
右对齐只让数和自己的标题分家),等宽字体留着。
|
||||
|
||||
### 4.1 运营中心沙箱看板:`viewTemplates[].data` 取数声明(2026-08-27)
|
||||
|
||||
工单件的行由引擎按**本单草稿层**给(`mine:`);运营中心活动详情底部那张沙箱看板摆的是**最近一次已放行实例**
|
||||
的落账快照 —— 草稿层放行后已清空,行只能按案号从**正式表**圈。「哪几行是这一单的」是活动自己的知识
|
||||
(案号前缀、哪张表按哪一列圈),所以写在模版旁边的 `data` 里,基座只照它查:
|
||||
|
||||
```ts
|
||||
{ name: 'activity-ledger', html: LEDGER_BOARD, data: {
|
||||
case: { ledger: 'sub_eval.verdict', key: 'eval_ref', prefix: 'W05-' }, // 案号 = prefix + 开案时刻 14 位数字(与模型铸主键那串同源)
|
||||
rows: [
|
||||
{ as: 'sub_eval.pn_check', ledger: 'sub_eval.pn_check', by: { column: 'eval_ref', from: 'case' }, orderBy: [{ field: 'role', dir: 'desc' }] },
|
||||
{ as: 'parts.profile', ledger: 'parts.profile', by: { column: 'internal_pn', from: 'sub_eval.pn_check.internal_pn' } },
|
||||
{ as: 'validation.history', ledger: 'validation.record', by: { column: 'validation_internal_pn', from: 'sub_eval.pn_check.internal_pn' },
|
||||
not: { column: 'request_id', from: 'sub_eval.verdict.request_id' } },
|
||||
] } }
|
||||
```
|
||||
|
||||
- `rows` **按序**求值:`by.column ∈ values(by.from)`,`from` 只能是 `case` 或**前面**某个 `<as>.<列>`;每个值单独一次
|
||||
等值读(正式表里历次运行的行并排躺着),结果按 `from` 值的顺序拼接 —— 想让原 PN 排第一,就让核对表按 `role desc` 排;
|
||||
`not` 排除一批(同料号历史 = 按料号圈的减去本单挂的);同一张表圈两批就另起 `as`。
|
||||
- 作用域:`<as>` 行数组(`data-rows="<as>"`,嵌套行照旧 `data-by`)、`<as>.<列>` 首行标量(一单一行的 verdict / demand
|
||||
直接 `data-slot="demand.request.request_id"`)、`<as 去符号>_rows` 行数、`<as 去符号>_<列>_<值>` tally 计数(先铺 0)、
|
||||
`case:instanceNo / openedAt / releasedAt / owner / ref`、`board:state`(`ready | missing | none`,挂在 `.page` 上
|
||||
`data-class-of` 投成 `v-ready` 等,横幅与区块的显隐交样式表)。
|
||||
- 表未物化 / 查询失败:那一块空着、stderr 一行,整屏不 500;案号那一行查无 → `missing`;没放行过 → `none`。
|
||||
- 看板**只读**:没有 `data-edit` / `data-col`;仍不算不判(MATCH 行淡显、放弃的候选只在有 abandoned 行时露面,
|
||||
都是 `data-class-of` 投出的 class 交样式表;计数摆基座读数)。渲染在 `apps/api/src/app/activity-ops/view-scope.ts`。
|
||||
|
||||
## 5. 模版不许算,但基座算过的可以摆
|
||||
|
||||
两件事别混:
|
||||
|
||||
+37
-1
@@ -1245,7 +1245,11 @@ pnpm 硬链到全局 store,真实占盘远小于这个数,但 `du` 看着吓人
|
||||
要么在拒回里明说「本平台没有弃用计划项这回事,不需要办的项什么都不用做」。
|
||||
**现状**:活动侧全包清了 `disable`,并在哨兵上加了「真有料号不在库」才开门。
|
||||
|
||||
- **前一项不收掉,后一项的件就推不出来**:引擎挑画面按「当下还没干完的第一步」取 view
|
||||
- ~~**前一项不收掉,后一项的件就推不出来**~~(2026-08-27 晚销账:用户送来 3ef3fc3e 当场复现 —— 模型没 finish
|
||||
S0d_p08 就发了 P-10 的卡,件停在 P-08。现在**画面跟着这一拍发出去的卡走**:human / entry / decide 把
|
||||
「发给了哪一步」交回拍内,那一步声明了画面就推它,压过「第一步没干完的」;有测。**根治**(同夜,用户:「不要只修表象」):
|
||||
人工激活的项在人答过卡之后照常求 doneWhen(拍首拍尾各一遍),W05 两张数据工单的 doneWhen 只读入库事实,
|
||||
S1 哨兵不再等模型写 created 旗 —— 上一步办完与否不再靠模型记得 finish。):引擎挑画面按「当下还没干完的第一步」取 view
|
||||
(`turn-runner.ts` 2058-2064 附近)。模型把「人交回 → 发下一张卡」压成一拍、忘了 `finish`
|
||||
上一项时,卡是新的、件还是旧的 —— **人拿到的卡写着「把资料填到件上」,屏上一个格子都没有**,
|
||||
提交闸如实拦死,整单挂在那儿。E04 的 S4→S5 撞过同一堵墙(2026-08-23 已按 `currentRuntime`
|
||||
@@ -1272,3 +1276,35 @@ pnpm 硬链到全局 store,真实占盘远小于这个数,但 `du` 看着吓人
|
||||
真治法待议:若一张必交付台账本单一行都没写,闸该拦并说「这张表还没有内容」;
|
||||
但也有活动是让人在件上加第一行的(那时零行合法)—— 得由活动声明区分。
|
||||
**现状**:活动侧把「发卡前清单必须先有行」写进说明书(每拍都在),配测试。
|
||||
|
||||
## 运营中心 · 活动模块接口(2026-08-27 落地时记下的)
|
||||
|
||||
- **实例清单的过滤 / 分页在内存里做**:`listInstances` 全量取该活动的 `sys.task`,非终态行逐单读记忆与
|
||||
loop 运行态判驳回,再在内存里筛、数、切页。MVP 量级(一个活动几十到几百单)够用;
|
||||
上千单后该把状态落成一列(或物化视图),过滤下推到 SQL。
|
||||
- **`sys.activity_profile` 只有 seed 一个写口**:负责人 / 说明 / 图标 / 色相由 `seed-activities.ts` 的
|
||||
`ACTIVITY_PROFILES` 按包填,负责人按岗位取第一个在职的人。运营面的改口(改负责人、改说明)
|
||||
等「创建活动」功能一起定。
|
||||
- **`format: 'file'` 的启动字段不上表单**:`launch-params` 直接省略它们(W05 的 datasheets 走数据工单)。
|
||||
文档 §4 的控件种类里没有文件控件;要上得前后端一起加。
|
||||
- **禁用只拦运营端启动**:`POST /api/gov/activities/:id/instances` 看 `enabled`;触发器 / 工作流 / 测试台起单
|
||||
都不看它(`task.start` 里没有这道门)。文档 §0 的「禁用只拦新启动」目前就是这一个口。
|
||||
- **combo 候选内联、封顶 500 行**:`x-options` 指的表按 label 升序取前 500;客户 / 料号台账更大时要走检索式候选
|
||||
(文档 §4 预留的 `optionsSource`)。
|
||||
- **E04 的「新客户」入参形状启动不了**:`customers` 数组元素可以是对象(新客户档案),启动表单只收字符串数组。
|
||||
运营端要起新客户那条路,得给 list 控件一个对象形态或另开录入。
|
||||
|
||||
|
||||
## 运营中心 · 活动详情沙箱看板(2026-08-27 接数据时记下的)
|
||||
|
||||
- **只摆最近一次已放行的实例,挑不了单**:用户定 MVP 先这样。要看别的单 / 在办中的单,`opsActivityViewRoute` 得加
|
||||
`?instanceId=`(在办的单要走 `taskView` 连草稿层一起圈,`missing` 那一态也会多一种说法)。
|
||||
- **行级来源标记只有 P-08 有**:P-08 借 `sub_eval.pn_check.exists_status`(found = 在库直读 / created = 本单建档)说了
|
||||
每颗料是不是这一单建的;P-10 / P-06 只按「本单挂的 / 同料号历史」分两个 `<tbody>`,P-10 分不出哪份资料是本单
|
||||
数据工单建的。要分,得在放行留痕里记主键名单(`ledger-write` 的 detail 现在只有表与行数)。
|
||||
- **`vtok` / `badgeCss` 三处各一份**(`report.ts` / `views/badge.ts` / `activity.test.ts`)——都注明「必须与 `classToken`
|
||||
一字不差」;该抽进 `@sdk` 一处,包内测试改 import。report.ts 当时另一会话在改,没动它。
|
||||
- **`viewTemplates[].data` 没有装包期静态审**:`from` 指到没声明的表 / 后面的集合、`by.column` 不是那张表的列,
|
||||
现在只有 W05 包内测试钉着 + 运行时「那一块空着 + stderr 点名」。该并进 `static-audit`(与 `refersTo` 目标核对同款)。
|
||||
- **`docs/数据域字段说明-W05.md` §二 / §十二.4 的参数集口径过时**:仍写 `normalized_parameter_set` 是 text 列「不建子表」,
|
||||
而清单早已拆成子表 `parts.parameter`(库里那一列全 null)。一览表也少 `parts.parameter` 一行。
|
||||
|
||||
+30
-7
@@ -82,7 +82,7 @@ activities/<id>/src/ ──(pnpm activities:build)──> dist/{manifest.json,in
|
||||
|---|---|---|
|
||||
| `declarations.ledger` | 运行时**只准写**这里声明的地址与列名;**人从件上改回来的值也走同一道门**(§3.1) | 编出来的列当场拒;未声明地址的保存一格不落 |
|
||||
| `declarations.tools` | Agent 可调的工具名单 | 未白名单授权报错(越权不转人) |
|
||||
| `assets.viewTemplates` | 工作区能推的画面 | 模版名对不上,「换画面失败」留痕、屏上不动 |
|
||||
| `assets.viewTemplates` | 工作区能推的画面;带 `data` 的那张(`activity-ledger`)是运营中心沙箱看板,`data` 定它按案号从正式表圈哪几张表的行(《HTML报告生成规范》§4.1) | 模版名对不上,「换画面失败」留痕、屏上不动;`data` 指了没声明的表或后面的集合 → 那一块空着、stderr 点名 |
|
||||
|
||||
静态审还核:**谓词里的名字必须是声明过的台账列或基座读数**(`域_对象_rows` /
|
||||
`_missing` / `_gaps` / `_<列>_<值>` 这些基座读数在审的白名单里)。
|
||||
@@ -112,6 +112,19 @@ activities/<id>/src/ ──(pnpm activities:build)──> dist/{manifest.json,in
|
||||
读己之写,不抛事件)/ `releaseWrite`(放行合并,此刻抛事件)。三个方法不是一个带 flag 的方法。
|
||||
- **`draftDrop`**:撤掉本单草稿层的一行 —— 不是第四种写(正式版碰不到、不抛事件)。
|
||||
它存在的理由:门拦住一件办错的事却不给改正的手段,那扇门就只是个死胡同。
|
||||
- **验收卡上的条目是人工验收清单,不是系统判据**(2026-08-27 用户定):派验收卡的那一步(终局 `submit`
|
||||
的 T_release,或 `cardVariant:'review'` 的审核步)在剧本上声明 `acceptanceChecklist: string[]` —— 人拿着这份
|
||||
工单要亲自核的步骤,一条一句可核对的动作,**每份验收工单固定**;引擎发卡时带上,卡上一条一枚「达标 / 不达标」
|
||||
开关,全部达标才能「确认通过」(服务端同样把关)。系统判的 `acceptanceCriteria` 照旧把提交门,不再摆到卡上让人签。
|
||||
写清单的口径:先看这份件人要看什么(汇总表 / 明细表 / 落库预览),每张表一条「核对什么、对到什么算对」;
|
||||
别抄机检判据的话(那是引擎数的数),要写人眼睛能核的事。
|
||||
- **数据工单确认即入库**(2026-08-27 用户定):`cardVariant: 'data'` 那一步派的卡,人一确认,
|
||||
基座就把卡上 `gateLedgers`(或绑的 `blocks`)那几张表并进正式表 —— 与提交闸同一份名单,不等整单放行。
|
||||
并过的行仍算「本单写下的行」(`mine:` / `_rows` / 任务视图照旧有它),整单放行时不再写。
|
||||
活动侧要知道的只有两件:①剧本别再教模型「人填的东西已落草稿层、放行前还能改」—— 已入库的键
|
||||
再 write 会被当场拒(拒回会说清是本单建好的行,别 drop);②**数据工单必须给 `gateLedgers`**,
|
||||
不给就没有一张表会因确认而入库(闸也没牙)。轨迹里有一条「数据工单确认入库:表 N 行」的痕,
|
||||
试跑单不落主数据时如实写「只留在活动缓存」。
|
||||
- **归型前移**:`draftWrite` 按声明列型归(空值 = 不写这一列、数值/布尔字符串转真类型、
|
||||
归不了当场拒)。**人手改的值与 AI 写的值过同一道门**。
|
||||
- **字段五标记**(`fieldDeclarationSchema`):
|
||||
@@ -252,7 +265,7 @@ activities/<id>/src/ ──(pnpm activities:build)──> dist/{manifest.json,in
|
||||
| `ask` | ~~已退役~~ | 基座原地转成零输入执行工单(字段名并进指导书);别再用 |
|
||||
| `entry` | `{itemId, ask, ledger, entryKey, fields, also?}` | 数据录入卡,挂起;确认那一下基座直写 |
|
||||
| `decide` | `{itemId, ask, options(≥2), basis}` | 决策卡,挂起 |
|
||||
| `human` | `{itemId, workOrder, card{title,ask,steps?,standard?,basis}}` | 执行/验收工单,挂起。**执行卡零输入**(2026-08-02 用户定):不摆 `fields` 不绑 `blocks`,填写全在工作区的件上(editGate + 孪生件),人按「保存」基座直写草稿层;必填由提交闸看住 —— **卡上加 `gateLedgers:["域.对象"]` 告诉闸这一张要拦哪几张表**,不给才回落到必交付物声明。**数据工单**(让人从零建一张主数据表)在那一步的剧本上声明 `cardVariant: 'data'` —— 引擎那一侧与执行工单无异,对话区据此换成「数据工单」那副面孔;卡骨架上的 `variant:"data"` 只是给模型看的提示,模型抄丢了也不影响(实测它会丢) |
|
||||
| `human` | `{itemId, workOrder, card{title,ask,steps?,standard?,basis}}` | 执行/验收工单,挂起。**执行卡零输入**(2026-08-02 用户定):不摆 `fields` 不绑 `blocks`,填写全在工作区的件上(editGate + 孪生件),人按「保存」基座直写草稿层;必填由提交闸看住 —— **卡上加 `gateLedgers:["域.对象"]` 告诉闸这一张要拦哪几张表**,不给才回落到必交付物声明。**数据工单**(让人从零建一张主数据表)在那一步的剧本上声明 `cardVariant: 'data'` —— 引擎那一侧与执行工单只差一处:**人一确认,卡上 `gateLedgers` 那几张表就并进正式表**(2026-08-27,见 §3.1),对话区据此换成「数据工单」那副面孔;卡骨架上的 `variant:"data"` 只是给模型看的提示,模型抄丢了也不影响(实测它会丢) |
|
||||
| `listen` | `{itemId, eventType, keyFilter, deadline}` | 立监听,挂起;时限必配 |
|
||||
| `finish` | `{itemId, rationale}` | 宣告一项完成;非人工激活的项就地过 Active 再收 |
|
||||
| `submit` | `{rationale, fields?}` | 提交放行 → 预检 → 发验收卡挂起 |
|
||||
@@ -266,7 +279,7 @@ activities/<id>/src/ ──(pnpm activities:build)──> dist/{manifest.json,in
|
||||
标了 `manualActivationRule` 的项,**模型显式动它(调工具/发卡/finish)就算启动**,
|
||||
不必单发 `start`(2026-08-02 拆墙)。它的分量在引擎那一侧,原样保留:
|
||||
**引擎不因哨兵满足替它启动**(哨兵只推到 Available/Enabled),
|
||||
**也不给 doneWhen 替人收**(自动收步跳过人工激活项)—— 收它只能是模型的 finish。
|
||||
**人答卡之前不给 doneWhen 替人收**;答过卡之后 doneWhen 照常生效(见 §4.4)。
|
||||
|
||||
实测账(两轮,同一堵墙):先是「话与门同宽」—— 提示词写「先 start 再调工具」只说了
|
||||
调工具,而门拦 tool/ask/human/decide/entry/finish 一整片,模型发 `human` 照字面漏了
|
||||
@@ -279,8 +292,17 @@ start 已收项无事发生同族)。剧本里也别再教 start —— 教它
|
||||
### 4.4 自动收步(doneWhen)
|
||||
|
||||
引擎每拍开头对任务视图求每一步的 `doneWhen`,**真了就自己收那一项,不问模型**
|
||||
(与模型同拍撞车时:引擎收过了,模型这拍的 finish 当已完成,不抛非法迁移)。
|
||||
人工激活的项**不给 doneWhen** —— 给了等于给引擎一把替人签字的钥匙。
|
||||
(与模型同拍撞车时:引擎收过了,模型这拍的 finish 当已完成,不抛非法迁移);
|
||||
**拍尾再求一次**(人答卡那一拍里模型写完东西 doneWhen 才真,不等下一拍;这一拍刚发卡的项不算)。
|
||||
|
||||
**人工激活的项也可以给 doneWhen,引擎只在人答过卡之后才求它**(2026-08-27 晚立):
|
||||
门槛是 `worldTouched`(卡真发过)且没有未答的卡 —— 卡没发过时 doneWhen 再真也不收,
|
||||
那才是替人签字。答过之后,「办完了没有」若是基座数得出来的事实,就写成 doneWhen 交给引擎:
|
||||
W05 的两张数据工单(人填的值已入库、必填不缺、逐颗对账)就是这一类 —— 从前靠模型记得 finish,
|
||||
剧本两处写死「先 finish 再发下一张」它照样忘,两步同时 Active、件停在上一步、人无处可填。
|
||||
**指南让模型判的事,引擎有现成事实的,一律改成读事实** —— 这条也管收步。
|
||||
仍不给 doneWhen 的:终局放行(T_release,由 submit 走)、审核循环、以及「办完了没有」
|
||||
数不出来只能由人说了算的项。
|
||||
|
||||
---
|
||||
|
||||
@@ -331,12 +353,13 @@ A1 是 `customerEmail / subject / body / attachments`)。
|
||||
裁量项),模型全程跟 harness 较劲,一单二三十万 token 收不了口;扁平 7 项后零被拒。
|
||||
2. **案卷项 id 就是任务视图键名**(入参与台账列摊平后的名字)。对不上 = 前提永不满足 =
|
||||
第一个项都不 Enabled,而每一层单看都「正常」。
|
||||
3. **`manualActivationRule` 只标触达世界与关键交付的项**,且**不给 doneWhen**。
|
||||
3. **`manualActivationRule` 只标触达世界与关键交付的项**;它的 doneWhen 只在人答过卡之后才求 ——
|
||||
「办完了没有」基座数得出来的(数据工单确认入库)就给,数不出来的(放行 / 审核 / 交人补缺口)不给。
|
||||
A1 标两项:S3_confirm(要打断真人)、T_release(签下去触达世界)。
|
||||
4. **人的门要建成一项,不要挂成某一步收步条件里的半句。** 「缺东西才叫人」的写法,
|
||||
一封齐整的询价进来那半句当场为真,引擎自己收步,人一眼没看过就被叫去验收
|
||||
(用户原话:「我都没确认需求 它就让我验收了」)。做法:独立一项 + 人工激活 +
|
||||
不给 doneWhen + 下一步的入场前提取**只有人的回复才产生的计数列**(`confirmed_total`)。
|
||||
人答卡之前不收 + 下一步的入场前提取**只有人的回复才产生的计数列**(`confirmed_total`)或人填的值入库的基座数。
|
||||
5. **哨兵必须有 ifPart,且读基座数、认「办完了没有」**(§3.3 放行门那行的教训)。
|
||||
6. `repetitionRule` 标常来回的项;判断菱形 = 两条互斥前提的 sentry,不是一个计划项。
|
||||
7. `autoComplete="true"`;里程碑前提达成即达成;`ifPart` 前缀 `semantic:` 交 judge。
|
||||
|
||||
Reference in New Issue
Block a user