Skip to contentScreenplay.Company

Standard vocabulary and lifecycle profiles

1. Open library, precise opt-in contracts

The following terms are the proposed standard library. A record can use any term with partial fields and still be stored, read and queried. This document defines intended meaning and interoperable field shapes. A producer advertising a profile MUST use those meanings and shapes for the fields it supplies. A profile-specific operation can require the fields necessary for that operation; it cannot require the entire work to be complete.

Notation: T text, B boolean, I integer, D exact decimal, R rational, Ref<K> reference to the indicated kind, Exact<K> exact reference, [] ordered array, Map open object of Values, Anchor language §5. Unless explicitly stated all fields are optional; title:T, notes:T, sources:Anchor[], derivedFrom:Exact[] and dependsOn:Ref[] are available on EVERY record. A display label or notes field is never evidence of authority. Natural-language fields are never silently parsed into asserted structure.

Table fields use name:Type; alternative kinds use |. Definitions may describe additional properties. A matching kind is checked by expanded namespace identity. Fields with undeclared specialised meanings survive as open data. Profile validation returns field-level findings (missing-for-operation, type-mismatch, unresolved, unsupported), not rejection of the whole story.

2. Core library

KindStandard fields / meaning
core.contributorname:T, kind:T, provider:T, model:T, version:T; human, agent or system attribution, never credentials
core.dependencyfrom:Exact, to:Exact, role:T, scope:Map; typed dependency beyond generic dependsOn
core.definitionAs language §4; an evolving term definition
core.asseturi:T, mediaType:T, byteLength:I, digest:T, availability:T, representations:Ref<core.asset>[]; digest is sha256: over original bytes; uri is a locator, not identity
core.aliasfrom:Ref, to:Ref, reason:T; navigational suggestion, never historical rewriting
core.tombstoneprevious:Exact, reason:T; deleted head retaining identity
core.proposalenvelope:Map, digest:T, rationale:T, findings:Ref[]; exact proposed operation, not authority
core.receiptMirror of an authenticated SSL-P receipt; authenticity still belongs to the host
core.messagesender:Ref, recipients:Ref[], snapshot:T, goal:T, allowedEffects:T[], material:Exact[], findings:Ref[], proposals:Ref[]; transport metadata is not access permission
core.calculationquery:Map, parameters:Map, purpose:T, outputDefinition:Exact<core.definition>
core.viewcalculation:Exact<core.calculation>, presentation:Map; disposable presentation preferences
core.checkquery:Map, expectation:T, severity:T, scope:Ref[]; SSL-Q expectations
core.derivedinputs:Exact[], calculation:Exact, snapshot:T, functionVersions:T[], accessScope:T, complete:B, output:Value, digest:T
core.findingtarget:Exact[], result:T, severity:T, evidence:Anchor[], explanation:T, proposedAction:Ref<core.proposal>, author:Ref

Assets are metadata and references. Large video/audio/binary payloads remain outside JSON. The same bytes can have different rights/access contexts; content identity never implies permission. Different transcoded/proxy representations have different hashes and explicit links to their source.

3. Story and memory

KindStandard fields / meaning
story.worktitle:T, language:T, form:T, logline:T, premise:T, intent:T, currentEdition:Ref<film.edition>, parts:Ref[]; no mandatory dramatic formula
story.fragmenttext:T, expression:Ref<story.expression>, about:Ref[]; unclassified thought, image or question
story.pagebody:Ref<story.expression>, about:Ref[], purpose:T, folder:Ref<story.collection>
story.collectionmembers:Ref[], parent:Ref<story.collection>; organisation, not story chronology
story.sourcesourceKind:T, expression:Ref<story.expression>, asset:Ref<core.asset>, origin:T, author:Ref, capturedAt:T, trust:T; original exchange/research/recording
story.expressionformat:T, body:T, language:T, originalAsset:Ref<core.asset>, attribution:Map; exact words, including screenplay, treatment, poem, song or transcript
story.personname:T, aliases:T[], description:Ref<story.expression>, attributes:Ref<story.claim>[]; fictional person distinct from performer
story.actorname:T, actorKind:T, description:Ref<story.expression>, attributes:Ref<story.claim>[]; nonhuman or unspecified narrative agent
story.diagrambody:Ref<story.expression>, asset:Ref<core.asset>, elements:Map[], layout:Map; authored arrangement retained as material, distinct from disposable view
story.groupname:T, members:Ref<story.person|story.group>[], attributes:Ref<story.claim>[]
story.placename:T, within:Ref<story.place>, description:Ref<story.expression>, coordinates:Map; fictional place distinct from filming venue
story.objectname:T, description:Ref<story.expression>, attributes:Ref<story.claim>[]; meaningful physical or imagined object
story.conceptname:T, description:T, examples:Ref[]; theme, motif, institution, rule, genre, idea; specialisation stays open
story.relationshipparticipants:Ref[], relation:T, context:Ref<story.context>, claims:Ref<story.claim>[], validDuring:Map; direction/roles belong to explicit role map if needed
story.claimproposition:T, subject:Ref, predicate:T, object:Value, mode:T, stance:T, modality:T, context:Ref<story.context>, perspective:Ref, validDuring:Map, evidence:Anchor[], author:Ref
story.contextframe:T, parent:Ref<story.context>, description:T, alternatives:Ref<story.context>[], basis:Exact[], effects:Map[]; world, dream, testimony, hypothetical or development alternative
story.eventdescription:T, participants:Ref[], place:Ref<story.place>, context:Ref<story.context>, time:Map, causes:Ref<story.event>[]; world occurrence, not its presentation
story.temporalbefore:Ref<story.event>, after:Ref<story.event>, relation:T, context:Ref<story.context>, evidence:Anchor[]; temporal relation, not automatic causation
story.readingmaterial:Exact[], interpretation:T, evidence:Anchor[], author:Ref, uncertainty:T, context:Ref<story.context>, coverage:Map, basisSnapshot:T; selected reading remains a sourced choice
story.questionquestion:T, about:Ref[], possibilities:Ref[], answer:Ref, state:T; default state open; answering does not imply writer choice
story.choicestatement:T, selected:Exact[], alternatives:Ref[], evidence:Anchor[], receipt:Ref<core.receipt>, supersedes:Exact<story.choice>; validated writer decision requires host attestation
story.constraintinstruction:T, scope:Ref[], strength:T, evidence:Anchor[], check:Ref<core.check>; intention, keep or must-not; not all are machine decidable
story.goalholder:Ref, desire:T, obstacle:T, stakes:T, context:Ref<story.context>, evidence:Anchor[]; explicitly incomplete is valid
story.arcsubject:Ref, moments:Ref[], interpretation:T, evidence:Anchor[]; ordered reading of change, never compulsory character template
story.setupmaterial:Ref[], payoffs:Ref[], intention:T, context:Ref<story.context>; declared links support impact queries

story.claim.mode standard values: world, belief, utterance, interpretation, research, intention. stance: asserted, denied, uncertain. Missing mode/stance means unspecified, never world/asserted. modality independently carries possible, conditional, counterfactual, obligation or reported; it is not collapsed into mode. Context effects are explicit include/exclude/replace entries over exact refs, preserved as data unless a selected context evaluator defines their composition; no implicit inheritance inference. A computable triple requires subject, predicate and object together; a prose-only proposition is valid. To infer a contradiction, the predicate definition must specify exclusivity and value comparison; open properties are not assumed single-valued.

Story acceptance is orthogonal to claim stance. A host-confirmed choice can select a claim about a belief or denial. Profile queries for settled story material follow valid choices/receipts and context, never a mutable label alone. Prototype imports may mark historical authority unverified while preserving the original evidence.

Temporal relation terms include before, after, overlaps, simultaneous and unknown. Explicit time can be an expression ("three winters later"), a rational interval relative to a named story clock, or a sourced calendar representation. Without a shared clock, numerical comparison is unknown. A causal link is a claim, not inferred from temporal adjacency. Cyclic before constraints create a finding; a fictional time loop can use distinct context/clock semantics and remain represented.

4. Narrative and screenplay

KindStandard fields / meaning
film.unitunitKind:T, children:Ref[], intent:T; act, sequence, episode, chapter, montage or other grouping
film.beatdescription:T, change:T, events:Ref<story.event>[], seam:T, sceneOccurrences:Ref<film.occurrence>[]
film.sceneheading:T, spec:Ref<film.spec>, drafts:Ref<film.draft>[], events:Ref<story.event>[], participants:Ref[], location:Ref<story.place>, state:T; durable creative unit
film.specscene:Ref<film.scene>, enters:T, leaves:T, change:T, wants:Map, turn:T, keep:Ref<story.constraint>[], mustNot:Ref<story.constraint>[], evidence:Anchor[], attribution:Map, receipt:Ref<core.receipt>; attribution may map each instruction to its exact source anchor
film.draftscene:Ref<film.scene>, expression:Exact<story.expression>, spec:Exact<film.spec>, parent:Exact<film.draft>, revisionNote:Ref, checks:Ref<core.finding>[]; writing a draft does not select it into Script
film.occurrencescene:Ref<film.scene>, draft:Exact<film.draft>, beat:Ref<film.beat>, context:Ref<story.context>, presentation:Map; one presentation of scene material
film.editionorder:Ref<film.occurrence|film.beat>[], context:Ref<story.context>, titlePage:Map, selectedBy:Ref<story.choice>, parent:Exact<film.edition>
film.alternativebase:Exact<film.edition>, forkAfter:Ref<film.occurrence|film.beat>, rejoinBefore:Ref<film.occurrence|film.beat>, order:Ref[], context:Ref<story.context>
film.disclosurematerial:Exact[], claim:Ref<story.claim>, audience:T, perspective:Ref, mode:T, at:Ref<film.occurrence>, phase:T, evidence:Anchor[]; audience exposure/intention, not proof of comprehension
film.annotationanchor:Anchor, kind:T, body:T, author:Ref, resolvedBy:Ref<story.choice>
film.revisionNoteinstruction:T, scope:Ref[], evidence:Anchor[], drafts:Ref<film.draft>[], receipt:Ref<core.receipt>
film.translationsource:Exact<story.expression>, expression:Exact<story.expression>, language:T, alignments:Map[]; independent expression and explicit alignment

An edition's order is authoritative for that edition. Do not independently sort by scene number or filename. Resolve an edition order left to right. A direct occurrence emits that occurrence. A beat expands its sceneOccurrences in stored array order; a missing or empty list emits a labelled beat placeholder (missing also reports unresolved). No recursive beat nesting is implied. An occurrence appearing more than once in the flattened order produces duplicate-occurrence and blocks a frozen export claiming conformance; repeat presentation instead creates a new occurrence referencing the same scene/event. Draft selection is explicit and exact. Missing drafts become labelled placeholders in a development reading. A delivery operation may require all entries resolved, but an unfinished edition remains valid.

The proposed Studio profile derives this order from its existing Outline owner; it does not create a second editable order. Script reading pins a snapshot. A frozen edition/export additionally records the complete exact-reference closure of every traversed beat, occurrence, draft and expression, so a later head cannot change an older export. Inserting/omitting unwritten placeholders is an explicit export option, recorded in the export receipt.

Fountain adapter requirements: pin parser/dialect; retain full body and original source assets when available; preserve title page, action, dialogue, parentheticals, dual dialogue, transitions, lyrics, emphasis, sections, synopses, notes and omitted/boneyard material. Structured views are derived. Unsupported syntax is shown literally and included in a loss report; it cannot disappear silently. Scene numbers are labels, and Fountain names are text, not automatic person identity. A parsing suggestion to link a character requires disambiguation when names collide.

5. Shared production value contracts

These contracts are normative when a producer advertises production-values/0.1. Partial/informal values remain valid open data but fail a dependent precision check.

  • Money: {"amount":{"$decimal":"1250.5"},"currency":"INR"}. Three-letter currency code is a label; conversions require explicit dated rates and sources. Different currencies cannot be summed implicitly.
  • Quantity: a Decimal or Rational with a declared unit. Dimensions and conversion factors must be supplied by the selected unit registry. day is not implicitly 24 shooting hours.
  • Instant: {"utc":"2026-11-04T03:30:00Z","zone":"Asia/Kolkata"} with optional original local form and declared timezone database version. UTC identifies the instant; zone supports display. Unknown local dates remain text; nonexistent/ambiguous local times need resolution before scheduling.
  • Media time: {"frames":I,"rate":{"$rational":[24000,1001],"unit":"frames/second"}}. Frames are integer frame/tick positions on a declared asset or timeline clock. A MediaTime may include clock:Ref; when absent it inherits the unambiguous owning recording/asset for source time or edit for timeline time. If that context is missing, comparison returns unknown. Equal rates do not make different clocks comparable; explicit sync mappings are required. Rate MUST be positive. A range is {start:MediaTime,duration:MediaTime} using the same rate/clock, duration nonnegative, interval half-open.
  • Timecode: {label:T,nominalFps:I,dropFrame:B,rate:R,origin:MediaTime}. The label is display notation, not time itself. Portable drop-frame conversion supports only 30000/1001 at nominal 30 skipping labels 00–01 at second 00 of every minute not divisible by 10, or 60000/1001 at nominal 60 skipping labels 00–03 at those boundaries; other combinations require a declared profile. Labels use HH:MM:SS;FF for drop-frame, HH:MM:SS:FF otherwise, HH 00–23, MM/SS 00–59 and FF below nominalFps. Parsing skipped labels is invalid. No frames are physically dropped. Day rollover requires an explicit integer dayOffset. Unsupported label conversions preserve the label and return unsupported.
  • Geometry: {system:T,unit:T,value:[D,D] | [D,D,D]}; right/left handedness and axis conventions belong to system definition. An unknown coordinate system prevents transformation, not storage.

6. Pre-production profile

KindStandard fields / meaning
prep.breakdownscene:Exact<film.scene>, draft:Exact<film.draft>, items:Ref<prep.requirement>[], author:Ref, evidence:Anchor[]
prep.requirementcategory:T, subject:Ref, quantity:Value, scene:Ref<film.scene>, occurrence:Ref<film.occurrence>, evidence:Anchor[], status:T; costume, prop, cast, stunt, animal, vehicle, extras, effect etc. remain extensible categories
prep.participantname:T, roles:T[], contact:Map, availability:Ref<prep.availability>[]; real person/organisation, separate privacy scope
prep.castingcharacter:Ref<story.person>, performer:Ref<prep.participant>, status:T, validDuring:Map, evidence:Anchor[]
prep.venuename:T, address:Map, coordinates:Map, portrays:Ref<story.place>[], permissions:Ref<prep.rights>[]
prep.resourcecategory:T, name:T, capacity:Value, provider:Ref<prep.participant>, availability:Ref<prep.availability>[]
prep.availabilitysubject:Ref, intervals:Map[], status:T, source:Anchor; available/held/unavailable is a claim with provenance
prep.scheduleitems:Ref<prep.booking>[], timezone:T, basis:Exact<film.edition>, version:T
prep.bookingstart:Map, end:Map, resources:Ref[], scenes:Ref<film.occurrence>[], status:T, receipt:Ref<core.receipt>; plan vs confirmed reservation must remain distinguishable
prep.budgetlines:Ref<prep.cost>[], currency:T, basis:Exact[], scenario:T
prep.costcategory:T, amount:Map, quantity:Value, rate:Map, basis:Exact[], status:T; amount either explicit or derived, never double counted
prep.rightssubject:Ref, holder:Ref<prep.participant>, document:Ref<core.asset>, territories:T[], uses:T[], period:Map, status:T, evidence:Anchor[]; assertion about rights, not legal determination
prep.plandepartment:T, scope:Ref[], body:Ref<story.expression>, requirements:Ref[]; art, costume, makeup, stunt, safety, locations or other plans

Pre-production computations include declared breakdown counts, affected departments after draft changes, resource overlaps over comparable instants, budget totals in a specified scenario/currency and missing permissions. Extracted breakdowns name the draft and evidence; a script revision makes them stale. No parser can guarantee every practical requirement was inferred from prose. A schedule solver is a versioned capability taking explicit constraints and returning a proposal plus feasibility status.

7. Production profile

KindStandard fields / meaning
shoot.daydate:T, zone:T, schedule:Exact<prep.schedule>, units:Ref<shoot.unit>[], reports:Ref<shoot.report>[]
shoot.unitname:T, participants:Ref<prep.participant>[], venue:Ref<prep.venue>
shoot.callSheetday:Ref<shoot.day>, expression:Exact<story.expression>, schedule:Exact<prep.schedule>, distribution:Ref<core.receipt>[]; generated sheet and sending it are separate effects
shoot.shotoccurrences:Ref<film.occurrence>[], description:T, setup:Ref<shoot.setup>, storyboard:Ref<core.asset>[], requirements:Ref<prep.requirement>[]
shoot.setupunit:Ref<shoot.unit>, venue:Ref<prep.venue>, camera:Map, lighting:Map, sound:Map; open department details
shoot.takeshot:Ref<shoot.shot>, slate:T, number:I, recordedAt:Map, media:Ref<core.asset>[], selected:B, reports:Ref<shoot.report>[]; selected is a sourced preference, not editorial insertion
shoot.recordingtake:Ref<shoot.take>, asset:Ref<core.asset>, device:Ref<prep.resource>, role:T, start:Map, duration:Map, timecode:Map, channels:Map[], sync:Ref<shoot.sync>[]
shoot.syncsources:Ref<shoot.recording>[], offsets:Map[], method:T, confidence:T, evidence:Anchor[]; offsets relative to named clocks; uncertain sync stays uncertain
shoot.continuitytake:Ref<shoot.take>, subject:Ref, observation:T, images:Ref<core.asset>[], evidence:Anchor[], comparison:Ref<shoot.take>
shoot.reportdepartment:T, day:Ref<shoot.day>, takes:Ref<shoot.take>[], body:Ref<story.expression>, author:Ref<prep.participant>

A shot can cover several screenplay occurrences; one occurrence can have many shots. Multiple cameras can produce recordings for the same take. Media filenames/slates can collide and are never IDs. A production event that happened on set is distinct from the fictional event being portrayed. Metadata supplied by devices retains original representations and parser versions.

8. Post-production profile

KindStandard fields / meaning
post.edittracks:Ref<post.track>[], rate:R, origin:Map, basis:Exact<film.edition>, parent:Exact<post.edit>, status:T
post.trackrole:T, items:Ref<post.clip|post.gap|post.transition>[], layer:I, enabled:B
post.clipsource:Ref<core.asset>, take:Ref<shoot.take>, sourceRange:Map, timelineRange:Map, speed:R, occurrences:Ref<film.occurrence>[], effects:Ref<post.effect>[]
post.gaptimelineRange:Map; intentional empty range, never missing media
post.transitionfrom:Ref<post.clip>, to:Ref<post.clip>, timelineRange:Map, effect:Ref<post.effect>; overlaps require available source handles
post.effectoperator:T, version:T, parameters:Map, inputs:Ref[]; declarative intent, requires trusted render capability
post.vfxclip:Exact<post.clip>, plates:Ref<core.asset>[], handles:Map, brief:Ref<story.expression>, versions:Ref<core.asset>[], status:T, review:Ref<core.finding>[]
post.audioassets:Ref<core.asset>[], role:T, layout:T, sampleRate:I, edit:Exact<post.edit>, processing:Map; dialogue, ADR, foley, effects, music, mix
post.coloursource:Ref<core.asset>, configuration:Ref<core.asset>, inputSpace:T, workingSpace:T, outputSpace:T, decision:Map; no implicit colour conversion
post.subtitleexpression:Exact<story.expression>, language:T, cues:Map[], edit:Exact<post.edit>; each cue has exact range and exact text; overlaps may be intentional
post.reviewtarget:Exact, anchor:Anchor, note:T, author:Ref, status:T, resolution:Ref<core.proposal|core.receipt>

The portable media-time contract assumes constant frame rate. Variable-frame-rate media retains a presentation-timestamp mapping in an extension/asset; precise operations require an advertised evaluator and otherwise return unsupported.

A portable editorial calculation requires edit rate/origin, each clip's source/timeline ranges and understood speed mapping. At speed 1, source duration in seconds equals timeline duration in seconds, even if source and edit rates differ. Constant speed maps sourceTime = sourceStart + (timelineTime - timelineStart) × speed, with all terms expressed in exact seconds after rate conversion and mapped clocks; negative speed is allowed with an explicit supported profile, zero speed means freeze and needs an explicit source frame. Variable speed curves are opaque extensions until a versioned evaluator is selected. Unknown effects can remain in the edit but an output claiming fully rendered effects must fail its readiness check.

Track ordering uses explicit timeline ranges; array order breaks identical-start ordering only. Overlap without a declared composite/transition is a finding, not an arbitrary clip deletion. Interchange adapters must distinguish source time from parent/timeline time and nested compositions. Media duration, source handles, sample/frame grids and missing assets need validation before rendering. Exact media specifications such as codec, channel labels and colour transforms should bind external standards/profiles rather than invent incompatible synonyms.

9. Delivery profile

KindStandard fields / meaning
delivery.packageedit:Exact<post.edit>, edition:Exact<film.edition>, assets:Ref<core.asset>[], spec:Exact<delivery.spec>, manifest:Map, checks:Ref<core.finding>[], receipt:Ref<core.receipt>
delivery.specrecipient:T, purpose:T, requirements:Ref<core.check>[], technical:Map, language:T, territory:T
delivery.versionbase:Exact<delivery.package>, changes:T, territory:T, language:T, assets:Ref<core.asset>[]; territorial, accessibility, censorship or platform version
delivery.qctarget:Exact<delivery.package|core.asset>, checks:Ref<core.finding>[], toolVersion:T, operator:Ref, performedAt:Map
delivery.archivemanifest:Map, assets:Ref<core.asset>[], digests:Map, locations:T[], verification:Ref<core.finding>[], retention:T

A delivery manifest pins exact edit/edition, source snapshot, complete transitive exact-reference closure of composition records, asset digests, selected profiles, renderer/adapter versions and known loss. A root exact reference alone does not freeze live child refs. Working compositions may use snapshot refs; historical reproduction uses the recorded closure and snapshot, never current heads. Missing closure/assets prevents a claim of complete reproducibility. A delivery can be described before all dependencies are present. Publishing or asserting delivery completeness requires the chosen specification's checks and an authorised effect receipt. Rights, labour, financial and safety decisions remain professional/human responsibilities; SSL records evidence and constraints rather than declaring compliance from a label.

10. Interoperability contracts

External format/modelSSL relationshipRequired loss report
FountainExact screenplay expression plus derived elementsUnsupported syntax, omitted annotations, name/scene identity ambiguity
OTIOEditorial timeline/track/clip/gap/transition adapterRational-rate conversion/rounding, unsupported effects, nesting, speed maps, asset resolution
OpenUSDReferenced scene/asset composition; bind stable asset revision plus prim path and layer identifierUnit/axis/time conversion, composition resolution, unsupported schemas, identity mapping
MovieLabs OMCSemantic mapping for creative work, narrative/production entities, tasks, participants and assetsUnmapped/custom terms, relation cardinality, identity and authority differences
FDX, EDL, AAF, FCPXML, subtitle/audio/colour formatsFuture separately versioned adapter capabilitiesUnsupported fields, precision, encoding and metadata; no 0.1 conformance implied

Every adapter result identifies source format/version, adapter version, original byte digest, resulting snapshot, mapping of identities and preserved opaque payloads. Loss reports list exact affected fields/assets and severity. An export that cannot preserve extension data must either attach a lossless SSL sidecar or explicitly report it; it must never advertise complete round-trip fidelity. Sidecars cannot be required by tools that do not support them, so recipient capability is checked.

The goal is a shared language across departments with practical interchange, not a claim that all department semantics are solved by these first-cut terms. Extensions are the intended route for concepts uncovered through actual use.

11. Doctrine profile

Namespace prefix doctrine → urn:ssl:0.1:doctrine. The writer's doctrine (the craft rules that bind their screenplays) as records, so queries can join rules with scenes, drafts, claims and findings. These records are a host-derived projection of the story's active doctrine (projectDoctrine in packages/screenplay/src/story-source/doctrine.ts); writes to the doctrine go only through the writer's own words, never through SSL-P. See doctrine in SSL.

KindStandard fields / meaning
doctrine.setstorySlug:T, rules:Exact<doctrine.rule>[], assignments:{rule:Exact,applicability:{mode:"all"}|{mode:"selected",storySlugs:T[]},position:I,parent?:Exact}[], digest:T, defaultVersion:I|null, useDefault:B; the story's active doctrine at one digest
doctrine.ruleruleId:T, title:T, truth:T, constrains?:T, origin:"writer"|"default", copiedFrom?:T, parentId?:T (the original parent declaration), tags:T[], scope:"draft"|"scene"|"outline"|"person"|"story", method:"computed"|"judged", checks:Exact<core.check>[], judge:{question:T, passWhen:T, failWhen:T}
core.check (for a rule)core fields plus explanation:T (the query in plain words) and scope:[Exact<doctrine.rule>]
core.finding (doctrine)doctrine.rule:Exact<doctrine.rule>, doctrine.ruleId:T, doctrine.method:"judged"|"computed", target:Exact[], result:"pass"|"fail"|"unknown", severity:T, evidence:{quote?:T, target?:Exact}[] (a full Anchor is also accepted), explanation:T, author:T (the reader's release or the evaluator version)

Identities are deterministic within projection generation 2: a rule is urn:screenplay-company:doctrine:v2:rule:<origin>:<encoded rule id> at its semantic revision (existing writer rules begin at 1; default rules use the published version). Checks and sets also use the doctrine:v2: prefix. A check identity includes the doctrine evaluator version and uses its rule revision. A set identity includes the story slug and active doctrine digest, at revision 1. Older unversioned references remain untouched; their findings are displayed as stale history and cannot count toward current coverage. Native read receipt identities include the generation so a new reading cannot replay an older finding's receipt. Membership, current order, applicability and effective parent bindings live in the immutable set, so renaming a selected screenplay or reordering rules cannot change an exact rule record. Writers change rules only through the doctrine owner; SSL imports cannot grant account policy authority.

The built-in computed checks use expectation:"none" and return one row per violation; the row's record and exact-reference cells become the finding's targets, a reason text cell its explanation and a quote text cell its evidence. A custom check may declare none, all-true or nonempty and is evaluated according to that expectation. A judged finding is an attributed reading by a doctrine reader, stored by the host, never writer canon. It is stale once the rule revision changes or any target is no longer at the exact state it read (absent from the snapshot, or at a different revision): stale findings are listed but do not count. A rule's status rolls up its current findings: followed (all current findings pass and required material is covered), broken (any fail), mixed (some pass, with unknown or unread material), unknown (the data cannot decide) or unchecked (no current finding). Unknown and unchecked never count as followed.

Judged findings target exact states. In the Studio work projection, scenes, drafts, specs and beats keep stable identities across reads, and their revisions change only when their projected state does, so a finding stays fresh until what it read changes.

Doctrine reports expose coverage.required, read, unchecked and complete per rule. A new relevant record requires a reading; one passing example does not establish the whole story. Computed checks describe only what their exact query proves. A complete custom query does not establish that every scene was individually examined. Whole-story and outline judgments bind their complete creative basis. Scope, unsupported data and bounded evaluation limits remain explicit.