Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ on:
pull_request:
branches: [main]

# Coverage gate (--cov-fail-under=40) is enforced via pyproject.toml's
# [tool.pytest.ini_options].addopts; the test job intentionally does not
# duplicate the flag here. FORGELM_OPERATOR is set so future operator-identity
# checks (Phase 3 hardening) do not raise on distroless runners where USER is
# unset.
env:
FORGELM_OPERATOR: ci-smoke

jobs:
# --- Job 1: Lint (fast, no heavy deps) ---
lint:
Expand All @@ -30,6 +38,7 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
Expand All @@ -46,7 +55,10 @@ jobs:
python -m pip install -e ".[dev]"

- name: Run tests with coverage
run: pytest -q --tb=short --cov=forgelm --cov-report=term-missing --cov-report=xml:coverage.xml
# --cov, --cov-report=term-missing, and --cov-fail-under=40 come from
# pyproject.toml addopts (single source of truth). Only the XML report
# is added here because it is CI-specific (artifact upload).
run: pytest -q --tb=short --cov-report=xml:coverage.xml

- name: Upload coverage (3.11 only)
if: matrix.python-version == '3.11' && always()
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ on:

# No workflow-level permissions — each job declares the minimal set it needs.

# Set FORGELM_OPERATOR so future operator-identity checks (Phase 3 hardening)
# do not raise on distroless runners where USER is unset.
env:
FORGELM_OPERATOR: ci-smoke

jobs:
test-latest-deps:
name: Test with latest dependencies
Expand Down Expand Up @@ -71,6 +76,18 @@ jobs:
forgelm --config "/tmp/qs-$tpl.yaml" --dry-run
done

- name: Forbid git+https in notebooks
run: |
# Notebooks must install ForgeLM from PyPI with a pinned version,
# never from a git+https URL. Closure plan Faz 5 — git+https makes
# Colab installs depend on a specific branch HEAD, breaking
# reproducibility and confusing users when main moves ahead of
# the latest released wheel.
if grep -rn 'git+https://github.com/cemililik/ForgeLM' notebooks/; then
echo "::error::Notebooks must install from PyPI, not git+https"
exit 1
fi

- name: Ingestion + audit smoke test (Phase 11)
run: |
# Minimal end-to-end: TXT in → JSONL out → audit report out.
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/usermanuals-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@ name: Validate user-manuals
# source. Catches structural problems before they hit main.

on:
push:
branches: [main, development]
paths:
- "docs/usermanuals/**"
- "tools/build_usermanuals.py"
pull_request:
branches: [main]
paths:
- "docs/usermanuals/**"
- "tools/build_usermanuals.py"

# Mirror CI's operator identity so any future pytest invocation does not
# raise on distroless runners where USER is unset.
env:
FORGELM_OPERATOR: ci-smoke

jobs:
validate:
runs-on: ubuntu-latest
Expand Down
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
# Internal strategy, marketing, and analysis docs (not public)
docs/marketing/
docs/analysis/
# Explicit exceptions: a small set of v0.5.5-closure planning artifacts
# is exposed publicly (referenced from closure PRs and the roadmap). The
# rest of docs/analysis/** stays internal — including all subdirectories
# (QKV-Core, Trion, autoresearch, proposals, ...) and every other file
# under code_reviews/.
#
# Pattern explanation:
# 1. docs/analysis/ — ignore everything under this dir
# 2. !docs/analysis/ — re-allow the directory itself (so we can descend)
# 3. docs/analysis/* — ignore every direct entry (subdirs + files)
# 4. !docs/analysis/code_reviews/ — re-allow code_reviews/ subdir only
# 5. docs/analysis/code_reviews/* — ignore every entry in code_reviews/
# 6. !<three named files> — re-include the 3 closure planning artifacts
!docs/analysis/
docs/analysis/*
!docs/analysis/code_reviews/
docs/analysis/code_reviews/*
!docs/analysis/code_reviews/closure-plan-202604300906.md
!docs/analysis/code_reviews/master-review-opus-202604300906.md
!docs/analysis/code_reviews/split-design-data_audit-cli-202604300906.md

# Generated by tools/build_usermanuals.py — produced from
# docs/usermanuals/<lang>/**/*.md during the CI deploy. Not committed;
Expand Down Expand Up @@ -70,3 +90,4 @@ logs/
# Claude Code runtime artifacts
.claude/scheduled_tasks.lock
.claude/state/
.claude/worktrees/
88 changes: 83 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,89 @@ All notable changes to ForgeLM are documented here.

## [Unreleased]

### Added
> **Active cycle:** v0.5.5 closure — a single-release consolidation of
> the master review's 175 findings + 4 new feature tracks (Library API,
> ISO 27001 / SOC 2 alignment, GDPR right-to-erasure, Article 14 real
> staging directory). Detailed plan:
> [closure-plan-202604300906.md](docs/analysis/code_reviews/closure-plan-202604300906.md).
> No interim releases; v0.5.5 ships once Faz 1-33 are complete.
> Per-PR CHANGELOG entries below collapse into the v0.5.5 release
> notes at tag time.

### Added — Foundation bundle (PR #19, Faz 1-8)

- `forgelm verify-audit` subcommand + library function
`forgelm.compliance.verify_audit_log` (Faz 6 — closes F-compliance-103
Critical).
- `forgelm._http.safe_post` — single boundary for outbound HTTP with
SSRF guard, redirect refusal, scheme policy, timeout floor, TLS
pinning, secret-mask error reasons (Faz 7 — closes M-201 Major).
Migrated webhook + judge + synthetic call sites.
- `WebhookNotifier.notify_reverted` and `notify_awaiting_approval` —
paired with `training.reverted` and `approval.required` events
(Faz 8 — closes F-compliance-104 Major).
- `SafetyEvalThresholds` dataclass — bundles five Phase 9 knobs so
`run_safety_evaluation` stays under the 13-param ceiling (Faz 4 v2
+ complexity refactor).
- `audit.classifier_load_failed` audit event with `audit_logger=`
parameter on `run_safety_evaluation` (Faz 3 — closes F-compliance-120
Minor).
- `tests/test_lazy_imports.py` — regression test pinning that
`import forgelm.trainer` / `import forgelm.model` do not eagerly
load torch (Faz 4 — closes F-performance-101 Major).
- `docs/reference/audit_event_catalog.md` + TR mirror — comprehensive
event vocabulary with payload schemas (Faz 3 + Faz 8 union).
- `docs/standards/release.md` "Deprecation cadence" section (Faz 2
— closes F-business-011 Major).

### Changed

- `AuditLogger` — operator identity raises `ConfigError` instead of
falling back to literal `"unknown"` (Faz 3 — closes F-compliance-102
Critical). `getpass.getuser()@socket.gethostname()` chain with
`FORGELM_ALLOW_ANONYMOUS_OPERATOR=1` escape hatch.
- `AuditLogger.log_event` — `os.fsync(f.fileno())` after flush; chain
durability across power-cut (Faz 3 — closes F-compliance-114 Major).
- `compute_dataset_fingerprint` — split into three helpers (local file
/ HF metadata / HF revision); HF Hub revision SHA pinned (Faz 3
— closes F-compliance-117 Minor + complexity refactor).
- `_generate_safety_responses` and `_generate_responses_batched` —
`batch_size=8` default with token-pad-longest + per-batch CUDA-OOM
fallback to single-prompt (Faz 4 — closes F-performance-102 Major).
Per-batch error handling extracted to `_generate_*_batch_with_oom_retry`
helpers.
- `_chunk_paragraph_tokens` — single-encode + offset slicing (Faz 4
— closes F-performance-103 Major).
- `_post_payload` — delegates to `safe_post` with `min_timeout=1.0`
for back-compat (Faz 7).
- 7 notebooks — install from PyPI (`forgelm[qlora]==0.5.0`) instead
of `git+https://...` (Faz 5 — closes F-business-005 Major).
- CI now enforces `pytest --cov-fail-under=40` via `pyproject.toml`
`addopts` (Faz 2 — closes F-test-001 Critical).
- CI matrix `fail-fast: false`; `usermanuals-validate.yml` runs on
push + PR (Faz 2 — closes F-test-006 + F-test-017 Major).
- Site honesty: `compliance.html` artefact tree, `quickstart.html`
template names, GPU stat (16 vs claimed 18) — all refreshed against
real code (Faz 1 — closes F-business-001/002/004 Critical+Major).
- QMS `sop_data_management.md` — single v0.5.0 story; v0.5.1+/v0.5.2
splits removed (Faz 1 — closes M-DOC-001 Critical).
- Roadmap (`roadmap.md`, `roadmap-tr.md`, `releases.md`) — v0.5.0
marked released; tristate status legend added (Faz 1 — closes
F-business-003 Critical).
- `forgelm.webhook` exports `_is_private_destination` via `__all__`
for back-compat (Faz 7).

### Documentation

- (next entry goes here — Phase 14 / Multi-Stage Pipeline Chains is the active phase; see [docs/roadmap.md](docs/roadmap.md))
- Full Faz 1-8 closure plan:
[closure-plan-202604300906.md](docs/analysis/code_reviews/closure-plan-202604300906.md)
(33 phases, ~47 PRs).
- Master review:
[master-review-opus-202604300906.md](docs/analysis/code_reviews/master-review-opus-202604300906.md)
(175 findings).
- `data_audit/` + `cli/` package split design:
[split-design-data_audit-cli-202604300906.md](docs/analysis/code_reviews/split-design-data_audit-cli-202604300906.md)
(Faz 14-15 forward-looking).

---

Expand Down Expand Up @@ -153,9 +233,7 @@ Touch points (so the next reviewer can audit blast radius quickly):

Inline-comment batches landing on top of PR #13 (now merged to `main`).
Same review surface as rounds 4-7; further hardening on top of the
`v0.5.2` content. The `v0.5.2` git tag + PyPI publish are the
remaining release-engineering steps before this section can be
frozen into a release.
`v0.5.2` content.

- **Audit log hardening** (`forgelm/compliance.py`) — HMAC `_hmac` field is now
emitted only when `FORGELM_AUDIT_SECRET` is set; without a secret, a key
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ ForgeLM/
│ ├── webhook.py # Slack/Teams notifications
│ ├── grpo_rewards.py # Built-in GRPO format/length shaping reward fallback
│ └── ... # benchmark, judge, merging, synthetic, wizard, ...
├── tests/ # pytest, 26 test modules
├── tests/ # pytest test modules
├── docs/
│ ├── roadmap.md # Public roadmap (short index)
│ ├── roadmap/ # Detailed phase files + archive
Expand Down
28 changes: 4 additions & 24 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,30 +59,10 @@ Push your branch and open a Pull Request against `main`.

### Project Structure

```
forgelm/
├── cli.py # CLI entry point
├── config.py # Pydantic config models
├── data.py # Dataset loading
├── model.py # Model + LoRA setup
├── trainer.py # Training orchestration
├── results.py # TrainResult dataclass
├── benchmark.py # lm-eval-harness
├── safety.py # Safety evaluation
├── judge.py # LLM-as-Judge
├── compliance.py # EU AI Act artifacts
├── model_card.py # Model card generation
├── merging.py # Model merging (TIES/DARE/SLERP)
├── wizard.py # Interactive config wizard
├── synthetic.py # Synthetic data pipeline
├── webhook.py # Notifications
└── utils.py # Auth & checkpoints

tests/ # 47 test files
notebooks/ # 10 Colab notebooks
configs/deepspeed/ # ZeRO presets
docs/guides/ # user guides
```
ForgeLM is a single-package layout: ~26 single-file modules under `forgelm/`,
~47 test files under `tests/`, plus `configs/`, `docs/`, and `notebooks/`. For
the authoritative module-by-module map (purpose, public surface, dependency
arrows), see [`docs/reference/architecture.md`](docs/reference/architecture.md).

### Running Tests

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
- **Synthetic Data Pipeline**: Teacher-to-student distillation with `--generate-data` CLI flag
- **DeepSpeed & FSDP**: Multi-GPU distributed training with ZeRO-2/3 presets
- **MoE Support**: Fine-tune Mixture of Experts models (Qwen3, Mixtral, DeepSeek)
- **GPU Cost Estimation**: Auto-detection for 18 GPU models with per-run cost tracking
- **GPU Cost Estimation**: Auto-detection for 16 GPU models with per-run cost tracking

### Evaluation & Safety
- **Automated Benchmarking**: Post-training evaluation via `lm-evaluation-harness`
Expand All @@ -39,7 +39,7 @@
- **Wizard "audit first"**: when the wizard resolves a JSONL (typed or produced by `forgelm ingest`) it offers to run `forgelm audit` inline and prints the verdict before continuing — closes the BYOD audit loop end-to-end.

### Quickstart Layer (v0.4.5)
- **One-Command Templates**: `forgelm quickstart customer-support` — 4 bundled templates (SFT customer-support, code-assistant, medical-qa-tr, GRPO math-reasoning) plus a bring-your-own-data domain-expert scaffold. Auto-downsizes models on small GPUs.
- **One-Command Templates**: `forgelm quickstart customer-support` — 5 bundled templates (SFT customer-support, code-assistant, medical-qa-tr, domain-expert, GRPO grpo-math). Auto-downsizes models on small GPUs.
- **Conservative Defaults**: Every template ships QLoRA 4-bit, rank=8, batch=1, gradient checkpointing on — designed to run on a single 12 GB GPU.
- **Wizard Integration**: `forgelm --wizard` opens with "Start from a template?" — same code paths, same YAML schema as a hand-written config.

Expand Down Expand Up @@ -231,7 +231,7 @@ forgelm --version # Show version

```
forgelm/
├── cli.py # CLI with 10+ modes (train, dry-run, merge, benchmark, wizard, ingest, audit, ...)
├── cli.py # CLI entry point (train, dry-run, merge, benchmark, wizard, ingest, audit, ...)
├── config.py # Pydantic config (19 models: training, evaluation, distributed, ...)
├── data.py # Dataset loading (SFT, DPO, KTO, GRPO formats + multi-dataset)
├── data_audit.py # Audit pipeline (length / language / dedup / leakage / PII / secrets / quality) — `forgelm audit`
Expand Down
Loading