About SOP binding
An inspection question about a review check is never “which SOP” but “which version of the SOP applied when the work was done, and who accepted the requirements the check used”. Phase 1 bound a check to an SOP with an integer version and an approve route inside Trovensa. Phase 2 mirrors controlled versions from the QMS and makes the binding explicit, auditable and reproducible.
The problem
Controlled SOPs live in a QMS with major.minor versions, effective and superseded dates and lifecycle labels
configured per tenant. A check that names only the SOP cannot say which clauses were in force; a check that
uses requirements the agent extracted without review lets agent output drive findings unreviewed; and two
approval systems for one document (the QMS’s and Trovensa’s) would contradict each other.
Versions are mirrored, not owned
The QMS/SOP connector mirrors every version as a sop_versions row: major, minor, lifecycle_state
mapped per connection (draft, in_review, effective, superseded, obsolete, unmapped), effective_at
from the effective-date field when present, else first observation with effective_on_observed = true,
superseded_at from the source or from the successor’s effective_at, rendition_hash and the document
that holds the version text. The QMS is authoritative for content and state: Trovensa’s approve route applies
to local SOPs only and answers 409 sop_external for connector SOPs. Only effective versions can bind.
The binding rule
By default a check binds the version whose effective_at <= target_reference_at < superseded_at, where the
reference time is the target’s last modification (binding_rule = auto); drafting a protocol uses the version
effective now. A person can name another version with a required binding_reason (binding_rule = manual),
for example when the work predates an inferred effective date. The check stores sop_version_id,
requirements_hash, check_logic_version and agent_version_id; the rail and the finding cards print “Bound
to SOP-BA-012 v3.1 (effective 2026-05-02, inferred from first observation)”. A different triple is never an
update: it creates a new check with supersedes_check_id, so the old result stays attributable to the old
inputs.
Requirement sets need QA acceptance
Requirement extraction is agent-proposed and person-accepted. Each requirement is {code, text, page, paragraph, chunk_id, modality MUST|SHOULD|MAY, role, evidence_expectation}; codes stay stable across minor
versions and are re-issued on major versions with a mapping table in the sop_diff artifact. The set moves
from proposed to accepted only through a decision signature by a holder of review.sops.approve
(how-to); only accepted sets are usable, and their
requirements_hash is copied onto every check that uses them. Extraction is enabled for the pilot only after
a measured result on one partner SOP (precision and recall against a QA-labelled set) is registered.
What happens when a version changes
The 15-minute poll sees the new effective version and the worker enqueues two runs. review_extract_requirements
proposes the new set and diffs it against the previous one. review_sop_impact lists open checks and drafts
bound to the superseded version, adds targets modified inside the observation gap (between the true effective
date and the first observation), and proposes a re-check batch; QA approves it and the checks run in the
background lane with supersedes_check_id. Holders of review.sops.manage get a sop_changed
notification; a system thread carries the summary and the sop_diff artifact.
Selecting SOPs from a question
“Does this entry follow our SOPs” selects candidate SOPs by applicability tags (QMS type, subtype and
classification mapped per connection, program stage, experiment type tags on sops.applicability), ranks them
by retrieval, caps them at five per check, and shows the considered-and-rejected list in the run rail.
Why this design
- Binding to a version answers the inspection question; binding to an SOP does not.
- Explicit
autoormanualwith a reason makes the observation-gap problem visible instead of hiding it behind a proxy date. - QA acceptance with a signature keeps agent output out of the record until a person owns it.
- One authority per document avoids two contradictory approval states.
Related
- How to connect a QMS and How to launch from your notebook.
- Statuses for the requirement-set and check lifecycles.
- ADR 0016.