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:
xcs
2026-08-27 23:20:16 +08:00
co-authored by Claude Fable 5
parent 909b1fe4b7
commit 7b85a79323
79 changed files with 3903 additions and 1297 deletions
+24
View File
@@ -29,6 +29,7 @@ import {
import { ReplyRejectedError } from '@modules/human-tool';
import { advanceOrder } from '@modules/process';
import { assetRowsOf, keyText, listArchived, readArchived } from '../asset-archive.ts';
import { landDataOrder } from '../data-order-landing.ts';
import { composeFile, isFileFormat, MIME_OF, safeFileName, type FileFormat } from '../file-compose.ts';
import { toFileDoc } from '../file-doc.ts';
import { displayLog } from './log-lines.ts';
@@ -1441,6 +1442,29 @@ export function registerDeskRoutes(app: Hono<AppEnv>, container: Container): voi
* 仍守铁律②:写的是草稿层,放行那一刻才并进正式版。
*/
await applyBoundTableEdits(container, outcome.taskId, outcome.order, parsed.data);
/*
* **数据工单确认即入库**(2026-08-27 用户定):这张卡让人从零建一张主数据表,
* 确认落下那一刻,它的提交闸盯着的那几张表就并进正式表 —— 不等整单放行。
* 从前卡上写着「确认后即入库」而系统里没有一行代码兑现它;试跑单更是永远不落。
* 放在保存与回传都落定之后:并进去的就是人交卷那一刻件上的样子。失败不拦人(痕上说清,放行时再并)。
*/
await landDataOrder(
{
ledger: container.ledger,
memory: {
append: (entry) =>
container.memory.append({ ...entry, stamp: { contractVersion: '1', businessModelVersion: '1', skillVersions: [] } }),
},
labelOf: async (address) => {
const task = await container.task.get(outcome.taskId).catch(() => undefined);
const manifest = task === undefined ? undefined : await container.registry.manifestOf(task.activityId).catch(() => undefined);
return manifest?.declarations.ledger.find((l) => `${l.domain}.${l.object}` === address)?.label ?? address;
},
touched: () => container.broadcaster.publish({ kind: 'system', id: 'ledger', reason: 'data-order-landed' }),
},
outcome.taskId,
outcome.order,
);
/*
* **返回之前就把这单标成「在办事」**(2026-08-25 用户:「右边聊天框先有反应,中间的
* html 过一会儿才变成 AI 正在推进中,看上去很不流畅」)。
+2 -1
View File
@@ -1305,7 +1305,8 @@ export function registerGovernanceOpsRoutes(app: Hono<AppEnv>, container: Contai
/** 草稿层:一次查完按地址分组 —— 每张表单独查会把这一屏拖成几十条 SQL */
const draftRows = rowsOf<{ domain: string; object: string; n: string; at: Date | string }>(
await container.db.execute(
sql`select domain, object, count(*)::text as n, max(updated_at) as at from ledger.__draft group by domain, object`,
// 已在数据工单确认时入库的行(landed_at 非空)不算「在办草稿」—— 它们已经在正式行数里了
sql`select domain, object, count(*)::text as n, max(updated_at) as at from ledger.__draft where landed_at is null group by domain, object`,
),
);
const drafts = new Map(