Skip to content

feat(export): write the SHA-256 sidecar verify-gguf relies on, and document the converter requirement - #998

Merged
cemililik merged 6 commits into
developmentfrom
consolidated/gguf
Oct 18, 2026
Merged

cemililik merged 6 commits into
developmentfrom
consolidated/gguf

Conversation

@cemililik

@cemililik cemililik commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

forgelm export now writes the SHA-256 sidecar that forgelm verify-gguf and the documentation already assumed, and the GGUF documentation describes what really happens. Two earlier pull requests combined into one (#982 and #995, which will be closed as superseded); the bot findings on #982 are folded in.

Related issues

Refs #84, #85, #86 (docs), #83, #113. Making verify-gguf stricter than "magic header + optional sidecar", and searching the locations real llama-cpp-python wheels use for the converter, are separate changes and stay open. The site strings that mention the sidecar are in a later pull request.

Changes

Sidecar (was #982)

  • forgelm/export.py: after the GGUF is written and hashed, <output>.sha256 is written in sha256sum format (<digest> *<name>) through a temporary file and os.replace. A write failure returns success=False (runtime error, exit 2) naming the GGUF path. For a K-quant request the file written is the intermediate .f16.gguf and the sidecar belongs to it. The model_integrity.json update failure is now a WARNING, not DEBUG.
  • The sidecar detects corruption and accidental change; it is not tamper evidence, because whoever can replace the GGUF can replace the sidecar next to it. The docs say so.
  • docs/usermanuals/{en,tr}/deployment/{gguf-export,verify-gguf}.md and docs/reference/verify_gguf_subcommand{,-tr}.md: real output, the K-quant two-step flow, the real exported_artifacts JSON, what verify-gguf checks and what it cannot, and the --adapter pitfall. Review findings applied: the intermediate file is named by replacing .gguf with .f16.gguf; the manifest entry is best effort.

Converter script (was #995)

  • pip install 'forgelm[export]' does not provide convert_hf_to_gguf.py: no released llama-cpp-python wheel puts it where ForgeLM searches (0.2.90 installs it under bin/, 0.3.x does not ship it). The installation page, CLI reference, usage and quickstart guides, the notebook, pyproject.toml comment and export.py docstring now say to point FORGELM_GGUF_CONVERTER at the script in a llama.cpp checkout; the upstream repository location, requirements path and imports were checked.
  • The not-found error message names FORGELM_GGUF_CONVERTER and a llama.cpp checkout instead of advising a reinstall.

Type

  • Feature (sidecar)
  • Documentation

Testing

  • tests/test_export.py: sidecar format and content, sha256sum -c and verify-gguf accept it, atomic write and cleanup, K-quant sidecar, failure path, plus the new converter hint test (fails against the old message).
  • The full CLAUDE.md gauntlet from a clean worktree of this branch: exit 0.

Checklist

  • English and Turkish mirrors updated together (Turkish wording needs the owner's review)
  • CHANGELOG entries under [Unreleased]
  • Tests added

🤖 Generated with Claude Code

Summary by Sourcery

Add reliable SHA-256 sidecars to GGUF export and align converter requirements, verification behavior, and user documentation with the implemented workflow.

New Features:

  • Write SHA-256 sidecar files for exported GGUF artifacts, including intermediate files produced for K-quant requests.
  • Fail exports when the required sidecar cannot be written and elevate integrity-manifest update failures to warnings.

Bug Fixes:

  • Correct GGUF export and verification documentation to reflect actual outputs, checks, limitations, K-quant workflow, and adapter usage.
  • Correct converter setup guidance and error messaging to require a llama.cpp checkout through FORGELM_GGUF_CONVERTER.

Enhancements:

  • Clarify that sidecars detect accidental corruption but do not provide tamper evidence.
  • Document the actual exported_artifacts manifest structure and verification behavior in English and Turkish documentation.

Documentation:

  • Update installation, CLI, usage, quickstart, notebook, and GGUF deployment documentation with the llama.cpp converter prerequisite and sidecar workflow.

Tests:

  • Add coverage for sidecar format, verification, atomic cleanup, K-quant output, write failures, manifest warnings, and converter guidance.

Chores:

  • Update the unreleased changelog and related export comments and docstrings.

cemililik and others added 5 commits October 18, 2026 10:02
…mentation rely on

`forgelm export` computed the digest of the GGUF but never wrote `<output>.sha256`; the only writer in the package
was the checkpoint-tarball helper. `forgelm verify-gguf`, the user manual and the GGUF reference all describe the
sidecar as something the exporter produces, so the sidecar check had nothing to compare against unless the operator
created the file by hand.

The exporter now writes `<output>.sha256` in `sha256sum` binary-mode format (`<hex> *<name>`) through a temporary name
and a rename. A sidecar that cannot be written fails the export (exit 2, `error_kind="runtime"`) rather than leaving a
GGUF the documentation says is covered; the digest is still reported. For a K-quant request the file written is the
intermediate `*.f16.gguf`, so the sidecar belongs to that file. A `model_integrity.json` that cannot be updated is now
logged as a warning instead of at debug level.

The sidecar detects corruption and accidental change; it is not tamper evidence, and the pages now say so. The same
change rewrites the parts of the GGUF pages that described things the code does not do: the invented manifest and
`verify-gguf` output (vocabulary and tokenizer checks that do not exist), K-quants shown as one-step, "always merges
LoRA", and a clean `verify-gguf` exit presented as more than it proves. English and Turkish.

Refs #83, #84, #85

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…the export extra

forgelm export runs llama.cpp's convert_hf_to_gguf.py with ForgeLM's own Python. The installation page, the export extra's
comment in pyproject.toml, the module docstring, the usage and quickstart guides and the post-training notebook said it was
llama-cpp-python's "bundled" script, and the error hint advised `pip install 'llama-cpp-python>=0.2.90'`. No released wheel
puts the script where ForgeLM searches (0.2.90 installs it under bin/, 0.3.x does not ship it), so a plain install ends with
"convert_hf_to_gguf.py not found inside the llama-cpp-python installation" (exit 2) unless FORGELM_GGUF_CONVERTER points at
the script in a llama.cpp checkout. The upstream script imports sibling modules (conversion, gguf), which is why the
checkout's copy has to be used; the upstream repository and the requirements path were checked.

The pages now say so, with the two commands that make it work; the error message names FORGELM_GGUF_CONVERTER and a
llama.cpp checkout instead of a reinstall, and a test pins that. Searching the locations real wheels use, or bundling the
script, are code changes and stay open.

Refs #113, #83

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…est entry is best effort

Review findings on the export page: the K-quant intermediate is the output name with its .gguf suffix replaced by .f16.gguf
(model.gguf becomes model.f16.gguf), not <output>.f16.gguf appended; and the exported_artifacts entry is best effort, because
_update_integrity_manifest logs a warning and the export succeeds when model_integrity.json is not valid JSON or cannot be
written. English and Turkish.

Refs #84

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts:
#	CHANGELOG.md
@sourcery-ai

sourcery-ai Bot commented Oct 18, 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 12 hours and 24 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR makes GGUF export produce the SHA-256 sidecar expected by verification, handling atomic writes, K-quant intermediates, and failures; it also rewrites English and Turkish guidance to reflect actual verification/export behavior and documents the required llama.cpp converter setup.

Sequence diagram for GGUF export with SHA-256 sidecar

sequenceDiagram
    participant User
    participant Export as forgelm_export
    participant Converter as convert_hf_to_gguf.py
    participant Filesystem
    participant Manifest as model_integrity.json

    User->>Export: export_model()
    Export->>Converter: convert_hf_to_gguf.py
    Converter->>Filesystem: write GGUF
    Export->>Export: _sha256_file()
    Export->>Filesystem: _write_sha256_sidecar()
    Filesystem-->>Export: atomic os.replace()
    opt K-quant request
        Export-->>User: intermediate .f16.gguf and .f16.gguf.sha256
        Export-->>User: followup_command for llama-quantize
    end
    opt integrity manifest exists
        Export->>Manifest: update exported_artifacts
        Manifest-->>Export: warning on update failure
    end
    Export-->>User: ExportResult success
Loading

Sequence diagram for GGUF verification with optional checks

sequenceDiagram
    participant User
    participant Verify as forgelm_verify_gguf
    participant GGUF
    participant Sidecar
    participant Metadata as gguf_package

    User->>Verify: verify-gguf path
    Verify->>GGUF: check GGUF magic
    opt gguf package installed
        Verify->>Metadata: parse metadata
        Metadata-->>Verify: metadata result
    end
    opt path.sha256 exists
        Verify->>Sidecar: read digest
        Verify->>GGUF: recompute SHA-256
        Sidecar-->>Verify: expected digest
        Verify-->>User: sidecar match or mismatch
    end
    Verify-->>User: result proves only checks that ran
Loading

Flow diagram for GGUF export converter setup

flowchart TD
    A["Install forgelm[export]"] --> B[Clone llama.cpp checkout]
    B --> C[Set FORGELM_GGUF_CONVERTER]
    C --> D[forgelm export]
    D --> E[convert_hf_to_gguf.py]
    E --> F[GGUF output]
    D --> G{K-quant requested?}
    G -->|No| H[Write output.sha256]
    G -->|Yes| I[Write intermediate .f16.gguf.sha256]
    I --> J[Run llama-quantize manually]
    J --> K[Create quantized-file.sha256]
Loading

File-Level Changes

Change Details Files
Add atomic SHA-256 sidecar generation to GGUF export, including K-quant intermediate-output handling and explicit failure reporting.
  • Compute the exported artifact digest and write <actual-output>.sha256 in sha256sum format via temporary-file replacement.
  • Fail the export with a runtime error if the sidecar cannot be written, while retaining best-effort integrity-manifest updates at warning level.
  • Cover sidecar format, verifier compatibility, corruption detection, cleanup, K-quant behavior, and failure paths with tests.
forgelm/export.py
tests/test_export.py
CHANGELOG.md
Align GGUF export and verification documentation with the implemented behavior and its limitations.
  • Document real verifier checks, exit semantics, optional metadata parsing, sidecar limitations, and the --adapter requirement.
  • Describe K-quant exports as an intermediate .f16.gguf plus a manual llama-quantize step, including where sidecars belong.
  • Replace the previous manifest and fabricated verification examples with actual output and exported_artifacts structures in English and Turkish documentation.
docs/usermanuals/en/deployment/gguf-export.md
docs/usermanuals/tr/deployment/gguf-export.md
docs/usermanuals/en/deployment/verify-gguf.md
docs/usermanuals/tr/deployment/verify-gguf.md
docs/reference/verify_gguf_subcommand.md
docs/reference/verify_gguf_subcommand-tr.md
forgelm/verify/_gguf.py
CHANGELOG.md
Correct converter installation guidance and error messaging to require an explicit llama.cpp converter path.
  • Update converter docstrings, project metadata comments, CLI references, installation and usage guides, quickstarts, and notebook instructions.
  • Tell users to clone llama.cpp and set FORGELM_GGUF_CONVERTER because released llama-cpp-python wheels do not provide the script in the searched location.
  • Replace the reinstall-oriented not-found hint and test the actionable environment-variable guidance.
forgelm/export.py
pyproject.toml
docs/usermanuals/en/getting-started/installation.md
docs/usermanuals/tr/getting-started/installation.md
docs/usermanuals/en/reference/cli.md
docs/usermanuals/tr/reference/cli.md
docs/guides/quickstart.md
docs/guides/quickstart-tr.md
docs/reference/usage.md
docs/reference/usage-tr.md
notebooks/post_training_workflow.ipynb
tests/test_export.py
CHANGELOG.md

Possibly linked issues

  • #unknown: The PR implements the issue’s core fix by writing a SHA-256 sidecar for exported GGUFs and testing that verify-gguf detects changes.
  • #CR-A09-006: The PR replaces the invented vocabulary and tokenizer checks with real verifier output and explicitly states those comparisons are not performed.

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 18, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 21 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available. Your 50 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 932455c3-a2c9-4b4a-bbe1-7768f996a2e4
📥 Commits

Reviewing files that changed from the base of the PR and between 675c3e3 and 04d5ae4.

📒 Files selected for processing: 20
  • CHANGELOG.md
  • docs/guides/quickstart-tr.md
  • docs/guides/quickstart.md
  • docs/reference/usage-tr.md
  • docs/reference/usage.md
  • docs/reference/verify_gguf_subcommand-tr.md
  • docs/reference/verify_gguf_subcommand.md
  • docs/usermanuals/en/deployment/gguf-export.md
  • docs/usermanuals/en/deployment/verify-gguf.md
  • docs/usermanuals/en/getting-started/installation.md
  • docs/usermanuals/en/reference/cli.md
  • docs/usermanuals/tr/deployment/gguf-export.md
  • docs/usermanuals/tr/deployment/verify-gguf.md
  • docs/usermanuals/tr/getting-started/installation.md
  • docs/usermanuals/tr/reference/cli.md
  • forgelm/export.py
  • forgelm/verify/_gguf.py
  • notebooks/post_training_workflow.ipynb
  • pyproject.toml
  • tests/test_export.py
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

# Conflicts:
#	CHANGELOG.md
@cemililik
cemililik merged commit 48c7582 into development Oct 18, 2026
9 of 10 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