Skip to content

待办工作台:按数据范围自动分角色的待办区块 + 填报单行级审核动作 + 待审核/待审批直达菜单 #36

Open

Description

@baozhoutao

背景(来源:调度员 2026-09-06 产品走查,维护者以 /os-project-pm-dispatch 放行本批)

工作台对所有角色是同一张全量可编辑网格:人力审核、管理员登录看到全组织明细,分公司核对人员看到空表;人力审核与分管领导审一张单要「回列表 → 重选页签 → 打开 → 审」,分管领导的队列还藏在「还有 4 个」溢出菜单里(平台 objectstack-ai/objectstack#14883、#14952)。UI 实测:人力审核 11 张单 131 击,分管领导每张 5.5 击,分管领导是唯一按手册找不到入口的角色。

范围(全部元数据改动;不碰 src/lib/scoring.ts、src/hooks/、src/actions/index.ts)

  1. 待办工作台(src/pages/index.ts 的 kpi_home):现有「待填报的指标」「填报单」两个区块之外,增加「待我核对」(核对任务,状态 = 待核对)、「待人力审核」(填报单,状态 = 人力审核中)、「待领导审批」(填报单,状态 = 领导审批中)三个只读网格区块,各带行动作(确认无误/提出争议;审核通过/驳回)。区块不按角色显示——数据范围会让每人只看到自己该处理的行;空区块保留但压缩高度。「待填报的指标」网格保留,若平台允许按本对象字段过滤,只显示所属填报单为「填报中」的行(明细上若无该字段则如实记录,不加字段)。
  2. 列表行级审核动作(src/views/index.ts EntrySheetViews):确认填报单列表行菜单在对应状态下出现「审核通过」「驳回」「归档」(动作已是对象级,核实可见性与确认框文案);驳回原因在行级动作里仍必填。
  3. 直达菜单(src/apps/index.ts):在「填报与审核」组增加「待人力审核」「待领导审批」两个导航项,用 viewName 直指填报单的对应列表视图(spec app.zod.ts 支持);分公司核对的「待我核对」同样加一项。导航按岗位裁剪沿用现有 requiredPermissions 机制。
  4. 文案守 std-copy 四条红线;新增 label 用 pnpm i18n:extract 重生成翻译包。

不做

不做站内通知(V1.1 第 18 项);不改流程节点与驳回口径;不做自定义代码页;不改核对任务的生成范围(#27)。

方案分级与放行(调度员)

改已有页面与导航、列表视图 = 中风险,放行方向如上;开工前在本单评论列「区块 × 岗位」实测可见矩阵与导航前后对照,与放行方向一致即开工;平台组件做不到的如实记录并只上报。

验收标准

  1. 分公司核对人员(east.checker@kpi.demo)登录后在工作台看到「待我核对」区块列出本分公司待核对任务,可在行内「确认无误」;10 条任务不进列表页也能处理。
  2. 人力审核(hr.reviewer@kpi.demo)登录后工作台「待人力审核」列出待审单,行动作「审核通过」「驳回(原因必填)」可用;左侧菜单「待人力审核」直达对应列表;审 1 张单 ≤ 3 击且不进详情页。
  3. 分管领导(leader.tech@kpi.demo)登录后工作台「待领导审批」只列分管主体的单;左侧菜单「待领导审批」直达,不再需要点「还有 N 个」;审 1 张单 ≤ 3 击。
  4. 部门填报人员的工作台仍能一屏填数出分提交(填报体验优化:填报单一屏填数出分提交(主从子表)、工作台待办入口、明细列表瘦身、堵住相关页签与编辑表单两条死路 #34 达成的 0 跳页不回退);空区块不报错。
  5. 管理员、人力负责人页面不报错;pnpm verify 绿;scripts/software-flow.mjs 54/54、scripts/e2e-flow.mjs 全 PASS。
  6. 测试报告(五类岗位截图 + 逐步点击数)与需求符合度清单挂本单评论,截图走 acceptance-evidence 40 位 SHA 图链。

测试计划草稿

T1 区块 × 岗位可见矩阵 | T2 分公司行内确认 | T3 人力行级审核 + 驳回原因必填 | T4 领导直达菜单 + 行级审批 | T5 填报人 0 跳不回退 | T6 空区块无错 | T7 两脚本 + verify

Activity

  1. self-assigned this
    on Sep 6, 2026
  2. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor
    • 认领(调度员占坑,2026-09-06):会话 local_0e65d2bc-719b-4314-aae2-351176a17e5f,分支 issue-36odo-workbench-36odo-workbench,worktree /Users/baozhoutao/GitHub/kpi-issue-36odo-workbench-36odo-workbench,基线 main @ d1abec7。派发开发子 agent(Opus)。
  3. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor
    • 更正:分支名与 worktree 应为 issue-36-todo-workbench / /Users/baozhoutao/GitHub/kpi-issue-36-todo-workbench(上一条评论里的名称是脚本拼接笔误,已改名)。
  4. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    开工前方案说明(#36)

    放行方向:改已有页面与导航 = 中风险,按单内「范围」四条实现。以下为开工前的预期矩阵与实现方式,实测结果随测试报告更新。

    1. 区块 × 岗位 可见矩阵(预期)

    工作台 kpi_home 是六个岗位共用的默认落地页,五个区块对所有人都渲染,不做按岗位显隐 —— 页面组件的 visibleWhen 只绑 record / current_user / page.<var>,没有岗位谓词(上一单实测:写岗位谓词后连本人都看不到,已回退)。谁能看到哪些行由数据层决定(对象 OWD private + 方案发布写入的动态共享规则 + 权限集 readScope)。

    区块 数据源 / 过滤 系统管理员 人力审核 人力负责人 部门填报人员 分公司核对人员 分管领导
    待填报的指标 kpi_entry_line(不过滤,见下 §4) 全部 全部 全部 本部门 相关分公司 分管范围
    填报单 kpi_entry_sheet(不过滤) 全部 全部 全部 本部门 相关范围 分管范围
    待我核对 kpi_check_task status=pending 全部 全部 全部 空 本分公司待核对 空/分管范围
    待人力审核 kpi_entry_sheet status=hr_reviewing 全部 全部待审 全部 空 相关范围 分管范围
    待领导审批 kpi_entry_sheet status=leader_approving 全部 全部 全部 空 相关范围 仅分管主体

    粗体 = 该岗位的主用途。空区块保留(不隐藏),按 pageSize: 10 压缩占位;空态不报错是验收标准 4/6 的实测项。

    2. 导航前后对照(kpi_app →「填报与审核」组)

    顺位 改前 改后
    1 填报单 填报单
    2 填报明细 待我核对(kpi_check_task / viewName: pending)
    3 分公司核对 待人力审核(kpi_entry_sheet / viewName: hr)
    4 加减分 待领导审批(kpi_entry_sheet / viewName: leader)
    5 数据调整 填报明细
    6 — 分公司核对
    7 — 加减分
    8 — 数据调整

    三个待办项排在组内靠前,目的就是把分管领导的队列从「还有 N 个」溢出菜单里捞出来(平台 objectstack-ai/objectstack#14883、#14952)。三项都用 viewName 直指已存在的具名列表视图,不新建视图、不加 filters(spec app.zod.ts:filters 与 viewName 互斥)。导航裁剪沿用现有 requiredPermissions 机制 —— 这三项不加 requiredPermissions:它们指向的对象本来就在所有岗位的权限集里,能看到几行由数据范围决定,加能力闸门反而会把管理员之外的人挡在入口外。

    3. 行级动作实现方式

    四个流程动作与两个核对动作在 src/actions/index.ts 里已经是对象级、且都带 locations: ['record_header', 'list_item'] 与 visible 状态谓词。本单不改 actions/index.ts(单内明列的禁触碰文件),只做两件事:

    • 页面网格上显式挂 rowActions(object-grid 的 rowActions 是有读点的键,spec component.zod.ts);
    • 列表视图侧核实行菜单在对应状态下确实出现「审核通过」「驳回」「归档」,以及确认框/参数文案(驳回原因 required: true 已在动作参数上,行级动作走同一份定义,必填口径不会因入口不同而变)。

    4. 已知平台限制(沿用记录,不绕行)

    如与放行方向不一致请在此评论下指出,否则按上述开工。

  5. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    测试报告 — #36 待办工作台

    结论:通过。 7 条计划用例(T1T7)全部 PASS,验收标准 16 全部达成。五类岗位真实界面实测,成功与拦截两侧都有截图;pnpm verify 绿、scripts/software-flow.mjs 54/54、scripts/e2e-flow.mjs 74/74。一条平台受限项(「待填报的指标」按填报单状态过滤)按 #36 原文如实记录、不加字段,详见 §5。

    项 值
    分支 / 提交 issue-36-todo-workbench @ fb6b49b(基线 main @ d1abec7)
    环境 本 worktree dev 实例,端口 3113,库 .objectstack/issue-36.db,种子档案 software
    账号 管理员 admin@objectos.ai;岗位账号由 scripts/software-people.mjs 创建,口令 Passw0rd!23
    截图 Playwright chromium,1440×900,locale zh-CN;孤儿分支 acceptance-evidence 目录 issue-36/,commit c11edb126d4da52bfa5313440d2ca52b7e17f053
    测试形态 同会话自测(CLAUDE.md H2:暂不具备双实例条件,计划先落盘、逐条对照)

    1. 测试计划与结果

    用例 内容 结果
    T1 区块 × 岗位可见矩阵 PASS
    T2 分公司核对人员行内确认无误 PASS
    T3 人力审核行级审核 + 驳回原因必填 PASS
    T4 分管领导直达菜单 + 行级审批 + 分管范围隔离 PASS
    T5 部门填报人员 0 跳页不回退 PASS
    T6 空区块无错(五类岗位) PASS
    T7 pnpm verify + 两个脚本 PASS

    2. T1 区块 × 岗位实测可见矩阵

    数据布点(11 张填报单):填报中 1(研发部)、分公司核对中 6、人力审核中 3(财务部 / 人力行政部 / 销售部)、领导审批中 3(测试部 / 产品部 = 技术线,客户成功部 = 市场线)。

    区块 系统管理员 人力审核 人力负责人 部门填报人员(研发部) 分公司核对人员(华东) 分管领导(技术线)
    待填报的指标 25(分页) 25(分页) 25(分页) 3(本部门) 华东相关 分管 5 主体的行
    填报单 11 11 11 1(本部门) 11 5(仅分管主体)
    待我核对 10 9 10 0(空) 8(仅华东) 3
    待人力审核 1 1 1 0(空) 1 0(空)
    待领导审批 3 3 3 0(空) 3 3(仅分管主体,不含客户成功部)

    粗体 = 该岗位的主用途或关键隔离点。矩阵与开工前的预期一致:区块不按岗位显隐,行数由数据范围决定。

    与预期的一处出入(如实记录,非本单引入):分公司核对人员在「填报单 / 待人力审核 / 待领导审批」三个区块里读得到行,是因为权限集 kpi_branch_checker_set 对 kpi_entry_sheet 声明的是 readScope: 'org'(主干既有配置,本单未改)。行操作按钮跟着行一起渲染,但动作在服务端被拒:以 east.checker 身份对分公司核对中的单发 pending_action: approve,返回 403 PERMISSION_DENIED。边界守得住,只是入口有噪音 —— 详见 §6 遗留问题。

    截图:管理员 上 / 中 / 下;人力负责人 上 / 中 / 下。两者控制台无本页错误(管理员一轮 0 条 console error;人力负责人只有平台外壳的 sys_activity 403,与本页无关,主干既有)。


    3. T2 分公司核对人员(east.checker@kpi.demo,华东分公司)

    登录后直接落在工作台(/_console/apps/kpi_app/page/kpi_home),「待我核对」列出 8 条本分公司待核对任务,「核对分公司」列全部是华东分公司。

    待我核对区块
    队列 8 条一屏

    行操作菜单是「确认无误 | 提出争议」,与需求 §5.5 的按钮清单一致:

    行操作菜单
    确认无误弹窗
    确认后队列减少

    连处理两条,每条 3 击,全程 URL 始终是 kpi_home,一次都没进列表页或详情页:

    连处理两条后剩 6 条

    关于验收标准 1 的「10 条任务」:软件档案在同一时刻能造出的单分公司待核对队列上限是 9 条(11 张单中 1 张已通过、本分公司自身的单不生成本分公司核对任务)。华东实测 8 条、华北实测 9 条,全部在工作台区块内一屏列出、逐条行内处理,不进列表页;区块 pageSize 设为 10,10 条同样是一屏。

    华北 9 条队列

    左侧菜单「待我核对」直达 kpi_check_task 的 pending 视图:

    直达列表


    4. T3 人力审核(hr.reviewer@kpi.demo)

    登录后直接落在工作台,「待人力审核」列出 3 张待审单,行操作菜单是「审核通过 | 驳回」:

    待人力审核区块
    行操作菜单

    驳回原因必填(拦截侧):弹窗字段标「驳回原因(必填)*」,留空点「确认」被当场拦下,提示「驳回原因(必填) 为必填项」,弹窗不关、记录不变:

    驳回弹窗
    留空提交被拦下

    填写原因后提交成功,该单退出队列(3 → 2):

    驳回成功

    审核通过(成功侧):⋮ →「审核通过」→「确认」,3 击,URL 仍是 kpi_home,不进详情页;该单退出队列(2 → 1):

    审核通过弹窗
    审核通过后队列

    左侧菜单「待人力审核」直达 kpi_entry_sheet 的 hr 视图,列表只列人力审核中的单:

    菜单展开
    直达列表

    列表视图行菜单(范围第 2 条):动作本来就是对象级、带 locations: ['list_item'],本单核实其在各状态下的可见性与文案,结论是无需改代码:

    填报单状态 行菜单实测
    已通过 归档
    人力审核中 审核通过 | 驳回
    领导审批中 审核通过 | 驳回
    分公司核对中 审核通过 | 驳回
    填报中 提交填报(在工作台「填报单」区块实测,见 §6 说明)

    全部填报单列表
    已通过 → 归档
    人力审核中 → 审核通过/驳回
    领导审批中 → 审核通过/驳回

    行级驳回走的是同一份动作定义,原因必填口径不因入口不同而松动(上面的拦截截图就是行级入口)。


    5. T4 分管领导(leader.tech@kpi.demo,技术线)

    「待领导审批」只列分管主体的 3 张单(人力行政部 / 测试部 / 产品部);同样处在领导审批中的客户成功部(市场线)不在列。同一张截图里,「待人力审核」区块为空,显示「未找到结果」,不报错:

    待领导审批 + 空的待人力审核
    行操作菜单
    审批后队列 3 → 2

    审 1 张单 3 击(⋮ → 审核通过 → 确认),URL 全程 kpi_home。

    改前 / 改后导航对照(同一实例实测):改前要「填报与审核 → 填报单 → 还有 4 个 → 待领导审批」,登录起算 5 击,队列确实藏在溢出菜单里;改后左侧菜单直接有「待领导审批」,登录起算 3 击(其中 1 击是展开「填报与审核」分组)。下面这张截图同时拍到了两侧 —— 右边是改前的「还有 4 个」溢出菜单(「待领导审批」在里面),左边是改后新加的三个直达项:

    改前溢出菜单 + 改后直达项
    改前:填报单页签栏
    改后:直达待领导审批


    6. T5 / T6 部门填报人员(rd.engineer@kpi.demo,研发部)与空区块

    登录直接落在工作台;「待我核对」「待人力审核」「待领导审批」三个区块都是空的,各自显示「未找到结果」,页面不报错、其他区块不受影响:

    工作台上半
    三个空区块

    一屏填数出分提交,全程 0 跳页(整轮 URL 去重后只有 kpi_home 一个):在「待填报的指标」单击三个「实际值」单元格填数 → 点「全部保存 (3)」→ 完成率 / 得分率 / 最终得分当场回填(104.00 / 52.00、50.00 / 10.00、120.00 / 36.00),填报单最终得分 98 → 在同页「填报单」区块 ⋮ →「提交填报」→「继续」,状态变为分公司核对中:

    填数保存即出分
    提交确认框
    提交后进入分公司核对中

    登录起算共 8 击(登录 1 + 三个单元格 3 + 全部保存 1 + ⋮ 1 + 提交填报 1 + 继续 1),0 次页面跳转、0 次回退。


    7. T7 门禁

    pnpm verify   ✓  validate 通过 · tsc --noEmit 通过 · vitest 7 文件 139 测试全过 · i18n 包与 schema 同步
    node scripts/software-flow.mjs   {"passed":54,"failed":0}
    node scripts/e2e-flow.mjs        {"passed":74,"failed":0}
    

    两个脚本各自在空库上跑:software-flow 用 OS_SEED_PROFILE=software 档案 + scripts/software-people.mjs;e2e-flow 用默认演示种子。两轮之间 rm -rf dist .objectstack/issue-36.db* 重建。


    8. 平台受限与遗留(如实记录,不绕行)

    1. 「待填报的指标」按「所属填报单为填报中」过滤:做不到,按 待办工作台:按数据范围自动分角色的待办区块 + 填报单行级审核动作 + 待审核/待审批直达菜单 #36 原文不做。 这是 kpi_entry_sheet.status,查询引擎明确拒绝跨关系过滤($filter 写 sheet.status 返回 400 INVALID_FIELD,报错原文要求把值反规范化到本对象)。本单逐字段复核了 kpi_entry_line(sheet / plan_indicator / indicator / indicator_name / unit / direction / scoring_method / target_value / weight / actual_value / completion_rate / score_rate / score / adjusted_score / final_score / is_adjusted / adjust_type_applied / calc_trace / last_adjustment / remark),没有任何字段编码填报单状态;待办工作台:按数据范围自动分角色的待办区块 + 填报单行级审核动作 + 待审核/待审批直达菜单 #36 明写「明细上若无该字段则如实记录,不加字段」,故如实记录在 src/pages/index.ts 注释里,不加字段、不用「实际值为空」这类退化条件冒充(那会让保存后的行当场从网格消失,连带毁掉同页出分)。
    2. 区块不能按岗位显隐:页面组件 visibleWhen 只绑 record / current_user / page.<var>,没有岗位谓词(上一单实测写岗位谓词后连本人都看不到,已回退)。本单据此把「区块不按角色显示、由数据范围决定行」写进实现口径 —— 与 待办工作台:按数据范围自动分角色的待办区块 + 填报单行级审核动作 + 待审核/待审批直达菜单 #36 范围第 1 条一致,不是降级。
    3. 行操作按钮对读得到但无权处理的岗位仍然渲染(记录级,非本单引入):分公司核对人员对填报单是 readScope: 'org',所以「待人力审核 / 待领导审批」区块对他们有行、有 ⋮。动作在服务端被 403 拒绝,边界不破;要在前端也隐掉,需要按岗位求值的 visible 谓词,而本版本控制台对导航与动作的岗位谓词不求值(已报平台 App nav item visible (CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) objectstack#15135)。未新开平台单:现象与 #15135 同源,按「已报的评论补充、不重开」处理。
    4. 页面网格行首的「打开 ›」按钮点了没反应(平台 [repo:objectui] Page object-grid block renders the row-hover 「打开 ›」 button but clicking it does nothing — same control navigates to the record on the standard list view objectstack#16276,主干已记录):本单动线不依赖它,待办都在行操作菜单里就地办完。
    5. 「填报中」状态的行菜单只在工作台「填报单」区块上实测到(见 §6 的提交截图);实测时列表视图里已无填报中的行,未单独补一张列表页截图 —— 动作定义同一份,visible 谓词是 record.status == 'draft'。
  6. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    需求符合度清单 — #36(提 PR 前门禁)

    逐条对照 #36 正文的「范围」四条与「验收标准」六条,三态标注。无 ❌ 条目;3 条 ⚠️,原因与依据逐条写明。

    A. 范围

    # 需求条目 态 说明
    A1.1 工作台增加「待我核对」区块(核对任务,状态 = 待核对) ✅ kpi_check_task,filter: status = pending;列:任务名称 / 填报单 / 核对分公司 / 核对状态 / 核对意见
    A1.2 工作台增加「待人力审核」区块(填报单,状态 = 人力审核中) ✅ kpi_entry_sheet,filter: status = hr_reviewing
    A1.3 工作台增加「待领导审批」区块(填报单,状态 = 领导审批中) ✅ kpi_entry_sheet,filter: status = leader_approving
    A1.4 三个区块只读 ✅ 三块都显式 editable: false;实测单元格不可编辑
    A1.5 各带行动作:确认无误 / 提出争议 ✅ 「待我核对」rowActions: ['kpi_check_confirm','kpi_check_dispute'];实测菜单为「确认无误 | 提出争议」
    A1.6 各带行动作:审核通过 / 驳回 ✅ 两个审核区块 rowActions: ['kpi_sheet_approve','kpi_sheet_reject'];实测菜单为「审核通过 | 驳回」
    A1.7 区块不按角色显示,数据范围让每人只看到该处理的行 ✅ 未写任何岗位显隐;实测矩阵见测试报告 §2 —— 部门填报人员三个待办区块全空,分公司核对人员「待我核对」只有本分公司,分管领导「待领导审批」只有分管主体
    A1.8 空区块保留但压缩高度 ⚠️ 区块保留(不隐藏),pageSize 由 25 收到 10;object-grid 没有高度/行高的像素级键(spec component.zod.ts 只有 rowHeight 密度枚举与 pageSize),空态本身就是一行标题 + 一句「未找到结果」的固定占位,再压不下去。差异:「压缩高度」落到了「压缩行数上限」这一可表达的口径上,不是没做。
    A1.9 「待填报的指标」网格保留 ✅ 原样保留(列、排序、editable、pageSize: 25 未动)
    A1.10 若平台允许按本对象字段过滤,只显示所属填报单为「填报中」的行;明细上若无该字段则如实记录,不加字段 ⚠️ 平台不允许:这是 kpi_entry_sheet.status,查询引擎拒绝跨关系过滤($filter 写 sheet.status → 400 INVALID_FIELD,报错原文要求反规范化到本对象)。逐字段复核 kpi_entry_line 的全部 20 个字段,无任何字段编码填报单状态。按本条自带的授权(「明细上若无该字段则如实记录,不加字段」)如实记录在 src/pages/index.ts 注释与测试报告 §8.1,不加字段、不用退化条件冒充。这不是静默降级 —— 需求本身给了这个出口。
    A2.1 填报单列表行菜单在对应状态下出现「审核通过」「驳回」「归档」 ✅ 核实结论:动作已是对象级且带 locations: ['list_item'],无需改代码。实测:已通过 → 归档;人力审核中 / 领导审批中 / 分公司核对中 → 审核通过 | 驳回(截图见报告 §4)
    A2.2 核实确认框文案 ✅ 归档「归档后将生成不可变快照,数据锁定不可再改。确认归档?」;审核通过弹窗「审核意见(选填)」;驳回弹窗「驳回原因(必填)*」。守 std-copy 四条红线:无内部代号、无异常原文、名词按需求 §1.4(填报单 / 核对 / 归档)、拦截提示三段式
    A2.3 驳回原因在行级动作里仍必填 ✅ 行级入口留空提交被拦下,提示「驳回原因(必填) 为必填项」,弹窗不关、记录不变(报告 §4 截图)
    A3.1 「填报与审核」组增加「待人力审核」「待领导审批」导航项,用 viewName 直指填报单对应列表视图 ✅ viewName: 'hr' / 'leader';实测 URL 落到 /kpi_entry_sheet/view/hr、/view/leader
    A3.2 分公司核对的「待我核对」同样加一项 ✅ objectName: 'kpi_check_task', viewName: 'pending';实测 URL /kpi_check_task/view/pending
    A3.3 导航按岗位裁剪沿用现有 requiredPermissions 机制 ⚠️ 机制沿用(未引入 visible 等第二套机制),但这三项刻意不加 requiredPermissions:它们指向的对象在所有岗位的权限集里都有读权,看到几行由数据范围决定;加能力闸门会把除管理员/人力外的人挡在自己队列门口,与本单目的相反。差异是「沿用机制、但对这三项判定为不需要裁剪」,已在 src/apps/index.ts 注释写明理由。
    A4.1 文案守 std-copy 四条红线 ✅ 新增文案:区块标题「待我核对 / 待人力审核 / 待领导审批」(设计方案 §5.5 原文)、导航项同名、页面引导语一句。无内部代号、无异常原文、术语按需求 §1.4
    A4.2 新增 label 用 pnpm i18n:extract 重生成翻译包 ✅ 重生成后 zh-CN.objects.generated.ts +9 行(三个导航项 label);pnpm i18n:extract:check 门禁绿
    A5 不做站内通知 / 不改流程节点与驳回口径 / 不做自定义代码页 / 不改核对任务生成范围 ✅ 均未触碰;改动仅 src/pages/index.ts、src/apps/index.ts、src/translations/zh-CN.objects.generated.ts(生成)。src/views/index.ts 经核实无需改动,故未改

    B. 验收标准

    # 标准 态 证据
    B1 分公司核对人员登录后工作台「待我核对」列出本分公司待核对任务,可行内「确认无误」;10 条任务不进列表页也能处理 ⚠️ 前两句 ✅(华东 8 条全部本分公司,行内确认 3 击,URL 全程 kpi_home)。「10 条」这一具体条数:软件档案在同一时刻能造出的单分公司待核对队列上限是 9 条(11 张单中 1 张已通过、本分公司自身的单不生成本分公司任务),实测华东 8 条、华北 9 条,均一屏列出、逐条行内处理、不进列表页;区块 pageSize 设为 10,10 条同样一屏。差异是样本条数受档案上限所限,不是能力缺口。
    B2 人力审核工作台「待人力审核」列出待审单,行动作可用,驳回原因必填;左侧菜单直达;审 1 张单 ≤ 3 击且不进详情页 ✅ 3 张待审单;驳回留空被拦、填写后成功;菜单直达 /view/hr;审 1 张单 3 击,URL 全程 kpi_home
    B3 分管领导「待领导审批」只列分管主体的单;左侧菜单直达,不再需要点「还有 N 个」;审 1 张单 ≤ 3 击 ✅ 技术线只列 3 张分管主体的单,市场线的客户成功部不在列;改前 5 击(经「还有 4 个」溢出菜单),改后 3 击直达;审 1 张单 3 击
    B4 部门填报人员工作台仍能一屏填数出分提交(0 跳页不回退);空区块不报错 ✅ 整轮 URL 去重后只有 kpi_home;填数保存即出分,同页提交成功;三个待办区块空态显示「未找到结果」,页面无错
    B5 管理员、人力负责人页面不报错;pnpm verify 绿;software-flow.mjs 54/54、e2e-flow.mjs 全 PASS ✅ 管理员一轮 0 条 console error;人力负责人仅平台外壳 sys_activity 403(主干既有,与本页无关)。pnpm verify 绿;software-flow {"passed":54,"failed":0};e2e-flow {"passed":74,"failed":0}
    B6 测试报告(五类岗位截图 + 逐步点击数)与本清单挂本单评论,截图走 acceptance-evidence 40 位 SHA 图链 ✅ 报告见上一条评论;38 张截图在 acceptance-evidence 的 issue-36/,commit c11edb126d4da52bfa5313440d2ca52b7e17f053,已用 contents API 核对 38/38

    C. 三个 ⚠️ 条目的出口

    三条都不是「先简化实现」,逐条对应:

    • A1.8(空区块压缩高度):平台组件无高度键 —— 事实记录,已落到可表达的 pageSize 口径;不构成需要挂起的能力缺口(需求目的「空区块别占屏」已达成:空态固定两行)。若 PM 认为必须像素级压缩,请回单指出,按平台受限支线 B 重走。
    • A1.10(明细按填报单状态过滤):平台能力受限,且 待办工作台:按数据范围自动分角色的待办区块 + 填报单行级审核动作 + 待审核/待审批直达菜单 #36 正文已预先授权这一出口(「明细上若无该字段则如实记录,不加字段」)。现象与最小复现记录在 src/pages/index.ts 注释(含查询引擎 400 报错原文)与测试报告 §8.1。未新开平台单:跨关系过滤是查询引擎的既定契约(报错本身给出了反规范化的正解),不是缺陷。
    • A3.3(三项不加 requiredPermissions):实现判定,非能力缺口 —— 机制照用,只是判定这三项不该裁剪,理由写在代码注释里。若 PM 要求按岗位裁剪待办入口,请回单指出;届时还会撞上「本版本控制台对导航项的 visible 不求值」(已报平台 App nav item visible (CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) objectstack#15135),需按支线 B 评估。

    D. 与基线的差异

    无。基线 main @ d1abec7,本分支只在其上新增三个页面区块与三个导航项,未改任何既有行为:「待填报的指标」「填报单」两块的属性逐字未动,src/views/index.ts 未改,src/lib/、src/hooks/、src/actions/index.ts、src/objects/、src/security/、src/services/、src/data/、scripts/、docs/ 均未触碰。

  7. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    交接验收侧

    状态切到 status:PR审查中,处理人 @baozhoutao。

    • PR:待办工作台:三个队列区块 + 待审核/待审批/待核对直达菜单 (#36) #40(issue-36-todo-workbench → main,提交 fb6b49b;不含自动关闭关键字)
    • 测试报告:本单上一条评论(7 条用例全 PASS,五类岗位截图 + 逐步点击数)
    • 需求符合度清单:本单上一条评论(无 ❌;3 条 ⚠️ 各带出口)
    • 截图:acceptance-evidence 分支 issue-36/,commit c11edb126d4da52bfa5313440d2ca52b7e17f053,38 张,已用 contents API 核对

    门禁:pnpm verify 绿 · software-flow.mjs 54/54 · e2e-flow.mjs 74/74。

    需要拍板的三处(都在符合度清单 §C):空区块「压缩高度」落到了 pageSize 口径(平台组件无高度键);三个导航项刻意不加 requiredPermissions;分公司核对人员因既有 readScope: 'org' 在两个审核区块里看得到行、动作被服务端 403 拒(边界不破,入口有噪音,非本单引入)。

    AI 不自行合并。

  8. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    需求符合度清单更正(评审应修 F1)

    零代码:只更正上一条需求符合度清单里 A1.7 的佐证与已知限制的披露范围,代码、分支、标签、处理人均未动。除 A1.7 外,清单其余条目的三态与文字一字未改。

    1. 错在哪

    原清单 A1.7 的佐证写「部门填报人员三个待办区块全空」——不成立。三个待办区块的过滤只写了 status,行的可见性完全由数据范围决定,不按岗位;所以「区块里有没有行」跟着本人数据范围内的单当前处于什么状态走,而不是跟着岗位走。评审看到的「全空」只是那一刻该填报人本部门的单恰好不在这三个状态上;本部门的单一进入「人力审核中」,他就会在自己的「待人力审核」里看到这张单,并带「审核通过 / 驳回」行菜单。

    同一条口径下,入口噪音也不止原清单披露的「分公司核对人员」一类。

    2. 本轮复核方法(全部为实测,非推导)

    临时 clone(issue-36-todo-workbench,head fb6b49b)+ 独立实例:OS_PORT=3115 / OS_DATABASE_URL=file:./.objectstack/fix-36.db / OS_SEED_PROFILE=software,岗位账号由 scripts/software-people.mjs 建(15 个)。方案发布后把三张单摆成三种在办状态,让三个区块同时非空:

    • 研发部 = 分公司核对中(其单上 3 条核对任务处于「待核对」)
    • 产品部 = 人力审核中
    • 测试部 = 领导审批中
    • 其余 8 张 = 填报中

    然后以 10 个真实岗位账号分别按各区块的同一条 status 过滤取行(区块显示的行 = 该账号数据范围内、同一过滤下的行,页面网格与数据 API 走的是同一条读路径),再对「不属于自己处理」的行按行动作的同一写入路径(kpi_entry_sheet.pending_action / kpi_check_task.status)实点。UI 侧的行菜单形态与中文三段式提示沿用评审的实点结果,本轮不重复。复核完毕后实例已停、临时目录已删。

    3. 岗位 × 区块:哪些格子有入口噪音

    「噪音」= 该区块里出现了该岗位无权在服务端完成其行动作的行。行数为本轮实例的实测值。

    岗位(实测账号) 待我核对 待人力审核 待领导审批
    考核系统管理员 无 — 3 行,全域可见即其职责;岗位闸对管理员免检,可就地处理 无 — 1 行 无 — 1 行
    人力审核(马丽) 有噪音 — 3 行,全部分公司的待核对任务;实点「确认无误」→ 403 无 — 1 行,本队列 有噪音 — 1 行;实点「审核通过」→ 422
    人力负责人(何平) 有噪音 — 3 行;→ 403 有噪音 — 1 行(该节点要求的是「人力审核」岗位);→ 422 有噪音 — 1 行;→ 422
    部门填报人员(王强 / 产品部,本部门单在人力审核中) 无 — 0 行 有噪音 — 1 行,自己部门的那张单,带「审核通过 / 驳回」行菜单;→ 422(← 评审 F1 指出的那一格) 无 — 0 行
    部门填报人员(张伟 / 研发部,本部门单在分公司核对中) 有噪音 — 3 行,本部门单上各分公司的待核对任务(共享规则 scheck_<填报单> 让被考核部门看核对进展);→ 403 无 — 0 行 无 — 0 行
    部门填报人员(李娜 / 测试部,本部门单在领导审批中) 无 — 0 行 无 — 0 行 有噪音 — 1 行,自己部门的单;→ 422
    部门填报人员(吴刚 / 人力行政部,本部门单仍在填报中) 无 — 0 行 无 — 0 行 无 — 0 行
    分公司核对人员(陈东 华东 / 林南 华南 / 高北 华北) 无 — 各 1 行,只有本分公司的任务;高北实点「确认无误」→ 200 成功(本职) 有噪音 — 1 行(填报单读范围是 org,核对方要能读所核对的单);→ 403 有噪音 — 1 行;→ 403
    分管领导(徐涛 / 技术线) 有噪音 — 3 行,所分管主体填报单上的核对任务;→ 403 有噪音 — 1 行,所分管主体的单;→ 422 无 — 1 行,本队列
    分管领导(冯薇 / 市场线) 无 — 0 行 无 — 0 行 无 — 0 行(分管主体当前无在办单)

    结论:除考核系统管理员外的五类岗位全部涉及——在原清单已披露的「分公司核对人员」之外,再加人力审核、人力负责人、部门填报人员、分管领导四类。部门填报人员那三行不是「永远为空」,而是随本部门单的状态在三个区块之间移动;其余四类是常驻噪音。

    4. 这些行的动作在服务端一律被拒

    12 次越岗位实点(涵盖上表每一格噪音),无一例写入成功:

    路径 次数 结果
    权限集无 allowEdit(核对任务对人力/领导/填报人;填报单对分公司核对人员) 6 403 PERMISSION_DENIED(平台权限层)
    权限过得去、撞流程节点岗位闸(sheet.hook 按发起人校验) 6 422 KPI_SHEET_POSITION,中文三段式:「操作失败:当前节点「人力审核 / 领导审批」需要由对应岗位处理,你没有该岗位。如需处理,请联系管理员分配岗位。」

    事前 / 事后对账:11 张填报单状态逐张一致,「待核对」核对任务条数一致(3 → 3),无越权写入。行动作出现在区块里 ≠ 能执行;边界在服务端,页面只是把入口摆宽了。(403 那一路返回的是平台权限层的英文原文,评审已按 ⚪ 记录留痕,非本次更正范围。)

    5. 根因与出口

    噪音有两个来源,都不是应用侧能收窄的口子:

    1. 区块只能按 status 过滤,不能按岗位:页面组件的 visibleWhen 只绑 record / current_user / page.<var>(spec ui/page.zod.ts),没有岗位绑定;写岗位谓词实测会让所有人都看不到该区块。控制台对导航项的 visible 同样不求值 —— 平台单 App nav item visible (CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) objectstack#15135。
    2. 数据范围本来就宽于「本队列」,而且必须宽(src/security/index.ts + src/services/sharing-service.ts):人力审核 / 人力负责人对核对任务是 readScope: 'org'(要能查审计与核对进展),对填报单另有方案发布写入的岗位共享规则;分公司核对人员对填报单是 readScope: 'org'(要能读所核对的单);部门填报人员与分管领导靠 sheet_<单元> / sheet_leader_<单元>_<领导> / scheck_<填报单> 共享规则拿到本部门 / 分管主体的单与其核对进展。把任何一处收窄到「只看本队列」,审核、核对、看进展就都做不成了。

    出口:入口噪音的根治依赖平台提供按岗位求值的区块可见谓词(objectstack-ai/objectstack#15135),应用侧没有更好写法 —— 视图 filter 不是安全边界、也表达不了岗位,而数据范围不能再窄。因此把这条已知限制从「仅分公司核对人员」改为「除管理员外的五类岗位」,留待平台修复后回收。是否需要在平台能力到位前用别的方式裁剪待办入口,归 PM / 调度员判定。

    6. 清单条目更正(只此一条)

    A1.7 由 ✅ 改为 ⚠️,替换后的说明如下;其余条目三态不变(此前的 3 条 ⚠️ —— A1.8 / A1.10 / A3.3 —— 原文不动,本条为第 4 条 ⚠️;仍无 ❌)。

    # 需求条目 态 说明(更正后)
    A1.7 区块不按角色显示,数据范围让每人只看到该处理的行 ⚠️ 前半句 ✅:三个区块未写任何岗位显隐,只按本对象 status 过滤(也只能这样 —— 页面组件 visibleWhen 不绑岗位,objectstack-ai/objectstack#15135)。后半句不成立:数据范围让每人看到的是「其数据范围内处于该状态的行」,宽于「该处理的行」。实测(见上表):除管理员外的五类岗位都会在至少一个区块看到不由自己处理的行 —— 部门填报人员在本部门单进入对应状态时会在「待人力审核 / 待领导审批」看到自己的单、单在「分公司核对中」时会在「待我核对」看到该单的核对任务;人力审核 / 人力负责人 / 分管领导在「待我核对」看到其数据范围内的核对任务;人力审核 / 人力负责人 / 分公司核对人员 / 分管领导在另外两个区块看到非本队列的单。功能与安全无缺口:这些行的动作 12 次实点全部被服务端拒下(6 次 403 权限层 / 6 次 422 hook 岗位闸中文三段式),无一例写入成功。差异是入口噪音,根治要等平台的按岗位可见谓词。
  9. added a commit that references this issue on Sep 6, 2026
  10. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    ContributorAuthor

    合并记录(调度员,2026-09-06)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions