Repository navigation
fix(presentation): read session dash status markers as whole words - #7553
Conversation
_status_bucket folded a goal's free-form status and waiting_on into one of
five operator buckets by testing marker words as substrings, so `installed`
read as `stalled`, `incomplete` as `complete`, and `undone` as `done`. It also
left `controller` out of the human-gate vocabulary, although
session_runtime emits waiting_on="controller" and acceptance_observation and
project_agent_context both read {controller, user_or_controller} as the human
gate, so a controller-gated goal was counted as `other` instead of
`needs_user`.
Match markers as whole words, treat a negated status (not_completed) as
not-done, and add `controller` to the human-gate set. The module had no tests;
add tests/presentation/test_session_dash_status_bucket.py covering the
documented statuses, the marker-inside-a-word case, the human-gate set, and
the projection counts end to end.
No input, field, bucket precedence, or schema change. _todo_tally still
compares todo statuses by exact membership and its markers are untouched.
Signed-off-by: ChengLong GU <88359731+gcl-coder@users.noreply.github.com>
53e84f8 to
64975e2
Compare
CI note: the
|
Follow-up: what the rerun showedReopening this PR (same head The rerun has two remaining reds, and they are the same event:
Scope reminder: this PR changes
|
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.
动机 / Motivation
查看会话看板的操作者需要分清正在执行、等待本人、阻塞和已完成的目标。原先 installed 会因含有 stalled 被标为阻塞,incomplete 与 not_completed 会误报完成,waiting_on=controller 则遗漏人工等待;新版本修正这些徽标和总数。这些误报使操作者把未完成工作当作结束,或把健康状态当成阻塞。同一份24目标输入经真实导出CLI和HTTP读取,原版7项误分类在新版本全部修正,其余17项及全部非分类字段保持相同。本提案只修正既有只读看板的分类,不改变任务执行、权限、调度或持久状态。
改动思路 / Approach
沿用 loopx dash generate 与 DashRequestHandler 到同一个 build_session_dash_projection 的路径,只在展示层解释现有状态。匹配改为有边界的标记,完成信号先排除既有否定前缀,并消费运行时已经发出的 controller 等待值;完成、阻塞、人工等待、活动的优先级保持。无变化与更正后的信息仍由原HTML渲染器显示。
架构判断:保留既有投影边界,两个局部匹配函数足以修正已复现错误;无需增加状态库、共享协议或第二个权限判断。当前PR边界:仅状态桶、汇总计数及针对真实投影的回归保护。对已完成目标,不因 waiting_on=controller 又要求操作者介入;真实 blocked 也仍先于人工等待。
| 相同输入 | 原分类 | 当前分类 |
|---|---|---|
| installed / uninstalled | blocked | other |
| incomplete / undone / not_completed / not_shipped | done | other |
| 未结束且 waiting_on=controller | other | needs_user |
具体改动 / Changes
准确审查 64975e2f98b35c4eff429f1e29d3f172adda2308 的全部两个路径:生产代码+48/-4,测试+120;PR差分相对共同祖先 5ebeb55796883284db82f06c7f0dcfed9bf9b65f,没有把分支落后的主干历史算进提案。真实合并树检查可与已观察主干干净组合。
关键代码讲解
_has_status_marker:80 对转义后的标记使用字母数字边界,阻止 installed、incomplete 等词内命中。_status_bucket:129 在既有优先级中处理否定完成和 controller;它只返回展示桶,不写控制面。_goal_entry:189 继续读取 attention/run 投影,保留原始状态、等待原因、Todo与最近执行;汇总复用这一结果,避免徽标与统计各自解释。
规范依据 docs/product/surfaces/session-dash-panel-design.md,固定版本 5ebeb55796883284db82f06c7f0dcfed9bf9b65f:原接受文本。该文没有编号,以下直接使用原小节/条目名:Overview、Per goal 已由桶和徽标对照实现;Command Surface 的只读CLI/HTTP、Public/Private Boundary 的转义/导出扫描保持,现有公开smoke通过。
对主干的风险 / Risks
PASS:全 tests/presentation 50项、原 session-dash smoke、两文件Ruff,以及标准premerge的5个直接检查和5个选中检查;严格CQR独立核验有效。24目标实路对照使用合成 collect_status 输入,真实执行CLI解析、处理器、HTTP、投影、HTML和边界扫描;两次重复、状态更正再恢复、来源字节不变均通过。原比较投影与共同祖先逐字相同,但周边CLI并非把整个旧仓库重建,未据此声称全主干集成或安装态覆盖。
首次把旧分支验证器接到较新的操作环境时,检查在读取不支持的 context_delivery 配置命名空间处退出。保留该失败;随后使用源分支本地premerge,并由当前验证器单独强制同一准确作用域的严格CQR,未修改任何共享配置、断言或门槛。没有查询远端CI;作者关于旧CI的说明不作为本次独立归因。
剩余风险是自由文本分类仍属兼容启发式,例如既有 not_failed 仍可能被当成 blocked;当前修复未解决所有自然语言否定。未来有规范生产者字段时,应在既有投影owner优先消费显式类型、保留有界旧输入映射;这不构成本次已验证错误修复的阻断。新词组仅为本地展示匹配,不是权限或共享状态枚举。
我的整体评价 / Verdict
未发现阻断问题,APPROVE。长程工作语义 preserved:反复读取和更正不写任务或产生执行效果;用户体验 improved:人工等待和完成总数与具体目标相符,已有意图无需新增确认或配置。视觉观察:实际HTML使用3会话、24个长中英标题及混合状态;检查1200桌面整页、390首屏和下方完整长行,徽标与主读数更正,既有窄屏横向表格仍需横滚,右侧等待/行动完整可读。当前页面没有折叠/展开控制,默认即完整行;下方和横向内容已查看。未验证范围:正式安装App、自然现场新鲜度、完整无障碍与所有自由文本语义;这些不被合成画面或无溢出断言替代。此次代码规模与错误影响相称,局部词匹配的解释边界明确。合并资格及授权另行判断。
English verdict: APPROVE — the exact-head read-only classification fix is verified; no blocking finding.
What this changes
session_dash._status_bucketfolds a goal's free-formstatusandwaiting_oninto one of five operator buckets (
active/needs_user/blocked/done/
other). It decided that fold by testing marker words as substrings(
marker in status_text), and_USER_WAITING_MARKERSdid not listcontrollereven though the runtime emits it as a human gate.Two consequences, both reproduced below:
bucket:
installedreads asstalled,incompletereads ascomplete,undonereads asdone.This PR matches markers as whole words, treats a negated status
(
not_completed) as not-done, and addscontrollerto the human-gatevocabulary. It adds the first test file for this module, which had none.
Why (evidence)
loopx/control_plane/runtime/session_runtime.py:76builds an attention itemwith
status="unregistered_runtime_goal",waiting_on="controller".loopx/control_plane/goals/acceptance_observation.py:186andloopx/control_plane/handoff/project_agent_context.py:240both read{"controller", "user_or_controller"}as the human-gate set.session_dashwas the only reader that disagreed, so the same gate showed up as
needs_userorotherdepending on which emitter wrote it.Measured on this tree before the change:
After the change every one of those is
other, and the buckets that werealready right are unchanged (
done/completed/closed/shipped/archived/blocked_by_safety/stalled/failed/active-progress/in_progress/running/keepalive/relaunched).The projection is rendered by
loopx dashanddash_server, so the overviewstrip's needs-you count and each goal's status badge were reading it.
What did not change
_todo_tallystill compares a todo status by exact membership in_DONE_STATUS_MARKERS; that path was already exact and its markers areuntouched.
done->blocked->needs_user->active->other.session_dash_projection_v1keeps its shape.Tests
New
tests/presentation/test_session_dash_status_bucket.py(the module had notests at all before this PR):
controlleranduser_or_controllerboth land inneeds_user, whileagent/codex/auto/external_evidencedo not,blockedstatus still outranks the waiting reason,build_session_dash_projection: a controller-gated goalis counted under
overview.goals_by_status.needs_user, and aninstalledgoal is not counted as
blocked.Against the code on
mainthe new file fails 4 of its 16 cases; against thisbranch all 16 pass.
Scope note
This is the same read-a-word-as-a-substring defect class reported in #4336 one
layer down (a prose matcher reading
installedasstalled). #4336's fix wentinto the quota path; this closes the presentation reader that still had it. It
does not change, and is not required for, that issue's typed-observation
contract.