TOP / Recruit / spec / v1
2026-05-09 · backed by source/top-strawman.json (v0.4.0-strawman) · the human in the recruitment realm, pre-consent · 2 SHACL invariants · ninth top-level (lifted alongside Participant per Decision 9)
Sections: 1. TL;DR 2. Why a separate entity 3. Architectural anchor 4. Model summary 5. Funnel state machine 6. Twin-for-enrollment context 7. SHACL invariants 8. Stress-test scenarios 9. Query patterns 10. Open issues

1.TL;DR pre-consent funnel · separate entity · light data shape · fuels twin-for-enrollment

Recruit is the human in the recruitment realm — pre-consent. Separate top-level (top-level count moves 8 → 9), not a pre-consent state on Participant. Recruiter is a distinct operator role with its own workflow (ad response, pre-screening calls, eligibility pre-check, scheduling, contact attempts). Data shape is lighter than Participant — no consent, often only contact info + light eligibility flags. PHI handling differs (no full medical history; HIPAA Safe Harbor easier to maintain). Recruit→Participant transition: when Recruit consents, a Participant entity is created with convertedFromRecruit pointing back. Recruit data persists post-conversion as recruitment-funnel analytics (conversion rates per source, channel ROI).

2.Why a separate entity first-principles reasoning

Per first-principles.md, each operator role with a distinct workflow gets a first-class entity. The recruiter's day is operationally different from the coordinator's:

Folding the Recruit into a pre-consent participantStatus state would mean:

  1. Stretching Participant's data shape to accommodate light pre-consent data (most fields empty for Recruits) — schema-noisy.
  2. Mixing the recruiter's workflow into Participant's CTAs — UX-confusing.
  3. Forcing PHI handling on data that doesn't yet need it — compliance-burdening.
  4. Losing the analytical separation between "people who entered the funnel" and "people who became participants" — analytics-impeding.

Separate entity solves all four.

3.Architectural anchor where Recruit sits

ad / referral / EMR-mining │ ▼ Site ── manages ──▶ StudySite ── for ──▶ Study ── attracts ──▶ Recruit │ │ │ │ (when consent obtained) │ ▼ └── enrolledAt ────────────────▶ Participant ▲ │ convertedFromRecruit │ └── consentedTo ──▶ InformedConsent

Recruit is anchored at forStudy (1..1) and optionally at forStudySite (0..1; some Recruits enter the funnel before site assignment is finalized in multi-site studies with central recruitment routing). The Recruit→Participant transition is via convertedToParticipant (and the inverse Participant.convertedFromRecruit). The InformedConsent sub-object's existence on the Participant IS the canonical conversion event; the Recruit→Participant linkage is the operational-funnel-side trace.

4.Model summary attributes, relationships

Recruit attributes (~18) — selected

AttributeTypeNotes
recruitIdNGSI-LD URIGlobally unique.
firstName / lastNamestring · optionalOperator-grounded; identification-status-agnostic posture (same as Participant).
phone / emailstring · optionalOften the only identifiers captured at first response.
preferredContactMethodenum (5)PHONE / EMAIL / TEXT / PORTAL / OTHER.
recruitStatusenum (10)Funnel state (NGSI-LD temporal property for trajectory queryability). See Section 5.
recruitmentSourceenum (11) · optionalHow the Recruit entered the funnel; drives channel ROI analysis.
recruitmentSourceDetailsstring · optionalFree-text detail (campaign ID, registry name, referring physician).
responseDatedateDate Recruit first entered the funnel.
preScreeningOutcomeenum (4) · optionalQUALIFIED / NOT_QUALIFIED / DEFERRED / PENDING. Light recruiter assessment, not formal protocol screening.
preScreeningNotesstring · optionalHigh-level eligibility flags. Limited PHI by design.
contactAttemptsinteger · optionalOperational metric for follow-up cadence.
lastContactDatedate · optionalMost recent contact attempt.
consentScheduled / consentAppointmentDateboolean · date · optionalBridges to Participant creation.
country / primaryLanguageISO codes · optionalUseful for multi-country recruitment funnel analytics + recruiter language-matching.
validFrom / validUntildateTime · optionalNGSI-LD temporal-property semantics on the entity record.

Recruit relationships (4)

RelationshipTargetCard.Notes
forStudyStudy1..1Recruits are scoped per-Study.
forStudySiteStudySite0..1Site assignment may not be finalized in multi-site studies with central recruitment routing.
recruitedByPerson0..1The recruitment coordinator (Person) handling this Recruit.
convertedToParticipantParticipant0..1Inverse of Participant.convertedFromRecruit. Empty until conversion. Required when recruitStatus=CONVERTED_TO_PARTICIPANT (SHACL hard, Inv. #24).

5.Funnel state machine 10 states · NGSI-LD temporal property

RESPONDED ──▶ CONTACTED ──▶ PRE_SCREENING_SCHEDULED ──▶ PRE_SCREENED │ ▼ QUALIFIED_PENDING_CONSENT │ ▼ CONVERTED_TO_PARTICIPANT (terminal, success) ┌─────────────┬──────────────┬──────────────┐ │ │ │ │ DECLINED NO_SHOW NOT_QUALIFIED DROPPED (terminal, attrition)

The recruiter's day moves Recruits along this funnel. Each state transition produces a NGSI-LD temporal-property change on recruitStatus (validFrom/validUntil bracketing) so the trajectory is queryable for funnel analytics and twin-for-enrollment downstream.

Conversion-rate analytics (a recruiter's primary metric) compute as: count(CONVERTED_TO_PARTICIPANT) / count(all Recruits with same recruitmentSource), grouped by source. Channel ROI emerges directly from the foundation.

6.Twin-for-enrollment context deferred game-changing use case

Recruit is the operational counterpart to twin-for-enrollment — the highest-value digital-twin use case for clinical trials. Enrollment is the most expensive bottleneck (80%+ of trials miss timelines; ~30% of trial cost is recruitment-related). A patient-twin foundation enables:

Real Recruits + synthetic-Recruits-from-twin populations + historical Participants from completed trials feed a unified twin synthesizer that predicts cohort composition, recruitment timeline, and drop-out risk before the trial opens. TOP's foundation decisions made now (Recruit-as-separate-entity + twin-queryability discipline on participantStatus) are the load-bearing pre-conditions; twin synthesis itself is computational infrastructure for v0.5+ when Visit / Activity / Observation lift expands the queryability surface.

See the Participant spec § 5 (digital-twin posture) for the foundation contract and PMDT prior-art context.

7.SHACL invariants 2 new Recruit invariants · 25 total in the graph

#SeverityConstraint
24HardConverted recruit needs participant. Recruit with recruitStatus=CONVERTED_TO_PARTICIPANT must have convertedToParticipant relationship populated. The terminal-funnel-success status requires the operational link to the created Participant.
25SoftStalled recruit (many attempts). Recruit with contactAttempts > 5 still in {RESPONDED, CONTACTED} states should probably transition to DROPPED. Surfaces stale recruits to the recruiter for funnel hygiene.

8.Stress-test scenarios three cases

Successful conversion
Funnel happy path

Mary responded to a digital ad, qualified at pre-screening, attended consent appointment. Coordinator obtained consent.

Recruit_r001 created with recruitStatus=RESPONDED. Through funnel: CONTACTED → PRE_SCREENED → QUALIFIED_PENDING_CONSENT. At consent: Coordinator creates Participant_p001 with convertedFromRecruit=Recruit_r001. Recruit_r001.recruitStatus → CONVERTED_TO_PARTICIPANT, convertedToParticipant=Participant_p001 (Inv. #24 satisfied). Participant_p001.hasInformedConsent populated. Both records persist; Recruit_r001 stays for analytics.
Funnel attrition (declined)
Funnel sad path

Robert qualified at pre-screening but declined at consent appointment (concerns about randomization).

Recruit_r002 reaches QUALIFIED_PENDING_CONSENT. Recruiter logs decline; recruitStatus → DECLINED with notes. No Participant created. Recruit_r002 persists for funnel-attrition analytics (declined-at-consent vs declined-at-pre-screen vs no-show patterns inform recruitment process improvements).
Stalled recruit (cadence trigger)
SHACL soft warning

Jennifer responded to an ad; recruiter has tried 6 times to reach her with no response.

Recruit_r003.contactAttempts=6, recruitStatus=CONTACTED. SHACL Inv. #25 fires soft warning to surface in recruiter dashboard. Recruiter decides: continue trying (rare) or transition to DROPPED. Soft (not hard) because there are legitimate cases where high contact-attempts reflect a hard-to-reach but eligible candidate.

9.Query patterns three concrete NGSI-LD HTTP shapes

Recruiter: today's funnel queue
Operational

"Who do I need to follow up with today?"

GET /ngsi-ld/v1/entities?type=Recruit&q=recruitedBy=="urn:ngsi-ld:Person:jones";recruitStatus=="CONTACTED","PRE_SCREENING_SCHEDULED","QUALIFIED_PENDING_CONSENT"
Sponsor PM: channel ROI for this study
Analytics

"Which recruitment sources are converting at the highest rate?"

GET /ngsi-ld/v1/entities?type=Recruit&q=forStudy=="urn:ngsi-ld:Study:ONCO-423"
[group by recruitmentSource client-side; count CONVERTED_TO_PARTICIPANT vs total]

Client-side aggregation in v0.4; SPARQL backing query later for direct GROUP BY.

Twin synthesizer: recruit population for synthetic enrollment simulation
v0.5+ deferred

"What recruit-population characteristics for studies in this therapeutic area / geography?"

[Federated query across Studies — defer until federation lifts in v0.6+]
[For now, single-Study recruit population queryable per-Study]

10.Open issues

  1. Recruit data retention policy: how long do unconverted Recruit records persist? Channel ROI analytics value declines over time; PHI minimization argues for a sunset (12-24 months for unconverted). Deployment-side concern; document the recommendation here, leave the policy to deployment.
  2. Cross-Study Recruit reuse: a single human responding to two trial ads creates two Recruit records (per-Study scoping). Analytics on "this person is repeatedly responding to studies but not converting" is a cross-Study federation concern, deferred to v0.6+ alongside Participant cross-Study federation.
  3. Pre-screening question bank: TOP doesn't model the pre-screening questionnaire structure (questions, answers, scoring rules). When operational complexity warrants, lift as a sub-object on Recruit (PreScreeningQuestionnaire) or as a separate horizontal — not in v0.4.0.
  4. Twin-for-enrollment foundation readiness: when Visit / Activity / Observation lift, the foundation gains the time-varying observation surface a twin synthesizer needs. Recruit's role as "real-Recruit-corpus + synthetic-Recruit-from-twin populations" becomes architecturally available in v0.5+.