Skip to content

fix(optimizer): skip edits whose target overlaps a protected region - #373

Merged
Yifan Yang (Yif-Yang) merged 2 commits into
microsoft:mainfrom
Shizoqua:fix/protected-region-overlap
Nov 7, 2026
Merged

Yifan Yang (Yif-Yang) merged 2 commits into
microsoft:mainfrom
Shizoqua:fix/protected-region-overlap

Conversation

@Shizoqua

@Shizoqua Lanre Shittu (Shizoqua) commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #372.

A step-level replace or delete edit whose target starts in editable skill text and runs into a protected region's start marker was applied. That removed <!-- SLOW_UPDATE_START --> (or <!-- APPENDIX_START -->) and left the protected content in the editable body. An insert_after with such a target wrote into the protected region. These edits are now skipped with skipped_protected_region, the same as edits that target text inside the region.

User impact: without this fix, a training run can silently lose its slow-update or appendix guidance: the marker disappears, the protected text becomes editable body text, and later steps can rewrite or duplicate it.

Proof: the regression test fails on upstream eb959c3 and passes with this change.

Root cause

_is_in_protected_region() in skillopt/optimizer/skill.py only tested whether the target's start index was inside a region:

if start_idx <= target_idx < region_end:

A target that begins before the start marker and extends into it fails that test. _apply_edit_with_report() then runs skill.replace(target, ..., 1) across the marker.

Changes

  • _is_in_protected_region() now treats a target as protected when its span [target_idx, target_idx + len(target)) overlaps [start_idx, region_end). A target that ends exactly where the region starts does not overlap and still applies.
  • _apply_edit_with_report() is the only caller, so this covers the trainer path (apply_patch_with_report) and the exported apply_edit / apply_patch.
  • Regression test in tests/test_skill_aware_reflection.py next to the existing protected-region tests, covering both regions and all three targeted ops, plus an adjacent edit that must still apply. It is also registered in the file's standalone main() runner.
  • CHANGELOG entry under Unreleased / Fixed.

Reproduction

from skillopt.optimizer.skill import apply_patch_with_report
from skillopt.optimizer.slow_update import (
    has_slow_update_field, inject_empty_slow_update_field, replace_slow_update_field,
)

skill = replace_slow_update_field(
    inject_empty_slow_update_field("# QA Skill\n\n## Rules\n- Answer briefly."),
    "Prefer exact spans.",
)
edit = {"op": "delete", "target": "- Answer briefly.\n\n<!-- SLOW_UPDATE_START -->"}
new, report = apply_patch_with_report(skill, {"edits": [edit]})
print(report[0]["status"], has_slow_update_field(new))

Before: applied_delete False, and the result is '# QA Skill\n\n## Rules\n\nPrefer exact spans.\n<!-- SLOW_UPDATE_END -->\n'.

After: skipped_protected_region True, and the skill is unchanged.

Testing

  • python -m pytest tests/test_skill_aware_reflection.py -q: the new test fails on upstream eb959c3 with AssertionError: delete across <!-- SLOW_UPDATE_START --> must not change the skill, and passes with the fix.
  • python tests/test_skill_aware_reflection.py: 7/7 passed.
  • python -m pytest tests/test_skill_aware_reflection.py tests/test_semantic_density.py tests/test_sleep_engine.py -q: 158 passed, 1 skipped.
  • python -m pytest -q: 2034 passed, 12 skipped, 4 xfailed.
  • python -m mkdocs build --strict: passed.
  • python -m ruff check on the changed files: no new findings. The 6 import-order findings are on lines that are unchanged from main.

Risk and compatibility

Only targets that overlap a protected region change behavior, and those previously broke the region. Edits fully outside the regions, append, and insert_after fallbacks are unchanged; the existing byte-identical and coexistence tests still pass. No backend, role, config key, file format or CLI change.

_is_in_protected_region only checked where an edit target starts. A
replace or delete target that began in editable text and ran into
<!-- SLOW_UPDATE_START --> or <!-- APPENDIX_START --> passed the check,
so applying it removed the start marker and left the protected content
in the editable body with an orphaned end marker. An insert_after with
such a target wrote into the protected region.

Treat a target as protected when its span overlaps the region, markers
included. Targets that only touch text before the region still apply.
Keep both CHANGELOG entries; no other change.
@Yif-Yang
Yifan Yang (Yif-Yang) merged commit 69a6ece into microsoft:main Nov 7, 2026
1 check passed
@Yif-Yang

Copy link
Copy Markdown
Contributor

Merged, thank you. _is_in_protected_region now rejects any target that overlaps a protected region, not only one that starts inside it, so delete/replace/insert_after can no longer remove a SLOW_UPDATE/APPENDIX start marker or write inside the region. I reproduced #372 on main and confirmed all three ops are now skipped with the skill unchanged. The new test fails on main and passes here, and the full suite passes. Closes #372.

Note: your branch and #375 each added an entry at the same place in CHANGELOG.md. After #375 merged, I pushed one maintainer merge commit to your branch that keeps both entries and changes nothing else, then merged.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Step-level edits whose target spans into a protected region remove the region's start marker

2 participants