Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@ tip,即 tag `v0.28.0` = `2cf0a691`,并校验预编译 wheel 可用):
构建;对 schedule-only 流水线,按 adapter 声明
(`rebase.ci.ignore_branch_filters`)直接创建构建。

**上游正式发版后的收尾**:冻结 release tag 的完整 SHA,核对 CI/生产镜像、
ROCm/XPU 变体、Python 依赖范围和源码安装文档指向同一版本。仅在正式产物仍需要时
保留候选版的临时 wheel/依赖修补;既有发布版示例维持其原配 vLLM 版本,
独立发版的平台 pin 要单独核实。模块导入检查
不能证明所有构造函数和运行路径兼容:对照已安装的目标 vLLM API,审查 Omni 的
override、必填输出字段、dummy/profile/capture 与异步输出转换,并用真实上游类写
小型回归测试。远端 CI 只对精确提交下结论;按具体 traceback 和测试节点比较最近
main/分支构建。如果 main 构建早于刚合入的改动,还要追溯该改动,再决定失败归属。
延迟超阈值但正确性通过的结果单独记录并复测,不直接归为功能回归。
合并目标仓库的最新 main 后,还要复核 PR review/comment 与安装文档;最终
说明和 Buildkite 结果必须对应实际推送的同一个 commit。

## 快速上手 3 · 更新知识库

上游发版或目录变化后,用 `imupdate` 把**结构事实**(模型清单、registry、
Expand Down
38 changes: 35 additions & 3 deletions adapters/vllm_omni/rebase/prompt_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,42 @@
# doc/DRIFT_TRIAGE.md for the pre-cutover decision — do NOT "fix" one side
# to match the other here.
template: module_rebase.prompt.tmpl
# live variant: identical except the two prose references to the retired
# shell wrapper name imx-omni-pytest instead (recorded divergence — the
# parity template above stays parent-verbatim for the byte-equality pin)
# live variant: wrapper-name fixes plus release/API checks. The parity
# template above stays parent-verbatim for the byte-equality pin.
template_live: module_rebase.live.prompt.tmpl
# Live debug guidance may evolve without changing the pinned parent-parity
# prompt/goldens. The old template remains the comparison fixture below.
debug_prompt_template_live: |
## Debug: fix failing test for module `{module}`

### Test
{test_path}

### Traceback
```
{traceback}
```

### Your task
1. Find the first causal traceback and every failed test in this job. Group
jobs by failure signature, not job label; one startup error can fail
several jobs, and one job can contain independent failures.
Comment on lines +26 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Provide the complete log before requesting every failure

When a test job has multiple failures and an earlier traceback falls more than 200 lines before the end, the agent cannot reliably perform this instruction: both local and remote-CI callers pass only splitlines()[-200:] (rebase_v3.py:1410-1413 and rebase_v3.py:2131-2135), while the rendered prompt includes neither the source log path nor a truncation marker. The agent therefore sees the tail as the complete traceback and can group or fix the wrong signature; pass the log path/full failure summary or explicitly direct it to the complete artifact.

Useful? React with 👍 / 👎.

2. Compare the exact traceback and test node with recent main and branch
builds when those logs are available. If main's last build predates a
merged main change, inspect that change before calling the failure a
rebase regression. Separate assertion failures, latency-only failures,
cancellation, and broken reporting steps. Record unknown attribution
when evidence is insufficient; do not weaken thresholds or skip tests.
3. Read the target vLLM API and `git show origin/main:<path>` for Omni intent.
Fix the smallest confirmed rebase-specific cause. After a startup API
fix, inspect adjacent constructor, override, result-field, dummy-run,
and async-output contracts that the first crash could have masked.
4. Reproduce with a targeted test using the real upstream API when possible,
then run the owning suite. Report the exact validated commit and whether
a new remote CI build has reached a terminal result.
5. Write MODULE_DONE {module} to the signal file only after verification.

MODULE={module}

# command template for PYTEST_COMMANDS / IMPORT_CHECK lines; goldens set this
# to the parent's run_module_pytest.sh path to prove byte-parity, live runs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ Goal: make `{OMNI_FILES}` compatible with upstream while preserving vllm-omni in
7. **No-op fail-fast:** if output unchanged across **two** consecutive repair attempts, stop.
8. Repeated identical `TypeError` / ctor args on one stack → **one** kwargs/wiring fix, then re-verify.

## Release transition and adjacent API checks (live rebase)
- If the target is a published vLLM release, compare its tag SHA with the
commit-pinned wheel and container tags before retaining any temporary wheel,
torch/FlashInfer, or ABI repair block. Keep a repair only when the released
artifact still needs it. Check CI and production images, ROCm/XPU variants,
Python dependency bounds, and source-install docs as one version set. Keep
already published Omni/version examples paired with their historical vLLM;
leave separately released platform pins alone unless their matching release
exists.
- Import and signature checks do not exercise every override. For a changed
upstream class or `execute_model`/output path, compare *all* Omni constructors,
overridden method signatures, required result fields, and conversions with
the installed target API. Include dummy/profile/capture and async-output paths
before declaring a startup fix complete. Use a CPU regression against the
real upstream constructor or method, then run the owning test suite.
- When a test fixture bypasses `__init__`, initialize newly required fields in
that fixture to the real disabled-feature defaults. Do not add production
fallbacks solely to satisfy an incomplete mock.

**Engine / unpack:** Fix return-shape, kwargs, ordering at the real omni engine boundary; keep `shutdown` kwargs in sync with upstream.

**Diffusion / subprocess:** `StageDiffusionProc died during handshake` → full worker traceback; handshake/init vs OOM; one controlled retry if GPU contention is plausible.
Expand Down Expand Up @@ -265,4 +284,4 @@ OUT_OF_SCOPE_EDITS:

If tests still fail after {MAX_DEBUG_RETRIES}, write a **detailed, self-contained** failure summary to:
`{SIGNAL_DIR}/module.{MODULE_KEY}.fail`
and stop. The orchestrator reads this file to diagnose failures, so include: (a) the failing command and exit code, (b) last 20 lines of traceback/error output, (c) out-of-scope edits attempted (if any), and (d) remaining root cause.
and stop. The orchestrator reads this file to diagnose failures, so include: (a) the failing command and exit code, (b) last 20 lines of traceback/error output, (c) out-of-scope edits attempted (if any), and (d) remaining root cause.
4 changes: 3 additions & 1 deletion doc/architecture/SPEC/engine/steps/rebase_v3.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# engine/steps/rebase_v3.py —— 规范

<!-- verified-against: 2026-09-19 -->
<!-- verified-against: 2026-09-29 -->

`LOC ~2204 · step 库(v3 rebase 装配层) · refactor-status: oversized`

Expand Down Expand Up @@ -60,6 +60,8 @@ step —— 薄的受治理 wrapper,substate-first、类型化失败、发布
unstaged+untracked 字节+mode+symlink)→ 复跑/本地验证 → patch policy;自动
patch 不得修改 assertion/tolerance,test 文件编辑必须有明确本地 passed。
被拒、验证失败或策略违规的尝试**回滚**。
- debug agent 的 prompt 与 `rebase_module` 同源选择:`debug_prompt_template_live`
优先,缺省回落 `debug_prompt_template`。
- 空/损坏 manifest ⇒ `manifest_empty`(push gate 阻塞,绝不空洞通过);
不可运行的命令归 STRUCTURAL —— 绝不借 bash rc=0 假通过。
- **A5**:一切仓库知识来自 adapter manifest;parity 词汇泄漏上限 14,
Expand Down
6 changes: 4 additions & 2 deletions doc/architecture/SPEC/rebase_engine.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# rebase_engine/ —— 规范

<!-- verified-against: 2026-09-21 -->
<!-- verified-against: 2026-09-29 -->

`LOC ~7500(26 个模块) · repo-rebase-v3 的原生 rebase 引擎 · refactor-status: ok`

Expand Down Expand Up @@ -31,7 +31,7 @@
| `path_sync.py` | 模块路径图同步 + manifest modules 段重写 + L2 决定应用 |
| `phase1_steps.py` | phase-1 组合(归类 + 路径同步),父级报告文件名不变 |
| `plan_review.py` | L4 计划评审后端(注入的 LLM client,父级形状的结果) |
| `prompt_builder.py` | 模块/调试 prompt 渲染 —— 等输入下与父级字节一致(golden 钉住) |
| `prompt_builder.py` | 模块/调试 prompt 渲染 —— 等输入下与父级字节一致(golden 钉住);`*_live` 变体不受 parity 钉 |
| `push_gate.py` | 推送闸裁决:结构性 vs 断言失败的确定性分类(Rev 8 §2.3) |
| `push_to_ci.py` | commit+push-to-CI 编排:preflight、WAL 卫生、C4 双闸、单一传输 |
| `push_wal.py` | 推送 WAL:先落盘的 intent、精确 OID 三分对账、回滚数据 |
Expand Down Expand Up @@ -98,6 +98,8 @@ runner/LLM/CI client 全部可注入 —— 每个模块都能离线测试。
坐标随 round 持久化,供恢复和审计使用。
- 自动 debug agent 不能修改 assertion/tolerance oracle;任何 test 文件编辑只有
在对应本地验证明确 passed 时才可进入远端重试。拒绝的尝试由调用方恢复快照。
- 调试 prompt 优先用 adapter 的 `debug_prompt_template_live`,缺省才回落到父级
`debug_prompt_template`;后者保持父级原文,作为 parity golden 的比较基准。
- **A5** —— 全包仓库中立:仓库值经 `WheelSpec`/`PinSpec`/`ManifestSpec`/
`ModulePromptData`/`tool_schemas.json`/hooks 注入;`test_repo_neutral_core` 钉住。

Expand Down
3 changes: 2 additions & 1 deletion src/infermatrix_copilot/engine/steps/rebase_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,8 @@ async def _run_debug_agent(ctx: StepContext, manifest: dict, module: str,
tools = build_rebase_tools(
defs, paths, _build_backends(ctx, manifest, repo_root, target))
prompt = build_debug_prompt(module or slug, traceback_text,
data.debug_prompt_template, slug)
data.debug_prompt_template_live
or data.debug_prompt_template, slug)
agent_log = ctx.run_dir / "agents" / f"debug-{slug}.log"
agent_log.parent.mkdir(parents=True, exist_ok=True)
ctx.trace.record("debug_attempt", slug=slug, module=module,
Expand Down
3 changes: 2 additions & 1 deletion src/infermatrix_copilot/rebase_engine/module_rebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ async def _attempt(p: str, *, require_plan_review: bool = True) -> dict:
debug_attempts += 1
debug_prompt = build_debug_prompt(
module, result.get("text", ""),
prompt_data.debug_prompt_template, "")
prompt_data.debug_prompt_template_live
or prompt_data.debug_prompt_template, "")
result = await _attempt(debug_prompt,
require_plan_review=not gate_passed)
gate_passed = gate_passed or bool(result.get("plan_done"))
Expand Down
3 changes: 3 additions & 0 deletions src/infermatrix_copilot/rebase_engine/prompt_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ModulePromptData:
template_live: str = ""
pytest_wrapper_live: str = ""
debug_prompt_template: str = ""
debug_prompt_template_live: str = ""
module_vllm_paths: Mapping[str, str] = field(default_factory=dict)
module_omni_files: Mapping[str, str] = field(default_factory=dict)
module_test_map: Mapping[str, Sequence[str]] = field(default_factory=dict)
Expand All @@ -49,6 +50,8 @@ def load(cls, rebase_data_dir: Path) -> "ModulePromptData":
template_live=data.get("template_live", ""),
pytest_wrapper_live=data.get("pytest_wrapper_live", ""),
debug_prompt_template=data.get("debug_prompt_template", ""),
debug_prompt_template_live=data.get(
"debug_prompt_template_live", ""),
module_vllm_paths=data.get("module_vllm_paths", {}),
module_omni_files=data.get("module_omni_files", {}),
module_test_map=data.get("module_test_map", {}),
Expand Down
24 changes: 19 additions & 5 deletions test/test_adapter_knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,35 @@ def test_debug_prompt_matches_parent_golden():
assert ours == (GOLDENS / "debug_prompt.txt").read_text()


def test_live_debug_prompt_carries_rebase_attribution(prompt_data):
live = build_debug_prompt(
"worker_runner", "TypeError: RopeState",
prompt_data.debug_prompt_template_live, "tests/worker_v2/test_state.py")
assert "TypeError: RopeState" in live
assert "failure signature" in live
assert "main's last build predates a" in live
assert "adjacent constructor, override, result-field" in live


def test_templates_are_parent_verbatim():
"""Every shipped template byte-equals the parent's (they are DATA; any
edit belongs upstream of a fresh copy + golden refresh, not here)."""
"""Parity templates match the parent; live additions are bounded."""
parent = Path("/data/zhoutaichang/copilot/vllm-omni-rebase-agent/agent/templates")
if not parent.is_dir():
pytest.skip("parent checkout not present on this machine")
for tmpl in sorted((REBASE_DATA / "templates").iterdir()):
if ".live." in tmpl.name:
# the ONE recorded exception: the live variant differs from its
# parity sibling only in the wrapper-name prose (pinned below)
# Live guidance is intentionally outside the parent-parity pin.
continue
assert tmpl.read_bytes() == (parent / tmpl.name).read_bytes(), tmpl.name
live = (REBASE_DATA / "templates" / "module_rebase.live.prompt.tmpl")
parity = (REBASE_DATA / "templates" / "module_rebase.prompt.tmpl")
live_text = live.read_text()
start = live_text.index("## Release transition and adjacent API checks")
end = live_text.index("**Engine / unpack:**", start)
assert "real upstream constructor" in live_text[start:end]
without_live_guidance = live_text[:start] + live_text[end:]
diff = [(a, b) for a, b in zip(parity.read_text().splitlines(),
live.read_text().splitlines()) if a != b]
without_live_guidance.splitlines()) if a != b]
assert len(diff) == 2
assert all("imx-omni-pytest" in b and "run_module_pytest" in a
for a, b in diff)
Expand Down Expand Up @@ -385,6 +398,7 @@ def on_module_result(self, module, result):
debug_req = retry_client.requests[2]["messages"][0]["content"]
assert debug_req.startswith("## Debug: fix failing test for module")
assert "half done, ran out of road" in debug_req
assert "failure signature" in debug_req
# the debug turn ADVERTISED the gated tools (gate persisted as passed)
assert "edit_file" in [x["name"] for x in retry_client.requests[2]["tools"]]

Expand Down
Loading