myxce/docs/aibot_poc_investiagting.md
lei.chen 86265fb7bc docs: mark PEND reason end-to-end done (bug-1513), note main_reason follow-up
- aibot_poc_investiagting.md: PEND reason 调查完成 + 转换层补全;新增遗留项(main_reason 恒 0)
- buglog.json: bug-1513 entry
- memory.md: session log

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-13 09:16:49 +00:00

67 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AI Bot 对外 POC 能力建议(scheduler-agent MCP)
> 状态:建议稿(2026-08-13)。讨论稿,未实施。
> 目标:对外 POC 演示 XCE 的 AI agent(scheduler-agent MCP)能力。出彩的关键不是"更多查询工具",而是**闭环 + 叙事**——让观众看到 agent 不只是读状态,还能诊断、能动手、能解释。
## 一、现状:已注册 14 个 MCP 工具
| 类别 | 工具 |
|------|------|
| 只读·状态(6) | `scheduler_list_jobs` / `get_job` / `list_queues` / `list_nodes` / `job_logs` / `cluster_metrics` |
| 只读·高级(4) | `wait_job` / `analyze_failure` / `suggest_resources` / `estimate_wait_time` |
| 写(4,需确认) | `submit`(dry_run 审查 + general_serial 模板)/ `cancel` / `hold` / `release` |
## 二、推荐增强方向(按 POC 性价比排序)
### 1. 失败作业「自愈闭环」— 首选,对外 POC 的 money shot
现状 `analyze_failure` 只是"把数据打包给你看"。升级为 **诊断 → 归因 → 行动 → 复跑验证** 的闭环:
- **归因分类**:按 exit code / signal / 日志特征分类——OOM、被信号杀(segfault/killed)、命令不存在、超时、基础设施失败(节点掉了);每类给一句人话解释 + 证据链
- **自动重试策略**:OOM → 建议加内存重交;被信号杀 → 检查资源限值;脚本错误 → 不改资源、指出错在哪行
- **自愈动作**:`rerunable` 作业 → 用调整后的规格 re-submit → `wait_job` 验证 → 报告"第一次 OOM 失败 → 加大内存后成功"
数据已齐(failinfo code、日志、submit 全参数);主要是把 `analyze_failure` + `submit` + `wait_job` 编排成智能逻辑。
演示剧本:"提交一个会 OOM 的作业 → agent 自己把它修好跑通"。
### 2. 作业旅程「实时叙事」— 最便宜、最抓眼球
SSE 事件流已建好(PEND→RUN→DONE),缺把事件转成有人味的实时解说:
> "作业 #12 已排队(第 3 位)→ 预计 40s 后开始 → 已分配到 t2 节点(负载 30%)→ 运行中,耗时 2m10s → 完成 ✅"
配合 `wait_job` 即"提交后 agent 全程盯着并讲解"。live demo 连续跑几个作业画面感极强。工程量最小(prompt/模板活)。
### 3. 调度决策「解释」(PEND reason)— XCE 差异化,别家抄不走
**"为什么我的作业等了 10 分钟 / 为什么没排到更空的节点?"** HPC 特有。
scheduler 侧已有 PEND 原因(`PREASON_NO_RESOURCE`、`PREASON_MATCH_FAIL`、资源不满足 slots/mem…),agent 若能读取并翻译:
> "作业 PEND 是因为 8 槽节点全满,你的 2 核需求需等 t3 释放 1 个作业(约 3 分钟)"
**前置检查(2026-08-13 完成)**:PEND reason 全链路**只差一环**——apiserver Go 转换层没填充 `PendingReason` 字段。详见下方「五、PEND reason 现状调查」。
### 4. 集群调优(数据可行,次优先级)
- **热点/碎片化分析**:扫节点 + 资源分布 → "t1 长期 90% 满载、t3 只有 20%,建议放宽 big 队列 affinity"(`resources/distribution` + hosts 数据已可做)
- **排空时间预测**:估算当前队列多久清空(`estimate_wait_time` 的队列维度扩展)
- **配置变更 what-if**:模拟改队列限制/加节点对等待时间的影响——最"调优"但需调度模型,工程量最大,POC 后置
## 三、POC 演示剧本建议
按感染力排序:**①自愈闭环(故事核心)→ ②实时叙事(视觉)→ ③PEND 解释(差异化)→ ④调优(收尾卖点)**。
## 四、待办
- [x] 检查 PEND reason 全链路(scheduler → apiserver)是否暴露齐全(2026-08-13 完成,结论:只差 apiserver Go 转换层)
- [x] 补 apiserver 转换层:`cJobToModel` / `rawJobToModel` 填充 `PendingReason`(convert.go / convert_pure.go)—— **ac6131d 完成并集群验证**
- [ ] **(新)scheduler `main_reason` 恒为 0**:allocator 只加 host/res 明细 reason(`add_job_preason` host≠NULL 时只走 add_host/add_res 分支),从不设 main_reason → API 显示 `main_reason:0 / "unknown(0)"`。host_reasons(如 `[{t1,3},{t2,3},{t3,3}]`)信息完整可用;要不要让 `add_job_preason` 在 main_reason==0 时补首个 code,待定(需重建 lib+scheduler+controller)
- [ ] ① 自愈闭环:失败归因分类器 + 自愈复跑流程
- [ ] ② 实时叙事 prompt/模板
## 五、PEND reason 现状调查(2026-08-13)
**结论:全链路只差一环——apiserver Go 转换层没把 C 的 `pend_reasons` 映射到 `models.JobInfo.PendingReason`,API 的 `pending_reason` 恒为空。** 上游全部就绪:
| 环节 | 状态 | 位置 |
|------|------|------|
| scheduler 计算并 publish PEND 原因 | ✅ | `sched_make_allocation` 返回 0 → `make_pend_decision(reason)`(scheduler.c:267);main.c:189 `sched_publish_pend_reason` → `setpreason` opcode |
| 原因类型 | ✅ | `PREASON_BAD_RESREQ`/`NO_RESOURCE`/`MATCH_FAIL` + host/res 明细(preason.h;resource.c allocator `add_job_preason`) |
| controller 存储 | ✅ | `do_set_preason` → `job->pend_reasons`(controller/job.c:2585-2613);`do_clr_preason` 清除 |
| capnp wire 编解码 | ✅ | `JobInfo.pendreason @10` encode/decode(xce.build/lib/controller.capnp.c:6152/6168) |
| C 结构体字段 | ✅ | `xce_job_t.pend_reasons`(src/include/xce/types.h:479) |
| apiserver model | ✅ | `JobInfo.PendingReason json:"pending_reason"`(models/jobs.go:553)+ 在 `JSONBJFields`(:140),填充后 processJobData 会自动解析浮现(jobs.go:3208) |
| **apiserver Go 转换** | ❌ | `cJobToModel`(backend/convert.go:74)与 `rawJobToModel`(backend/convert_pure.go:210)**均未读取 `pend_reasons`** → PendingReason 恒 nil |
**修复量**:小。在两个转换函数各加一段把 C `pend_reasons`(main_reason + host/res reasons)编码为 JSONB 塞进 `PendingReason`,配单测即可。