Skip to content

test(steward): assert the shipped steward prompt row and close journey gap 1 - #4616

Merged
huangruiteng merged 2 commits into
mainfrom
codex/steward-gap1-flip-20260917
Sep 17, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/steward-gap1-flip-20260917

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Goal/source and gap: the steward qualification case carried its prompt row as gap 1 — the bounded prompt set was defined in the client model while the Goal conversation could not reach it. PR feat(steward): make the steward prompts reachable from the Goal composer #4591 shipped the row, so the gap and the case disagreed with the product.
  • Observable before → after: LOOPX_PERSONAL_WORKSPACE_SCENARIO=steward-journey printed gaps=2-steward-prompts,3-confirm,…; it now prints gaps=3-confirm,4-readiness,5-correction,6-recovery,7-return, and beat 2 asserts the shipped contract instead of probing for it.
  • Issue/task and intended base: main (809f0cf). Related to the steward use-case qualification; no tracking issue.

Scope And Continuation

  • Completed scope and remaining work: beat 2 now asserts that the shipped quick-prompt row exposes the five released labels (询问下一步 / 向 Agent 获取进度报告 / 配置定时检查 / 看阻塞 / 查证据), that clicking 看阻塞 posts its message as an accepted Turn, and that the composer is left empty. A regression throws with the missing labels named rather than passing silently. Both locale mirrors renumber the remaining gaps and record why the prompt row left the list. Gaps 2–5 remain, each still recorded with the probe that looked for the surface.
  • Slice boundary / successor: complete within this scope. The remaining gaps already have owners in the case; no successor task is needed for this slice.

Validation

  • Tested revision: 9a878c7
  • Run state: finished
  • Input classes: synthetic (the scenario runs on a deterministic browser fixture; no live Goal, Agent, credential or local path is read)
Check kind Result Public-safe evidence / limitation
real_entrypoint passed LOOPX_PERSONAL_WORKSPACE_SCENARIO=steward-journey node examples/personal-workspace-browser-smoke.mjs — development mode ok, beats=4; packaged mode (LOOPX_PERSONAL_WORKSPACE_PACKAGED=1) ok against the shipped loopx/web/chat bundle
regression_parity passed Negative control: deleting the 看阻塞 / 查证据 buttons from personal-workspace-page.tsx makes the scenario fail naming both labels plus the chip and Turn assertions; restoring the file returns it to green. The assertion cannot pass on a missing row
integration passed node examples/personal-workspace-browser-smoke.mjs — all seven development scenarios ok
unit passed workspace-theme.test.mjs (ok), npm run smoke:goal-order (order invariants passed)
static passed docs-governance-smoke ok; docs-asset-integrity-smoke: ok (6 assets verified); loopx check --scan-path over the three changed files reports errors=0 and public boundary scan clean: 3 files
  • Coverage and gaps: the changed scenario drives the real packaged frontend over the fixture, and the negative control shows the new assertion has teeth. The case's own untested paths are unchanged and still listed in the document: Lark audience and remote/cloud host are not exercised.

Frontend / Visual Evidence

  • UI impact: none (the scenario and both mirrors change; no shipped frontend file is touched in this PR)
  • Before: N/A
  • After: N/A
  • States and viewports shown: N/A
  • Source data: synthetic

Type of Change

  • Test update
  • Documentation update

LoopX Area

  • Public docs or presentation surface (README, protocols, dashboard)

Technical Direction

  • Direction / acceptance reference, when applicable: steward qualification case (docs/product/use-cases/steward), the frontend-first end-to-end journey for the local steward lane.

Shared-authority RFC fixture impact

  • Production-scale fixture schema: N/A
  • Semantic dimensions changed, or reviewed no-impact rationale: N/A
  • Provider conformance arms run: N/A
  • Read-only legacy/file/PostgreSQL three-arm rehearsal: N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths
  • I did not duplicate maintainer-owned benchmark work
  • I kept the change scoped to the linked issue/task
  • I completed the visual evidence section for UI changes, or marked UI impact none
  • Every commit includes a DCO Signed-off-by trailer

中文摘要

  • 缺口:管家资格用例此前把“快捷提示行”记作缺口 1 —— 提示集只定义在客户端模型里,Goal 对话里点不到。PR feat(steward): make the steward prompts reachable from the Goal composer #4591 上线了该行,缺口与产品事实已经不一致。
  • 变化:拍子 2 从“探针”改为“断言”:提示行必须出现五个已发布标签(询问下一步 / 向 Agent 获取进度报告 / 配置定时检查 / 看阻塞 / 查证据),点击“看阻塞”必须把消息作为一次被接受的 Turn 发出,且输入区保持为空。回归时失败信息会点名缺失标签,不会静默通过。
  • 镜像:中英两份用例文档同步重编号,并写明提示行为何不再是缺口;缺口 2–5 仍保留各自的探针证据。
  • 验证:开发模式与 packaged 模式(走已发布的 loopx/web/chat bundle)的 steward-journey 场景均通过;负向对照(移除两个按钮)会以点名缺失标签的方式失败;七个场景的开发套件、workspace-theme、goal-order、docs-governance-smoke、docs-asset-integrity-smoke 通过;三个改动文件的 loopx check --scan-path 为 errors=0 且边界扫描干净。

…ng it

The steward journey recorded its prompt row as gap 1 because the bounded
prompt set lived in the client model while the conversation could not
reach it. PR #4591 shipped the row, so the scenario now asserts the
shipped contract: the row must expose the five released labels, clicking
看阻塞 must post its message as an accepted Turn, and the composer must
stay empty afterwards. A regression fails with the missing labels named,
so it cannot pass silently.

Both locale mirrors renumber the remaining gaps and record why the prompt
row is no longer one of them.

Validation: steward-journey in development and packaged modes; the
negative control (row buttons removed) fails naming 看阻塞 / 查证据 as
missing; the full seven-scenario personal-workspace development suite;
workspace-theme contract; docs-governance-smoke; docs-asset-integrity-smoke;
loopx check --scan-path over the three changed files (errors=0, boundary
scan clean).

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
…ip-20260917

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

动机

owner 已在 Goal 对话里回复 ,接受 PR #4591 在 head 18153f5 上交付的管家快捷提示行(预览树与当时的 head 是同一份 revision),#4591 以 aae37d90a 合入。于是本车道记录的 journey gap 1——“管家有界提示集只活在客户端模型里、对话里点不到”——在事实层面已经关闭,但用例本身还停在旧结论上:场景仍然对提示行做探针,缺口表里仍然列着它。

这个 PR 就是把用例追平产品:拍子 2 从“探针”升格为“断言”,缺口 1 从缺口表移除,中英两份镜像同步重编号。不这样做的话,用例会在产品已经做到之后继续宣称这是缺口,这正是「状态真相落在事实之后」的那类漂移。

改动思路

断言的写法选择了“正向列出已发布契约 + 反向可证伪”两条腿,而不是只断言存在某个元素:

  1. 提示行必须暴露五个已发布标签(询问下一步 / 向 Agent 获取进度报告 / 配置定时检查 / 看阻塞 / 查证据),缺哪个就在失败信息里点名哪个;
  2. 点击“看阻塞”必须把它的消息作为一次被接受的 Turn 发出(复用的是场景已有的 fixture turn 记录,不是新增替身);
  3. 点击后输入区必须保持为空——这正是 owner 要的“点击即发送、不留草稿”。

第 3 条是 owner 那条“全都改成立即发送”的要求在用例里的落点,所以它必须被断言而不是被描述。断言在 owner 输入之前读取,避免把 owner 自己敲的字误认成渲染出来的控件。

具体改动

  • examples/personal-workspace-browser/steward-journey.mjs:拍子 2 的 probe 换成 check,新增五标签断言、看阻塞 点击断言(等待 fixture 里出现对应 turn)、以及 composer.inputValue() === "" 断言;record("2-steward-prompts", …) 记录实际读到的标签、是否发出 turn、点击后的输入区内容,失败时这些值直接出现在报告里。
  • docs/product/use-cases/steward/README.md 与 README.zh-CN.md:拍子 2 的描述补上快捷提示行与“点击即发送、不留草稿”;缺口表删除原缺口 1 并把其余缺口重编号为 1–5;正文里指向缺口编号的交叉引用同步改正;新增一段说明提示行“从缺口变为断言”的原因与失败行为。
  • 没有改任何产品代码:apps/presentation/dashboard 与 loopx/web/chat 在本 PR 里逐字节未动。

对主干的风险

需要说清楚的是这次断言到底证明了什么、没证明什么。它证明的是这一版包装好的前端在确定性 fixture 上确实渲染了这五个 chip、点击确实发出一次被接受的 Turn、且不留草稿;它不证明真实 Goal 上的语义正确性,也不覆盖 Lark 受众与 remote/cloud host —— 这两条仍然如实留在用例的“未测”清单里。

断言会不会只是变绿?我把两个 chip(看阻塞、查证据)从 personal-workspace-page.tsx 摘掉后重跑:场景失败并点名 missing: 看阻塞 / 查证据,同时报出 chip 与 Turn 两条断言;恢复文件后回到绿色。这条负向对照说明新断言无法在提示行缺失时静默通过。开发态与打包态(LOOPX_PERSONAL_WORKSPACE_PACKAGED=1,从已发布的 /chat/ bundle 提供)都跑到 beats=4,gap 列表里已经没有 2-steward-prompts。

顺带修掉一个仓库级红:本 PR 第一次 check 跑的 test-shard (2) 失败在 tests/canary/test_maintainability_ratchet.py(chat_actions.py 1604 行 > ledger 1590)。该失败在干净的 origin/main worktree 上可复现、也是 main 自己的失败(run 35176730888),与本 PR 的 diff 无关,属于所有在飞 PR 的公共阻塞;已由 #4618 结清(3937f6b99),本 head 是 rebase 到含该修复的 main 之后重跑的。

我的整体评价

把“产品已经做到、用例还说是缺口”的漂移收口,并且用负向对照证明断言有牙齿,这是这次改动的主要价值;产品面零改动,回退成本是删一个 commit。建议在该 head 的必过检查全绿的前提下合并。

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

Head: 2773256

English verdict: APPROVE

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

动机

owner 已在 Goal 对话里回复「确认首屏」,接受 PR #4591 在 head 18153d15c 上交付的管家快捷提示行(预览树与当时的 head 是同一份 revision),#4591 以 aae37d90a 合入。于是本车道记录的 journey gap 1——“管家有界提示集只活在客户端模型里、对话里点不到”——在事实层面已经关闭,但用例本身还停在旧结论上:场景仍然对提示行做探针,缺口表里仍然列着它。

这个 PR 就是把用例追平产品:拍子 2 从“探针”升格为“断言”,缺口 1 从缺口表移除,中英两份镜像同步重编号。不这样做的话,用例会在产品已经做到之后继续宣称这是缺口,这正是「状态真相落在事实之后」的那类漂移。

(更正:本条评审的前一版把 owner 那句话误写成命令替换而丢失,并把 head 误记为 18153f5;同一 head 上以此版为准。)

改动思路

断言的写法选择了“正向列出已发布契约 + 反向可证伪”两条腿,而不是只断言存在某个元素:

  1. 提示行必须暴露五个已发布标签(询问下一步 / 向 Agent 获取进度报告 / 配置定时检查 / 看阻塞 / 查证据),缺哪个就在失败信息里点名哪个;
  2. 点击“看阻塞”必须把它的消息作为一次被接受的 Turn 发出(复用的是场景已有的 fixture turn 记录,不是新增替身);
  3. 点击后输入区必须保持为空——这正是 owner 要的“点击即发送、不留草稿”。

第 3 条是 owner 那条“全都改成立即发送”的要求在用例里的落点,所以它必须被断言而不是被描述。断言在 owner 输入之前读取,避免把 owner 自己敲的字误认成渲染出来的控件。

具体改动

  • examples/personal-workspace-browser/steward-journey.mjs:拍子 2 的 probe 换成 check,新增五标签断言、看阻塞 点击断言(等待 fixture 里出现对应 turn)、以及 composer.inputValue() === "" 断言;record("2-steward-prompts", …) 记录实际读到的标签、是否发出 turn、点击后的输入区内容,失败时这些值直接出现在报告里。
  • docs/product/use-cases/steward/README.md 与 README.zh-CN.md:拍子 2 的描述补上快捷提示行与“点击即发送、不留草稿”;缺口表删除原缺口 1 并把其余缺口重编号为 1–5;正文里指向缺口编号的交叉引用同步改正;新增一段说明提示行“从缺口变为断言”的原因与失败行为。
  • 没有改任何产品代码:apps/presentation/dashboard 与 loopx/web/chat 在本 PR 里逐字节未动。

对主干的风险

需要说清楚的是这次断言到底证明了什么、没证明什么。它证明的是这一版包装好的前端在确定性 fixture 上确实渲染了这五个 chip、点击确实发出一次被接受的 Turn、且不留草稿;它不证明真实 Goal 上的语义正确性,也不覆盖 Lark 受众与 remote/cloud host —— 这两条仍然如实留在用例的“未测”清单里。

断言会不会只是变绿?我把两个 chip(看阻塞、查证据)从 personal-workspace-page.tsx 摘掉后重跑:场景失败并点名 missing: 看阻塞 / 查证据,同时报出 chip 与 Turn 两条断言;恢复文件后回到绿色。这条负向对照说明新断言无法在提示行缺失时静默通过。开发态与打包态(LOOPX_PERSONAL_WORKSPACE_PACKAGED=1,从已发布的 /chat/ bundle 提供)都跑到 beats=4,gap 列表里已经没有 2-steward-prompts。

顺带修掉一个仓库级红:本 PR 第一次 check 跑的 test-shard (2) 失败在 tests/canary/test_maintainability_ratchet.py(chat_actions.py 1604 行 > ledger 1590)。该失败在干净的 origin/main worktree 上可复现、也是 main 自己的失败(run 35176730888),与本 PR 的 diff 无关,属于所有在飞 PR 的公共阻塞;已由 #4618 结清(3937f6b99),本 head 是 rebase 到含该修复的 main 之后重跑的。

我的整体评价

把“产品已经做到、用例还说是缺口”的漂移收口,并且用负向对照证明断言有牙齿,这是这次改动的主要价值;产品面零改动,回退成本是删一个 commit。建议在该 head 的必过检查全绿的前提下合并。

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

Head: 2773256

English verdict: APPROVE

@huangruiteng
huangruiteng merged commit a921f01 into main Sep 17, 2026
25 checks passed
@huangruiteng
huangruiteng deleted the codex/steward-gap1-flip-20260917 branch September 17, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant