Repository navigation
[Wave 4] Low/info — Module sweep: Config schema & public library API (part 4/4) #664
Description
Wave 4 · 16 finding(s) in 16 fix package(s). Fix these whenever a pull request touches this module ("clean the module you touch").
Findings
-
CR-A01-135 (code, Low) — model-merging.md presents DARE as pairing with TIES ('DARE-TIES'); ForgeLM has no DARE-TIES method, and its DARE has no sign election
severity Low · reachabilitydefault· intentcontract-violation· confidence likely · single reviewer · not reproduced (code trace)
Failure scenario. An operator sets method: dare expecting DARE-TIES behaviour and gets plain DARE with no sign-conflict resolution.
Where.docs/usermanuals/en/deployment/model-merging.md:27,docs/usermanuals/tr/deployment/model-merging.md:27,forgelm/config.py:186,forgelm/merging.py:432-456
Recommended fix. State that only plain DARE is implemented, or add a dare_ties method. -
CR-A01-136 (code, Low) — exit-codes manual says '${HF_TOKEN} set in YAML but env var missing' exits 1; ForgeLM does not expand it, dry-run exits 0 and the run continues with the literal string
severity Low · reachabilitydefault· intentcontract-violation· confidence likely · independently confirmed · reproduced with stubs
Failure scenario. A CI author follows the exit-code table and alarms on 1 for a missing token. The job either succeeds unauthenticated (public model) or fails with 2 at model load, so the alarm never fires.
Where.docs/usermanuals/en/reference/exit-codes.md:85,forgelm/config.py:1507-1513,forgelm/utils.py:47-54,docs/usermanuals/tr/reference/exit-codes.md:85
Recommended fix. Remove the row, or implement explicit ${VAR} expansion for secret fields that fails with ConfigError (exit 1) when the variable is unset. -
CR-A01-137 (code, Info) — load_config and _load_config_or_exit convert only an enumerated set of exceptions; UnicodeDecodeError, RecursionError and -W error DeprecationWarning escape as raw tracebacks with no JSON envelope
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN C33-CLI-ERROR-ENVELOPE — docs/roadmap/phase-16-trust-surface-hardening.md:499,507-508 (S7 open)
Failure scenario. A Windows-edited cp1252 config breaks a CI JSON parser: there is no {success:false} object and the log holds only a raw traceback.
Where.forgelm/config.py:2250-2254,forgelm/cli/_config_load.py:26-47(confirmed),forgelm/cli/subcommands/_purge.py:1438-1441(confirmed),forgelm/config.py:2259-2269
Recommended fix. Catch UnicodeDecodeError in load_config and raise ConfigError(...) from it. -
CR-A01-138 (code, Info) — dumps_strict sanitises only non-finite values: finite non-float64 numpy scalars, tensors and non-finite dict keys escape
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence likely · independently confirmed · reproduced end to end · already tracked: PARTIALLY-FIXED TRUST-15 — docs/roadmap/phase-16-trust-surface-hardening.md:9-11,339-343 (S2 done); CHANGELOG.md:91-101
Failure scenario. A future metric path hands np.float32 to the audit logger. The value is written as a string, so a consumer computing on the field silently gets a str, unlike float64 metrics.
Where.forgelm/_strict_json.py:53-56,forgelm/_strict_json.py:62-84,forgelm/_strict_json.py:87-95,forgelm/compliance.py:574-582(confirmed)
Recommended fix. For NumPy scalars, return value.item() after the finiteness check (and sanitise or str() float keys). -
CR-A01-139 (code, Info) — forgelm.version (stamped into compliance, model card and pipeline manifests) comes from distribution metadata, not the running package tree
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence likely · independently confirmed · reproduced end to end
Failure scenario. After a version bump in a checkout that is run without re-installing, or with a leftover dist-info from an older install, Annex IV manifests record the old forgelm_version. An auditor then reads provenance for a release that did not produce the artefact.
Where.forgelm/_version.py:24-29(confirmed),forgelm/compliance.py:24(confirmed),forgelm/compliance.py:2359,forgelm/model_card.py:279-338(confirmed)
Recommended fix. Either compare the tree's own version (a generated _version file or pyproject) with the metadata at import and log a mismatch warning, or record the module's file origin alongside the version in provenance records. -
CR-A01-140 (code, Info) — mix_ratio of large finite weights passes validation but overflows to inf on sum, sampling zero rows from every dataset
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. mix_ratio: [1e308, 1e308] with one extra dataset: config validates, sum = inf, _apply_mix_ratio returns datasets of length [0, 0].
Where.forgelm/config.py:828-843,forgelm/data.py:496-509,forgelm/data.py:521-529,forgelm/data.py:698-708
Recommended fix. In the validator, also require math.isfinite(sum(v)) (or normalise by max first). Correct the 'before anything is loaded' comment, or move the length check ahead of the primary load. -
CR-A01-141 (code, Info) — Refuted for torch/transformers/trl/peft/datasets/accelerate and the optional extras. ModuleNotFoundError escapes hasattr/getattr/star-import/getmembers only when a core dependency (requests or huggin…
severity Info · reachabilityundocumented· intentintended-and-acceptable· confidence likely · independently confirmed · reproduced end to end
Where.forgelm/__init__.py:301-313,forgelm/utils.py:10,forgelm/webhook.py:6,forgelm/_http.py:56
Recommended fix. Document the contract in library_api_reference.md under 'Lazy-import discipline': resolving a name imports its submodule, a missing core dependency surfaces as ModuleNotFoundError (also from hasattr and star-import), and feature detection should use api_version. Optionally add a parametrised subprocess test that blocks each heavy package and asserts every name resolves, to pin RC-0064. -
CR-A01-142 (code, Info) — Config-level warnings repeat once per ForgeConfig instantiation: 7 copies in a 3-stage pipeline run
severity Info · reachabilitydefault· intentintended-but-harmful· confidence likely · independently confirmed · reproduced end to end
Failure scenario. Operators and log-based alerting see repeated identical warnings and learn to ignore them. Cosmetic, but inconsistent with the dedupe rationale applied to the tier warning.
Where.forgelm/config.py:304-342,forgelm/config.py:1707-1748,forgelm/config.py:2233,forgelm/cli/_pipeline.py:970-1011
Recommended fix. Apply one dedupe policy to all config warnings within a pipeline run, or suppress validator warnings on the internal re-validation in merge_pipeline_stage_config. -
CR-A01-143 (code, Info) — Lazy-import section says import forgelm touches only importlib.metadata; the package eagerly imports forgelm.config (pydantic, yaml)
severity Info · reachabilitydefault· intentcontract-violation· confidence likely · single reviewer · reproduced end to end
Failure scenario. A minimal-footprint consumer reads the claim and is surprised by pydantic and yaml being required at import.
Where.docs/reference/library_api_reference.md:229,docs/reference/library_api_reference-tr.md:229,forgelm/__init__.py:13-15,forgelm/__init__.py:62
Recommended fix. Reword to 'no heavy ML dependency'. Name pydantic and yaml as the cheap eager imports. -
CR-A01-144 (code, Info) — Deployment manuals and post-training notebook teach reach-ins to modules the library API design marks Internal ('reach-in is unsupported')
severity Info · reachabilityundocumented· intentcontract-violation· confidence likely · independently confirmed · reproduced (plumbing only)
Failure scenario. An automation pipeline built on the manual's 'Programmatic merging' recipe breaks on a minor release that renames or removes merge_peft_adapters, which the design doc allows without notice.
Where.docs/design/library_api.md:122,docs/usermanuals/en/deployment/model-merging.md:128-145,docs/usermanuals/tr/deployment/model-merging.md:133,notebooks/post_training_workflow.ipynb:145
Recommended fix. Either promote merge_peft_adapters and inference.load_model/generate/generate_stream to Experimental via all and _STABILITY_TIERS, or add an 'Internal, unsupported, may change without notice' callout to model-merging.md (EN and TR), vram-fit-check.md and the notebook. -
CR-A01-145 (code, Info) — model-merging.md implies a DARE-TIES combination that does not exist
severity Info · reachabilitydefault· intentcontract-violation· confidence likely · independently confirmed · not reproduced (code trace)
Failure scenario. A user sets method: dare expecting DARE-TIES behaviour (sign-resolved) and gets plain DARE.
Where.docs/usermanuals/en/deployment/model-merging.md:27,docs/usermanuals/tr/deployment/model-merging.md:27,forgelm/config.py:186,forgelm/merging.py:431-451
Recommended fix. Reword to say that DARE-TIES is not offered and that mergekit provides it. -
CR-A01-146 (code, Info) — Deprecation start of evaluation.staging_ttl_days recorded inconsistently (v0.7.0 vs v0.5.5)
severity Info · reachabilitydefault· intentcontract-violation· confidence likely · independently confirmed · not reproduced (code trace)
Failure scenario. An auditor cannot use the shipped artefacts to establish that the removed field was deprecated for the required window.
Where.forgelm/config.py:1224-1226,docs/reference/configuration.md:268,docs/standards/release.md:109-111,docs/design/gdpr_erasure.md:79
Recommended fix. Correct whichever statement is wrong so the code comment and the reference doc name the same deprecation release. -
CR-A01-147 (code, Info) — baseline_loss allow_inf_nan=False (M4b) has no test in the five task files; the +inf case relies on a test in tests/test_trainer.py
severity Info · reachabilitydefault· intentintended-and-acceptable· confidence likely · independently confirmed · reproduced end to end
Failure scenario. A refactor drops allow_inf_nan from baseline_loss. The matrix and the other config tests still pass.baseline_loss: .infthen loads. The trainer demotes it to a warning and sets baseline_loss to None, so the configured regression-vs-baseline gate never fires and the run reports passed with no revert.
Where.forgelm/config.py:1207-1211,tests/test_config_non_finite_matrix.py:43-47,forgelm/trainer.py:826-829,forgelm/trainer.py:892-893
Recommended fix. Add("evaluation.baseline_loss", ".inf", "a +inf baseline disarms the regression check")to the matrix at tests/test_config_non_finite_matrix.py:46-47. Fix the trainer comment that calls the baseline check informational. -
CR-A01-148 (code, Info) — lora.task_type values other than CAUSAL_LM pass peft validation and silently train a CausalLM under the wrong PeftModel class, recording a wrong task_type and phantom modules_to_save
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence likely · independently confirmed · reproduced end to end
Failure scenario. An operator experimenting with an encoder-style config sets task_type: SEQ_CLS. The run completes with exit 0 and success:true. The produced adapter is labelled SEQ_CLS with a classifier/score modules_to_save that does not exist. It is registered in the model card and compliance bundle as a sequence-classification fine-tune, although the training was causal-LM SFT. It is later loaded by a tool that trusts adapter_config.json.
Where.forgelm/config.py:386-388,forgelm/model.py:534,forgelm/model.py:609,forgelm/inference.py:111-113
Recommended fix. Constrain task_type to Literal['CAUSAL_LM'], since every ForgeLM trainer (SFT/DPO/SimPO/KTO/ORPO/GRPO) is causal-LM only. Alternatively, validate against the supported subset and reject the rest at schema time with exit 1. Add a test that every non-CAUSAL_LM value is rejected. -
CR-A01-149 (code, Info) — pipeline.output_dir is never checked against stage dirs; nested inside a stage's final_model, that stage's auto-revert deletes the pipeline audit log, state and manifest mid-run, and verify-audit the…
severity Info · reachabilityundocumented· intentintended-but-harmful· confidence likely · independently confirmed · reproduced end to end
Failure scenario. Operator points pipeline.output_dir under a stage's final_model, for example to keep the index next to the deliverable. A failed gate in that stage erases the pipeline's Art. 12 records for the start of the run, and the verifiers report the remaining log as intact.
Where.forgelm/config.py:2110-2119,forgelm/cli/_pipeline.py:1416-1417,forgelm/compliance.py:542-544,forgelm/compliance.py:607-608
Recommended fix. Include pipeline.output_dir in the pre-flight scan. Refuse it inside any stage's output_dir/<final_model_dir>, or inside any stage output_dir at all, and either enforce 'Distinct' or reword the field description to match the guide. -
CR-A01-150 (code, Info) — neftune_noise_alpha documentation and prompts are SFT-centric and misdescribe the mechanism
severity Info · reachabilitydefault· intentintended-but-harmful· confidence likely · single reviewer · not reproduced (code trace)
Failure scenario. Operators enable NEFTune on non-SFT trainers on the strength of 'improves training quality' wording.
Where.forgelm/config.py:582-585,forgelm/wizard/_collectors.py:605-609,docs/usermanuals/en/training/long-context.md:107-115,tests/test_long_context.py:46-57
Recommended fix. State 'uniform noise, SFT-oriented' in the field description, bound the value, and add a test that exercises each trainer's config build with the field set.
Done when
- Every finding above is fixed or closed with a reason (tick it here).
- Code fixes carry a test; doc fixes update the Turkish mirror in the same PR.
Found by the October 2026 ForgeLM code and documentation review against commit cab2947. Code links point at that commit; line numbers may have moved since. Finding IDs (CR-…, DOC-…, TECH-…) are stable references for this backlog.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
cemililik commentedon Oct 9, 2026
Progress on
development— verified 2026-10-09 at08f2426.Fixed (ticked in the list above):
CR-A01-147— a schema-derived test now feeds NaN and ±inf to every scalar float field,evaluation.baseline_lossincluded (08f2426)Partly fixed (still unticked):
CR-A01-138— finite NumPy scalars are written as JSON numbers now (08f2426), but a torch scalar tensor and a NaN dict key still fail the strict writerEverything else in this issue is unchanged.
cemililik commentedon Oct 23, 2026
Note from #1058:
forgelm purge --check-policynow reads its--configthrough_load_retention_policy(forgelm/cli/_config_load.py). That function reads and parses the YAML itself before it decides whether to callload_config, so a fix for CR-A01-137 has to cover that read as well. Today, a retention-only file with invalid UTF-8 still raises a rawUnicodeDecodeErrorthere, just asload_configdoes for a full config.