Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
c723495
fix(safety): bound + cross-validate gate thresholds; fail closed on d…
cemililik Jun 14, 2026
a19d720
fix(safety-eval): exit 2 on classifier-load failure, wire AuditLogger…
cemililik Jun 14, 2026
34fa791
fix(cli): stop advertising GGUF support for safety-eval (H2 / XP-07, …
cemililik Jun 14, 2026
5c168d6
fix(grpo): anchor math reward to final Answer; unify reward pattern (…
cemililik Jun 14, 2026
b290abf
fix(pipeline): honour approve→resume + reset terminal fields on resum…
cemililik Jun 14, 2026
be237c2
fix(data): reject non-string dataset cells in clean_string (H9 / F-P6…
cemililik Jun 14, 2026
efa39a7
fix(compliance): HMAC fail-open, exit-code drift, config_hash binding…
cemililik Jun 14, 2026
8260f24
docs(compliance): strike msvcrt.locking claim, fix webhook 8-vs-5 + p…
cemililik Jun 14, 2026
190c032
fix(config): tighten distributed/mix_ratio validation + merge round-t…
cemililik Jun 14, 2026
634bb80
fix(config): resolve sample_packing dead field + deprecation cadence …
cemililik Jun 14, 2026
ad5ea3c
fix(cli): add success key to dry-run JSON envelope (H7 / F-P7-OPUS-16)
cemililik Jun 14, 2026
2d9c263
fix(docs): correct exit-0 contract for auto_revert=false gate failure…
cemililik Jun 14, 2026
d6d9523
fix(docs): replace phantom regenerate_config_doc.py control with the …
cemililik Jun 14, 2026
b66519d
fix(http): unify URL masking + strip secret-bearing paths from transp…
cemililik Jun 14, 2026
8eb358d
fix(purge): constrain run-scoped erasure to output_dir via realpath+c…
cemililik Jun 14, 2026
bee30ea
docs(supply-chain): document fail-closed UNKNOWN pip-audit policy (H8…
cemililik Jun 14, 2026
d6c5f69
fix(wizard): honour cancel/back/non-tty + JSON-envelope at CLI seam (…
cemililik Jun 14, 2026
91ab77b
fix(docs): align CLI help, exit-code & JSON-envelope docs to code (H1…
cemililik Jun 14, 2026
21d4882
test(coverage): add test_model.py + test_data.py for untested core mo…
cemililik Jun 14, 2026
7b3b56e
fix(guards): harden check_no_unguarded_sys_modules_pop + add own test…
cemililik Jun 14, 2026
8fadc31
fix(guards): wire orphan CI guards + add guard-wiring meta-test + fix…
cemililik Jun 14, 2026
6bb9639
fix(trainer): harden OOM recovery, eval gate, safety evidence, gate d…
cemililik Jun 14, 2026
0593d96
fix(pipeline): stage-filter + resume state-machine correctness (M1 / …
cemililik Jun 14, 2026
53629e8
test(trainer): cover gate application, baseline capture, per-stage cr…
cemililik Jun 14, 2026
e7c3321
fix(compliance): close 6 compliance-completeness gaps (M2 / F-P4-OPUS…
cemililik Jun 14, 2026
de4bfaf
fix(data): reject empty messages list, strip control chars in clean_t…
cemililik Jun 14, 2026
c7c8bac
fix(ingestion): correct _is_frontmatter_page docstring alpha threshol…
cemililik Jun 14, 2026
faa2c60
fix(strip-pattern): reject double-group nested unbounded ((a+))+b (M4…
cemililik Jun 14, 2026
0e9214f
fix(data-audit,synthetic): scan all synthetic shapes, survive non-dic…
cemililik Jun 14, 2026
d19ffe4
fix(cli): close exit-code class & JSON-envelope gaps (M5 / F-P7-OPUS-…
cemililik Jun 14, 2026
3c09fb9
fix(docs): route verify-integrity-tr cross-links to their TR mirrors …
cemililik Jun 14, 2026
970f627
fix(config): numeric bounds, dtype enum, benchmark/lora gate hygiene …
cemililik Jun 14, 2026
ecd31f3
docs(reference): document max_steps, early_stopping_patience, benchma…
cemililik Jun 14, 2026
44eff68
docs(usermanuals): drop stale cost_tracking/deployment version stamps…
cemililik Jun 14, 2026
c3608b8
fix(library-api): single-source stability tiers, lazy-parity + signat…
cemililik Jun 14, 2026
5a5d79e
fix(guards): check_field_descriptions scans indirectly-inherited Pyda…
cemililik Jun 14, 2026
4388dec
fix(http): strip port from Host header before TLS assert_hostname (M6…
cemililik Jun 14, 2026
1936012
fix(purge): mask + PII-redact + bound erasure_failed error_message (M…
cemililik Jun 14, 2026
33cece7
fix(compliance): bound model-integrity hashing to the model tree (M6 …
cemililik Jun 14, 2026
89133ae
fix(docs): GFM-faithful anchor slugify + resolve 37 masked 404s (M7 /…
cemililik Jun 14, 2026
f7d854e
fix(notebooks): bump forgelm pins to released 0.7.0, make guard rc-aw…
cemililik Jun 14, 2026
70bc222
test(utils): cover setup_authentication + manage_checkpoints branches…
cemililik Jun 14, 2026
02450fb
fix(parity): auto-discover all 66 usermanual EN/TR pairs for spine pa…
cemililik Jun 14, 2026
d823963
fix(grpo): reward edge-cases — leading-dot/comma/empty/placeholder-go…
cemililik Jun 14, 2026
694a686
fix(utils): checkpoint delete/compress + auth token-store error bread…
cemililik Jun 14, 2026
70c611f
fix(compliance): harden audit write-time integrity + decision-gate tr…
cemililik Jun 14, 2026
590d749
docs(audit-log): align user manual with the real envelope (L2 / F-P4-…
cemililik Jun 14, 2026
d475ecc
fix(approvals): surface audit-log corruption in --show instead of sil…
cemililik Jun 14, 2026
2b5d589
fix(model_card): neutralize Markdown injection in base_model/dataset/…
cemililik Jun 14, 2026
563f56e
fix(webhook): TLS-only toggle + correct transport-error log level (L2…
cemililik Jun 14, 2026
ffcd714
fix(supply-chain): warn on stale pip-audit verified_at suppressions (…
cemililik Jun 14, 2026
18278f3
fix(config): validate merge/synthetic payloads, bound operational kno…
cemililik Jun 14, 2026
4b33312
fix(tooling+docs): harden check_field_descriptions, correct stale doc…
cemililik Jun 14, 2026
2ef925e
fix(tooling): wizard-defaults generator handles top-level scalar + mi…
cemililik Jun 14, 2026
a63e6f3
test(library-api): pin verify result types through the top-level faca…
cemililik Jun 14, 2026
e73a69f
fix(cli): default-on quality_filter fallback + validate bounded numer…
cemililik Jun 14, 2026
f45dd24
fix(cli): enforce exit-code clamp at dispatch seam + pin chat SIGINT …
cemililik Jun 14, 2026
b2a075b
fix(wizard): widen persist guard, use grad-accum constant, document p…
cemililik Jun 14, 2026
e6eea99
fix(doctor+docs): list pypdf_normalise probe, stop over-promising ext…
cemililik Jun 14, 2026
0afff22
fix(export): malformed converter env exits config-error + pin deploy/…
cemililik Jun 14, 2026
2345b16
fix(docs): correct safety-eval exit-code table + drop chat 'safety ro…
cemililik Jun 14, 2026
363cd18
fix(data): loud signals + accurate docstrings on ingest/audit edges (…
cemililik Jun 14, 2026
6e2917d
test(core): cover chat REPL, judge/safety batch_size guard, merge dis…
cemililik Jun 14, 2026
929fa04
fix(docs): bilingual registry + stale-status + dead-anchor + provenan…
cemililik Jun 14, 2026
1451c2d
fix(tooling): harden + test HTTP-discipline / numerical-claims guards…
cemililik Jun 14, 2026
dd3047c
fix(facade): correct design §-references and drop dead __dir__ statem…
cemililik Jun 14, 2026
9688fa3
fix(trainer): correct .staging path comments to .staging.<run_id> (N1…
cemililik Jun 14, 2026
99d839a
fix(rewards/safety): correct boundary-strip + safety/file-teacher com…
cemililik Jun 14, 2026
4bbe88a
fix(cli/compliance): JSON ensure_ascii/indent consistency + fsync + m…
cemililik Jun 14, 2026
3228089
fix(data-audit): docstring/comment accuracy + symmetric ReDoS test (N…
cemililik Jun 14, 2026
47db82b
fix(cli/wizard): comment accuracy, chat dual-path test, BYOD audit WA…
cemililik Jun 14, 2026
bc934ea
fix(docs/sbom): canonical SBOM sort + doc-citation accuracy (N1 / F-P…
cemililik Jun 14, 2026
2a72a3c
fix(trainer/cli): isolate failure-handler emits + stop reverse-pii ra…
cemililik Jun 14, 2026
1141921
fix(ci): wire check_doc_numerical_claims + clear the now-stale unwire…
cemililik Jun 14, 2026
a4e02d8
fix(trainer): deepspeed config-error class + OOM/checkpoint docs + sa…
cemililik Jun 14, 2026
0d67405
fix(pipeline): realpath collision + accurate skip-reason + state/chec…
cemililik Jun 14, 2026
4881fe5
fix(eval): harden judge/benchmark/safety eval-pipeline boundaries (L1…
cemililik Jun 14, 2026
1a0e8f5
fix(trainer+model+merge+synthetic): L1b LOW cleanup (L1b / F-P3-FABLE…
cemililik Jun 14, 2026
7351e73
fix(compliance): deterministic set hashing + cross-platform manifest …
cemililik Jun 15, 2026
5daf016
fix(config): make TIES/DARE merge knobs + synthetic sanity bound conf…
cemililik Jun 15, 2026
1f96124
fix(grpo): last-marker answer extraction + non-consuming gold probe (…
cemililik Jun 15, 2026
3bdb47e
fix(_http): set server_hostname for IP-pinned non-standard-port HTTPS…
cemililik Jun 15, 2026
767c5be
fix(reverse-pii): don't echo re.error text into JSON error envelope (…
cemililik Jun 15, 2026
365bc5c
fix(synthetic): bare-string JSON seed line uses parsed value not quot…
cemililik Jun 15, 2026
419fc88
fix(docs): normalise exit-code + top-level-block contradictions (PR#6…
cemililik Jun 15, 2026
3ae68fc
fix(docs): markdown-lint + mirror-link minors from doc sweep (PR#63-r…
cemililik Jun 15, 2026
9765849
fix(ci): drop obsolete test_cost_estimation filename guard from publi…
cemililik Jun 15, 2026
43f206e
fix(tools): notebook-pin guard imports on Python 3.10 via tomli backp…
cemililik Jun 15, 2026
22a3924
fix(tests): tighten brittle asserts + drop silent import fallback (PR…
cemililik Jun 15, 2026
ff0fc2e
fix(tests): probe top-level rich, not submodule, in chat availability…
cemililik Jun 15, 2026
df529b2
fix(tests): stub safe_post chokepoint, not requests.post, in judge na…
cemililik Jun 15, 2026
49124bf
fix(config): exclude_unset on pipeline stage-override dumps (PR#63-re…
cemililik Jun 15, 2026
ab68ca8
fix(cli): reject NaN/inf in float flag validators (PR#63-review)
cemililik Jun 15, 2026
357a618
fix(cli): exact-prefix checkpoint suffix match in resume resolver (PR…
cemililik Jun 15, 2026
14a283a
fix(cli): guard reject-path audit write with OSError handling (PR#63-…
cemililik Jun 15, 2026
cf53e38
fix(cli): sanitise PathTraversalRefused audit error_message (PR#63-re…
cemililik Jun 15, 2026
02ac6e6
fix(cli): reject non-list manifest 'artifacts' with exit-1 contract (…
cemililik Jun 15, 2026
4c1bac8
fix(compliance): surface rollback failures + reject empty strict-HMAC…
cemililik Jun 15, 2026
5d19ce5
perf(data_audit): single-decode JSONL streaming hot path (PR#63-review)
cemililik Jun 15, 2026
09713ec
fix(data): route falsy non-string System cells through clean_string (…
cemililik Jun 15, 2026
fbe9ad0
fix(judge): reject positional {} placeholders in rubric validation (P…
cemililik Jun 15, 2026
82a024d
fix(safety): broaden placeholder-head detection to any LABEL_N vocabu…
cemililik Jun 15, 2026
d0e016e
fix(review): resolve critical + high findings (PR#61/#63 review)
cemililik Jun 15, 2026
1d5dc4e
fix(review): resolve medium findings (PR#61/#63 review)
cemililik Jun 15, 2026
65ea3ab
fix(review): resolve low + nit findings (PR#61/#63 review)
cemililik Jun 15, 2026
8c77847
test(review): reset tier-disagreement dedup set in eu_ai_act test (PR…
cemililik Jun 15, 2026
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
4 changes: 2 additions & 2 deletions .agents/skills/cut-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ From [release.md](../../../docs/standards/release.md):
| Stable library symbol added to `forgelm.__all__` (e.g. new `verify_*` function) | MINOR | MINOR |
| Stable library symbol removed or signature changed | MAJOR | MAJOR |

`__version__` (single source of truth: [`pyproject.toml`](../../../pyproject.toml) line 7) tracks the *CLI / YAML / behavioural* contract. `__api_version__` (single source of truth: [`forgelm/_version.py`](../../../forgelm/_version.py)) tracks the *Python library* contract — operators who pin against it for feature detection rely on this signal. The two version numbers are decoupled by design: a release that adds a new training paradigm bumps `__version__` MINOR while leaving `__api_version__` untouched (no new public symbol), and a release that adds a new lazy-import target bumps both.
`__version__` (single source of truth: the `version =` line in [`pyproject.toml`](../../../pyproject.toml)) tracks the *CLI / YAML / behavioural* contract. `__api_version__` (single source of truth: [`forgelm/_version.py`](../../../forgelm/_version.py)) tracks the *Python library* contract — operators who pin against it for feature detection rely on this signal. The two version numbers are decoupled by design: a release that adds a new training paradigm bumps `__version__` MINOR while leaving `__api_version__` untouched (no new public symbol), and a release that adds a new lazy-import target bumps both.

Library consumers should compare `__api_version__` via `packaging.version.Version` rather than string `>=`, because lexicographic comparison breaks for two-digit minor / patch components (e.g. `"1.10.0" < "1.2.0"` as strings):

Expand Down Expand Up @@ -92,7 +92,7 @@ Rules:

### 3. Bump version

Edit [`pyproject.toml`](../../../pyproject.toml) line 7:
Edit the `version =` line in [`pyproject.toml`](../../../pyproject.toml):

```toml
version = "0.4.0" # was "0.3.1rc1" or "0.4.0rc1"
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/cut-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ From [release.md](../../../docs/standards/release.md):
| Stable library symbol added to `forgelm.__all__` (e.g. new `verify_*` function) | MINOR | MINOR |
| Stable library symbol removed or signature changed | MAJOR | MAJOR |

`__version__` (single source of truth: [`pyproject.toml`](../../../pyproject.toml) line 7) tracks the *CLI / YAML / behavioural* contract. `__api_version__` (single source of truth: [`forgelm/_version.py`](../../../forgelm/_version.py)) tracks the *Python library* contract — operators who pin against it for feature detection rely on this signal. The two version numbers are decoupled by design: a release that adds a new training paradigm bumps `__version__` MINOR while leaving `__api_version__` untouched (no new public symbol), and a release that adds a new lazy-import target bumps both.
`__version__` (single source of truth: the `version =` line in [`pyproject.toml`](../../../pyproject.toml)) tracks the *CLI / YAML / behavioural* contract. `__api_version__` (single source of truth: [`forgelm/_version.py`](../../../forgelm/_version.py)) tracks the *Python library* contract — operators who pin against it for feature detection rely on this signal. The two version numbers are decoupled by design: a release that adds a new training paradigm bumps `__version__` MINOR while leaving `__api_version__` untouched (no new public symbol), and a release that adds a new lazy-import target bumps both.

Library consumers should compare `__api_version__` via `packaging.version.Version` rather than string `>=`, because lexicographic comparison breaks for two-digit minor / patch components (e.g. `"1.10.0" < "1.2.0"` as strings):

Expand Down Expand Up @@ -92,7 +92,7 @@ Rules:

### 3. Bump version

Edit [`pyproject.toml`](../../../pyproject.toml) line 7:
Edit the `version =` line in [`pyproject.toml`](../../../pyproject.toml):

```toml
version = "0.4.0" # was "0.3.1rc1" or "0.4.0rc1"
Expand Down
98 changes: 82 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,20 @@ jobs:
# safe_get). This grep guard fails CI if any new module reaches
# for requests / urllib / httpx directly.
# Phase 16: every Pydantic field in forgelm/config.py must carry a
# description= argument so the autogenerated configuration reference
# stays in lockstep with the schema. Strict mode exits 1 on any
# description= argument so the hand-maintained configuration reference
# (docs/reference/configuration.md + -tr.md mirror) always has
# authoritative field text to mirror. Strict mode exits 1 on any
# undocumented field — a new contributor adding a field forgets the
# description here, not silently drifting from the operator-facing docs.
- name: Pydantic description= guard
run: python tools/check_field_descriptions.py --strict forgelm/config.py

# F-P8-C-19: promoted from an inline grep (which missed
# requests.Session()/aliased-import/whitespace-before-paren forms
# and had no own test) to a tested tool with its own
# tests/test_check_http_discipline.py.
- name: HTTP discipline guard
run: |
set +e
# Match ACTUAL CALLS only (the function name followed by an
# opening paren) so docstring prose mentioning the same names
# is not flagged.
violations=$(grep -rn -E '(requests\.(get|post|put|delete|patch|request|head)\(|urllib\.request\.urlopen\(|httpx\.[a-z]+\()' forgelm/ --include='*.py' | grep -v 'forgelm/_http.py')
if [ -n "$violations" ]; then
echo "::error::Found undisciplined HTTP call(s) outside forgelm/_http.py:"
echo "$violations"
echo ""
echo "Route through forgelm._http.safe_post / safe_get instead."
echo "See docs/standards/architecture.md 'HTTP discipline' section."
exit 1
fi
run: python tools/check_http_discipline.py

# --- Job 2: Test (matrix across Python versions) ---
test:
Expand Down Expand Up @@ -195,6 +187,15 @@ jobs:
# tools/check_site_claims.py for what's checked and why.
run: python3 tools/check_site_claims.py --strict

- name: Doc numerical-claims drift check (strict)
# F-P8-C-06 (W1/H5): re-derives the canonical counts (secret
# families, trainer types, quickstart templates, webhook events)
# from the Python sources of truth and fails the build when a doc
# asserts a stale number — e.g. the "five webhook events" prose that
# drifted after the vocabulary grew to eight. Wired once H5's 5->8
# doc-drift fix made the guard green at HEAD.
run: python3 tools/check_doc_numerical_claims.py --strict

- name: Bilingual doc H2/H3/H4 parity check (strict)
# Phase 24: extended structural parity guard. Where the prior
# inline check counted H2 only and missed reordered / demoted
Expand Down Expand Up @@ -251,6 +252,71 @@ jobs:
# tools/check_audit_event_catalog.py.
run: python3 tools/check_audit_event_catalog.py --strict

- name: TR cross-links prefer the TR mirror (strict)
# W1/H11 (F-P8-C-04): a docs/**/*-tr.md page must route its in-prose
# cross-references to the Turkish sibling when a <stem>-tr.md mirror
# exists — a Turkish operator following a 'Bkz.'/'See also' link must
# stay in Turkish, not silently land on the English page. Neither
# check_anchor_resolution (link resolves) nor check_bilingual_parity
# (heading spine) catches this. The **Ayna:** backlink line is exempt.
# 62 leaks across 19 files at HEAD were swept to zero in H11.
run: python3 tools/check_tr_links_prefer_mirror.py --strict

- name: Library-API doc ↔ __all__ drift check (strict)
# W1/H11 (F-P8-C-07): forgelm.__all__ must match the symbol roster in
# docs/reference/library_api_reference.md in both directions. Previously
# unwired — a renamed/removed public symbol could drift from the doc.
run: python3 tools/check_library_api_doc.py --strict

- name: Bilingual fenced-code-block parity (strict)
# W1/H11 (F-P8-C-13): the Wave 6 fenced-block-count + per-ordinal
# YAML-key parity guard was an orphan (wired nowhere, no own test).
# Catches TR code-block / YAML-key drift the spine guard cannot see.
run: python3 tools/check_bilingual_code_blocks.py --strict

- name: ForgeConfig YAML snippet validation (strict)
# W1/H11 (F-P8-C-07): every ForgeConfig-shaped YAML snippet in the docs
# must pass Pydantic validation. Previously unwired despite catching
# real doc-vs-schema drift.
run: python3 tools/check_yaml_snippets.py --strict

- name: Site chrome (EN/TR translation) parity
# W1/H11 (F-P8-C-07): the active-tier (EN<->TR) translation-key sets in
# site/js/translations.js must stay in lockstep. Run WITHOUT --strict:
# --strict additionally gates the deferred de/fr/es/zh tiers, which are
# a known v0.6.x backlog the guard's own help text says is "NOT wired
# into CI". Default mode enforces only the active-tier parity rule.
run: python3 tools/check_site_chrome_parity.py

- name: Module-size ceiling guard (strict)
# W1/H11 (F-P8-C-07): no forgelm/ module may drift past the
# architecture-doc ~1000-LOC sub-package-split ceiling. Previously
# unwired — module-size regressions could merge with green CI.
run: python3 tools/check_module_size.py --strict

- name: Wizard defaults schema-sync (strict)
# W1/H11 (F-P8-C-07): the wizard's shipped defaults JSON must match the
# Pydantic schema source of truth. Was gauntlet-only (human discipline).
run: python3 tools/check_wizard_defaults_sync.py

- name: No public-tree refs into gitignored working-memory
# W1/H11 (F-P8-C-07): public-tree files must not cite docs/analysis/ or
# docs/marketing/. Was gauntlet-only (human discipline) until now.
run: python3 tools/check_no_analysis_refs.py

- name: Marketing-site version sync (strict)
# W1/H11 (F-P8-C-07): the marketing site's displayed version must match
# CHANGELOG's latest released header. Was gauntlet-only.
run: python3 tools/update_site_version.py --check

- name: Notebook forgelm pin lockstep (strict)
# W2/M7 (F-P8-C-09): every notebooks/*.ipynb !pip install forgelm pin
# must target a shipping wheel — the exact pyproject version or the
# latest released CHANGELOG version (so onboarding notebooks never
# point users at a pre-release rc). Previously unwired; the pins had
# drifted two minors (0.5.7 vs released 0.7.0) undetected.
run: python3 tools/check_notebook_pins.py --strict

- name: User-manual self-contained link guard (strict)
# Post-v0.7.0 cycle: the docs/usermanuals/ tree is the source of
# truth for the static-site SPA viewer (site/usermanual.html +
Expand Down
18 changes: 7 additions & 11 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,15 @@ jobs:
shell: bash
run: python -m pip install pytest pytest-cov

- name: Verify --ignore target exists
shell: bash
# Guard against silent rename: if test_cost_estimation.py is renamed
# or removed without updating the --ignore flag below, the publish
# would silently start running it (or no-op the ignore). Fail fast.
run: test -f tests/test_cost_estimation.py

- name: Test (CPU-only, no-network)
shell: bash
# test_cost_estimation is excluded per Faz 31 closure plan: it
# depends on a snapshot pricing fixture that drifts on a different
# cadence than the release matrix.
run: pytest tests/ -q --ignore=tests/test_cost_estimation.py
# Drift-sensitive tests (test_cost_estimation: snapshot pricing
# fixture on a different cadence than the release matrix) are
# excluded via the @pytest.mark.fixture_drift marker — F-P8-C-20
# made the marker the single source of truth, so no filename guard
# is needed: a renamed/removed test simply keeps (or drops) the
# marker, and the exclusion follows the marker, not a brittle path.
run: pytest tests/ -q -m 'not fixture_drift'
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Generate SBOM (CycloneDX 1.5)
shell: bash
Expand Down
21 changes: 17 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ ForgeLM/
│ │ # _aggregator, _streaming, _simhash, _minhash,
│ │ # _pii_regex, _pii_ml, _secrets, _quality,
│ │ # _croissant, _summary, _splits
│ ├── config.py # Pydantic schemas (19 models)
│ ├── config.py # Pydantic schemas (23 models)
│ ├── trainer.py # TRL wrapper (SFT/DPO/SimPO/KTO/ORPO/GRPO)
│ ├── model.py # HF + PEFT model loading
│ ├── data.py # Dataset loading + format detection
Expand Down Expand Up @@ -158,11 +158,13 @@ Default workflow for a non-trivial change:
python3 tools/check_no_analysis_refs.py && \
python3 tools/check_no_unguarded_sys_modules_pop.py && \
python3 tools/check_audit_event_catalog.py --strict && \
python3 tools/check_tr_links_prefer_mirror.py --strict && \
python3 tools/check_usermanual_self_contained.py --strict && \
python3 tools/check_notebook_pins.py --strict && \
python3 tools/update_site_version.py --check
```

All thirteen must pass. The first four are the historical gauntlet;
All fifteen must pass. The first four are the historical gauntlet;
the three doc guards (Wave 3 / Wave 4 / Wave 5 additions) catch
bilingual structural drift, broken markdown anchors, and CLI ↔ docs
help-text drift before the PR opens. The wizard-defaults guard
Expand All @@ -180,7 +182,14 @@ Default workflow for a non-trivial change:
table in `docs/reference/audit_event_catalog.md` in both directions —
the append-only audit log is an EU AI Act Art. 12 contract, and this
guard was previously unwired while six `pipeline.*` stage events
drifted into the code uncatalogued. The
drifted into the code uncatalogued. The TR-links-prefer-mirror
guard (full-project-review W1/H11, F-P8-C-04) fails when a
`docs/**/*-tr.md` page links the un-suffixed English sibling even
though a `<stem>-tr.md` mirror exists — a Turkish reader following
an in-prose link must stay in Turkish; the `**Ayna:**` backlink
line is the one exempt case. 62 leaks across 19 files were swept
to zero when this guard landed — see `docs/standards/localization.md`
"Structural mirror rule". The
usermanual self-contained guard (post-v0.7.0 cycle) blocks any
link inside `docs/usermanuals/` that would 404 in the static SPA
viewer: every link must be either a `#/<section>/<page>` SPA
Expand All @@ -192,7 +201,11 @@ Default workflow for a non-trivial change:
latest released header and fails the PR if any of the 15+ literals
across `site/*.html` and `site/js/translations.js` has drifted; the
v0.5.5 → v0.6.0 release shipped with the hero badge still reading
`v0.5.5`, which this guard now prevents.
`v0.5.5`, which this guard now prevents. The notebook-pin guard
(v0.7.0 / F-P8-C-09) verifies that every `*.ipynb` in the repo
pins its kernel and package versions so that example notebooks
remain reproducible; it was wired into CI at the v0.7.0 pin bump
but was absent from the local gauntlet until this update.

## Etiquette when communicating with the user

Expand Down
Loading
Loading