Skip to content

Legacy replan matcher treats 'installed' as a stall signal #4336

Description

@JerryChaox

Problem

LoopX 0.4.3 can classify successful progress summaries containing the word installed as a no_progress_streak and return autonomous_replan_required.

Expected behavior: prose that merely reports an installation must not create a stall signal. Replanning should be driven by typed progress observations.

Actual behavior in 0.4.3: the legacy prose fallback searches for stalled? without token boundaries, so the stalled substring inside installed is treated as evidence of a stalled turn.

Minimal reproduction:

  1. Record consecutive progress runs whose bounded summaries include phrases such as CLI installed or package installed successfully.
  2. Run the public quota should-run flow for that goal and agent.
  3. Observe autonomous_replan_required with a no_progress_streak trigger even though both runs report completed work.

The current stable release no longer relies on this prose matcher after #3161. This issue tracks an explicit regression contract and actionable upgrade guidance for affected installations, so the false positive cannot silently return through a compatibility path.

Root Cause Analysis

The legacy autonomous-replan read model inferred control-plane state from free-form run summaries. Its stall expression matched a substring rather than a complete token, so unrelated words containing stalled could become control signals.

The modern typed-progress design removes that class of ambiguity. The remaining gap is explicit behavioral coverage for installation wording and a clear diagnostic or upgrade path when an affected legacy runtime produces this trigger.

TDD Fix Plan

  1. RED: Add a public CLI regression in which two successful progress records contain installed, uninstalled, and installation completed, then assert that quota should-run does not emit a no-progress replan trigger.
    GREEN: Keep autonomous-replan decisions sourced from typed progress observations; if a compatibility text path remains, require complete control tokens rather than substring matches.

  2. RED: Add a contrast case using an explicit typed no-progress observation and assert that it still creates the expected replan obligation.
    GREEN: Preserve the typed stall path independently of human-readable summary text.

  3. RED: Exercise diagnosis or update guidance for an affected 0.4.3 installation and assert that the output identifies the runtime as stale and points to an unaffected release.
    GREEN: Surface bounded version-aware recovery guidance without interpreting the user's project text.

REFACTOR: Centralize the contract that prose fields are presentation data and typed observations are control-plane inputs.

Acceptance Criteria

  • installed, uninstalled, and installation completed never create a no-progress trigger.
  • An explicit typed no-progress observation still creates the correct replan obligation.
  • Affected legacy installations receive actionable upgrade guidance.
  • The regression uses public CLI behavior rather than private helper state.
  • All new tests pass.
  • Existing tests still pass.

Activity

  1. JerryChaox commented on Sep 13, 2026

    @JerryChaox
    Author

    补充建议:把修复范围扩大为一次全仓的“自由文本 → 控制状态”正则审计,而不只修 installed 这个单词。

    我做了一个初步静态清点:

    • 在 0.4.3 中发现两条独立的 legacy stall 文本路径都包含无词边界的 stalled?:自主重规划触发器和运行历史状态摘要。因此同一类误报可能影响多个读模型。
    • 同一 legacy 触发器组还有 readiness .*done、todo.*mismatch 等宽泛表达式;它们可能跨越无关文本,或把展示文案误当成状态事实。
    • 当前 main 已通过 feat(control-plane): close replan through semantic progress #3161 移除自主重规划的 prose trigger,这是正确方向。对当前 loopx/ 运行时代码的关键词正则清点仍找到 16 个与 progress/stall/block/fail/review 等控制语义有关的 re.compile 调用,主要分布在 owner-gate 投影、外部证据观察、Todo 合约和 reviewer/provider 错误识别。多数已有词边界或结构锚点,但它们仍值得按输入来源逐项分类,而不是仅按正则外观判断安全性。

    建议审计时建立以下规则:

    1. 影响调度、权限、阻塞、完成、重规划或外部写入的判断,优先消费 typed fields / enums / provider error codes;自由文本只能用于展示或显式兼容层。
    2. 必须保留文本兼容层时,限定输入来源和最大跨度,使用完整 token、锚定结构或 fullmatch,禁止裸子串和无限制 .* 参与控制决策。
    3. 为每个控制型文本分类器生成对抗性词表,例如 installed/stalled、unblocked/blocked、incomplete/complete、not ready/ready、failed to detect failure,验证词内碰撞、否定、引用文本和跨句匹配。
    4. 增加一个仓库级静态检查:枚举控制平面中的 regex/string heuristics,并要求每条规则声明输入来源、是否影响控制状态、对应的负例测试。该检查应作为审计清单,不应简单禁止正则,因为结构化 marker 和 provider 固定错误格式仍可合理使用。

    这样可以把本 Issue 从单点单词修复提升为一条长期约束:人类/Agent 文案不能在没有类型化证据的情况下改变控制平面状态。

  2. huangruiteng commented on Sep 17, 2026

    @huangruiteng
    Collaborator

    Scoped verification reply from the issue-intake lane (read-only; no issue state or metadata changed).

    I tried to reproduce this on current main (d8e7af141) rather than 0.4.3, and could not find the described free-text matcher at all:

    • There is no stalled?-style text match anywhere in the repository (searched loopx/, packages/, apps/, scripts/, deprecate/).
    • Frontier stall handling on current main is typed state, not prose: the long-chain/monitor stall path keys off no_change_count fields (loopx/control_plane/goals/goal_frontier/__init__.py, the stalled collection around the monitor-no-change rule), and the remaining stall occurrences are typed field names or status tokens (e.g. stall_suspected, session_stalled), not substring matches over free text.
    • The "run-history status summary" path likewise reads structured status rather than matching words.

    So the installed → stall misclassification you saw looks like it belongs to the 0.4.3 legacy matcher, which does not appear to exist on the current release line. If you can still reproduce it on the current version, could you share the exact loopx ... invocation and loopx --version output? With that I can trace which read model produced the stall text, and if the second suggestion (a repo-wide free-text → control-state audit) is still warranted afterwards, it should probably be tracked as its own item rather than folded into this report.

  3. added a commit that references this issue on Oct 10, 2026
    a7de7e1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions