Repository navigation
fix(OMN-20291): code-edit loop stops re-reading, keeps its own absolute paths, applies indent-slipped edits, caps bulk edits by files changed - #3285
Merged
Conversation
…te paths, applies indent-slipped edits, caps bulk edits by files changed The OMN-20291 replay of 26 crush tasks left the node failing 8. Four node-side causes are fixed here: - Read loop (a16a3138, e3a2c923: 40 turns, 0 and 1 edits). The prompt sat at its 90k-character cap and held only the last one to three turns, and one turn's reads (8 to 12 views of up to 16 KB) exceeded the whole history, so even the newest turn was cut. Now every earlier turn keeps its action lines, the newest turns keep their output, a re-viewed window points at the later turn, a view of a file changed later is marked stale, one turn's reads total at most 30,000 characters, and after three turns that read and change no file the next turn's reads are refused, saying so in its prompt. History turns are structured, and the resume block (OMN-20391) stores them as JSON. - Absolute paths inside the worktree (58744096). The loop prints check argv with the worktree's absolute PYTHONPATH; the model searched that path and was refused as leaving the worktree. Such a path is now used and recorded as its worktree-relative form; any other absolute path is still refused. - Edit anchors (ea3ee264). The view prints ' 96| text'; the model copied the separator's blank into old_string, on every line or on the first line only. An old_string that matches exactly one place up to that shift is applied, with new_string moved back the same way. An edit whose result is already in the file is reported applied and writes nothing. - Bulk edit cap (8e1b5f72, OMN-20392 AC2 loop 7ea45ffe). replace_in_files refused a glob matching more node contracts than MAX_BULK_FILES before skipping the files without old_string. The cap now counts the files the glob would edit. Onex-Lane: code-edit-node-compare Onex-Session: 4380aed584814eab8ef70338fafb073d
✅ Architectural Review — PASSEDErrors: 0 What this checks
No architectural violations found. Static architectural lint — no model inference (OMN-14176). |
✅ Hostile Reviewer — PASSEDBlocking findings (critical/error): 0 Gate semantics
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524) |
| #: Characters the reads (view, grep, ls) of one turn may show together. The | ||
| #: history holds about 66,000 characters, so a turn's reads fit it whole with | ||
| #: room for the turn before (OMN-20291). | ||
| MAX_READ_CHARS_PER_TURN = 30_000 |
| #: room for the turn before (OMN-20291). | ||
| MAX_READ_CHARS_PER_TURN = 30_000 | ||
| #: Below this many characters left, a turn's further reads are not run. | ||
| MIN_READ_CHARS = 2_000 |
| #: Turns in a row that read and change no file before the next turn's reads are | ||
| #: refused, so a model that cannot hold every file it wants to read writes with | ||
| #: what it has instead of reading to the turn cap (OMN-20291). | ||
| MAX_READ_ONLY_TURNS = 3 |
…o the pull request's tests Onex-Lane: code-edit-node-compare Onex-Session: 4380aed584814eab8ef70338fafb073d
onexbot-occ-writer Bot
added a commit
to OmniNode-ai/onex_change_control
that referenced
this pull request
Oct 3, 2026
…nimarket#3285 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/37098457184
jonahgabriel
enabled auto-merge (squash)
October 3, 2026 05:11
jonahgabriel
pushed a commit
to OmniNode-ai/onex_change_control
that referenced
this pull request
Oct 3, 2026
) * evidence(OMN-20291): author OCC companion for OmniNode-ai/omnimarket#3285 OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head e793efaeef65d40cd00cec7afcc2ffee5cb74b17. * evidence(OMN-20291): self-bind OCC#12497 + rebind contract_sha256 * evidence(OMN-16859): executed test_passes receipts for OmniNode-ai/omnimarket#3285 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/37098457184 --------- Co-authored-by: omnimarket-bot <bot@omninode.ai> Co-authored-by: onexbot-occ-writer[bot] <307849072+onexbot-occ-writer[bot]@users.noreply.github.com>
jonahgabriel
added a commit
that referenced
this pull request
Oct 3, 2026
…ests already on dev dod-verify failed with 'bound test also passes at the merge base' for the three AC1-AC3 entries shipped in #3285. Drop them; bind AC5 (file list scope, skip files without old_string, prompt rule) and AC6 (refused calls counted separately) to this PR's new tests.
jonahgabriel
added a commit
that referenced
this pull request
Oct 3, 2026
…ip files without old_string, refused calls leave the budget (#3302) * fix(OMN-20291): code-edit bulk edits stay inside the task's file list, skip files without old_string, and refused calls leave the budget Comparison report knowledge-base-internal#986 left bulk edits over a named file list failing (replay tasks 8e1b5f72 and f76301f0). The turn prompt now says, before the task, that the task's file list is the only edit scope and that helper scripts are not available (no shell; a task that suggests a script is to be ignored). The model had tried a helper script first because the task text recommended one. The request takes a file_list (CLI: --file-list, one path per line). When it is given, replace_in_files reaches only those files: a glob narrows the list and never widens it, and a named file outside it is refused. Before, a glob over all node contracts edited 141 files for a 114-file task (8e1b5f72 run 2) and changed 5 contracts outside the 105 of f76301f0 (run 2). A named file without old_string is skipped and reported, not a failed call. A call where no listed file holds old_string still fails. A refused action (a write outside the writable scope, a read while reads are paused, an undeclared check) is recorded with refused=true. The within_budget criterion counts the calls that ran against max_tool_calls and reports refused_calls apart: a refused call changed and showed nothing, and the other criteria still score it. * fix(OMN-20291): replace_in_files skips a file the replacement was already applied to A repeated insertion over the task's file list inserted its line again in files that already had it (8e1b5f72, lab re-run attempt 2: the same call sent in turns 1, 3, 9, 11 and 12, then 31 turns of clean-up). A file whose old_string occurs only inside an earlier result of the same replacement is now skipped and reported as already applied; a call that finds every file done is reported unchanged, not failed. * fix(OMN-20291): contract binds this PR's new tests, not the AC1-AC3 tests already on dev dod-verify failed with 'bound test also passes at the merge base' for the three AC1-AC3 entries shipped in #3285. Drop them; bind AC5 (file list scope, skip files without old_string, prompt rule) and AC6 (refused calls counted separately) to this PR's new tests. * chore(OMN-20291): bump version to 0.4.284 Bump project.version in pyproject.toml and the omnimarket entry in uv.lock from 0.4.283 to 0.4.284. This resolves a Release Identity Gate (scripts/check_release_identity.py, OMN-16344) failure on PR #3302 head ccf36b1, which reported that the packaged source changed but pyproject version 0.4.283 was not ahead of the latest published version 0.4.283. After the bump, the script confirms version 0.4.284 is ahead of latest published 0.4.283.
jonahgabriel
added a commit
that referenced
this pull request
Oct 3, 2026
…nothing, and points a missing path at the paths that end with it (#3315) * fix(OMN-20291): code-edit prompt names writable files that do not exist yet; a no-op edit says it changes nothing Replay tasks 0192c135 (loop df4d5ca5) and 8d6e9b45 (loop 692d96fe) failed no_phantom_paths on omnimarket dev 32b6f90: in turn 1 the model viewed the test file the task told it to create, before creating it. The FILES index is cut at 12,000 characters, so on omnibase_core (7,211 files) the model cannot see that the path is absent. The same failure hit a0cbacca before #3285. The turn prompt now names each literal writable path missing from the worktree as a NEW FILE until a turn has written it. Replay ab8d7ef6 (loop 1c966a4a) sent an edit whose old_string equals its new_string three times and was told each time it 'was applied before'. Such an edit is now reported as changing nothing. Onex-Lane: code-edit-regress-2a21 Onex-Session: ead7bf3424ea48e49decfc434456da87 * chore(OMN-20291): bind the new-file and no-op edit tests in the ticket contract Onex-Lane: code-edit-regress-2a21 Onex-Session: ead7bf3424ea48e49decfc434456da87 * fix(OMN-20291): code-edit grep says a path that does not exist is missing Replay ab8d7ef6 failed on omnimarket dev 32b6f90 twice (loops 1c966a4a and f7c345be). Both times the model guessed the node path without the src/ prefix and grepped 'omnimarket/nodes/...' or 'omnimarket'. git grep answers a missing pathspec with exit 1, which the port reported as "no matches"; in loop f7c345be that happened eight times, so the model never learned the path was wrong and never read the contract its new test asserts on. view and ls already say a missing path is missing. grep now raises the same WorkspacePathError, which the loop shows as "error: <path> does not exist". Onex-Lane: code-edit-regress-2a21-mac Onex-Session: ead7bf3424ea48e49decfc434456da87 * fix(OMN-20291): a missing view, ls or grep path names the worktree paths that end with it Replay ab8d7ef6 on the code-edit PR head (loop 33cecc23) still spent 20 turns guessing 'omnimarket/nodes/node_navigation_history_reducer/...' in a src-layout repo after view and ls said the path was not a file or not a directory. A missing path now names up to three worktree paths that end with it, shortest first, e.g. "omnimarket/nodes is not a directory; did you mean: src/omnimarket/nodes?". A path that exists, or that nothing ends with, gets no hint. Onex-Lane: code-edit-regress-2a21-mac Onex-Session: ead7bf3424ea48e49decfc434456da87
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket: OMN-20291
Lab: hosts h201 and h202, model turns on the
.201dev lane (Qwen3.8-27B). The OMN-20291 comparison's ownrun2_<id>.shreplay scripts were run with this branch first onPYTHONPATH, twice per task. Results are in the table below. The comparison's original outputs were set aside and restored afterwards.Summary
The OMN-20291 comparison replayed 26 crush tasks through the delegated code-edit node. The tool_use rubric passed 18 node runs and 17 crush runs, and the node failed 8 tasks. Reading each failure's loop receipt and turn replies turned up four causes in the node itself. This PR fixes all four:
t6a1 grep path=/data/.../wt/58744096/omnimarket/srcwas refused withleaves the worktree. The model copied the path from the loop's own echo of the check command ($ env PYTHONPATH=/data/.../src ...).t3a7andt5a1: the view prints96| text, and the model copied the separator's blank into every line. In re-run 2 it did so on the first line only (' def umbrella_tickets(').t7a2re-sent an edit it had applied in turn 3.replace_in_files glob=src/omnimarket/nodes/*/contract.yamlwas refused withtargets over 200 files. The model fell back towrite /tmp/...and 117 single edits, which is the 8e1b5f72 failure.Two parts of the history change depend on the code that #3276 and #3270 brought to
dev. History turns are now structured, so the resume block from #3276 stores them as JSON.replace_in_filescounts as a file change for the read-pause streak.How the read-loop fix got here
Each step was driven by a lab re-run:
budget_exhaustedbefore.Both tasks still exceed the rubric's 80-tool-call budget. Crush finishes them in 8 and 5 turns. The remaining gap is prompt capacity:
onex delegatetakes the prompt as one argv word, which caps it at 120 KB. That is a separate omnibase_infra change, and the report describes it.Tests: RED, then GREEN
The focused tests are all in
tests/nodes/node_delegated_code_edit_orchestrator/test_handler_delegated_code_edit_orchestrator.py. Each group failed before its change:The resume tests from #3276 that asserted string history blocks now assert structured entries. The cut-not-dropped history test now builds
HistoryTurns.GREEN, focused only:
uv run pytest tests/nodes/node_delegated_code_edit_orchestrator/ tests/unit/delegated_code_edit tests/unit/cli/test_cli_code_edit.py tests/nodes/node_delegation_rubric_check_compute -qgave 504 passed.ruff format,ruff checkandmypy --stricton the node anddelegated_code_editare clean.pre-commitpassed on the changed files.ea3ee264 re-run 2's turn-3 replies, replayed offline against the base file, apply all nine edits with the file's indentation.
Lab re-runs
The code under test is
e793efaee. The PR head82534fca4is that code plusdev, merged in by the OCC bot, and the ticket contract. Each task ran twice through its ownrun2_<id>.sh. Loop ids are in brackets.replace_in_fileswith files lacking old_string), 7 / 394 s (a37e15a5)replace_in_filesruns now. Its remaining failures come from how the model uses it, and the report covers them.Report with the full 26-task table and every failure classified: knowledge-base-internal
reports/2026-10-03-code-edit-node-vs-crush-replay.md(knowledge-base-internal#986).Evidence-Ticket: OMN-20291
Evidence-Source: OCC#12497