Skip to content

docs(compliance): say that a safety evaluation with no verdict keeps the model and exits 0 - #988

Closed
cemililik wants to merge 1 commit into
developmentfrom
docs/wave0-no-verdict-safety-gate
Closed

cemililik wants to merge 1 commit into
developmentfrom
docs/wave0-no-verdict-safety-gate

Conversation

@cemililik

@cemililik cemililik commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Eight documents (and their Turkish mirrors) said that exit code 0 means every gate passed, that a safety-classifier load failure "halts" the pipeline and leaves no final_model/, and that classification errors count as unsafe. In code, a safety evaluation that produces no verdict (safety.evaluation_completed: false: the classifier failed to load, the probes file is missing or empty, or most verdicts were unreadable) keeps the model and the run exits 0 (4 with the approval gate) regardless of evaluation.auto_revert. This documents the real behaviour. The code is unchanged.

Related issues

Refs #87 — the documentation half. Making a missing verdict fail closed would turn exit 0 into a non-zero code for runs that exit 0 today, which is a breaking change to the public exit-code contract; the owner decided it waits for a major version.

Changes — each row shows what it said and what it says now

Where Said Now says
docs/standards/error-handling.md exit 0 ⇒ every gate passed …every gate that ran to a verdict passed; a safety evaluation with no verdict keeps the model and exits 0 regardless of auto_revert
docs/usermanuals/{en,tr}/reference/exit-codes.md exit 0 "does mean every configured gate passed" the same exception, and "check safety.passed and safety.evaluation_completed in the JSON output"
docs/usermanuals/{en,tr}/reference/json-output.md success: true when the run completed also true for a run whose safety evaluation produced no verdict; read safety.evaluation_completed
docs/reference/audit_event_catalog{,-tr}.md all gates passed every gate that produced a verdict passed
docs/guides/safety_compliance{,-tr}.md "Classification errors are treated as unsafe"; "any gate failure triggers auto-revert"; flow ends "exit code 3" a pair the classifier cannot answer is counted as unscored; no verdict ⇒ model kept, exit 0 (4 with the approval gate)
docs/guides/iso_soc2_deployer_guide{,-tr}.md (incident response) classifier load failure ⇒ pipeline.failed propagates, no final_model/ the audit.classifier_load_failed event fires and evaluation_completed: false is recorded, the model stays, exit 0; alert on those, not on the exit code
docs/qms/risk_treatment_plan{,-tr}.md "deployer pipeline halts on non-zero exit" the run is not halted; branch on safety.evaluation_completed / safety.passed or on the audit event
docs/reference/architecture.md "Errors are treated as unsafe (fail-safe principle)" an unanswerable pair is unscored; no verdict ⇒ model kept

Checked against the code

  • forgelm/safety/_orchestrator.py and _gates.py (_MAX_UNSCORED_RATIO = 0.5): when the classifier does not load, the probes file is missing or empty, or more than half the verdicts are unscored, the result has evaluation_completed=False.
  • forgelm/trainer.py: if not getattr(safety_result, "evaluation_completed", True): self._log_gate_kept_no_revert(...); return True: the model is kept and the run continues to success (or to the approval gate).

What this changes for a deployer

A pipeline that gates promotion on "exit 0" would promote a model whose safety evaluation never produced a verdict. The pages now tell it to read safety.evaluation_completed and safety.passed. This lowers what could be relied on from the exit code and matches the behaviour that has always been there.

Not done here

Type

  • Documentation

Testing

  • The full CLAUDE.md gauntlet from a clean worktree of this branch: exit 0 (bilingual parity, code-block parity, anchors, source-path references, exit-code prose).

Checklist

  • English and Turkish mirrors updated together (Turkish wording needs the owner's review)
  • CHANGELOG entry under [Unreleased]

🤖 Generated with Claude Code

…the model and exits 0

Exit 0 was documented as "every gate passed", a classifier load failure as
halting the pipeline with no final_model/, and classification errors as
unsafe. In code an evaluation that produces no verdict
(evaluation_completed=False: classifier not loaded, probes file missing or
empty, most verdicts unreadable) keeps the model and exits 0 (4 with the
approval gate) regardless of auto_revert. The behaviour is unchanged; making
it fail closed is a breaking exit-code change left for a major version.

Refs #87

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Sorry @cemililik, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 13 hours and 15 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 17 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 3 included reviews currently available. Your 48 included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 5a542cb3-7401-47cc-b325-8655ec52b94b
📥 Commits

Reviewing files that changed from the base of the PR and between 56b4f0d and 9f5f699.

📒 Files selected for processing: 15
  • CHANGELOG.md
  • docs/guides/iso_soc2_deployer_guide-tr.md
  • docs/guides/iso_soc2_deployer_guide.md
  • docs/guides/safety_compliance-tr.md
  • docs/guides/safety_compliance.md
  • docs/qms/risk_treatment_plan-tr.md
  • docs/qms/risk_treatment_plan.md
  • docs/reference/architecture.md
  • docs/reference/audit_event_catalog-tr.md
  • docs/reference/audit_event_catalog.md
  • docs/standards/error-handling.md
  • docs/usermanuals/en/reference/exit-codes.md
  • docs/usermanuals/en/reference/json-output.md
  • docs/usermanuals/tr/reference/exit-codes.md
  • docs/usermanuals/tr/reference/json-output.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

This documentation-only PR updates English and Turkish compliance, exit-code, JSON-output, audit, architecture, deployer, and risk-treatment guidance to reflect that a safety evaluation with no verdict keeps the model and exits 0 (or 4 with approval), while scored failures still revert and exit 3; it also adds a changelog entry.

Flow diagram for safety evaluation verdict handling

flowchart TD
    A[Safety evaluation] --> B{Verdict produced?}
    B -->|Yes| C{Safety gate passed?}
    C -->|Yes| D[Keep model]
    C -->|No, auto_revert enabled| E[Revert model and exit 3]
    B -->|No: evaluation_completed false| D
    D --> F[Exit 0]
    D --> G[Exit 4 with approval gate]
    F --> H[Inspect safety.evaluation_completed and safety.passed]
    G --> H
Loading

File-Level Changes

Change Details Files
Correct exit-code and gate semantics for safety evaluations that produce no verdict.
  • Document safety.evaluation_completed: false for classifier-load failures, missing or empty probes, and predominantly unreadable verdicts.
  • Clarify that the model is kept and the run exits 0, or 4 with human approval, regardless of auto_revert.
  • Distinguish no-verdict evaluations from scored gate failures, which still auto-revert and exit 3.
  • Update deployer guidance to branch on JSON safety fields or audit events rather than exit status alone.
docs/standards/error-handling.md
docs/usermanuals/en/reference/exit-codes.md
docs/usermanuals/tr/reference/exit-codes.md
docs/usermanuals/en/reference/json-output.md
docs/usermanuals/tr/reference/json-output.md
docs/reference/audit_event_catalog.md
docs/reference/audit_event_catalog-tr.md
docs/guides/safety_compliance.md
docs/guides/safety_compliance-tr.md
docs/guides/iso_soc2_deployer_guide.md
docs/guides/iso_soc2_deployer_guide-tr.md
docs/qms/risk_treatment_plan.md
docs/qms/risk_treatment_plan-tr.md
docs/reference/architecture.md
Align safety, audit, architecture, and operational documentation with the existing no-verdict runtime behavior.
  • Replace claims that classification errors are unsafe with the unscored-pair behavior.
  • Explain that no-verdict runs still complete successfully and emit the relevant audit signal.
  • Update audit-event descriptions so successful completion does not imply every safety gate produced a verdict.
  • Mirror the behavior changes in English and Turkish documentation.
docs/guides/safety_compliance.md
docs/guides/safety_compliance-tr.md
docs/guides/iso_soc2_deployer_guide.md
docs/guides/iso_soc2_deployer_guide-tr.md
docs/qms/risk_treatment_plan.md
docs/qms/risk_treatment_plan-tr.md
docs/reference/audit_event_catalog.md
docs/reference/audit_event_catalog-tr.md
docs/reference/architecture.md
Record the documentation correction in the unreleased changelog. CHANGELOG.md

Possibly linked issues

  • #DOC-TR10-011: The PR directly corrects the issue’s English and Turkish exit-code statements, including the no-verdict exception and JSON fields to check.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@cemililik

Copy link
Copy Markdown
Collaborator Author

Superseded by #1000: the wave-0 fixes are combined by theme into five pull requests to cut the review load. This branch's commits are included there unchanged apart from the CHANGELOG.md merge; the branch stays on the remote.

@cemililik cemililik closed this Oct 18, 2026
cemililik added a commit that referenced this pull request Oct 18, 2026
… six-language site copy, described as the code behaves (#1000)

## Summary

Compliance- and privacy-facing wording corrected to what the code does,
plus the six-language site copy that repeated the same claims. Six
earlier branches combined into one pull request, replacing #983, #986,
#988 and #991 (to be closed as superseded) and two branches that were
never opened. **This is compliance wording; please read the before/after
tables.**

## ⚠️ Localization exception

`docs/standards/localization.md` keeps German, French, Spanish and
Chinese as deferred tiers and says not to machine-translate them. At the
owner's decision I **wrote the DE / FR / ES / ZH site strings myself**,
with no native review. English and Turkish are authoritative; the other
four need a native reader before they can be trusted. A follow-up issue
for that is drafted, not yet filed.

## Related issues

Refs #73, #99, #90, #94, #101, #87, #114, #75, #86, #89, #92, #98, #110,
#112. The code halves stay open: whether the gate should ever compare
trainer and approver, failing closed on a missing safety verdict
(breaking), attaching SBOMs to the release.

## Changes

| Theme | Said | Now says |
|---|---|---|
| **Segregation of duties** (ISO 27001 / SOC 2 mappings, SoA, SOP,
deployer guide, manual) | the approval gate "enforces trainer ≠
approver", "dual-controlled" | it **records** trainer and approver
identities and does not compare them; both are self-asserted; keeping
them different people is the deployer's control.
`require_human_approval` is not enforced for strict tiers by
`ConfigError` (it only is when safety evaluation is off) |
| **GDPR / KVKK manual page** | identifiable subjects are removed; "no
specific person's data is recoverable from the model"; an
`international_transfers` setting; audit report with source attribution
and SHA-256 manifest; retention "auto-deletes originals" | eight
identifier formats are masked, names and free text are not; the report
is counts and summaries, not written to the audit log; retention is
reported, not enforced; memorisation is not measured |
| **No-verdict safety evaluation** (8 documents + TR) | exit 0 ⇒ every
gate passed; classifier load failure halts the run; classification
errors count as unsafe | a safety evaluation that produced no verdict
(`evaluation_completed: false`) keeps the model and exits 0 (4 with the
approval gate) regardless of `auto_revert`; code unchanged |
| **SBOM** (reference, SOP, guides, manuals, mappings) | `gh release
download …`; "re-emit from the git tag"; "licence extraction in SBOM" |
workflow-run artifacts, 90-day retention; `gh run download`; the file is
the CI runner's `pip list` (test tooling included, no dependency graph,
no licences) |
| **Article 12 / 14** (audit-event catalogue, audit-log and
human-oversight pages) | the audit log is "mandated by Article 12"; the
gate "implements" Article 14 | the log is development-time evidence that
supports Annex IV; Article 12 logging and Article 14 in-use oversight
belong to the deployed system |
| **Site, six languages** | benchmark failure "fails (exit 3)";
"dual-controlled"; Slack/Teams/Discord; "PII redacted"; "satisfying the
access-request side of the GDPR"; wizard "Enforce automatic deletion";
"SHA-256 manifest"; DeepSpeed "presets" | exit 3 only with `auto_revert:
true`; records the approver; Slack-format, Teams and Discord need a
relay; common formats masked, names not detected; reverse-pii finds only
what is literally in the scanned files; retention mode reserved; SHA-256
sidecar; bring your own DeepSpeed JSON |

The site GGUF strings describe the `.sha256` sidecar, the retention
strings the reserved mode, and the DeepSpeed strings the preset caveat;
they match the GGUF, code and docs pull requests, so **merge those
first**. A new site test keeps the retired phrases out of English,
Turkish and the HTML (mutation-checked).

### What this changes for a deployer

A DPIA or audit response can no longer cite ForgeLM for: segregation of
duties being enforced, personal data being removed or unrecoverable from
the model, the SBOM being on the release page, or the audit log being
the Article 12 mechanism.

## Type

- [x] Documentation (and site copy)

## Testing

- The full `CLAUDE.md` gauntlet from a clean worktree of this branch:
exit 0. (An earlier run failed `tests/test_turkish_glossary_terms.py`
because the Article 12 rewrite wrote "Ek IV" instead of "Annex IV",
fixed here, then two timing-based regex linearity tests failed while two
gauntlets ran at once; they pass alone and in this final run.)
- `node --test tests/site/*.test.cjs`: 81 pass; English ↔ Turkish keys
in lockstep.

## Checklist

- [x] English and Turkish updated together (Turkish wording needs the
owner's review)
- [ ] DE / FR / ES / ZH reviewed by a native speaker — **not done**
- [x] CHANGELOG entries under `[Unreleased]`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant