Skip to content

feat(cosh-ng): [shell] route unresolved natural-language input to Agent#1742

Open
SunnyQjm wants to merge 1 commit into
mainfrom
feat/shell-english-prompt-routing-v2
Open

feat(cosh-ng): [shell] route unresolved natural-language input to Agent#1742
SunnyQjm wants to merge 1 commit into
mainfrom
feat/shell-english-prompt-routing-v2

Conversation

@SunnyQjm

@SunnyQjm SunnyQjm commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What changed

  • Keep valid commands on the native Shell path and classify input only after a top-level command-not-found.
  • For unresolved inputs that stay Shell-owned, prefer a unique typo correction and otherwise offer the generic Agent diagnosis ghost.
  • Route Chinese input and high-confidence English requests such as Who are you and Just do it directly to Agent without printing command not found.
  • Keep ambiguous or command-shaped input in Shell, with the existing failed-command ghost prompt available as fallback.
  • Harden prompt/card input ownership across capture replacement, delayed escape sequences, EOF, overflow, and replay boundaries.

Why

The existing fallback could identify failed commands, but English natural-language prompts still leaked through as shell errors. Routing before Shell execution would avoid that error but could also intercept valid commands. This change lets Shell resolve real commands first, then handles only unresolved top-level input.

Related to #1666.

Routing strategy

flowchart TD
    A["User submits input"] --> B{"Explicit Cosh control?<br/>slash command or ??"}
    B -->|Yes| C["Handle control or Agent request directly"]
    B -->|No| D["Shell parses and executes input"]
    D --> E{"Proven top-level command miss?<br/>exit 127 and matching attempt"}
    E -->|No| F["Keep normal Shell result<br/>existing non-127 failure policy remains"]
    E -->|Yes| G{"Ownership and safety gates pass?"}
    G -->|No| H["Delegate to native or user command-not-found handler"]
    G -->|Yes| I["Classify the original input"]
    I --> J{"Command-shaped syntax?"}
    J -->|Yes| K["intent = command"]
    J -->|No| L{"Contains valid Han character?"}
    L -->|Yes| M["intent = natural_language"]
    L -->|Invalid UTF-8| N["intent = unsafe"]
    L -->|No| O{"Matches English language patterns?"}
    O -->|Yes| M
    O -->|No| P["intent = ambiguous"]
    M --> Q{"AI enabled?"}
    Q -->|Yes| R["Direct Agent<br/>suppress command-not-found"]
    Q -->|No| S["Keep command-not-found"]
    K --> T["Keep command-not-found<br/>record proven missing input"]
    N --> T
    P --> T
    S --> T
    T --> U{"Unique typo correction available?<br/>non-manual mode and intervention gates pass"}
    U -->|Yes| V["Shell rewrite ghost<br/>Tab to accept"]
    U -->|No| W["Generic Agent diagnosis ghost<br/>Tab to accept"]
Loading

The classifier is never called for a command that Shell can resolve. Command correction is therefore not attempted for input already classified as natural language; for the remaining proven command-not-found cases, a unique correction wins over the generic Agent fallback.

Natural-language rules

Rules are evaluated in this order:

Priority Rule Result Representative examples
1 Reject empty or over-4096-byte input; do not retain secrets; reject invalid UTF-8 No direct Agent sensitive input, malformed bytes
2 Protect command-shaped input: path-like first token, command/env/sudo/exec/nohup/time/xargs, shell quoting or operators, control characters, option tokens, and assignments Shell-owned command ./script, review --all, review FOO=bar, review this | cat
3 After command protection, any valid Han character is a strong natural-language signal Direct Agent when AI is enabled 帮我看看当前目录, 帮我看 ./日志
4 English question forms: WH words, auxiliaries/modals, subject-plus-predicate and negative-state patterns Direct Agent Who are you, how file, can you check this, service not running
5 English requests: optional polite/softening prefixes plus a request verb and content Direct Agent please explain this, maybe check this, review ./report.log, restart the service
6 Explicit conversational and continuation phrases Direct Agent Just do it, go ahead, try again, thank you, hello there
7 Everything else Shell-owned ambiguous ok, hello, thanks, just build, go test, kubectl get pods, emoji-only input

Important boundaries:

  • A trailing question mark may support a question form, but extra shell-like metacharacters keep the input Shell-owned.
  • A file path in an argument does not by itself veto natural language, so review ./report.log and 帮我看 ./日志 can route directly; a path-like first token such as ./script remains a command.
  • Single-token acknowledgements remain ambiguous to avoid intercepting a missing executable with the same name.
  • Non-Han languages are currently not promoted solely by Unicode presence; without an English rule match they remain ambiguous.
  • natural_language routes directly only when AI is enabled. command, ambiguous, unsafe, and AI-disabled cases preserve the native command-not-found result and can surface correction or Agent ghost suggestions afterward.

Real Linux/bash PTY evidence

Who are you is sent directly to Agent without a command not found line:

bash-direct-agent

The Shell remains usable after Agent returns:

bash-shell-continuity

Validation

  • cargo test -p cosh-shell --lib raw_input:: -- --test-threads=1 — 71 passed
  • ARM64 Linux/bash natural-language integration — 10 passed
  • ARM64 Linux/bash ambiguous-input integration — 2 passed
  • ARM64 capture/replay integration — 5 passed
  • cargo clippy -p cosh-shell --all-targets -- -D warnings
  • cargo build -p cosh-shell --bin cosh-shell
  • cargo fmt --all -- --check
  • ./crates/cosh-shell/scripts/check-layout.sh
  • git diff --check

@github-actions github-actions Bot added component:cosh-ng src/cosh-ng scope:documentation ./docs/|./*.md|./NOTICE labels Jul 24, 2026

SunnyQjm commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

PR number: #1742
head_sha: 3c9def1
reviewed_at: 2026-07-24T06:21:55Z

Findings

  • [P1] 当前 head 的远端 Test cosh-ng 仍是红的(run 30070267497, job 89409566791, cargo test --workspace)。失败面包括 external_hook::raw_cli_external_hook_stdout_holder_is_killed at crates/cosh-shell/tests/raw_cli/external_hook.rs:190:5external_hook::raw_cli_external_hook_stdin_holder_is_killed at :219:5failed_command::raw_cli_explain_after_usage_help_failure_invokes_adapter,以及 session::raw_cli_session_multi_clear_requires_confirmation_and_cancel_is_safesession::raw_cli_session_picker_loads_next_page_near_viewport_endsession::raw_cli_session_picker_surfaces_unhealthy_and_empty_entriessession::raw_cli_session_picker_keeps_list_workspace_for_validate_and_clear。这些失败覆盖 raw input、failed-command 和 session/card capture 面,本 PR 正在改同一批 ownership/relay 路径;在当前 head 变绿或证明失败与本 PR 无关前,这是 blocking。
  • [P2] src/cosh-ng/crates/cosh-shell/src/shell_host/marker.rs:610: PR head 的 zsh marker setup 只保留 NO_BEEP / NO_PROMPT_CR / NO_PROMPT_SP,丢了 main 上 marker.rs:592unsetopt NOMATCH 2>/dev/null || true。在 zsh 默认 NOMATCH 下,ls /tmp/cosh-no-such-glob-zzzz* 会被 shell expansion 拦截为 zsh: no matches found,而不是进入 ls 并产生普通 native command failure。这个行为变化和 natural-language routing 无关,会改变原本 shell-owned 的 unmatched-glob 路径;建议恢复该行,或补明确设计说明和回归测试。
  • [P3] src/cosh-ng/crates/cosh-shell/src/agent/failed_command.rs:71 / src/cosh-ng/crates/cosh-shell/src/shell_host/osc.rs:213: 两个 production 文件已超过 SDD 强提醒阈值,本 PR 继续塞入新 feature logic,当前 head 行数为 failed_command.rs 790 -> 853、osc.rs 844 -> 929,且文件头没有 owner note / split plan / waiver。按 specs/cosh-ng-code-organization/review.md 这不是 public API blocker,但需要作者解释为什么仍放在当前 owner 文件内,或补后续拆分/豁免说明。

Structure Review

  • 未发现 blocking package/module/public API 组织问题。变更仍收敛在 src/cosh-ng/crates/cosh-shell/ 与 PR body 图片证据资产下。
  • 未发现新增 crate/workspace dependency、Cargo.toml/lock/.env/lib.rs 变更、root src/*.rs implementation 文件、production cosh_shell:: self-crate public path,且未发现 forbidden shell_host -> agent/approval/ui/runtime dependency。

Remaining Risks / Not Run

  • 我没有在本地跑 cargo fmtcargo clippycargo test 或真实 Linux/bash PTY 套件;本轮保持 review-only,没有修改工作区文件。
  • 没有完整 root-cause 每个 raw_cli failure;P1 基于当前 head 的远端失败日志以及失败面与本 PR 修改面的重合。
  • feat(cosh-ng): [shell] route unresolved natural-language input to Agent #1742 仍是 draft;Qoder review eligibility 当前为 skipped;本地看到 origin/main 已前进到 d0398c791c740f97b5321fd7f138cc0d0d8b27ef,PR diff 按 merge-base d2af9b338ab7cef1e49fd85402f8d1f7901313e7 复审。

Validation

  • Inspected live PR feat(cosh-ng): [shell] route unresolved natural-language input to Agent #1742 metadata, comments, empty review-thread list, and status checks via GitHub connector plus gh.
  • Re-fetched origin/main and refs/pull/1742/head; confirmed current head is 3c9def11680a5d4012cdeb1e4b5b39513cb50ac8.
  • Inspected failing Test cosh-ng log for run 30070267497 / job 89409566791.
  • Ran static structure checks on fetched refs: git diff --check, Cargo/lock/.env/lib/root-src path checks, production cosh_shell:: grep, forbidden dependency grep, and PR-head line counts.
  • Verified zsh NOMATCH behavior locally on zsh 5.9 with and without unsetopt NOMATCH.
  • Inspected local specs/cosh-ng-code-organization/{README,standard,review,validation}.md for structure review.
  • Same marker comment had the same head_sha, so this run updated the existing top-level Conversation comment instead of adding a new one.

@SunnyQjm
SunnyQjm force-pushed the feat/shell-english-prompt-routing-v2 branch from 3c9def1 to 57cf5f8 Compare July 24, 2026 06:23
@SunnyQjm SunnyQjm changed the title feat(cosh-shell): route missing natural language to agent feat(cosh-ng): [shell] route unresolved natural-language input to Agent Jul 24, 2026
@SunnyQjm
SunnyQjm force-pushed the feat/shell-english-prompt-routing-v2 branch 4 times, most recently from 0bd89fd to 193b8ea Compare July 24, 2026 07:01
@SunnyQjm
SunnyQjm force-pushed the feat/shell-english-prompt-routing-v2 branch from 193b8ea to fc9db9e Compare July 24, 2026 07:17
@SunnyQjm
SunnyQjm marked this pull request as ready for review July 24, 2026 07:28
@SunnyQjm
SunnyQjm requested a review from samchu-zsl as a code owner July 24, 2026 07:28

@qoderai qoderai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • 捕获溢出/过期路径下仍累积并重放字节,可能泄露本应仅限卡片生命周期的输入。
  • 自然语言路由关闭原始命令时对用户 missing 处理器的约定不够显式,难以区分失败与交给 Agent。
  • capture 生命周期状态机较复杂,建议强化代际与 invalidated 不变式的系统化测试覆盖。

🤖 Generated by QoderView workflow run

Comment thread src/cosh-ng/crates/cosh-shell/tests/shell_host/marker.rs
Comment thread src/cosh-ng/crates/cosh-shell/src/raw_input/mode.rs

@kongche-jbw kongche-jbw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

审查当前 head fc9db9e 后发现 3 个需要处理的输入所有权与兼容性问题,详见行内评论。当前 CI 虽已通过,但相关测试没有阻止 capture-owned 字节进入 Shell,也未覆盖 UTF-8 字节上限和自然语言命中时的用户 missing handler。


let replay = std::mem::take(quarantined_suffix);
if !replay.is_empty() {
relay_passthrough_input(&replay, relay)?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] 不要把 capture-owned 的剩余字节重放为 Shell 输入

quarantined_suffix 中的字节是在原 capture generation 仍持有输入时读取的;consume_split 遇到第一个提交/取消事件后留下的 remainder 也在其中。这里直接写回 PTY 会让粘贴到自由文本卡片的 answer\n<command>\n 在卡片结束后执行 <command>。overflow 测试甚至明确断言尾部 echo 会运行,因此 overflow/expiry 并没有 fail closed。

建议丢弃仍属于旧 generation 的 remainder;只有能够证明是在所有权切回 Shell 后读取的字节才允许重放。至少应增加多行粘贴不会触发 Shell 命令的回归测试。

local han_status had_question=0 polite=0
local IFS=$' \t\n'

if [[ -z "$original" || ${#original} -gt 4096 ]]; then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 这里检查的是字符数,不是 PR 声明的字节数

在 UTF-8 locale 下 ${#original} 返回字符数。例如 帮我 加 2000 个汉字是 2003 个字符、6007 字节,但仍会通过此检查并按 Han 规则直达 Agent,突破“超过 4096-byte 不保留、不直达”的边界。

请按字节长度检查(例如在明确的 LC_ALL=C 语义下计算),并补 4096 字节上下的多字节输入测试。

return 127
local intent
intent="$(_cosh_classify_missing "$original" "$command")"
if [[ "$intent" == "natural_language" && "${_COSH_AI_ENABLED:-1}" == 1 ]]; then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 自然语言分支绕过了用户的 command-not-found handler

当用户定义了 command_not_found_handle / command_not_found_handler 时,这里直接返回 0,用户 handler 的输出、副作用和返回码都不会发生;只有其他 intent 才走下面的 delegate。当前兼容性测试仅覆盖 terraform plan 这类 ambiguous 输入,没有覆盖 natural-language 命中。

如果目标是保留 native Shell contract,建议检测到用户 handler 时优先 delegate,或要求用户显式 opt-in 才允许 Cosh 绕过它;同时补一个 natural-language + 自定义 handler 的回归测试。

@SunnyQjm

SunnyQjm commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

PR number: #1742
head_sha: fc9db9e
reviewed_at: 2026-07-24T07:51:58Z

Findings

  • [P2] src/cosh-ng/crates/cosh-shell/src/agent/failed_command.rs:132-144src/cosh-ng/crates/cosh-shell/src/shell_host/osc.rs:252-258src/cosh-ng/crates/cosh-shell/src/shell_host/raw_relay.rs:286-301 使用分号拼接字符串在 ShellEvent.message 中传递 routing provenance / capture generation,再通过 containsrsplit(':') 解析。这违反 standard.md 第 9 条“用结构化类型和 parser,不用 ad-hoc string manipulation”,建议将 provenance 建模为 types 结构化字段。

  • [P2] src/cosh-ng/crates/cosh-shell/src/types/mod.rs:122 在公开枚举 ShellEventKind 中新增 CommandRoutingObserved 变体,但 public-api-inventory.md 未同步登记 owner、caller、稳定性分类。新增 public API 必须同步 inventory。

  • [P2] 已登记 large-file debt 的 production 文件继续膨胀,与文件顶部 owner note 冲突:

    • src/cosh-ng/crates/cosh-shell/src/shell_host/marker.rs 顶部要求拆分 missing-handler scripts,本次却在 marker 脚本内新增 _cosh_classify_missing、attempt tracking、natural-language routing;
    • src/cosh-ng/crates/cosh-shell/src/agent/failed_command.rs 顶部要求拆分 candidate construction,本次却在 agent/failed_command.rs:199-244 新增 command_not_found_agent_candidate
    • src/cosh-ng/crates/cosh-shell/src/shell_host/osc.rs 顶部要求拆分 marker decoding/provenance,本次却新增 routing event 构造逻辑。
      需作者解释为何不在新增功能前先拆分,或补更具体的 waiver。
  • [P3] 自然语言分类逻辑从 input/mod.rs 迁移到 shell_host/input_intent.rsinput owner 职责收窄为 slash/control 识别,shell_host 承担 shell 级输入意图判定。standard.md 的 owner 表未体现该调整,建议更新 standard.mddecisions.md 避免共建漂移。

  • [P3] src/cosh-ng/crates/cosh-shell/tests/shell_host/input_intent.rs:1 通过 #[path = "../../src/shell_host/input_intent.rs"] 直接引用源码路径,测试与源码结构强耦合;后续文件重排会导致断裂。

Structure Review

未发现 blocking package/module/public API 组织问题。变更全部收敛在 src/cosh-ng/crates/cosh-shell/ 内;未新增 workspace crate、未改动 Cargo.toml/lockfile/.env/lib.rs、未新增 root src/*.rs implementation 文件、未发现 production cosh_shell::... self-crate public path、未发现 forbidden dependency direction。新增 shell_host/input_intent.rsraw_input/spawn/action.rsraw_input/spawn/capture.rsraw_input/card_capture/events.rs 均落在对应 owner 子目录下;raw_input/spawn.rs 拆分有助于降低单文件复杂度。

Remaining Risks / Not Run

  • 本轮为 review-only,未在本地执行 check-layout.shinventory-public-api.shcargo check/test/fmt/clippy,未修改工作区文件。
  • 文件行数为根据 patch 估算,实际以本地脚本为准。
  • 未验证 CommandRoutingObserved 结构化后的 public API 分类变化对 integration tests 的影响。
  • 未对真实 bash/zsh PTY 做本地复现。

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

Labels

component:cosh-ng src/cosh-ng scope:documentation ./docs/|./*.md|./NOTICE

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants