← Về thư mục
📄 / / academic-research-skills / shared / references / firm_rules.md

Firm Rules — Canonical Source

This file is the single source of truth for firm-rule wording that is otherwise duplicated verbatim across agent prompts. Each block below is the canonical text; the agent prompts listed under "Mirrored in" carry a byte-identical copy (modulo the agent's self-reference noun, where noted). scripts/check_firm_rules_sync.py fails CI if any mirror drifts from the canonical block here.

Why this file exists: the contamination R-L3-2-* wording provably drifted between v3.9.0 (contamination-only) and v3.9.4 (contamination-AND-temporal) drafts before being single-sourced here. Manual 5×-duplication is not enough; the sync lint pins it.

Related mechanisms: the Phase Boundary enforcement-status sentence (factual status prose, not a behavioral firm rule) is single-sourced as CANONICAL_ENFORCEMENT inside scripts/check_v3_9_2_phase_boundary.py (#491) rather than here — same defrift goal, separate mechanism co-located with its only consumer.

ID namespaces (do NOT confuse — they were overloaded until v3.10 PR-A):


Contamination advisory firm rules (R-L3-2-*)

Canonical wording note: R-L3-2-A carries the v3.10 PR-B broad form (default-advisory + opt-in strict extension across contamination AND temporal namespaces; temporal strict not yet wired). This block is the single source of truth for the wording; the contamination mirrors below are intentionally by-ID references, not full-block copies (see the "Mirrored in (contamination rules)" note).

Mirrored in (contamination rules):

These mirrors are intentionally by-ID prose references, not full-block copies (e.g. crossref's "the user retains discretion per R-L3-2-A", the formatter's "advisory per ... R-L3-2-A + R-L3-2-E"). The wording lives in exactly one place — the canonical block above — so the single-source goal (D3) is met without duplicating the full rule text into five files. The v3.10 PR-B reword therefore changes ONLY the canonical block, not the mirrors. Because the mirrors are by-ID references, the sync lint does NOT wording-check them; it (1) ID-guards the contamination side (no contamination context reuses an R-CIM-* ID, no claim-manifest surface reuses an R-L3-2-* ID), and (2) contradiction-guards the contamination mirrors against phrasing that would contradict the broad reword — a by-ID reference's surrounding prose MUST NOT assert an unqualified "advisory only" / "never block" / "cannot block" / "must not block" / "non-blocking" claim, since a strict terminal policy can now block (see check_firm_rules_sync.py contradiction guard). (Wording-sync IS enforced for the R-CIM-* blocks below, whose mirrors ARE full-block copies.)


Claim Intent Manifest emission firm rules (R-CIM-*)

Renamed from R-L3-2-A/B/C in v3.10 PR-A to remove the ID collision with the contamination rules above. The three writing-stage agents emit a claim intent manifest; the only difference between mirrors is the agent's self-reference noun ("synthesis agent" / "compiler" / "writer"), which the sync lint normalizes before comparison.

Mirrored in (claim-manifest rules):


Collision guard

scripts/check_firm_rules_sync.py additionally asserts:

  1. No R-L3-2-A/B/C token appears inside any ## Claim Intent Manifest Emission prompt section or inside claim_intent_manifest.schema.json.
  2. No R-CIM-A/B/C token appears inside any contamination context (formatter pass-through paragraph, crossref/openalex protocol, finalizer logic, contamination specs).

This pins the v3.10 PR-A disambiguation against regression.