Skip to content

fix: read the model-directory recheck's relpath with '/' on Windows - #1065

Merged
cemililik merged 3 commits into
developmentfrom
fix/windows-final-model-dir-recheck
Oct 23, 2026
Merged

cemililik merged 3 commits into
developmentfrom
fix/windows-final-model-dir-recheck

Conversation

@cemililik

@cemililik cemililik commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fix a Windows regression that stopped the v0.11.1 publish run, and bring main's release merge commit back into development. Merge with "Create a merge commit" so the sync keeps its second parent.

Related issues

None filed. #962 tracks the gap that let this through: tests run on Windows only when a release tag is pushed.

What happened

The v0.11.1 tag's publish run built the wheel and passed every Ubuntu and macOS combination, but all four Windows combinations failed on the same four tests in tests/test_eu_ai_act.py::TestFinalizedModelIntegrity. Because of that, the publish job was skipped and nothing reached PyPI.

The four tests are the ones that use a nested training.final_model_dir: models/final. The flow that failed:

  • _check_model_destination rechecks the destination before saving, finalising or reverting. It computes the relative path with os.path.relpath.
  • On Windows that call answers models\final. _validate_layout takes the config's / form and rejects any backslash.
  • So on Windows a run with a nested model directory would fail after training, at finalisation.

The rule arrived in this release cycle, so no published version has the bug.

Changes

  • forgelm/_artifact_paths.py. The recheck now reads the relative path with / separators (.replace("\\", "/")). On POSIX a backslash is part of a directory name, and such a path still fails, because the existing resolve() comparison right after the check rejects it. A comment records both points.
  • tests/test_config.py. Two regression tests that run on Linux:
    • test_runtime_recheck_accepts_a_windows_relpath makes relpath answer with backslashes, as it does on Windows, and checks that the final and staging destinations pass. It fails without the fix.
    • test_runtime_recheck_rejects_a_backslash_in_a_posix_name checks that models\final as one POSIX name is still refused. It fails if the resolve() comparison is removed. It is skipped on Windows, where a backslash is a separator.
  • CHANGELOG.md [0.11.1]. The existing entry already promised the recheck for "nested custom model directories". I amended that entry instead of adding a Fixed line, because no shipped version has the bug. The release record's test count moves from 6769 to 6771.
  • Merge of main. It brings back 6e050be, the Release v0.11.1 — Fail Closed #1064 merge commit, and changes no file.

Next steps (owner-approved)

  1. Merge this pull request.
  2. Open the second release pull request (development → main).
  3. After that merges, delete the unpublished v0.11.1 tag and recreate it, GPG-signed, on the new merge commit.

Type

  • Bug fix

Testing

  • The full local gauntlet passes on this branch: 6,673 passed, 98 skipped (6,771 collected); GAUNTLET_RC=0.
  • tests/test_config.py, tests/test_eu_ai_act.py and tests/test_trainer.py pass (551 tests).
  • Each new test fails against its mutant: no separator normalisation in one case, no resolve() comparison in the other.
  • Windows itself runs only in the publish matrix (Tests run on Windows and macOS only when a release tag is pushed #962); the re-tag runs it again.

Checklist

  • Tests added for the changed code
  • CHANGELOG updated ([0.11.1], which has not been published yet)
  • This pull request links no issue

🤖 Generated with Claude Code

Summary by Sourcery

Fix cross-platform model-directory validation so nested custom destinations pass runtime rechecks on Windows without weakening POSIX path safety.

Bug Fixes:

  • Fix Windows validation of nested custom model directories during runtime artifact-destination rechecks.

Documentation:

  • Update release and roadmap records to reflect the additional regression tests and Windows compatibility coverage.

Tests:

  • Add regression coverage for Windows-style relative paths while preserving rejection of literal backslashes in POSIX directory names.

Chores:

  • Restore the required release merge commit from main without changing project files.

Play the walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Model destination checks now handle Windows-style path separators correctly, helping ensure rejected final or staged models are handled at the intended destination.
  • Documentation
    • Updated the v0.11.1 release notes to report 6,771 tests.

cemililik and others added 3 commits October 23, 2026 21:44
Release v0.11.1 — Fail Closed
The v0.11.1 publish matrix failed on every Windows combination (nothing
was published): os.path.relpath answers 'models\final' there, and the
layout check, which takes the config's '/' form, rejected it, so a run
with a nested training.final_model_dir would fail after training, at
finalisation. The recheck now converts the separator; on POSIX a
backslash is part of a name and that path still fails the resolve()
comparison that follows.

Two Linux-runnable regression tests, one per mutant (no conversion; no
resolve comparison). The [0.11.1] CHANGELOG entry that promised the
recheck for nested directories now says it holds on Windows too, and the
release record's test count moves from 6769 to 6771.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bring back the merge commit of the first v0.11.1 release pull request so the next one starts up to date.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Architecture

Architecture diagram for HodeTech/ForgeLM at 49f9690

Play the walkthrough


Data flow

No data-flow sequence changed in this PR.


Tip

Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion
  • Set github.description: false in .github/pr-lens.yml to stop PR Lens adding buttons to your PR descriptions

Thanks for using PR Lens! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out on X, Bluesky, Mastodon, Reddit or LinkedIn

@sourcery-ai

sourcery-ai Bot commented Oct 23, 2026

Copy link
Copy Markdown

Sorry @cemililik, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 21 hours and 48 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 23, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes a Windows-only failure in runtime model-destination rechecks by translating platform backslashes to the config’s forward-slash layout format, while preserving resolve-based protection against POSIX path-name ambiguity. Adds focused regression tests, updates v0.11.1 release metadata, and restores the main merge history.

Sequence diagram for cross-platform model destination recheck

sequenceDiagram
    participant Runtime
    participant ArtifactPaths
    participant OS
    participant LayoutValidator
    participant PathResolver

    Runtime->>ArtifactPaths: _check_model_destination(output_dir, final_path, config)
    ArtifactPaths->>OS: os.path.relpath(final_path, output_dir)
    OS-->>ArtifactPaths: platform-relative path
    ArtifactPaths->>ArtifactPaths: replace("\\", "/")
    ArtifactPaths->>LayoutValidator: _validate_layout(output_dir, relative, benchmark_output_dir)
    LayoutValidator-->>ArtifactPaths: expected destination
    ArtifactPaths->>PathResolver: resolve comparison
    PathResolver-->>ArtifactPaths: actual destination matches or rejects
Loading

Flow diagram for Windows nested model-directory validation

flowchart TD
    A[Windows relpath: models\\final] --> B[Normalize separators: models/final]
    B --> C[_validate_layout accepts config path]
    C --> D[resolve comparison checks actual destination]
    D --> E[Runtime recheck passes]
    F[POSIX name containing backslash] --> G[resolve comparison detects mismatch]
    G --> H[Runtime recheck rejects path]
Loading

File-Level Changes

Change Details Files
Normalize Windows relative paths before validating model-directory layout while retaining the real-path safety check.
  • Convert backslashes returned by os.path.relpath to forward slashes for layout validation.
  • Keep the resolve comparison so POSIX backslashes cannot be interpreted as separators and bypass validation.
  • Document the platform-separator behavior and safety rationale.
forgelm/_artifact_paths.py
Add regression coverage for cross-platform relative-path handling and POSIX path safety.
  • Mock a Windows-style relpath and verify final and staging destinations pass.
  • Verify a literal backslash in a POSIX directory name is rejected.
  • Skip the POSIX-specific case on Windows.
tests/test_config.py
Update release documentation and test-count metadata for the two regression tests.
  • Clarify Windows support in the v0.11.1 changelog entry.
  • Update v0.11.1 test totals from 6769 to 6771 across roadmap documentation.
CHANGELOG.md
docs/roadmap-tr.md
docs/roadmap.md
docs/roadmap/releases.md
Restore the release merge history by merging main back into development without additional file changes.
  • Reintroduce the prior release merge commit and preserve its second parent.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 7fb80e45-910e-4696-a0d4-9ab5dd768acd
📥 Commits

Reviewing files that changed from the base of the PR and between 9049969 and 49f9690.

📒 Files selected for processing: 6
  • CHANGELOG.md
  • docs/roadmap-tr.md
  • docs/roadmap.md
  • docs/roadmap/releases.md
  • forgelm/_artifact_paths.py
  • tests/test_config.py

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.

📝 Walkthrough

The destination recheck now normalizes Windows path separators before validating model destinations. Tests cover Windows-style relative paths and literal backslashes on POSIX. The v0.11.1 release entries update the test count to 6,771.

Changes: Model Destination Recheck

Layer / File(s) Summary
Normalize destination separators
forgelm/_artifact_paths.py, tests/test_config.py, CHANGELOG.md
The destination check converts backslashes to forward slashes before layout validation. Tests cover Windows-style paths and POSIX literal backslashes. The changelog describes the deletion recheck behavior.

Release Test Count

Layer / File(s) Summary
Update v0.11.1 test count
docs/roadmap/releases.md, docs/roadmap.md, docs/roadmap-tr.md
The release entries update the test count from 6,769 to 6,771. The module and CI-guard counts remain unchanged.

Priority: ⬆️ High

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

Merge Risk: ⚪ Minimal · up to 49f96

The change appears ready to merge after normal checks. Windows execution remains to be confirmed by the publish matrix.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (4 skipped: 4… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main Windows path-separator fix for model-directory rechecks.
Description check Passed The description is complete and relevant. It explains the regression, implementation, tests, release updates, merge requirement, and testing status. The reference to issue #962 while declaring no link…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description is complete and relevant. It explains the regression, implementation, tests, release updates, merge requirement, and testing status. The reference to issue #962 while declaring no linked issue is a minor inconsistency but does not prevent approval.

Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (4 skipped: 4 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cemililik
cemililik merged commit 8c483eb into development Oct 23, 2026
17 checks passed
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.

1 participant