Repository navigation
[Wave 3] Medium — Module sweep: Marketing site and in-browser config wizard (part 1/2) #556
Description
Wave 3 · 20 finding(s) in 20 fix package(s). Fix these whenever a pull request touches this module ("clean the module you touch").
Findings
-
CR-A18-013 (code, Medium) — GaLore mode is presented as 'replaces LoRA / no adapter' while the runtime still applies LoRA with the hidden, stale r/alpha and silently drops lora.method
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Where.site/js/wizard.js:603-614,site/js/wizard.js:667-674,site/js/wizard.js:1831-1867,site/js/wizard.js:1944-1951
Recommended fix. Either keep the LoRA controls visible under GaLore and correct the copy (GaLore optimises the adapter parameters; LoRA is still applied), or add real adapter-free GaLore support in model.py before claiming it. -
CR-A18-014 (code, Medium) — High-risk tiers force monitoring.enabled into the YAML but never require the endpoint; the Annex IV manifest then records endpoint '$None'
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Where.site/js/wizard.js:451-453,site/js/wizard.js:822-834,site/js/wizard.js:2707-2731,forgelm/compliance.py:1583-1589
Recommended fix. Validate the endpoint when isStrictRisk(state) || state.monitoringEnabled. In compliance.py, do not render '$None' when both endpoint and endpoint_env are empty. -
CR-A18-015 (code, Medium) — Wizard use-case presets emit a repo-relative dataset path (forgelm/templates//data.jsonl) that fails outside a source checkout; dry-run cannot see it
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. A pip-installed user picks 'Customer support', downloads the YAML and runs dry-run (valid), then the real run fails at dataset load because ./forgelm/templates/customer-support/data.jsonl does not exist in the working directory (or is treated as a Hub id).
Where.site/js/wizard.js:535,forgelm/quickstart.py:240-274,forgelm/data.py:312-337,forgelm/templates/grpo-math/config.yaml:35-53
Recommended fix. Point bundled-dataset presets atforgelm quickstart <template>(or tell the operator to copy the seed file), and carry each template's hyperparameters into the preset. -
CR-A18-017 (code, Medium) — Wizard form controls have no accessible names, and selection and error states are not exposed (WCAG 1.3.1 / 4.1.2 / 3.3.1)
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace) · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15 a11y) — docs/roadmap/phase-16-trust-surface-hardening.md:772
Where.site/js/wizard.js:1586,site/js/wizard.js:1920-1943,site/js/wizard.js:1981-1998,site/js/wizard.js:2294-2313
Recommended fix. Generate ids and set label.htmlFor; add aria-describedby for hint and error; use aria-pressed or role=radio with aria-checked on cards. -
CR-A18-018 (code, Medium) — guide.html resets every visitor's stored language to English on load
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced with stubs
Failure scenario. Turkish user picks TR on index.html (localStorage forgelm-lang=tr) -> opens guide.html -> sidebar/content render in English, localStorage now 'en' -> returning to index.html shows English.
Where.site/js/guide.js:49,site/js/guide.js:253-255,site/js/i18n.js:78,site/js/i18n.js:137-139
Recommended fix. Do not persist from renderPage: either read state.lang via ForgeLMi18n.detectLanguage() at init, or add a non-persisting re-translate entry point (e.g. setLanguage(lang,{persist:false})) for re-render chrome refreshes; or load guide.js with defer after i18n.js. -
CR-A18-019 (code, Medium) — Homepage 'real config' demo uses webhook.url "${SLACK_WEBHOOK}", which ForgeLM never expands; the webhook is silently dead while dry-run reports it configured
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:772 (site/index.html:575 demo)
Failure scenario. An operator copies the demo and exports SLACK_WEBHOOK. No notification ever arrives, because the URL '${SLACK_WEBHOOK}' is rejected by the HTTP chokepoint and the failure is only logged.
Where.site/index.html:587(confirmed),site/index.html:542,site/index.html:565,forgelm/webhook.py:69-83
Recommended fix. Useurl_env: SLACK_WEBHOOKin the demo; retitle it as an SFT run, or show a pipeline block. -
CR-A18-020 (code, Medium) — Homepage use-case cards pair DPO / ORPO / multi-dataset / GGUF / safety-gate claims with quickstart templates that are single-stage SFT
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:771-772
Failure scenario. A user follows the card and ships a model that was never safety-evaluated, believing a Llama Guard gate ran.
Where.site/index.html:642-643,site/js/translations.js:405(disputed),forgelm/templates/customer-support/config.yaml,site/index.html:628-645
Recommended fix. Either add an evaluation block to the template or reword the card to say the gate is something you add. -
CR-A18-021 (code, Medium) — site/README.md misdescribes the site (no build step, no third-party JS, EN/TR data-lang), so documented no-build deploys ship a broken guide
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace)
Failure scenario. A fork deploys site/ to Netlify by drag-and-drop as instructed. /guide.html shows 'Page not found' for every route because js/usermanuals/en.js returns 404.
Where.site/README.md:48,site/README.md:49,site/README.md:90,site/guide.html:40
Recommended fix. Update the README (6 locales, data-i18n, Mermaid on the guide page, a required build steppython3 tools/build_usermanuals.py) and the build_usermanuals docstring. -
CR-A18-022 (code, Medium) — Wizard validates per step only: strict-tier (high-risk/unacceptable) governance rules are unreachable and the review step never re-validates
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Where.site/js/wizard.js:374-467,site/js/wizard.js:940-950,site/js/wizard.js:1128-1174,site/js/wizard.js:2941-3027
Recommended fix. On leaving the compliance step (and on entering Review) run validateStep over every step and route the user back to the first failing one; or move the risk tier before the dataset step. -
CR-A18-023 (code, Medium) — Wizard advertises 'prompt + response' as an SFT row shape, but the SFT loader rejects it and suggests GRPO
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An operator prepares a dataset in the format the wizard documents for SFT (prompt + response). Dry-run passes. Training exits 2 after model load, with a message that suggests switching to GRPO.
Where.site/js/translations.js:1566and :1581,site/js/wizard.js:641-644,forgelm/data.py:41-45and :437-438, :453,forgelm/data.py:436-450
Recommended fix. Either accept prompt/response (and prompt/completion) in _process_user_assistant_format, or correct the wizard text and YAML comment to the supported column names (instruction/output, User/Assistant, messages, text). -
CR-A18-024 (code, Medium) — Wizard default YAML never produces the Annex IV artefact it promises; the provider fields are hidden below the strict tiers
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end
Where.site/js/translations.js:1706,site/js/wizard.js:767-772,site/js/wizard.js:884-885,site/js/wizard.js:2283-2294
Recommended fix. Render the three Annex IV §1 inputs for every tier (as the code comment intends), or reword the callout and YAML comment to say the Annex IV file needs provider_name/system_name/intended_purpose. -
CR-A18-025 (code, Medium) — Wizard hint strings contradict the wizard's own behaviour (lora_alpha tracking, auto_revert default, RSLoRA range, batch default, approve command)
' command.
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace)
Where.site/js/translations.js:1622,site/js/wizard.js:1920-1945,site/js/translations.js:1703-1704,site/js/wizard.js:204
Recommended fix. Either link alpha to r (alpha = 2r unless the operator edits alpha) or drop 'tracks this automatically'. Make the auto_revert text say the wizard turns it on. Raise the r slider maximum or reword the RSLoRA guidance. Default batch to 2 or reword. Show the full 'forgelm approve --output-dir -
CR-A18-026 (code, Medium) — Wizard offers three layerwise GaLore optimisers that can never run: it always emits gradient_accumulation_steps: 2, which transformers rejects for layerwise optimisers
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced with stubs
Failure scenario. An operator picks GaLore and chooses 'galore_adamw_layerwise' (the lowest-VRAM option) in the wizard. The dry-run reports valid.forgelm --configdownloads and loads the 7B model and the dataset, then exits 2 with the transformers ValueError when training starts.
Where.site/js/wizard.js:1893-1899,site/js/wizard.js:184,site/js/wizard.js:665,site/js/wizard_defaults.js:21(not :22)
Recommended fix. Add a config-time validator that rejects a layerwise galore_optim when gradient_accumulation_steps != 1 (exit 1). Make the wizard either force gradient_accumulation_steps: 1 when a layerwise variant is selected or hide those variants. Fix the troubleshooting docs. -
CR-A18-027 (code, Medium) — Trainer step accepts any trainer after a use-case preset or a PDF dataset; the row shape cannot match, dry-run passes and training fails after the model loads
severity Medium · reachabilitydefault· intentintended-but-harmful· confidence confirmed · independently confirmed · reproduced end to end
Failure scenario. An operator picks the 'customer-support' card, switches the trainer to DPO (which the card advertises), and finishes the wizard. Dry-run says 'config is valid'.forgelm --configdownloads Qwen2.5-7B and then exits 2 with 'DPO trainer requires chosen and rejected columns'. The same happens with any PDF dataset combined with DPO, SimPO, ORPO, KTO or GRPO.
Where.site/js/wizard.js:501-546,site/js/wizard.js:374-466,site/js/wizard.js:1521-1527,site/js/wizard.js:618-644
Recommended fix. In the wizard, either reset or blank the preset dataset when the trainer's row shape differs, or show a blocking validation error on the trainer step for known preset/PDF datasets. In ForgeLM, have --dry-run inspect the first row of a local JSONL (cheap, no model load) and run _validate_trainer_columns, or call prepare_dataset before get_model_and_tokenizer. -
CR-A18-028 (code, Medium) — Wizard emits PiSSA together with 4-bit QLoRA (its default); PEFT refuses PiSSA initialisation on quantised weights
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced with stubs
Failure scenario. On a CUDA host, an operator keeps the default QLoRA and picks the PiSSA card. Dry-run reports valid.forgelm --configloads the 4-bit model, then get_peft_model raises TypeError and the run exits 2.
Where.site/js/wizard.js:145,site/js/wizard.js:590,site/js/wizard.js:1840,forgelm/model.py:443-450
Recommended fix. Reject method: pissa with load_in_4bit: true at config time (or implement PEFT's documented PiSSA-then-quantise flow). In the wizard, disable the PiSSA card while QLoRA is on. Correct the site capability copy. -
CR-A18-029 (code, Medium) — DE/FR/ES/ZH render the audit log as 'tamper-proof' where EN says 'tamper-evident'
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:749-751,772
Failure scenario. A German operator reads 'manipulationssicheres Audit-Log' and treats the local audit_log.jsonl as tamper-proof. They do not set FORGELM_AUDIT_SECRET and do not ship the log to WORM storage. Anyone with write access to the output dir can then rewrite the log and recompute the SHA-256 chain, and verify-audit still passes.
Where.site/js/translations.js:538,site/js/translations.js:644,site/js/translations.js:750,site/js/translations.js:856
Recommended fix. Use evidence-oriented terms: de 'manipulationserkennbar' / 'manipulationsnachweisbar', fr 'à preuve de falsification' / 'permettant de détecter toute altération', es 'con evidencia de manipulación', zh '可检测篡改'. Apply them in both keys and also in zh features.gov.annex.body ('防篡改' → '篡改检测'). -
CR-A18-030 (code, Medium) — 'Supply-chain evidence on every run' is overstated: supply-chain artefacts are per release and CI, and no run records its dependency versions
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced (plumbing only) · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:772
Failure scenario. An auditor asks for the software bill of materials of a specific training run. The run directory has none, and the deployer cannot regenerate it from a pip install.
Where.site/compliance.html:225,site/js/translations.js:3884,forgelm/compliance.py:2173-2236,pyproject.toml:250-252
Recommended fix. Either record the installed versions of the core ML packages in compliance_report.json for each run, or reword the claim to 'per release' for supply chain. -
CR-A18-031 (code, Medium) — Site Article 12 card (compliance.art12.body, all locales) claims the audit log records model export with per-event HMAC; export/deploy/merge emit no audit event
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace) · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:772
Failure scenario. A compliance reader relies on the audit log to show which GGUF was exported from which run. No such record exists.
Where.site/js/translations.js:3859(confirmed),site/js/translations.js:3918(confirmed),site/compliance.html:163,forgelm/export.py:207-239(confirmed)
Recommended fix. Either emit an export audit event (with the GGUF digest) or drop 'model export' from every translation of compliance.art12.body. -
CR-A18-032 (code, Medium) — Site Art. 16-17 card claims a 'conformity declaration template generated from the run's Annex IV'; no code does this, and the manual says ForgeLM does not generate one
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · not reproduced (code trace) · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15) — docs/roadmap/phase-16-trust-surface-hardening.md:776-778
Failure scenario. A provider expects an Article 47 / Annex V declaration template in the compliance bundle and plans conformity work around it. The bundle (export_compliance_artifacts) contains none.
Where.site/js/translations.js:3867,site/js/translations.js:3926,site/js/translations.js:3985,site/js/translations.js:4028
Recommended fix. Delete the sentence in all six locales and fix introduction.md:59 (and its TR mirror), or ship an actual template generator. -
CR-A18-033 (code, Medium) — Skip links (and every in-page anchor) never move keyboard focus; on guide.html the skip link also overwrites the #/route
severity Medium · reachabilitydefault· intentcontract-violation· confidence confirmed · independently confirmed · reproduced with stubs · already tracked: KNOWN-OPEN DOCS-02/14/15/16 (S15 a11y) — docs/roadmap/phase-16-trust-surface-hardening.md:772
Failure scenario. A keyboard user presses Tab on any page, sees 'Skip to main content' and presses Enter. The page scrolls, but focus stays on the skip link and the next Tab goes to the navbar. On guide.html at #/training/lora, the URL becomes guide.html#guide-content, and a reload shows the Introduction page.
Where.site/js/main.js:444-459,site/js/main.js:21,site/index.html:78,site/index.html:135
Recommended fix. In initSmoothAnchorOffset, focus the target after scrolling (add tabindex=-1 when it is not focusable) and leave the hash alone on the guide shell. Alternatively, drop the handler and rely on CSS scroll-behavior plus scroll-margin-top.
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 16, 2026
Status of CR-A18-017 after #954 (for #950).
Resolved:
id/forpairs.Still open:
aria-pressed, or radio semantics witharia-checked.aria-describedby.aria-invalid. The other validated fields mark errors with a class and an alert row only. A related bug, where a corrected model id or dataset name stays invalid, is filed as Browser wizard: a corrected model or dataset field stays marked invalid until the step re-renders #952.cemililik commentedon Oct 16, 2026
Status of CR-A18-017 after #954, measured on its head: accessible names are done (every captioned control is named by its caption). Two parts remain:
aria-pressedorrole="radio"witharia-checkedwould.aria-invalid, and none links its error or hint to the field witharia-describedby. Fix the wizard's Compliance step and field labels, guard CI against failure masking, correct monitoring copy #954 routes every field's in-place error update through one helper,syncFieldErrorinsite/js/wizard.js, so both attributes can be set in one place.