Skip to content

refactor(intrinsics): guardian.py whole-file migration + documents= kw-only + auto-context discovery (Epic #929 Phase 1) #1139

@planetf1

Description

@planetf1

Parent epic: #929
Design proposal: PR #1080 §17 Q3
Phase: 1 (Wave 3 — start after 1.A merges)
Depends on: 1.A
Independent of: 1.B, 1.C, 2.1
Closes: #1094

⚠️ Pre-flight dependency: PR #935 must be merged (or conflict-plan agreed) before starting this issue. PR #935 is a large open docs PR touching docs/docs/advanced/intrinsics.md, AGENTS.md, and guardian examples — the same files this issue touches. Rebased onto main 2026-05-19.

Do not start #1071 (intrinsic-backed Requirement subclass for Guardian) before this issue merges. Once merged, the new Adapter types from Phase 0/1 are the correct foundation for that feature.


Problem

mellea/stdlib/components/intrinsic/guardian.py (221 lines, verified main) contains four helpers: policy_guardrails, guardian_check, factuality_detection, factuality_correction. All construct via the old API. Three related concerns:

  1. factuality_detection/factuality_correction take documents as a positional argument — inconsistent with kw-only patterns elsewhere
  2. Return type for factuality helpers changed from float to str per fix: intrinsic function signatures #1003 (closed PR feat: normailze intinsics interfaces #1028 inherited the direction) — this PR codifies it
  3. When documents=None, callers are forced to pass documents explicitly even when those documents are already in conversation context

Agreed design

Follows the per-helper-file migration template from PR #1080. File-specific deltas:

(i) Migrate all four helpers to new types

Each helper has its own declared output contract; validate per-helper.

(ii) documents= keyword-only on factuality helpers

factuality_detection and factuality_correction get documents: list[str] | None = None as keyword-only. policy_guardrails and guardian_check do NOT take documents=.

(iii) Factuality return type str

Both factuality functions return str (per #1003). Update tests accordingly.

(iv) Auto-context document discovery (factuality only)

When documents=None: the helper auto-discovers user-supplied documents from ordinary conversation context (e.g. Message content). No _docs-specific extraction path — direction of PR #1028 adopted but not its specific code path. Per §17 Q3 (resolved 2026-05-20).

The helper reads whatever documents are present in the context it receives. Caller responsibility: populate context via explicit documents=, prior Messages, retrieval, etc.

Implementer's choice (and must be tested): what happens when documents=None AND no context documents exist — sentinel return or explicit error. Document the choice.

Why one PR

All four helpers share guardian.py. Three theoretical PRs (Guardian-core / factuality-pair / auto-context) would conflict on the same file.

Scope

Out of scope

Other helper files (1.B, 1.C), reviving #1028's _docs scanning code, modifying how callers populate context, adding new Guardian capabilities.

Acceptance criteria

policy_guardrails, guardian_check:

  • Construct via new types
  • Accept model_options: dict | None = None
  • Declared output contract; contract-break raises, forward-compat does not
  • No documents= parameter

factuality_detection, factuality_correction:

  • Construct via new types
  • Accept model_options: dict | None = None
  • documents: list[str] | None = None is keyword-only; positional second arg raises TypeError
  • Return type is str (per fix: intrinsic function signatures #1003)
  • documents=[...] works (explicit pass-through)
  • documents=None with documents in conversation context works (auto-discovery)
  • No _docs-specific code path in this file
  • Behaviour when documents=None and no context documents: documented and tested explicitly

Common:

Test plan

Common per-helper tests (see template). Plus:

  • test_factuality_detection_explicit_documents — pass-through
  • test_factuality_detection_auto_discovery_from_context
  • test_factuality_detection_no_documents_anywhere — implementer-chosen behaviour
  • test_factuality_documents_kwonly — positional second arg raises TypeError
  • test_factuality_return_type_is_str

Breaking changes

  • documents= becomes keyword-only for factuality_detection/factuality_correction. Positional callers must update. Surface in changelog with migration example.
  • Return type change (float → str) already in main per fix: intrinsic function signatures #1003 — this codifies it as a contract.

References

Metadata

Metadata

Assignees

Labels

area/intrinsicsGranite intrinsic adapters: RAG, Guardian, Corearea/stdlibCore abstractions: Context, MOT, SamplingStrategy, formatters, serializationrefactor

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions