Repository navigation
[Wave 3] Medium — Module sweep: CLI framework: parser, dispatch, exit-code contract, logging #542
Description
Wave 3 · 16 finding(s) in 15 fix package(s). Fix these whenever a pull request touches this module ("clean the module you touch").
Findings
-
CR-A05-007 (code, Medium) — Top-level --output DIR (documented as the --compliance-export directory, default ./compliance) is parsed but never read
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An operator expects artefacts in B and archives an empty or stale directory.
Where.forgelm/cli/_parser.py:1454-1460(--output declaration; --compliance-export at 1443-1453 takes a required OUTPUT_DIR),forgelm/cli/_no_train_modes.py:281-283(only args.compliance_export passed),forgelm/cli/_parser.py:1452-1458,forgelm/cli/_no_train_modes.py:281-283(confirmed)
Recommended fix. Remove the flag, or wire it and reject a conflicting combination. -
CR-A05-008 (code, Medium) — Chat --temperature 0 passes CLI validation, then every generation fails because sampling always uses do_sample=True
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN CLI-17 — docs/roadmap/phase-16-trust-surface-hardening.md:480,500-501 (S7 open; unit id inferred from commit-2 ordering)
Failure scenario. Operator wanting deterministic output passes --temperature 0 and gets an error on every turn (exit 0 at EOF).
Where.forgelm/cli/_argparse_types.py:60-74,forgelm/cli/_parser.py:48-53,forgelm/inference.py:248-249(confirmed),forgelm/inference.py:306-307(confirmed)
Recommended fix. Map temperature<=0 to do_sample=False in generate/generate_stream, or make the CLI type exclusive of 0 and align help/docs. -
↳ same root cause: DOC-BHELP-005 (docs, Medium) — forgelm: wrong detail — 'Sampling temperature in [0.0, 2.0] (default: 0.7).'
severity Medium · already tracked: KNOWN-OPEN CLI-17/CLI-18 (inferred) — docs/roadmap/phase-16-trust-surface-hardening.md:500
Where.forgelm/cli/_parser.py:48-53(--temperature) · type: wrong detail
The document says. 'Sampling temperature in [0.0, 2.0] (default: 0.7).'
What the code does. The CLI accepts 0.0, but every generation then fails. Verified on env/tiny-qwen: generate(temperature=0.0) raises ValueError 'temperature(=0.0) has to be a strictly positive float'. The REPL swallows it as '[Generation error]' on every turn. In-session /temperature requires 0.0 < t <= 2.0.
Code references.forgelm/cli/_argparse_types.py:78-92,forgelm/inference.py:219-249,forgelm/chat.py:204,262-285
Proposed correction. Reject 0.0 at parse time (range (0.0, 2.0]) or map 0 to do_sample=False. Update the help to match. -
CR-A05-009 (code, Medium) — Top-level --offline is accepted with every subcommand but never applied; quickstart forwards it to a chat child that ignores it
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN CLI-04 — docs/roadmap/phase-16-trust-surface-hardening.md:482-489,509-510 (S7 open)
Failure scenario. An operator on a policy-offline (but connected) host runsforgelm --offline safety-eval --model org/model --default-probes. The model and the Llama Guard classifier are fetched from the Hub, so the operator does not get the local-only evaluation the flag implies. On a truly air-gapped host, the run instead fails on a network timeout rather than a clear 'not cached' error.
Where.forgelm/cli/_parser.py:1368-1372,forgelm/cli/_dispatch.py:221-225,forgelm/cli/_dispatch.py:243(confirmed),forgelm/cli/_config_load.py:50-56
Recommended fix. Call_apply_offline_flag-equivalent env setting before_dispatch_subcommandwhen args.offline is set, or reject top-level --offline with subcommands that ignore it. Remove the dead forwarding in quickstart or make chat honour it. -
CR-A05-010 (code, Medium) — Ingest --chunk-tokens 0 is accepted and silently falls back to character chunking, although --help says 0 is rejected
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. A script computes--chunk-tokens $BUDGETand the budget evaluates to 0. Ingest succeeds with 2048-character chunks that can exceed the model's max_length, so training silently truncates. The run's notes claim token mode was used.
Where.forgelm/cli/_parser.py:282-293,forgelm/cli/_parser.py:291,forgelm/cli/_parser.py:213,forgelm/cli/_parser.py:225
Recommended fix. Type --chunk-tokens with _positive_int (and --chunk-size with _positive_int, --overlap with _non_negative_int). Change ingestion.py:2092 tochunk_tokens is not None. Reject or log a non-zero --overlap under paragraph. -
CR-A05-011 (code, Medium) — --resume is silently ignored on a pipeline: config; the run restarts every stage and exits 0
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. 'forgelm --config minimal_3_stage.yaml --resume' starts every stage from scratch with no warning, retraining completed stages and overwriting their outputs.
Where.forgelm/cli/_dispatch.py:253-260(the asymmetric single-stage guard),forgelm/cli/_pipeline.py:1738-1754(the tuple and its loop; 1725-1737 is the explanatory comment),forgelm/cli/_pipeline.py:1738-1754,forgelm/cli/_parser.py:1360-1366(--resume defined as a global flag; its help does not say it is single-stage only)
Recommended fix. Add ('resume', '--resume') to _UNSUPPORTED_ON_PIPELINE, pointing the operator at --resume-from. -
CR-A05-013 (code, Medium) — --pii-ml-language help advertises 'tr', which is unsupported; the ValueError escapes as a traceback with exit 1 and no JSON envelope
severity Medium · reachabilitydocumented-opt-in· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. A Turkish operator follows the help text and the run aborts with a Python traceback instead of a clear config error.
Where.forgelm/cli/_parser.py:618-630(the --pii-ml-language add_argument),forgelm/data_audit/_pii_ml.py:36-53,forgelm/data_audit/_pii_ml.py:101-110(the ValueError raise),forgelm/data_audit/_orchestrator.py:268-272(the docstring that also advertises 'tr')
Recommended fix. Fix the help text to name 'xx' for unsupported languages, and handle ValueError in _run_data_audit as a config error with the JSON envelope. -
CR-A05-017 (code, Medium) — product_strategy.md:74 documents a nonexistent
forgelm wizardsubcommand (and configuration.md a nonexistentforgelm compliance-only)
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. A new user reads product_strategy.md and typesforgelm wizard. argparse rejects it with exit 2, with no hint that the flag form is--wizard.
Where.docs/product_strategy.md:74,docs/product_strategy-tr.md:74,docs/guides/pipeline.md:293,docs/guides/pipeline-tr.md:296
Recommended fix. Useforgelm --wizard(EN and TR) in product_strategy and the pipeline guides, and change 'will provide' to the present tense for the shipped quickstart templates. -
CR-A05-018 (code, Medium) — No test parses a top-level flag placed before a subcommand that re-declares the dest (G-A05-01 confirmed; destructive consequence shown for purge)
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Where.forgelm/cli/_parser.py:182,forgelm/cli/_parser.py:485,forgelm/cli/_parser.py:1159,tests/test_cli_subcommands.py
Recommended fix. Add to tests/test_cli_subcommands.py (or a new tests/test_cli_parser_precedence.py), callingparse_argswith patched sys.argv. (1) Parametrized table asserting the parsed value for ['--dry-run','purge','--row-id','1','--corpus','c.jsonl'] -> dry_run is True; ['--dry-run','quickstart','customer-support'] -> dry_run True; ['--config','a.yaml','purge','--row-id','1','--corpus','c'] -> config == 'a… -
CR-A05-019 (code, Medium) — Extends M-A09-006 (not a new defect): H-A09-10 is a duplicate. More places tell operators that verify-annex-iv --pipeline exits 0 without saying it needs FORGELM_AUDIT_SECRET and a root audit log sig…
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An operator follows docs/guides/pipeline.md or verify_annex_iv_subcommand.md and runs a pipeline without exporting FORGELM_AUDIT_SECRET, or later appends one unsigned line to the pipeline root log. Every laterforgelm verify-annex-iv --pipeline <run_dir>then exits 1 ('FAIL', unattested), even when every structural, chain and evidence check passes. --help says 'Exits 0 on valid', and the reference doc's examples show exit 0, so the operator cannot tell from those docs why. The run can never b…
Where.forgelm/cli/_parser.py:829-836,forgelm/cli/_parser.py:850-855,forgelm/compliance.py:3396-3404,forgelm/compliance.py:3437-3443
Recommended fix. Merge H-A09-10 into M-A09-006. Extend M-A09-006's locations with _parser.py:833-835 and :850-855, the reference-doc lines above (EN and TR), docs/guides/pipeline.md:241-255 (EN and TR), and the stale docstrings. One fix covers them all: state in --help, the reference doc and the pipeline guide that a pipeline exits 0 only when FORGELM_AUDIT_SECRET was set during the run and at verification time a… -
CR-A05-020 (code, Medium) — Docs, site, wizard and the cache-tasks docs show a 'truthfulqa' score/status key that the code never produces
severity Medium · reachabilitydefault· intentcontract-violation· confidence likely (static only) · independently confirmed · not reproduced (code trace)
Where.docs/usermanuals/en/evaluation/benchmarks.md:43,docs/usermanuals/en/evaluation/benchmarks.md:78-96,docs/usermanuals/en/evaluation/benchmarks.md:111-114,docs/usermanuals/en/operations/experiment-tracking.md:116
Recommended fix. Use one concrete leaf (truthfulqa_mc2 is the usual headline) in all examples and help text, or document the expansion and the resulting key names. -
CR-A05-021 (code, Medium) — Audit has no rendered-sample / chat-template preview promised by the SFT guide
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An operator who switches model.name_or_path and follows the pitfall advice finds no preview and cannot do the check the guide describes. The tokenizer-mismatch diagnosis it offers cannot be carried out.
Where.forgelm/cli/_parser.py:498-680,forgelm/data_audit/_orchestrator.py:227-240,docs/usermanuals/en/training/sft.md:117,docs/usermanuals/tr/training/sft.md:117
Recommended fix. Remove the claim, or add an optional--modeltoauditthat renders N samples the same way the trainer does. -
CR-A05-022 (code, Medium) — pii-masking.md tells users to pass --pii-ml-language over a
forgelm ingestexample; ingest rejects the flag
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. A user follows the paragraph, gets an argparse error, or believes a locale-aware ML pass ran during ingest.
Where.docs/usermanuals/en/data/pii-masking.md:94-98,docs/usermanuals/tr/data/pii-masking.md:93-97,forgelm/cli/_parser.py:618-629
Recommended fix. Delete the paragraph and its ingest example, or reword it to point toforgelm audit --pii-ml --pii-ml-language. -
CR-A05-023 (code, Medium) — QMS SoA/RTP credit forgelm audit with masking and Presidio ML-NER as the A.8.11 data-masking control; the audit only counts, and ML-NER never masks anywhere
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An ISO auditor accepts A.8.11 as implemented byforgelm audit. The deployer runs the audit, gets counts, and trains on the unmasked corpus, believing masking happened. A PERSON/ORG name found only by Presidio is never masked by any ForgeLM path.
Where.docs/qms/statement_of_applicability.md:63,docs/qms/statement_of_applicability.md:119,docs/qms/statement_of_applicability-tr.md:64,docs/qms/statement_of_applicability-tr.md:120
Recommended fix. Re-attribute A.5.34 and A.8.11 masking toforgelm ingest --pii-mask/--secrets-mask(regex only). Describe Presidio as opt-in detection only. Either drop 'review of flagged rows' or add row locators to the report. -
CR-A05-024 (code, Medium) — Data-management SOP documents a non-existent
forgelm ingest --pii-mland calls the default-on quality filter optional
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An SOP-following operator plans ML-NER redaction at ingest. The command fails, or they assume names were scrubbed when no ingest path can do it.
Where.docs/qms/sop_data_management.md:104-106,docs/qms/sop_data_management.md:84,docs/qms/sop_data_management-tr.md:106,docs/qms/sop_data_management-tr.md:96-97
Recommended fix. Remove --pii-ml from the ingest bullet (it is audit-only, detection-only), describe the quality filter as default-on with --no-quality-filter, and complete the secrets family list. -
CR-A05-025 (code, Medium) — PII masking presented as an inherent ingest step ('Masks at ingest time', 'PII redacted at ingest'), but
forgelm ingestmasks nothing unless --pii-mask/--all-mask is passed
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace)
Failure scenario. An operator follows the homepage use case ('drop your corpus into forgelm ingest') and runsforgelm ingest docs/ --output data.jsonl. Emails, phone numbers and IBANs from the regulatory PDFs reach the training JSONL unmasked, although the site said PII is redacted at ingest.
Where.forgelm/cli/_parser.py:256-280,forgelm/data_audit/_pii_regex.py:39-88,site/js/translations.js:986,site/js/translations.js:1091
Recommended fix. Name the flag in both keys across six locales ('pass --all-mask to redact PII and secrets at ingest').
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