Skip to content

[Wave 4] Low/info — Docs: docs/design/gdpr_erasure.md #719

Open

Description

@cemililik

Wave 4 · 10 finding(s) in 10 fix package(s). One pass over this document; keep the Turkish mirror in sync.

Findings

  • DOC-D2B02-041 (docs, Low) — docs/design/gdpr_erasure.md: wrong detail — 'ForgeLM only needs to act on three' Art. 17(1) triggers.
    severity Low
    Where. docs/design/gdpr_erasure.md:35 · type: wrong detail
    The document says. 'ForgeLM only needs to act on three' Art. 17(1) triggers.
    What the code does. The table marks four triggers (a-d) as in scope. This is an internal count inconsistency, not a legal judgement.
    Code references. docs/design/gdpr_erasure.md:37-44
    Proposed correction. "…act on four…" (or adjust the table).

  • DOC-D2B02-042 (docs, Low) — docs/design/gdpr_erasure.md: false claim — data_audit_report.json has a lang_sample field carrying snippets of up to 512 characters.
    severity Low
    Where. docs/design/gdpr_erasure.md:63 · type: false claim
    The document says. data_audit_report.json has a lang_sample field carrying snippets of up to 512 characters.
    What the code does. lang_sample is internal aggregator state used only to compute the top-3 languages. It is not written to the report.
    Code references. forgelm/data_audit/_aggregator.py:78, forgelm/data_audit/_aggregator.py:128-135, forgelm/data_audit/_aggregator.py:287
    Proposed correction. Remove the lang_sample claim, or name the report fields that can actually carry text.

  • DOC-D2B02-043 (docs, Low) — docs/design/gdpr_erasure.md: wrong detail — The retention check uses filesystem mtime as its primary age signal (also L165), and logs a data.retention_age_source=mtime note for stand-alone JSONL co…
    severity Low
    Where. docs/design/gdpr_erasure.md:147-150 · type: wrong detail
    The document says. The retention check uses filesystem mtime as its primary age signal (also L165), and logs a data.retention_age_source=mtime note for stand-alone JSONL corpora.
    What the code does. Age comes from the audit log first (the per-run first event, else global genesis) and falls back to mtime. The fallback is a per-violation age_source field. No audit note/event is emitted, and corpora are not scanned at all.
    Code references. forgelm/cli/subcommands/_purge.py:1171-1237, forgelm/cli/subcommands/_purge.py:1372-1400
    Proposed correction. Describe audit-first age resolution with the age_source field, and note that corpora are not scanned.

  • DOC-D2B02-044 (docs, Low) — docs/design/gdpr_erasure.md: wrong detail — --run-id matches the top-level run_id in <output_dir>/audit_log.jsonl. §5.3/§5.4 list target_kind policy_check.
    severity Low
    Where. docs/design/gdpr_erasure.md:192 · type: wrong detail
    The document says. --run-id matches the top-level run_id in <output_dir>/audit_log.jsonl. §5.3/§5.4 list target_kind policy_check.
    What the code does. Run mode never consults the audit log for the run_id; it only resolves paths. --check-policy emits no events, so target_kind 'policy_check' never occurs.
    Code references. forgelm/cli/subcommands/_purge.py:821-866, forgelm/cli/subcommands/_purge.py:1108-1168
    Proposed correction. Drop the audit-log match claim and the policy_check value.

  • DOC-D2B02-045 (docs, Low) — docs/design/gdpr_erasure.md: wrong detail — --dry-run is mutually exclusive with --check-policy, and combining them is a ConfigError. L183: 'Combining flags is a ConfigError'.
    severity Low
    Where. docs/design/gdpr_erasure.md:198 · type: wrong detail
    The document says. --dry-run is mutually exclusive with --check-policy, and combining them is a ConfigError. L183: 'Combining flags is a ConfigError'.
    What the code does. --dry-run is outside the mutually-exclusive group. --check-policy --dry-run runs the report and exits 0 (reproduced). Mode-flag combinations are rejected by argparse with exit 2, not ConfigError (1).
    Code references. forgelm/cli/_parser.py:1096-1115, forgelm/cli/_parser.py:1158-1162
    Proposed correction. "--dry-run is ignored by --check-policy; mode flags are argparse-exclusive (exit 2)."

  • DOC-D2B02-046 (docs, Low) — docs/design/gdpr_erasure.md: stale — 'Standard ForgeLM 0/1/2/3/4 contract' plus code 5 (L204, L214), and '--check-policy always exits 0' (L214).
    severity Low · already tracked: KNOWN-OPEN C31-EXIT-CODE-PROSE — docs/roadmap/phase-16-trust-surface-hardening.md:782-785
    Where. docs/design/gdpr_erasure.md:204 · type: stale
    The document says. 'Standard ForgeLM 0/1/2/3/4 contract' plus code 5 (L204, L214), and '--check-policy always exits 0' (L214).
    What the code does. The contract is 0-6. --check-policy exits 1 when an explicit --config fails to load.
    Code references. forgelm/cli/_exit_codes.py:42-52, forgelm/cli/subcommands/_purge.py:1126-1140
    Proposed correction. Cite the 0–6 contract; "--check-policy exits 0 on a successful report and 1 when --config cannot be loaded".

  • DOC-D2B02-047 (docs, Low) — docs/design/gdpr_erasure.md: wrong detail — Exit 1 covers '--row-id directory mode without --row-matches=all', and the consent model is described in '§3.5'.
    severity Low
    Where. docs/design/gdpr_erasure.md:209 · type: wrong detail
    The document says. Exit 1 covers '--row-id directory mode without --row-matches=all', and the consent model is described in '§3.5'.
    What the code does. Directory corpora are always rejected (isfile check), whatever --row-matches says. The consent model is in §10 Q4, not §3.5.
    Code references. forgelm/cli/subcommands/_purge.py:262-269, docs/design/gdpr_erasure.md:441-443
    Proposed correction. "directory --corpus (always rejected)"; change the xref to §10 Q4.

  • DOC-D2B02-048 (docs, Low) — docs/design/gdpr_erasure.md: false claim — On a step-5 rename failure the temp file is left on disk for forensic inspection.
    severity Low
    Where. docs/design/gdpr_erasure.md:227 · type: false claim
    The document says. On a step-5 rename failure the temp file is left on disk for forensic inspection.
    What the code does. On OSError or UnicodeDecodeError the temp file is unlinked before re-raising.
    Code references. forgelm/cli/subcommands/_purge.py:354-366
    Proposed correction. "…the temp file is removed and a data.erasure_failed event is appended; the original corpus is unchanged."

  • DOC-D2B02-049 (docs, Low) — docs/design/gdpr_erasure.md: stale — §7 lists the named tests that ship. #​10 asserts dry-run leaves the corpus AND the audit log byte-identical; #​11 says a second concurrent purge 'sees a row already…
    severity Low
    Where. docs/design/gdpr_erasure.md:375-386 · type: stale
    The document says. §7 lists the named tests that ship. #​10 asserts dry-run leaves the corpus AND the audit log byte-identical; #​11 says a second concurrent purge 'sees a row already erased notice and exits 0'. Also L88, L229 and L302 name specific tests.
    What the code does. None of the named tests exist under those names (the actual suite uses class-based names, e.g. test_row_erasure_target_id_is_hashed_not_cleartext). Dry-run appends audit events by design (test_dry_run_creates_salt_and_audit_intent_by_design). A second purge of an erased row finds no match, emits data.erasure_failed (NoMatchingRow) and exits 1.
    Code references. tests/test_gdpr_erasure.py:87-1430, forgelm/cli/subcommands/_purge.py:556-567, forgelm/cli/subcommands/_purge.py:702-713
    Proposed correction. Replace the §7 table with the shipped test classes, and correct #​10 and #​11 to the implemented behaviour.

  • DOC-D2B02-050 (docs, Low) — docs/design/gdpr_erasure.md: stale — The file map lists compliance.py record_erasure_event(...), trainer.py pre-flight retention check, a sop_data_management.md 'Retention + erasure procedure' subsec…
    severity Low
    Where. docs/design/gdpr_erasure.md:400-407 · type: stale
    The document says. The file map lists compliance.py record_erasure_event(...), trainer.py pre-flight retention check, a sop_data_management.md 'Retention + erasure procedure' subsection, and (L405/L310) a new GDPR section in safety_compliance.md.
    What the code does. None of these exist: no record_erasure_event, no trainer retention code, no erasure subsection in the SOP, no GDPR section in safety_compliance.md (only the example prompt at L227).
    Code references. forgelm/compliance.py, forgelm/trainer.py, docs/qms/sop_data_management.md:110-115, docs/guides/safety_compliance.md:227
    Proposed correction. Mark these rows "not implemented" or remove them.

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.

Activity

  1. added
    documentationImprovements or additions to documentation
    backlog: knownAlready tracked in docs/roadmap
    severity: lowMinor defect, inaccuracy or rough edge
    source: review-2026-10Found by the October 2026 code and documentation review
    wave: 4Roadmap wave 4: low / info / watch, when touching the module
    on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backlog: knownAlready tracked in docs/roadmapdocumentationImprovements or additions to documentationseverity: lowMinor defect, inaccuracy or rough edgesource: review-2026-10Found by the October 2026 code and documentation reviewwave: 4Roadmap wave 4: low / info / watch, when touching the module

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions