Radiology Transcript Interpreter · research proof of concept
Documentation
These sections are rendered directly from the checked-in specifications, plans, and operator documents. The Markdown files remain authoritative.
RadLex to Prolog compiler specification
The original conceptual and implementation-ready specification for preserving RadLex meaning while compiling away RDF and OWL representational machinery.
Authoritative source: research/chatgpt/RADLEX-PROLOG-COMPILER-SPEC-FINAL.md · Permanent section link
# RadLex → Prolog Compiler Specification
**Status:** Implementation-ready specification derived from RadLex 4.3 and design discussion
**Source ontology:** RadLex 4.3 (`RadLex.owl`)
**Target runtime:** SWI-Prolog
**Scope:** RadLex-specific OWL dialect, not general OWL
> **Design intent:** preserve RadLex's meaning; compile away RDF/OWL representational machinery.
---
## Contents
1. [Vision](#1-vision)
2. [Technical Introduction](#2-technical-introduction)
3. [Survey of Decisions and Translation Rules](#3-survey-of-decisions-and-translation-rules)
4. [Reference Appendices](#4-reference-appendices)
## 1. Vision
RadLex is already a strong domain model. The full RadLex 4.3 ontology contains roughly 47,000 classes and more than 130,000 subclass axioms, but those facts are expressed through a surprisingly small and coherent logical vocabulary: named classes, class inclusion, existential class relationships, relation specialization, inverse relations, domain/range implications, a small number of unions, two relations declared as `owl:FunctionalProperty`, and lexical/documentary annotations.
The purpose of this project is **not to simplify or redesign RadLex's domain model. It is to expose it.**
RadLex is distributed as OWL encoded in RDF. That representation is useful to the Semantic Web ecosystem, but it introduces machinery that is not useful to the application architecture we want: RDF triples and lists, anonymous restriction nodes, OWL encoding conventions, duplicated class/individual identities, URI-heavy identifiers, and other serialization-level structures.
We will build a compiler that reads RadLex OWL and emits a small, explicit Prolog ontology language. The generated Prolog should make the structure of RadLex easier to inspect, test, reason about, and use as the foundation for application-specific logic.
The governing principle is:
> **If removing an OWL/RDF construct changes what RadLex means, preserve its meaning. If it changes only how that meaning is encoded, compile it away.**
This is a **RadLex compiler**, not a general OWL implementation. The source language is the OWL dialect actually exercised by RadLex 4.3. Unsupported source forms are compiler errors, not invitations to guess.
### 1.1 Ontology layer and application layers
The compiled ontology is abstract. It describes RadLex classes, class expressions, relations, relation properties, and lexical/documentary knowledge. It does not describe a particular patient, report, image, specimen, or other concrete case.
Application layers are separate consumers of the compiled ontology. An application may identify concrete referents from its own evidence and use RadLex to understand the classes and general relationships associated with those referents. The compiler does not define how an application creates individuals, resolves mentions, performs clinical reasoning, or materializes case-specific facts.
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
right_kidney ⊆ kidney
right_kidney ⊆
∃ contained_in.right_retroperitoneal_compartment
The ontology contains abstract knowledge about classes and relations.
It does not assert that a kidney, compartment, patient, or report exists.
APPLICATION LAYER
────────────────────────────────────────────────────────
An application may independently establish a concrete referent, for example:
instance_of(k1, right_kidney).
The application may consult the ontology to understand what `right_kidney`
means and how that class is related to other classes. The ontology axiom
above does not authorize the compiler to manufacture a concrete compartment
or to assert a case-specific `contained_in(k1, ...)` relationship.
```
The compiler therefore preserves RadLex's class-level commitments without imposing a particular application-world semantics on downstream consumers. A future clinical reasoner, transcript-enrichment system, validator, or other application may build additional reasoning policies on top of the same compiled ontology.
### 1.2 What the compiler produces
The target is a readable Prolog ontology rather than a generic RDF triple store.
Representative target forms include:
```prolog
class(rid205).
subclass(rid29662, rid205).
some_relation(
rid29662,
contained_in,
rid29541
).
label(rid205, en, preferred, "kidney").
xref(rid205, fma(7203)).
```
The compiler may additionally emit executable rules when an OWL declaration is more faithfully and transparently represented as an implication than as data.
For example, a simple OWL domain declaration whose meaning is
```text
P(x,y) → C(x)
```
may compile directly to a Prolog rule of the form:
```prolog
isa(X, c) :-
p(X, _).
```
rather than to a potentially misleading `domain(p, c)` fact.
---
## 2. Technical Introduction
This section establishes the empirical source boundary, notation, accepted source grammar, compiler architecture, invariants, and completion criteria. It describes the compiler as a system before the specification turns to individual translation decisions.
### 2.1 Empirical RadLex 4.3 Source Inventory
The compiler specification is grounded in the actual RadLex 4.3 source, not in the full theoretical expressiveness of OWL.
| Source construct | Observed count | Role |
|---|---:|---|
| `owl:Class` | 46,952 | Named ontology classes |
| `rdfs:subClassOf` → named class | 46,900 | Direct class inclusion |
| `owl:Restriction` | 83,161 | Class restrictions |
| `owl:onProperty + owl:someValuesFrom` | 83,161 | **100% of restrictions** |
| `owl:ObjectProperty` | 52 | Domain relation vocabulary |
| `owl:inverseOf` | 19 | Explicit inverse relation pairs |
| `rdfs:subPropertyOf` | 12 | Relation specialization |
| object-property `rdfs:domain` | 50 | Subject classification implications |
| object-property `rdfs:range` | 52 | Object classification implications |
| `owl:unionOf` | 52 | Anonymous union class expressions |
| unions used as domains | 48 | Most union usage |
| unions used as ranges | 4 | Remaining union usage |
| `owl:FunctionalProperty` | 2 | `Segment_Of`, `Tributary_Of` |
| `owl:equivalentClass` | 1 | Datatype definition, not anatomical class equivalence |
| `owl:oneOf` | 1 | Datatype enumeration |
| `owl:NamedIndividual` | 24,092 | Punned duplicate identities; see §3.8 |
The crucial observation is that tens of thousands of concrete classes are built from a very small number of abstract forms. The compiler should therefore be specified over those forms rather than over anatomical concepts individually.
#### 2.1.1 Object relation vocabulary
RadLex declares 52 object properties. Important families include:
```text
Partonomy
Part_Of / Has_Part
Regional_Part_Of / Has_Regional_Part
Constitutional_Part_Of / Has_Constitutional_Part
Branch_Part_of / Has_Branch_Part
Segment_Of
Containment and boundaries
Contained_In / Contains
Bounded_by / Bounds
Surrounded_by / Surrounds
External_to
Spatial ordering
Anterior_to
Posterior_to
Superior_to
Inferior_to
Proximal_to
Distal_to
Topology and branching
Continuous_With
Branch_Of / Has_Branch
Tributary_Of
Flow
Drains_Into / Receives_Drainage_From
Sends_Output_To / Receives_Input_From
Blood supply
Blood_Supply_of / Has_Blood_Supply
Lymphatics
Lymphatic_Drainage / Lymphatic_Drainage_Of
Innervation
Innervates / Has_Innervation_Source
Attachment
Attaches_to / Receives_attachment_from
Muscle anatomy
Has_origin / Origin_of
Has_insertion / Insertion_of
Projection
Projects_To / Receives_Projection_From
Projects_From
Membership
Member_Of / Has_Member
Causation
May_Cause / May_Be_Caused_By
Other
Anatomical_Site
Has_Entrapment_Site
Related_modality
```
The relation vocabulary is fixed and small enough that the compiler can explicitly specify its treatment rather than implement a generic relation calculus.
---
### 2.2 Translation Model and Notation
#### 2.2.1 Source and target notation
Examples use normalized Turtle to show the semantic shape of source OWL. The actual RadLex distribution is RDF/XML; Turtle is used only because it makes the relevant RDF graph readable.
We write:
```text
OWL ⟹RL Prolog
```
to mean “the supported RadLex OWL form on the left compiles to the Prolog ontology fragment on the right.”
Metavariables:
```text
C, D, E named RadLex classes
P, Q RadLex object properties
x, y application individuals
L literal value
```
Class expressions initially include:
```text
ClassExpr ::= NamedClass | union([ClassExpr, ...])
```
Additional class-expression forms are introduced only if required by the observed RadLex dialect.
#### 2.2.2 Core distinction: class theory versus application facts
The ontology layer has statements such as:
```prolog
subclass(C, D).
some_relation(C, P, D).
```
The application layer has statements about actual input-derived individuals:
```prolog
instance_of(x, C).
p(x, y).
```
These are deliberately not interchangeable.
---
### 2.3 Source-Language Grammar
The compiler accepts the RadLex-specific source forms below. This grammar describes recognized source shapes; it does not itself define their semantics.
```ebnf
ClassAxiom ::= NamedSubclass
| ExistentialSubclass
;
NamedSubclass ::= Class "rdfs:subClassOf" Class ;
ExistentialSubclass ::= Class "rdfs:subClassOf" Restriction ;
Restriction ::= "owl:onProperty" Relation
"owl:someValuesFrom" Class
;
PropertyAxiom ::= Domain
| Range
| SubProperty
| InverseProperty
| FunctionalProperty
;
Domain ::= Relation "rdfs:domain" ClassExpr ;
Range ::= Relation "rdfs:range" ClassExpr ;
ClassExpr ::= Class
| UnionExpr
;
UnionExpr ::= "owl:unionOf" "(" Class { Class } ")" ;
SubProperty ::= Relation "rdfs:subPropertyOf" Relation ;
InverseProperty ::= Relation "owl:inverseOf" Relation ;
FunctionalProperty ::= Relation "rdf:type" "owl:FunctionalProperty" ;
```
The grammar will be expanded only when an empirical inventory demonstrates another meaningful RadLex source shape.
---
### 2.4 Compiler Architecture
A practical implementation can use SWI-Prolog's RDF parser as a front end without adopting its RDF graph as the application's ontology representation.
```text
RadLex 4.3 RDF/XML
│
│ rdf_load/1
▼
SWI RDF graph ← parsing / namespaces / RDF syntax
│
│ RadLex-aware semantic extraction
▼
RadLex compiler IR ← supported logical forms only
│
│ normalization + validation
▼
Generated Prolog ontology ← readable target program
│
▼
Application reasoning layer
```
The compiler should distinguish source facts from generated semantic rules sufficiently for provenance and debugging.
#### 2.4.1 Candidate directory shape
```text
ontology/
upstream/
radlex/
RadLex.owl
generated/
radlex_classes.pl
radlex_relations.pl
radlex_lexicon.pl
radlex_rules.pl
src/
ontology/
radlex.pl
semantics.pl
application/
model.pl
compiler/
load.pl
extract.pl
validate.pl
emit.pl
tests/
compiler/
ontology/
application/
```
This directory structure is illustrative, not yet normative.
---
### 2.5 Translation Invariants
The following invariants are normative:
1. **The compiler produces ontology knowledge, not application individuals.** No concrete patient-, report-, image-, specimen-, or execution-specific individual is introduced by ontology compilation.
2. **No supported RadLex source axiom is silently discarded.** Every supported construct has a defined translation; unsupported constructs produce an explicit compiler diagnostic.
3. **Existential restrictions retain existential meaning without requiring named witnesses.** `C ⊆ ∃ P.D` remains a class-level proposition; compilation does not Skolemize the filler.
4. **The ontology and downstream application models remain semantically distinct.** The compiler does not define application-level closed-world policy, entity creation, clinical inference, or case-specific materialization.
5. **Class-level relationships and concrete individual relationships are never conflated.** A general RadLex relation between classes is not automatically projected onto particular application individuals.
6. **Every generated ontology assertion or rule is traceable to its RadLex source axiom or to an explicitly specified compiler inference.**
7. **The compiler is defined for the observed RadLex OWL dialect, not for arbitrary OWL.**
8. **Union expressions remain disjunctive.** `isa(X, union([A,B]))` does not imply either `isa(X,A)` or `isa(X,B)` individually.
9. **Inverse relations are translated through explicit fixed cases.** The compiler does not infer arbitrary inversions of class expressions.
10. **OWL functional-property declarations are represented by their mathematical meaning as partial functions.** `partial_function(P)` means that `P` is single-valued in its second argument for each first argument; it does not imply totality or injectivity.
11. **Lexical normalization does not mutate upstream ontology strings.** Exact source text and matching keys are separate concerns.
12. **Source identity is preserved.** Readable Prolog names may be emitted for convenience, but each generated class, relation, annotation property, and other named source entity remains traceable to its exact RadLex URI/RID.
### 2.6 Acceptance Criteria
This specification is implementation-ready when the compiler and its tests satisfy all of the following:
- every meaningful OWL/RDFS construct exercised by RadLex 4.3 has been inventoried;
- each supported source shape has a normative translation rule;
- each translation rule states the upstream meaning, target representation, formal consequence, and explicit non-consequences where ambiguity is possible;
- the punning validation confirms that no source axiom depends materially on the punned `owl:NamedIndividual` interpretation;
- any unsupported source construct causes an explicit compiler failure or diagnostic rather than silent omission;
- the compiler test suite demonstrates that no supported source construct is silently dropped;
- generated facts retain provenance sufficient to trace them to source RadLex axioms and exact source identities;
- the two RadLex `owl:FunctionalProperty` declarations compile as `partial_function/1` metadata with the correct single-valued semantics;
- the unused `Term_type` datatype enumeration is preserved, if retained at all, as annotation-schema metadata rather than medical class logic;
- representative anatomy and relation queries against the generated Prolog ontology return the expected class-level results;
- compilation does not create concrete application individuals or case-specific assertions.
## 3. Survey of Decisions and Translation Rules
This section is the normative survey of the RadLex-specific translation decisions. Each subsection addresses one recurring source construct or one compiler policy that affects the meaning of the generated Prolog. The repeated structure—upstream meaning, ontology/application interpretation, translation decision, example, formal rule, and non-consequences—is intentional.
### 3.1 Named Classes
#### Upstream meaning
An OWL named class identifies an abstract category. A RadLex RID identifies the class; labels and synonyms are annotations on that identity.
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
kidney is a named class identified by RID205.
The existence of the class does not establish the existence of any kidney individual.
APPLICATION MODEL
────────────────────────────────────────────────────────
A report-processing execution may establish:
instance_of(k1, rid205).
After that fact has been established, the application model contains
a particular individual that is classified as a kidney.
```
#### Translation decision
Each supported named RadLex class becomes one `class/1` fact. The RID is preserved as the stable ontology identity.
#### Example
Turtle:
```turtle
radlex:RID205 a owl:Class ;
rdfs:label "kidney"@en .
```
Prolog:
```prolog
class(rid205).
label(rid205, en, preferred, "kidney").
```
#### Formal translation
```text
C rdf:type owl:Class
──────────────────────────
C ⟹RL class(C)
```
#### Entails / does not entail
```text
ENTAILS
C is part of the ontology's class vocabulary.
DOES NOT ENTAIL
Any application individual is an instance of C.
```
---
### 3.2 Class Inclusion (`rdfs:subClassOf`)
#### Upstream meaning
For named classes C and D:
```text
C ⊆ D
```
means every instance of C is also an instance of D.
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
right_kidney ⊆ kidney
This statement expresses an inclusion relation between two ontology classes.
APPLICATION MODEL
────────────────────────────────────────────────────────
instance_of(k1, right_kidney)
The class hierarchy may classify the existing individual:
instance_of(k1, kidney)
This derivation does not create a new application individual.
```
#### Translation decision
Named subclass axioms compile directly to `subclass/2`.
#### Example
Turtle:
```turtle
radlex:RID29662 rdfs:subClassOf radlex:RID205 .
```
Prolog:
```prolog
subclass(rid29662, rid205).
```
Application inference may be defined by a separate ontology/application bridge:
```prolog
instance_of(X, Super) :-
instance_of(X, Sub),
subclass(Sub, Super).
```
#### Formal translation
```text
C,D ∈ Class
C rdfs:subClassOf D
───────────────────
C ⟹RL subclass(C,D)
```
Logical meaning:
```text
C(x) → D(x)
```
#### Entails / does not entail
```text
ENTAILS
Every C is a D.
DOES NOT ENTAIL
Every D is a C.
Any instance of either class exists in the application.
```
---
### 3.3 Existential Class Relationships (`owl:someValuesFrom`)
#### Upstream meaning
RadLex uses this construct extensively. All 83,161 restrictions observed in RadLex 4.3 are existential `someValuesFrom` restrictions.
The OWL statement
```text
C ⊆ ∃ P.D
```
means:
```text
For every x:
if C(x),
then there exists at least one y such that
D(y) and P(x,y).
```
The restriction identifies the **class of the required filler**. It does not identify a particular filler individual.
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
right_kidney ⊆ kidney
right_kidney ⊆
∃ contained_in.right_retroperitoneal_compartment
RadLex specifies the class of location required for instances
of right_kidney.
This ontology statement does not introduce an individual for a patient,
a kidney, or a retroperitoneal compartment.
APPLICATION MODEL
────────────────────────────────────────────────────────
instance_of(k1, right_kidney).
The application model contains k1 because k1 was established from
the input to this execution.
If no compartment has been established from the report or by an
explicitly permitted application derivation, no compartment individual
exists in this application model.
```
#### Translation decision
Existential restrictions compile to a class-level relation:
```prolog
some_relation(SubjectClass, Relation, FillerClass).
```
The compiler does not Skolemize and does not invent application individuals.
#### Example
Turtle:
```turtle
radlex:RID29662
rdfs:subClassOf [
a owl:Restriction ;
owl:onProperty radlex:Contained_In ;
owl:someValuesFrom radlex:RID29541
] .
```
Prolog:
```prolog
some_relation(
rid29662,
contained_in,
rid29541
).
```
#### Formal translation
```text
C,D ∈ Class P ∈ Relation
C ⊆ ∃ P.D
───────────────────────────
C ⟹RL some_relation(C,P,D)
```
#### Entails / does not entail
```text
ENTAILS
Every instance of C bears P to at least one instance
belonging to D.
DOES NOT ENTAIL
A named D individual is available to the application.
some_relation(C,P,D) does not by itself produce:
instance_of(y,D)
p(x,y)
```
This preservation of existential class knowledge without materializing witnesses is a foundational compiler rule.
---
### 3.4 Domain and Range: Relation Participation Implies Classification
#### Upstream meaning
OWL/RDFS domain and range are inference axioms, not programming-language type checks.
For a simple domain:
```text
domain(P) = C
```
meaning:
```text
P(x,y) → C(x)
```
For a simple range:
```text
range(P) = D
```
meaning:
```text
P(x,y) → D(y)
```
They do **not** mean “reject P(x,y) unless x and y were already known to have the declared types.”
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
The definition of relation P tells us something about any
entity that participates in P.
P(x,y) → C(x)
This axiom provides classification knowledge about entities that participate in P.
APPLICATION MODEL
────────────────────────────────────────────────────────
p(a,b).
If this concrete relation has been established from the application input,
the ontology may classify the existing individual a as an instance of C.
This classification does not create a new application individual.
```
#### Translation decision
For simple named domains/ranges, compile the inferential meaning directly into Prolog rules rather than preserve potentially misleading `domain/2` or `range/2` facts.
Representative target:
```prolog
isa(X, c) :-
p(X, _).
isa(Y, d) :-
p(_, Y).
```
For the ontology layer, the same implication must also apply to class-level existential relations. If a class C participates as the subject of `some_relation(C,P,_)`, the source domain of P may imply a superclass or class-expression membership for C.
#### Formal translation: named domain
```text
domain(P) = C
────────────────────────
P(x,y) → C(x)
```
Generated application-facing rule shape:
```prolog
isa(X, c) :-
p(X, _).
```
Generated ontology-facing rule shape:
```prolog
subclass(C, c) :-
some_relation(C, p, _).
```
#### Formal translation: named range
```text
range(P) = D
────────────────────────
P(x,y) → D(y)
```
Generated application-facing rule shape:
```prolog
isa(Y, d) :-
p(_, Y).
```
Generated ontology-facing rule shape:
```prolog
subclass(D, d) :-
some_relation(_, p, D).
```
#### Entails / does not entail
```text
ENTAILS
A participant in P receives the appropriate classification.
DOES NOT ENTAIL
P is a conventional typed function signature.
Unknown classification invalidates an asserted P relation.
C(x) and D(y) imply P(x,y).
```
> **Important:** the direction of inference is intentionally visible in generated Prolog.
---
### 3.5 Union Class Expressions (`owl:unionOf`)
#### Upstream meaning
RadLex 4.3 contains 52 union expressions. Forty-eight are used in property domains and four in property ranges.
A union class expression
```text
A ∪ B
```
means membership in at least one member class. If a property domain is a union:
```text
domain(P) = A ∪ B
```
then:
```text
P(x,y) → (A(x) ∨ B(x))
```
It does **not** imply A(x) individually, nor B(x) individually.
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
domain(P) = A ∪ B
P(x,y) implies:
x ∈ A ∪ B
RadLex has not selected which member class applies.
APPLICATION MODEL
────────────────────────────────────────────────────────
p(a,b).
The ontology may classify a as:
isa(a, union([a_class,b_class]))
If no other fact or rule provides a more specific classification,
the application must preserve the disjunction and must not select either member individually.
```
#### Translation decision
Anonymous union classes become first-class Prolog class expressions wherever a class expression is expected:
```prolog
union([a, b]).
```
More specifically, classification of an entity into the union is represented as:
```prolog
isa(X, union([a, b])).
```
A union-valued domain therefore compiles to a rule such as:
```prolog
isa(X, union([a, b])) :-
p(X, _).
```
Membership in a named member class may entail membership in the union:
```prolog
isa(X, union([A, B])) :-
isa(X, A).
isa(X, union([A, B])) :-
isa(X, B).
```
The reverse implication is invalid.
#### Example
Normalized Turtle shape:
```turtle
radlex:Anterior_to
rdfs:domain [
a owl:Class ;
owl:unionOf (
radlex:RID13218
radlex:RID13230
radlex:RID13389
radlex:RID50364
)
] .
```
Prolog rule shape:
```prolog
isa(
X,
union([rid13218, rid13230, rid13389, rid50364])
) :-
anterior_to(X, _).
```
#### Formal translation
```text
domain(P) = C₁ ∪ C₂ ∪ ... ∪ Cₙ
────────────────────────────────
P(x,y) → isa(x, union([C₁,C₂,...,Cₙ]))
```
For range, the same rule applies to the second relation argument.
#### Entails / does not entail
```text
ENTAILS
isa(x, union([A,B]))
DOES NOT ENTAIL
isa(x,A)
isa(x,B)
```
---
### 3.6 Relation Specialization (`rdfs:subPropertyOf`)
#### Upstream meaning
A subproperty assertion means every occurrence of the specialized relation is also an occurrence of the more general relation.
RadLex 4.3 uses 12 such declarations. Examples include:
```text
Regional_Part_Of ⊆ Part_Of
Constitutional_Part_Of ⊆ Part_Of
Segment_Of ⊆ Part_Of
Branch_Part_of ⊆ Regional_Part_Of
Branch_Of ⊆ Continuous_With
Tributary_Of ⊆ Continuous_With
Drains_Into ⊆ Sends_Output_To
```
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
regional_part_of ⊆ part_of
Every assertion of the specialized relation also satisfies the more general relation.
APPLICATION MODEL
────────────────────────────────────────────────────────
regional_part_of(a,b).
Therefore:
part_of(a,b).
This derivation does not create a new application individual.
```
#### Translation decision
Because the relation vocabulary is fixed, subproperty declarations may compile to explicit Prolog implication rules rather than generic runtime metaprogramming.
#### Example
Turtle:
```turtle
radlex:Regional_Part_Of
rdfs:subPropertyOf radlex:Part_Of .
```
Prolog:
```prolog
part_of(X, Y) :-
regional_part_of(X, Y).
```
The corresponding class-level existential implication is valid in the same direction:
```prolog
some_relation(C, part_of, D) :-
some_relation(C, regional_part_of, D).
```
#### Formal translation
```text
P ⊆ Q
P(x,y)
────────
Q(x,y)
```
and for existential class restrictions:
```text
C ⊆ ∃ P.D P ⊆ Q
────────────────────
C ⊆ ∃ Q.D
```
---
### 3.7 Inverse Relations (`owl:inverseOf`)
#### Upstream meaning
RadLex explicitly declares 19 inverse relation pairs. If P and Q are inverses:
```text
P(x,y) ↔ Q(y,x)
```
#### Fixed inverse table
```text
Attaches_to ↔ Receives_attachment_from
Blood_Supply_of ↔ Has_Blood_Supply
Bounded_by ↔ Bounds
Branch_Of ↔ Has_Branch
Branch_Part_of ↔ Has_Branch_Part
Constitutional_Part_Of ↔ Has_Constitutional_Part
Contained_In ↔ Contains
Drains_Into ↔ Receives_Drainage_From
Has_Innervation_Source ↔ Innervates
Has_Member ↔ Member_Of
Has_Part ↔ Part_Of
Has_Regional_Part ↔ Regional_Part_Of
Has_insertion ↔ Insertion_of
Has_origin ↔ Origin_of
Lymphatic_Drainage ↔ Lymphatic_Drainage_Of
May_Be_Caused_By ↔ May_Cause
Projects_To ↔ Receives_Projection_From
Receives_Input_From ↔ Sends_Output_To
Surrounded_by ↔ Surrounds
```
#### Ontology and application interpretation
```text
RADLEX ONTOLOGY
────────────────────────────────────────────────────────
part_of and has_part are inverse relations.
This specifies the relation algebra itself.
APPLICATION MODEL
────────────────────────────────────────────────────────
part_of(a,b)
The inverse relation therefore establishes:
has_part(b,a)
Both relation assertions refer to the same two concrete individuals.
The inverse inference does not introduce an application individual.
```
#### Translation decision
The compiler uses explicit, fixed translation cases for these 19 pairs. It does not implement a general mechanism that attempts to invert arbitrary ontology expressions.
For individual relations:
```prolog
has_part(Y, X) :-
part_of(X, Y).
part_of(X, Y) :-
has_part(Y, X).
```
**Critical limit:** inversion of an individual relation does not justify naïvely flipping an existential class restriction.
From:
```text
A ⊆ ∃ part_of.B
```
we may **not** infer:
```text
B ⊆ ∃ has_part.A
```
because “every A is part of some B” does not mean “every B has some A.” If RadLex asserts both directions at the class level, each source axiom is compiled independently.
#### Formal translation
```text
inverse(P,Q)
P(x,y)
────────────
Q(y,x)
```
and symmetrically for Q.
---
### 3.8 Class/Individual Punning
#### Empirical finding
RadLex 4.3 declares 24,092 `owl:NamedIndividual` resources. Every observed `owl:NamedIndividual` resource is also declared as an `owl:Class`, and the observed individual declarations contain no independent population of domain individuals.
This is treated as OWL encoding machinery rather than domain knowledge required by the target ontology.
#### Translation decision
The compiler **discards the duplicated individual interpretation** and represents each RID once in the ontology class/concept layer.
```text
RADLEX SOURCE
────────────────────────────────────────────────────────
RID29662 is declared as an owl:Class.
RID29662 is also presented through the punned owl:NamedIndividual pattern.
PROLOG TARGET
────────────────────────────────────────────────────────
class(rid29662).
source_uri(rid29662, 'http://www.radlex.org/RID/RID29662').
```
The compiler MUST validate this assumption against the source being compiled. If a future RadLex source contains an axiom whose meaning depends materially on the individual interpretation of a punned RID, compilation MUST fail with an explicit unsupported-construct diagnostic rather than silently discarding that meaning.
#### Non-consequences
Discarding punning does not mean that downstream applications cannot contain individuals. Application individuals are created by application evidence and logic, not by the duplicated ontology identity pattern in the RadLex OWL serialization.
### 3.9 Partial Functions (`owl:FunctionalProperty`)
RadLex declares exactly two object properties as `owl:FunctionalProperty`:
```text
http://www.radlex.org/RID/Segment_Of
http://www.radlex.org/RID/Tributary_Of
```
The source names are therefore `Segment_Of` and `Tributary_Of`, and their exact RadLex URIs MUST remain recoverable from the generated ontology.
#### Upstream meaning
OWL functionality means that a relation is single-valued in its second argument for each first argument:
```text
P(x,y₁) ∧ P(x,y₂) → y₁ = y₂
```
Mathematically, this is the behavior of a **partial function**:
```text
P : X ⇸ Y
```
The function is partial because OWL functionality does not require every `x` to have a `P`-successor. It is not necessarily injective because distinct subjects may have the same object.
#### Translation decision
The compiler translates an `owl:FunctionalProperty` declaration to an explicit proposition that the RadLex relation is a partial function:
```prolog
partial_function(segment_of).
partial_function(tributary_of).
```
The readable relation atom MUST be connected to its exact upstream identity, for example:
```prolog
relation_uri(segment_of, 'http://www.radlex.org/RID/Segment_Of').
relation_uri(tributary_of, 'http://www.radlex.org/RID/Tributary_Of').
```
The precise name of the source-identity predicate may vary with the compiler's general provenance representation; preservation of the URI is normative.
#### Formal translation rule
```text
P rdf:type owl:FunctionalProperty
──────────────────────────────────
P ⟹RL partial_function(P)
```
with semantic interpretation:
```text
partial_function(P)
P(x,y₁) ∧ P(x,y₂)
──────────────────
y₁ = y₂
```
#### Non-consequences
`partial_function(P)` does **not** entail that:
- `P` is total;
- `P` is injective;
- `P` is bijective;
- the compiler must implement equality merging;
- multiple observed fillers should be rejected as a database uniqueness error; or
- an application must adopt any particular identity-resolution policy.
The compiler's responsibility is to preserve the logical proposition. Downstream reasoning systems may build equality, validation, reconciliation, or other machinery around it as their use cases require.
### 3.10 Compiler/Application Semantic Boundary
The compiler produces general RadLex ontology knowledge. It does not define the facts of a particular patient, image, report, specimen, or other application world.
This boundary matters most for existential class relationships. For example:
```text
right_kidney ⊆
∃ contained_in.right_retroperitoneal_compartment
```
means that RadLex characterizes the class `right_kidney` using an existential `contained_in` relationship. The compiler preserves that class-level proposition.
It does **not** produce:
```prolog
contained_in(k1, invented_compartment).
```
for some downstream `k1`, because no concrete witness exists in the source ontology.
#### Normative compiler rule
> **The compiler MUST preserve general ontology propositions but MUST NOT convert them into case-specific assertions about application individuals.**
A downstream application may independently identify concrete referents from its own evidence. It may then consult the compiled ontology to expose relevant class hierarchy and relation knowledge about the concepts involved. Whether that application performs only semantic enrichment, clinical inference, validation, or some other reasoning task is outside the compiler specification.
For example, if an application independently identifies both a kidney referent and a retroperitoneal-compartment referent, the ontology may expose to that application that the identified classes participate in the RadLex relationship:
```text
kidney-class context
contained_in some retroperitoneal-compartment-class
```
The ontology alone does not establish that the particular kidney referent is contained in the particular compartment referent. A case-specific assertion requires application evidence or application-specific reasoning beyond the compiler.
#### Compiler non-responsibilities
The compiler does not specify:
- how transcript mentions become application entities;
- whether an application uses open-world or closed-world reasoning;
- whether an application performs clinical inference;
- how an application resolves identity or coreference;
- when an application may assert a relationship between two concrete referents; or
- how an application serializes enriched evidence for an LLM or another consumer.
Those concerns belong to downstream application specifications.
### 3.11 Lexical and Documentary Knowledge
RadLex is also a terminology source. These annotations are not logical class axioms, but they are first-class compiler output because the initial application goal is anatomical term recognition.
Representative target predicates:
```prolog
label(Class, Language, preferred, Text).
label(Class, Language, synonym, Text).
acronym(Class, Language, Text).
definition(Class, Text).
xref(Class, ExternalIdentifier).
source(Class, Source).
```
Source strings should be preserved exactly. Matching normalization—case folding, punctuation handling, Unicode normalization, token/span normalization—belongs in a separate lexical index or application-facing layer, not in the ontology compiler's source-preserving facts.
Example:
```prolog
label(rid205, en, preferred, "kidney").
label(rid205, de, synonym, "Niere").
label(rid205, la, synonym, "ren").
```
The ontology identity remains the RID; strings are lexical evidence pointing to it.
---
### 3.12 Unused `Term_type` Annotation-Schema Datatype
RadLex 4.3 declares an annotation property:
```text
http://www.radlex.org/RID/Term_type
```
whose range is the datatype:
```text
http://www.radlex.org/RID/Range_val_one_of_Term_type
```
That datatype is defined by the only observed `owl:equivalentClass` + `owl:oneOf` construct in the ontology and enumerates four literal strings:
```text
abbreviation
anatomical
clinical
proper
```
This is terminology-schema metadata, not medical class logic. A source scan found no populated `<RID:Term_type>` annotations in `RadLex.owl`; the property is declared but unused in this RadLex 4.3 source.
#### Translation decision
The compiler does not introduce general OWL class-equivalence or enumeration machinery solely for this declaration.
If annotation-schema metadata is retained, a narrow representation is sufficient, for example:
```prolog
annotation_property(term_type).
annotation_value_set(
term_type,
[abbreviation, anatomical, clinical, proper]
).
```
The exact upstream URI MUST remain recoverable if the declaration is emitted.
Because no populated uses occur in RadLex 4.3, no application behavior or medical inference may depend on this construct. An implementation MAY omit this unused schema declaration from the primary generated ontology if the compiler's source-metadata/provenance output records that omission explicitly. It MUST NOT treat the construct as anatomical or clinical class knowledge.
### 3.13 Representative End-to-End Fragment
This fragment illustrates the intended overall feel of the generated ontology.
#### Source meaning
```text
right_kidney ⊆ kidney
right_kidney ⊆
∃ contained_in.right_retroperitoneal_compartment
regional_part_of ⊆ part_of
part_of(x,y) ↔ has_part(y,x)
```
#### Generated ontology
```prolog
class(rid205).
class(rid29662).
class(rid29541).
label(rid205, en, preferred, "kidney").
label(rid29662, en, preferred, "right kidney").
subclass(rid29662, rid205).
some_relation(
rid29662,
contained_in,
rid29541
).
part_of(X, Y) :-
regional_part_of(X, Y).
has_part(Y, X) :-
part_of(X, Y).
part_of(X, Y) :-
has_part(Y, X).
```
#### Downstream boundary (non-normative illustration)
A downstream application may independently establish a concrete referent and associate it with `rid29662`. The compiled ontology then provides the class hierarchy and class-level existential relationship as available background knowledge.
The compiler itself does not create that referent, does not decide which ontology consequences the application should materialize, and does not fabricate a `rid29541` individual to satisfy the existential restriction. Those choices belong to the downstream application specification.
---
## 4. Reference Appendices
### 4.1 RadLex 4.3 Inverse Relation Table
| Relation | Inverse |
|---|---|
| `Attaches_to` | `Receives_attachment_from` |
| `Blood_Supply_of` | `Has_Blood_Supply` |
| `Bounded_by` | `Bounds` |
| `Branch_Of` | `Has_Branch` |
| `Branch_Part_of` | `Has_Branch_Part` |
| `Constitutional_Part_Of` | `Has_Constitutional_Part` |
| `Contained_In` | `Contains` |
| `Drains_Into` | `Receives_Drainage_From` |
| `Has_Innervation_Source` | `Innervates` |
| `Has_Member` | `Member_Of` |
| `Has_Part` | `Part_Of` |
| `Has_Regional_Part` | `Regional_Part_Of` |
| `Has_insertion` | `Insertion_of` |
| `Has_origin` | `Origin_of` |
| `Lymphatic_Drainage` | `Lymphatic_Drainage_Of` |
| `May_Be_Caused_By` | `May_Cause` |
| `Projects_To` | `Receives_Projection_From` |
| `Receives_Input_From` | `Sends_Output_To` |
| `Surrounded_by` | `Surrounds` |
### 4.2 RadLex 4.3 Subproperty Table
| Specialized relation | More general relation |
|---|---|
| `Branch_Of` | `Continuous_With` |
| `Branch_Part_of` | `Regional_Part_Of` |
| `Constitutional_Part_Of` | `Part_Of` |
| `Drains_Into` | `Sends_Output_To` |
| `Has_Branch` | `Continuous_With` |
| `Has_Branch_Part` | `Has_Regional_Part` |
| `Has_Constitutional_Part` | `Has_Part` |
| `Has_Regional_Part` | `Has_Part` |
| `Receives_Drainage_From` | `Receives_Input_From` |
| `Regional_Part_Of` | `Part_Of` |
| `Segment_Of` | `Part_Of` |
| `Tributary_Of` | `Continuous_With` |
---
### 4.3 Design Summary
```text
KEEP THE MODEL
────────────────────────────────────────────────────────
classes
class inclusion
existential class relationships
relation specialization
inverse relation semantics
domain/range implications
union class expressions
functional semantics (pending exact representation)
lexical/documentary knowledge
provenance
COMPILE AWAY THE ENCODING
────────────────────────────────────────────────────────
RDF/XML syntax
blank restriction nodes
RDF list plumbing
URI verbosity
owl:Restriction wrapper structure
class/individual punning, if final validation confirms no loss
other serialization-only machinery
KEEP THE WORLDS SEPARATE
────────────────────────────────────────────────────────
RadLex ontology:
abstract class theory
Application model:
concrete closed world of this execution
```
---
## Appendix D. Design Conversation and Prompt Provenance
This appendix records selected parts of the human–AI design conversation that produced this specification. It is non-normative. Its purpose is to preserve design provenance and to provide a teaching record for reviewing how short prompts, objections, corrections, empirical questions, and formalization requests changed the resulting specification.
The authorship represented here is genuinely collaborative. In particular, the human co-author repeatedly supplied the decisive conceptual correction when the discussion drifted toward a representation that was convenient but semantically weaker, broader, or less precise than the intended compiler. Those interventions are credited explicitly below rather than being retrospectively presented as conclusions reached by the assistant alone.
This is a curated design record rather than a complete transcript. Text identified as **Original author input** is quoted only when the wording survives reliably in the available conversation record. Where the exact wording is unavailable, the entry is labeled **Context summary** and does not purport to reconstruct a quotation.
### D.1 Separating RadLex from the proposed Prolog representation
**Context summary — human-led correction**
The human co-author objected when an explanation of RadLex used hypothetical Prolog as though it were the source representation. The objection established that an explanation must distinguish what RadLex literally contains from the logical meaning of that source and from our proposed compilation target.
**Resulting specification principle**
The project now maintains three explicit representational levels:
1. the actual RadLex OWL/RDF source;
2. the logical meaning of that source; and
3. the Prolog representation selected by this compiler.
**Prompt-engineering observation**
This was initially a correction to explanatory presentation, but it exposed a deeper specification error: source syntax, semantics, and target syntax had been conflated. A useful prompt need not prescribe the solution. Identifying a category error can force a better architecture.
### D.2 Reframing the project as a compiler over the RadLex dialect
**Context summary — human-led direction**
The human co-author emphasized that the implementation is a fixed compiler for RadLex rather than a general-purpose OWL grammar or OWL reasoner. Because the source ontology exercises a small, empirically discoverable fragment of OWL, the compiler can recognize and translate those forms explicitly.
**Resulting specification principle**
The supported language is defined by the OWL/RDFS constructs actually exercised by RadLex 4.3. Unsupported constructs must produce diagnostics rather than trigger speculative generalization.
**Prompt-engineering observation**
Narrowing the problem was productive rather than restrictive. The correction replaced an open-ended language-design problem with a finite compiler specification that can be tested against a known corpus.
### D.3 Preserving RadLex while removing OWL/RDF machinery
**Context summary — jointly developed, with human direction on scope**
The discussion converged on treating RadLex itself as a strong domain model while treating much of its RDF/OWL surface representation as compilation machinery that the target application does not need.
**Resulting specification principle**
> Preserve RadLex's meaning; compile away OWL/RDF's representational machinery.
The purpose of the project is not to simplify or redesign RadLex's domain model. It is to expose it in a representation that is explicit and useful to the application.
**Prompt-engineering observation**
A strong design prompt often supplies a criterion rather than a list of implementation instructions. The preservation criterion gives later decisions a common test: does a proposed simplification remove encoding machinery, or does it remove a logical commitment?
### D.4 Existential restrictions without invented application individuals
**Original author input**
> “we know the class that shows where a kidney is, but we don't claim to have a member of that class on hand.”
**Context summary — human-led semantic clarification**
This formulation clarified the intended treatment of `owl:someValuesFrom`. RadLex can specify that every member of one class participates in a relation to some member of another class without supplying a concrete member of the filler class to the current application execution.
**Resulting specification principle**
An axiom of the form `C ⊆ ∃ P.D` compiles to class-level knowledge such as `some_relation(C,P,D)`. Compilation does not Skolemize the filler and does not manufacture an application individual merely to satisfy the existential commitment.
**Prompt-engineering observation**
The effective move here was to restate formal semantics in concrete ontological language. The phrase “on hand” made the distinction between existential commitment and available application evidence immediately operational.
### D.5 Separating the ontology from application-world policy
**Context summary — human-led direction, subsequently refined**
The human co-author pushed against treating the entire Prolog program as a closed-world reinterpretation of RadLex. The key architectural correction was that RadLex remains abstract class-level knowledge, while questions about concrete individuals and case-specific facts belong to downstream applications.
The conversation initially discussed a closed-world application model. Later discussion refined the point further: the compiler should not prescribe the downstream application's open-world or closed-world policy at all.
**Resulting specification principle**
The compiler preserves RadLex's ontology commitments without creating concrete application individuals or defining application-world inference policy. The stricter final boundary is recorded in D.10 and Section 3.10.
**Prompt-engineering observation**
This intervention improved the specification by locating a policy at the correct architectural boundary. Asking *which layer owns this assumption?* can be more valuable than debating the assumption in the abstract.
### D.6 Representing unions without destroying the disjunction
**Context summary — human-selected target representation**
The human co-author preferred representing a union class expression directly in Prolog, for example `isa(X, union([a,b]))`, rather than compiling it into either member class or hiding the disjunction behind a representation that suggested more knowledge than RadLex provides.
**Resulting specification principle**
`isa(X, union([A,B]))` preserves the proposition that `X` belongs to `A ∪ B`. It does not entail `isa(X,A)` or `isa(X,B)` individually.
**Prompt-engineering observation**
The important contribution was not merely syntactic preference. Choosing a representation that visibly retains uncertainty makes an invalid downstream inference harder to write accidentally. Representation can enforce epistemic discipline.
### D.7 Treating punning as a hypothesis to test rather than semantics to inherit
**Original author input**
> “some kind of garbage”
**Context summary — human challenge followed by empirical verification**
The phrase referred to the apparent class/individual punning in the RadLex OWL representation. Rather than accepting the OWL construct as necessarily meaningful domain semantics, the human co-author challenged us to determine whether it carried information that the compiler actually needed.
The subsequent source inventory found 24,092 `owl:NamedIndividual` resources; every one is also a class, and the observed individual declarations contain no independent population of domain individuals.
**Resulting specification decision**
The compiler discards the duplicated individual interpretation and represents each RID once in the ontology class/concept layer. This is now normative. A validation pass remains mandatory: if a future source axiom depends materially on the punned individual interpretation, the compiler must fail explicitly rather than silently weaken the ontology.
**Prompt-engineering observation**
The productive pattern was **skepticism → empirical question → corpus measurement → guarded design decision**. The initial pushback was informal, but it led to a stronger specification because the response was not to rationalize the source representation; it was to inspect the ontology.
### D.8 Rejecting naïve inversion of existential class restrictions
**Context summary — jointly reasoned, with human insistence on explicit fixed cases**
The discussion distinguished inversion of a concrete binary relation from inversion of an existential class restriction. If `P` and `Q` are inverse properties, `P(x,y)` supports `Q(y,x)` for the same individuals. However, `A ⊆ ∃ P.B` does not imply `B ⊆ ∃ Q.A`.
The human co-author also emphasized that the compiler has a fixed relation vocabulary. With only 19 inverse pairs in RadLex 4.3, explicit compiler cases are preferable to an unnecessarily general inversion mechanism.
**Resulting specification principle**
Concrete inverse-relation rules are compiled explicitly. Existential class restrictions are not mechanically reversed.
**Prompt-engineering observation**
This illustrates two useful interventions at once: test a seemingly symmetric transformation against its quantifiers, and use the actual size of the source language to resist needless abstraction.
### D.9 Translating OWL functionality into the mathematical object it denotes
**Context summary — human-led naming correction followed by joint formalization**
RadLex declares `Segment_Of` and `Tributary_Of` as `owl:FunctionalProperty`. The discussion first clarified that OWL functionality means “at most one object per subject,” not one-to-one correspondence, totality, or injectivity. The human co-author then rejected the vague target name `functional_relation/1` and proposed naming the preserved proposition for the mathematical object it actually denotes: a partial function.
**Resulting specification decision**
`owl:FunctionalProperty` compiles to `partial_function(P)`. The generated ontology preserves the exact upstream RadLex relation URI. The compiler records the single-valued logical commitment but does not implement equality merging or application-level uniqueness policy.
**Prompt-engineering observation**
The useful pattern was **terminology challenge → mathematical clarification → better target vocabulary**. Naming the target construct by its semantics rather than by OWL jargon made the intended meaning substantially harder to misread.
### D.10 Separating ontological enrichment from case-specific inference
**Context summary — human-led scope correction**
The discussion initially treated the ontology/application boundary as a general question about which ontology entailments should become application facts. The human co-author narrowed the actual use case: the planned transcript application is concerned with ontological enrichment, not diagnosis or reconstruction of the patient's physical state. A kidney mentioned in a transcript could, in principle, be an isolated specimen rather than a kidney in the anatomical location normally described by RadLex.
The human co-author then added the complementary case: when two referents are independently identified from the transcript, exposing the relevant RadLex relationship between their identified classes is precisely the kind of context that is useful to an LLM. What must not happen is silently converting that class-level context into an assertion that those two particular referents stand in the relation.
**Resulting specification decision**
The compiler preserves general ontology propositions and never manufactures case-specific individuals or assertions. Downstream applications may use the ontology to enrich independently established referents, but application evidence or application-specific reasoning is required before a relationship is asserted between particular referents. Clinical reasoning remains a possible future layer, not a responsibility of the compiler.
**Short original formulation**
> “enrich the doctor's language; do not enrich the patient.”
**Prompt-engineering observation**
A concrete counterexample changed an abstract inference-policy discussion into a clean architectural boundary. The strongest part of the correction was not a new implementation rule; it was a sharper statement of what kind of knowledge the system is allowed to claim.
### D.11 Defining Technical Preview as a historical pre-design artifact
**Context summary — human-defined document semantics**
The human co-author supplied a specific meaning for **Technical Preview**: a pre-design sketch that records the problem, priorities, constraints, proposed architecture, responsibilities, exclusions, and especially the open questions that must be resolved before coding. Once those questions are resolved, the decisions belong in the specification; the preview remains a historical artifact rather than being rewritten to look prescient.
**Resulting documentation principle**
The current document is a specification. Decisions are recorded here as they become normative, while earlier exploratory artifacts retain their historical role.
**Prompt-engineering observation**
Defining the epistemic status of a document prevents exploratory suggestions from quietly becoming commitments. Prompting can govern not only *what* is written but also what authority a piece of writing is allowed to have.
### D.12 Requiring Standard Written English in explanatory prose
**Original author input**
> “SWE is standard written english btw not software engineering”
**Context summary — human editorial correction**
The human co-author had already objected to telegraphic, question-and-answer-style specification prose and requested proper SWE. The clarification established that SWE meant **Standard Written English**, not software engineering.
The requested standard is complete declarative and conditional prose with explicit subjects, objects, and relationships. Formal notation may remain terse because its terseness is part of the notation; explanatory prose should not imitate slide-deck fragments.
**Resulting editorial principle**
The specification uses Standard Written English for explanatory material and reserves compressed syntax for actual formal rules, code, tables, and other structures in which compression is semantically useful.
**Prompt-engineering observation**
Small editorial corrections can affect technical precision. Replacing fragments such as “No compartment established?” with explicit conditional sentences forces the author to state the condition, actor, scope, and consequence rather than leaving those relationships implicit.
### D.13 Reorganizing the information architecture around conceptual levels
**Original author input**
> “Vision is top Level, all the technical intro bably is top level and then the survey of decisions and translation rules is top level, inside of that we have all of those”
**Context summary — human-led structural correction**
The earlier draft promoted nearly every construct to the same heading level. The human co-author identified that this flattened the conceptual architecture of the specification. The document was reorganized around four top-level sections: Vision, Technical Introduction, Survey of Decisions and Translation Rules, and Reference Appendices. The detailed construct-by-construct rules now live beneath the survey rather than competing with it.
The human co-author then further constrained the table of contents to those four top-level entries.
**Resulting documentation principle**
Document hierarchy should express conceptual hierarchy. Navigation should expose the major intellectual divisions of the specification rather than enumerate every subsection merely because it exists.
**Prompt-engineering observation**
This is an example of directing an AI at the level of information architecture rather than line editing. The correction supplied a model of the hierarchy, allowing many local formatting decisions to follow from one structural instruction.
### D.14 A recurring pattern in the collaboration
Across these exchanges, several of the most consequential human inputs were short. Their value came from identifying the exact assumption that had gone wrong rather than from supplying a long replacement answer.
A recurring pattern was:
```text
assistant proposes or explains a model
↓
human identifies a semantic or structural mismatch
↓
the mismatch is restated as a precise distinction
↓
source data or formal semantics are checked where necessary
↓
the distinction becomes an invariant, translation rule, or open decision
↓
the specification is revised so the correction applies globally
```
Examples include:
- a presentation objection becoming the source/meaning/target distinction;
- an intuitive description of existential knowledge becoming the no-witness-materialization rule;
- skepticism about punning becoming an empirical validation requirement;
- a preference for `union([...])` becoming preservation of disjunctive knowledge;
- a concern about inverse relations becoming a quantified non-inference rule;
- a closed-world intuition becoming an explicit ontology/application boundary;
- a documentation complaint becoming an information-architecture rule; and
- a prose correction becoming a Standard Written English requirement.
The broader prompt-engineering lesson is that effective collaboration with a language model is often less about constructing a single comprehensive prompt than about **maintaining control of the conceptual model through precise corrective feedback**. A short pushback can be high leverage when it identifies which distinction, invariant, scope boundary, or evidentiary claim must change.
### D.15 Provenance limits
This appendix intentionally distinguishes quotations from summaries. The available working record preserves several original phrases and a detailed history of the design decisions, but it does not provide a complete verbatim transcript of every earlier exchange. No reconstructed sentence is presented as a quotation.
A future edition may expand this appendix if a complete conversation export becomes available. Such an expansion should preserve the same distinction between verbatim input, contextual summary, resulting specification change, and retrospective prompt-engineering analysis.
Conceptual interpretation specification
The authoritative conceptual model, system boundaries, domain objects, and source-preserving interpretation invariants.
Authoritative source: RADIOLOGY-TRANSCRIPT-INTERPRETATION-CONCEPTUAL-SPEC.md · Permanent section link
# Conceptual Specification of Radiology Transcript Interpretation
## Status
This document is a conceptual and normative specification of a system that transforms radiology transcripts into validated structured semantic data.
It is not an implementation plan.
It does not prescribe a particular parser, graph matcher, programming language, runtime topology, or downstream consumer.
It is intentionally written above those mechanisms.
The system may use technologies such as Universal Dependencies, UCxn, MoCCA, FrameNet, RadLex, Grew, and Prolog, but those technologies are treated as external bodies of knowledge or implementation resources. They do not define the conceptual architecture of the system.
The specification is organized around the concepts that give the system its meaning.
The governing principle is:
> Preserve source meaning, establish structure incrementally, never invent unsupported instance-level facts, and make every derived interpretation explainable.
---
# Table of Contents
1. Vision
2. Conceptual Model
3. System Concepts and Invariants
4. Reference Appendices
---
# 1. Vision
## 1.1 Purpose
The system interprets a radiology transcript and produces a validated structured representation of what the transcript says.
The system is not intended to diagnose disease, infer hidden clinical facts, or construct a complete model of the patient.
Its purpose is narrower:
> **Understand, structure, and enrich the language of the report without exceeding the evidence provided by the report and the explicitly permitted semantic knowledge of the system.**
The source transcript remains authoritative.
The system progressively introduces more explicit structure:
```text
SOURCE LANGUAGE
─────────────────────────────────────
What was actually said.
LINGUISTIC STRUCTURE
─────────────────────────────────────
How the source is grammatically organized.
CONSTRUCTIONAL STRUCTURE
─────────────────────────────────────
Which conventional form–meaning patterns occur.
DISCOURSE STRUCTURE
─────────────────────────────────────
What is being referred to and how mentions relate.
SEMANTIC STRUCTURE
─────────────────────────────────────
What roles, relations, quantities, states, and assertions are expressed.
DOMAIN GROUNDING
─────────────────────────────────────
Which external medical concepts the discourse objects correspond to.
VALIDATED STRUCTURED OUTPUT
─────────────────────────────────────
A source-grounded semantic representation suitable
for downstream applications.
```
The validated structured output is the product of this project.
A downstream system may later render, search, transform, summarize, or otherwise consume that output, including by a language-model-based application. Such downstream consumers are outside the scope of this specification.
## 1.2 Design Intent
The system should have the following qualities.
### 1.2.1 Source fidelity
No later representation should obscure what source evidence justified it.
### 1.2.2 Semantic restraint
The system should establish only the instance-level facts that are supported by the source or by explicitly permitted derivations.
### 1.2.3 Explicit ambiguity
When the source supports multiple interpretations, the representation should preserve those alternatives rather than silently selecting one.
### 1.2.4 Compositionality
Larger meanings should be assembled from smaller recognized structures.
### 1.2.5 External grounding
The system should reuse established linguistic and medical knowledge where appropriate instead of inventing private substitutes.
### 1.2.6 Explainability
Every accepted semantic assertion should retain enough provenance to explain why it exists.
## 1.3 Non-Goals
This system does not attempt to:
- infer diagnoses that are not stated;
- infer hidden patient anatomy merely because ontology knowledge implies it abstractly;
- reconstruct a complete clinical world;
- eliminate all ambiguity;
- define a universal theory of language;
- replace established linguistic standards;
- replace RadLex or any other external ontology;
- generate final report prose;
- perform downstream stylistic rendering.
## 1.4 The Fundamental Boundary
The most important architectural distinction is between:
```text
ABSTRACT KNOWLEDGE
─────────────────────────────────────
General linguistic and domain knowledge.
Examples:
- a construction type;
- a semantic frame type;
- a RadLex class;
- a MoCCA comparative concept;
- a grammatical relation.
TRANSCRIPT INTERPRETATION
─────────────────────────────────────
Concrete structures established while interpreting
this specific transcript.
Examples:
- a mention;
- a construct instance;
- a discourse referent;
- a frame instance;
- a grounded concept association;
- an explicit ambiguity.
```
Abstract knowledge constrains interpretation.
It does not, by itself, populate the transcript model with concrete individuals.
---
# 2. Conceptual Model
## 2.1 Overview
The system is described using a small set of concepts:
```text
Source
Mention
Construct
Construction Element
Referent
Frame
Composition
Grounding
Ambiguity
Provenance
Diagnostic
Validation
```
These concepts describe what the system means.
Implementation mechanisms such as parsers, graph matchers, rule engines, indexes, and serialized formats exist only to realize these concepts.
## 2.2 Representation Flow
The system transforms the input through a sequence of increasingly explicit representations.
```text
R0 Source Transcript
↓
R1 Linguistically Annotated Source
↓
R2 Construction-Annotated Source
↓
R3 Discourse and Frame Model
↓
R4 Domain-Grounded Semantic Model
↓
R5 Validated Structured Output
```
The transformations are not required to be implemented as five literal runtime stages.
The sequence expresses a conceptual ordering:
1. source evidence exists before interpretation;
2. linguistic structure exists before higher-order constructional interpretation;
3. constructional interpretation precedes semantic composition;
4. discourse objects and frames precede domain grounding;
5. validation constrains the final structured output.
## 2.3 Global Transformation Properties
Every transformation should satisfy the following properties.
### Source preservation
Later representations must retain access to the source evidence from which they were derived.
### No silent contradiction
A later representation may enrich an earlier representation but must not silently contradict an established source-backed fact.
### No unsupported instance creation
No transformation may create a discourse or application-level entity solely because external ontology knowledge implies that such an entity exists in the abstract.
### Explicit unresolved state
A transformation may produce unresolved or ambiguous structure.
Failure to resolve is not permission to guess.
### Traceable derivation
Every semantic assertion must be derivable from a known combination of:
- source evidence;
- recognized linguistic/constructional structure;
- discourse relationships;
- external semantic/domain knowledge;
- explicitly specified system rules.
---
# 3. System Concepts and Invariants
# 3.1 Source
## Purpose
The Source preserves the exact evidence supplied to the system.
The source is the authoritative record of what was said.
## Operational Principle
The system stores the original transcript and stable source locations that can be referenced by later objects.
A source location may be represented as:
```text
document
sentence
token
character span
```
or another equivalent representation.
The essential requirement is stable traceability.
## Model Interpretation
```text
SOURCE
─────────────────────────────────────
"There is a 6 mm pulmonary nodule
in the right upper lobe."
```
Later structures may refer back to:
```text
"6 mm"
"pulmonary nodule"
"right upper lobe"
```
without replacing the original source.
## Concrete Example
```prolog
source_span(
s1,
11,
17,
"6 mm"
).
```
The syntax is illustrative.
## Formal Properties / Invariants
For every derived object d:
```text
derived(d) → ∃ s : SourceEvidence(s) ∧ supports(s,d)
```
Source evidence is immutable with respect to interpretation.
## Entails
A source span establishes that the corresponding text occurred in the transcript.
## Does Not Entail
A source span does not establish the medical truth of the words it contains.
Mentioning a concept is not equivalent to asserting that the concept is present.
---
# 3.2 Mention
## Purpose
A Mention represents a linguistically identifiable expression in the source that participates in interpretation.
Mentions separate surface language from discourse identity.
## Operational Principle
A mention is anchored to source evidence and may carry linguistic, lexical, semantic, or normalization information.
Multiple mentions may later refer to the same discourse referent.
## Model Interpretation
```text
SOURCE
─────────────────────────────────────
"A nodule is present. It measures 6 mm."
MENTIONS
─────────────────────────────────────
m1 = "A nodule"
m2 = "It"
m3 = "6 mm"
```
`m1` and `m2` are distinct mentions even if they eventually refer to the same object.
## Concrete Example
```prolog
mention(m1, source_span(...)).
mention(m2, source_span(...)).
```
Later:
```prolog
refers_to(m1, f1).
refers_to(m2, f1).
```
## Formal Properties / Invariants
Every mention is source-grounded:
```text
Mention(m) → ∃ s : SourceEvidence(s) ∧ anchored_in(m,s)
```
A mention and a referent are distinct concepts:
```text
Mention(m) ⇏ Referent(m)
```
## Entails
A mention establishes that an expression occurred and has been identified as relevant to interpretation.
## Does Not Entail
A mention does not by itself establish:
- discourse identity;
- ontology identity;
- presence;
- absence;
- patient-world existence.
---
# 3.3 Construct
## Purpose
A Construct captures an instance of a conventional meaningful linguistic structure found in the source.
The concept exists because individual dependency edges or tokens often do not express the larger semantic organization of an utterance.
## Operational Principle
The system recognizes that a region of the linguistic representation instantiates a known construction type.
The construct binds construction elements to specific linguistic material.
Constructs may overlap.
A source region may participate in more than one construct.
## Model Interpretation
Source:
```text
A pulmonary nodule in the right upper lobe measures 6 mm.
```
Possible constructs:
```text
Measurement-Predicate
Finding-Location
Nominal-Modification
```
Each construct captures a different meaningful organization of the same source.
## Concrete Example
```prolog
construct(c1, measurement_predicate).
construction_element(c1, entity, m_nodule).
construction_element(c1, measurement, m_6mm).
```
## Formal Properties / Invariants
Every construct has exactly one construction type:
```text
Construct(c) → ∃! t : ConstructionType(t) ∧ instance_of(c,t)
```
Every construction element must be bound to valid source-backed linguistic material or an explicitly permitted derived element.
Constructs may overlap:
```text
overlap(c1,c2)
```
is legal.
## Entails
A construct establishes that the source instantiates a known linguistic form–meaning pattern.
## Does Not Entail
Construct recognition alone does not establish:
- ontology grounding;
- discourse identity;
- patient-world existence;
- a final application relation.
A location-like construct does not automatically mean that the application should assert `located_in/2`.
---
# 3.4 Construction Element
## Purpose
A Construction Element identifies the role played by a specific part of the source inside a construct.
## Operational Principle
A construct defines named roles.
A recognized construct instance binds those roles to source-backed linguistic objects.
Examples include:
```text
Entity
Measurement
Figure
Ground
Predicate
ResultState
Baseline
Degree
```
## Model Interpretation
For:
```text
The nodule measures 6 mm.
```
the construct might contain:
```text
Measurement-Predicate
─────────────────────────────────────
Entity → "The nodule"
Predicate → "measures"
Measurement → "6 mm"
```
## Concrete Example
```prolog
construction_element(c1, entity, m1).
construction_element(c1, predicate, m2).
construction_element(c1, measurement, m3).
```
## Formal Properties / Invariants
Every bound element must belong to the construct type's allowed role vocabulary.
```text
element(c,r,x) →
Construct(c)
∧ allowed_role(type(c),r)
```
## Entails
A construction element establishes a role within a recognized construct.
## Does Not Entail
A construction element name is not automatically an application-level semantic relation.
For example, `Ground` is a constructional/semantic role, not necessarily a RadLex relation.
---
# 3.5 Referent
## Purpose
A Referent represents the discourse object that one or more mentions are about.
The concept separates linguistic expressions from discourse identity.
## Operational Principle
Mentions may introduce or refer to discourse referents.
Multiple mentions may resolve to the same referent.
A referent exists in the interpretation of the transcript.
It is not automatically a metaphysical claim that an independently existing patient-world object has been established.
## Model Interpretation
```text
SOURCE
─────────────────────────────────────
"There is a nodule.
It measures 6 mm."
MENTIONS
─────────────────────────────────────
m1 = "a nodule"
m2 = "it"
DISCOURSE
─────────────────────────────────────
m1 → f1
m2 → f1
```
## Concrete Example
```prolog
referent(f1).
refers_to(m1, f1).
refers_to(m2, f1).
```
## Formal Properties / Invariants
Every referent must be grounded in one or more mentions or in an explicitly specified permitted derivation:
```text
Referent(r) →
∃ m : Mention(m) ∧ refers_to(m,r)
```
No external ontology existential creates a referent:
```text
OntologyImpliesExistence(c)
⇏
∃ r : Referent(r) ∧ grounded_as(r,c)
```
## Entails
A referent establishes a discourse-level identity.
## Does Not Entail
A referent does not necessarily establish:
- physical existence;
- clinical truth;
- independent ontology instance membership.
A negated mention may participate in semantic interpretation without creating a positive finding instance.
---
# 3.6 Frame
## Purpose
A Frame represents a structured semantic situation with named participant roles.
Frames provide an intermediate semantic vocabulary between linguistic constructions and application predicates.
## Operational Principle
A recognized construct may evoke one or more frame types.
Construction elements and discourse referents fill frame roles.
## Model Interpretation
Measurement:
```text
MEASUREMENT
─────────────────────────────────────
Entity → f1
Value → 6
Unit → mm
Dimension → unresolved or inferred if permitted
```
Location:
```text
LOCATION
─────────────────────────────────────
Figure → f1
Ground → a1
```
## Concrete Example
```prolog
frame(fr1, measurement).
frame_role(fr1, entity, f1).
frame_role(fr1, value, 6).
frame_role(fr1, unit, mm).
```
## Formal Properties / Invariants
Every frame role must be licensed by the frame type:
```text
frame_role(f,r,x) →
Frame(f)
∧ allowed_frame_role(type(f),r)
```
Every frame instance must retain evidence linking it to one or more constructs or explicitly specified semantic rules.
## Entails
A frame establishes a semantic organization of interpreted source material.
## Does Not Entail
A frame is not necessarily a final application assertion.
A `LOCATION` frame may still require domain grounding or disambiguation before being projected into a domain relation.
---
# 3.7 Composition
## Purpose
Composition combines smaller recognized structures into a larger coherent interpretation.
## Operational Principle
Constructs, referents, and frames may share participants.
When their roles and constraints are compatible, the system composes them.
Composition does not erase the components.
## Model Interpretation
Source:
```text
There is a 6 mm nodule in the right upper lobe.
```
Recognized structures:
```text
Existential/Presentation
Measured-Nominal
Location
```
Composition identifies a common referent:
```text
finding f1
```
and yields:
```text
measurement frame → f1
location frame → f1
```
## Concrete Example
```prolog
refers_to(m_nodule, f1).
frame_role(fr_measurement, entity, f1).
frame_role(fr_location, figure, f1).
```
## Formal Properties / Invariants
Composition may add relationships among existing objects.
It must not erase the provenance of the contributing structures.
If two structures are incompatible, composition must not silently choose one.
## Entails
Composition establishes that multiple semantic structures participate in one coherent interpretation.
## Does Not Entail
Shared source proximity alone does not justify composition.
Composition requires explicit structural or semantic evidence.
---
# 3.8 Grounding
## Purpose
Grounding connects linguistic or discourse objects to established external domain concepts.
For this system, the primary medical ontology is RadLex.
## Operational Principle
Mentions or discourse referents may be associated with one or more candidate ontology concepts using lexical, constructional, contextual, and semantic evidence.
Grounding may remain ambiguous.
## Model Interpretation
```text
SOURCE
─────────────────────────────────────
"right upper lobe"
MENTION
─────────────────────────────────────
m7
REFERENT
─────────────────────────────────────
a2
ONTOLOGY
─────────────────────────────────────
RadLex concept: right upper lobe
```
## Concrete Example
```prolog
grounding(
a2,
radlex_right_upper_lobe
).
```
## Formal Properties / Invariants
Grounding connects transcript interpretation to ontology classes:
```text
grounded_as(r,c) →
Referent(r) ∧ OntologyConcept(c)
```
Grounding does not create referents:
```text
OntologyConcept(c) ⇏ ∃ r : grounded_as(r,c)
```
Ontology knowledge may constrain interpretation but may not independently populate the transcript model.
## Entails
Grounding establishes that a transcript object is being interpreted through the semantics of an external concept.
## Does Not Entail
Grounding does not imply that:
- the external ontology asserts this transcript referent as an individual;
- every existential restriction of the ontology has a corresponding transcript referent;
- all ontology relationships become application relationships.
---
# 3.9 Ambiguity
## Purpose
Ambiguity prevents unsupported certainty from being represented as fact.
## Operational Principle
When the available evidence supports multiple interpretations and does not justify selecting one, the system preserves the alternatives explicitly.
Ambiguity is a normal structured result.
## Model Interpretation
Source:
```text
There is a nodule near the fissure measuring 6 mm.
```
Possible interpretations:
```text
measurement → nodule
measurement → fissure
```
If neither can be eliminated by permitted evidence:
```text
AMBIGUOUS ATTACHMENT
─────────────────────────────────────
Candidate A → nodule
Candidate B → fissure
```
## Concrete Example
```prolog
ambiguous_attachment(
measurement_1,
[
candidate(f1),
candidate(a1)
]
).
```
## Formal Properties / Invariants
If two interpretations are supported and neither dominates under the system's rules:
```text
supported(i1) ∧ supported(i2)
∧ ¬ preferred(i1,i2)
∧ ¬ preferred(i2,i1)
→ preserve({i1,i2})
```
No transformation may silently collapse explicit ambiguity.
## Entails
Ambiguity establishes that the system has identified multiple supported alternatives.
## Does Not Entail
Ambiguity is not an error.
It does not imply that the transcript is malformed.
It does not authorize arbitrary selection.
---
# 3.10 Provenance
## Purpose
Provenance explains how a derived interpretation arose.
## Operational Principle
Derived objects retain references to their relevant source evidence, recognized constructs, semantic rules, external concept alignments, and permitted derivations.
## Model Interpretation
A semantic relation might carry:
```text
SOURCE
"nodule measures 6 mm"
LINGUISTIC EVIDENCE
subject(measures, nodule)
quantity(6 mm)
CONSTRUCT
Measurement-Predicate
FRAME
Measurement
GROUNDING
nodule → pulmonary nodule
SEMANTIC RESULT
measurement_of(q1,f1)
```
## Concrete Example
```prolog
supports(
measurement_of(q1, f1),
[
source_span(...),
construct(c1),
frame(fr1)
]
).
```
## Formal Properties / Invariants
Every accepted semantic assertion must have a derivation path:
```text
SemanticAssertion(a) →
∃ p : ProvenancePath(p) ∧ derives(p,a)
```
Later transformations may add provenance but must not destroy the ability to trace the assertion back to source evidence.
## Entails
Provenance establishes why the system believes a representation is justified.
## Does Not Entail
Provenance does not itself guarantee correctness.
It makes correctness auditable.
---
# 3.11 Diagnostic
## Purpose
A Diagnostic represents a limitation, unsupported form, conflict, or incomplete interpretation without forcing the system to fabricate meaning.
## Operational Principle
When a representation cannot be completed under the system's rules, the system emits a structured diagnostic attached to relevant source evidence.
Examples:
```text
unknown construction
ambiguous attachment
unresolved referent
ambiguous grounding
unsupported semantic projection
malformed measurement
```
## Model Interpretation
```text
SOURCE
─────────────────────────────────────
"RUL noduel 6 mm"
DIAGNOSTIC
─────────────────────────────────────
unknown lexical normalization:
"noduel"
possible spelling candidate:
"nodule"
```
## Concrete Example
```prolog
diagnostic(
d1,
ambiguous_grounding,
mention(m7),
candidates([...])
).
```
## Formal Properties / Invariants
Diagnostics must not silently become semantic assertions.
A diagnostic must identify the relevant object or source region.
## Entails
A diagnostic establishes that some part of the interpretation is incomplete, uncertain, unsupported, or inconsistent.
## Does Not Entail
A diagnostic does not necessarily invalidate the entire transcript interpretation.
Partial success is permitted.
---
# 3.12 Validation
## Purpose
Validation ensures that the structured output satisfies the semantic contract of the system.
## Operational Principle
Validation checks structural, referential, semantic, ontological, and provenance constraints.
Validation may accept representations containing explicit ambiguity or diagnostics when those are valid outcomes.
## Model Interpretation
Validation may check:
```text
every mention has source evidence
every construct has a valid construction type
every construction element fills an allowed role
every referent is source-licensed
every frame role is valid
every grounding target exists in the external ontology
every semantic assertion has provenance
no ontology-only existential creates a transcript referent
explicit ambiguity has not been silently collapsed
```
## Concrete Example
Invalid:
```prolog
measurement_of(q1, f99).
```
if `f99` is not a valid discourse referent.
Valid:
```prolog
ambiguous_attachment(
q1,
[candidate(f1), candidate(f2)]
).
```
if both candidates are well-formed and source-supported.
## Formal Properties / Invariants
Let `Valid(R)` mean that representation `R` satisfies all applicable system invariants.
The final output must satisfy:
```text
Output(R) → Valid(R)
```
Validation is semantic, not merely syntactic.
## Entails
A validated output conforms to the system's explicit model and invariants.
## Does Not Entail
Validation does not mean that:
- every ambiguity has been resolved;
- every source phrase has a perfect interpretation;
- the representation constitutes a clinical diagnosis;
- the external ontology is itself infallible.
---
# 3.13 Cross-Cutting Invariants
The following invariants apply throughout the system.
## I1. Source Preservation
Every derived object is traceable to source evidence.
## I2. No Instance Invention
No discourse or application-level individual is introduced solely because external ontology knowledge implies that some individual exists abstractly.
## I3. Abstract Knowledge / Transcript Separation
General ontology and linguistic knowledge remain semantically distinct from concrete transcript interpretation.
## I4. Mention / Referent Separation
A linguistic mention is not identical to the discourse referent it denotes.
## I5. Construct Accountability
Every recognized construct must be justified by a known construction definition or rule.
## I6. Role Integrity
Every construction or frame role is filled by a valid object of the appropriate kind or is explicitly unresolved.
## I7. Ambiguity Preservation
Supported alternatives remain explicit until additional permitted evidence resolves them.
## I8. Compositional Provenance
Composed semantic structures preserve the provenance of their constituent structures.
## I9. No Silent Semantic Rewrite
Later representations may refine or enrich earlier ones but may not silently contradict source-backed established facts.
## I10. Explicit Diagnostics
Unsupported or unresolved interpretation is represented explicitly rather than silently discarded.
## I11. Validated Output
The final structured representation satisfies all applicable structural, referential, ontology, ambiguity, and provenance constraints.
---
# 3.14 Acceptance Criteria
This specification is ready to support implementation when:
- every core concept has a stable purpose and operational principle;
- global invariants are mutually consistent;
- the project boundary is clear;
- the distinction between source, mention, referent, construct, frame, and ontology concept is unambiguous;
- ambiguity and diagnostics are accepted as legitimate outputs;
- the external authorities used by each concept are identified;
- representative transcript examples can be described entirely using the conceptual vocabulary;
- no core semantic requirement depends on a specific implementation technology;
- the final structured output can be validated against the invariants in this document.
---
# 4. Reference Appendices
# Appendix A. Universal Dependencies
## Role in the System
Universal Dependencies supplies a standardized morphosyntactic representation.
The system may use UD for:
- tokenization;
- lemmas;
- universal part-of-speech tags;
- morphology;
- dependency relations;
- language-specific dependency subtypes;
- enhanced dependency information where useful.
UD is treated as linguistic evidence.
It is not the semantic model of the application.
## Conceptual Boundary
```text
UD
─────────────────────────────────────
What grammatical relationships are present?
THIS SYSTEM
─────────────────────────────────────
What larger constructions, discourse structures,
frames, and domain meanings are established?
```
## Important Property
A later semantic interpretation should not silently rewrite the imported linguistic analysis.
If the implementation permits alternative UD analyses, those alternatives should be represented explicitly.
---
# Appendix B. Construction Grammar
## Role in the System
Construction Grammar supplies the conceptual basis for recognizing conventional form–meaning pairings as first-class objects.
The system does not claim to implement a complete theoretical Construction Grammar formalism.
The relevant principle is:
> A recurrent linguistic configuration may contribute meaning that is not reducible to individual lexical items or dependency edges.
This motivates the concepts `Construct` and `Construction Element`.
---
# Appendix C. UCxn
## Role in the System
UCxn supplies a practical model for annotating construction instances on top of Universal Dependencies.
Relevant ideas include:
```text
Cxn
construction instance annotation
CxnElt
construction element annotation
```
UCxn also establishes that:
- constructions may overlap;
- construction elements may correspond to nodes, spans, full subtrees, or partial subtrees;
- construction recognition can be expressed over UD graphs.
The system should reuse UCxn-compatible conventions where practical.
---
# Appendix D. MoCCA
## Role in the System
MoCCA supplies a comparative-concept network for aligning language-specific constructions with cross-linguistic analytical concepts.
The most important distinction is:
```text
L-CONSTRUCTION
─────────────────────────────────────
A language-specific construction.
COMPARATIVE CONCEPT
─────────────────────────────────────
A language-neutral analytical category.
```
MoCCA also distinguishes construction concepts, strategies, semantic content, information packaging, and FrameNet frames.
The system should use MoCCA as the default reference model for classifying construction types where suitable.
A radiology-specific construction remains local when no appropriate comparative concept exists.
---
# Appendix E. Frame Semantics and FrameNet
## Role in the System
Frame Semantics provides a model for representing semantic situations through named participant roles.
FrameNet supplies an existing inventory of semantic frames.
The system may reuse suitable FrameNet frames rather than inventing private equivalents.
The frame model does not replace RadLex.
FrameNet describes general semantic situations.
RadLex describes radiological and medical domain concepts.
---
# Appendix F. RadLex
## Role in the System
RadLex supplies the principal domain ontology for medical and radiological grounding.
Relevant knowledge includes:
- classes;
- labels;
- synonyms;
- subclass relationships;
- object properties;
- class restrictions;
- relation specializations;
- ontology metadata required by the application.
## Critical Boundary
RadLex is abstract domain knowledge.
The transcript interpretation is a concrete discourse model.
For example:
```text
RADLEX
─────────────────────────────────────
right_kidney ⊆
∃ contained_in.right_retroperitoneal_compartment
TRANSCRIPT MODEL
─────────────────────────────────────
mention("right kidney")
referent(k1)
grounded_as(k1, right_kidney)
```
If no compartment is established by the source or by an explicitly permitted application derivation, no compartment referent is introduced.
Ontology existential meaning remains ontology-level knowledge.
---
# Appendix G. Compiler Concepts
The system intentionally borrows several concepts from compiler design.
## Source
The immutable input to interpretation.
## Intermediate Representation
A structured language used between transformation stages.
## Pass
A transformation from one representation into a richer or more normalized representation.
## Semantic Analysis
The stage in which syntactic or constructional structures are related to discourse identity, semantic roles, and domain meaning.
## Validation / Static Semantics
Rules that determine whether a structured representation is semantically well formed.
## Diagnostic
A structured account of unsupported, ambiguous, or invalid input or interpretation.
## Provenance
The derivation path explaining how later representation elements arose.
The compiler analogy is conceptual.
Natural language is not treated as if it were a conventional deterministic programming language.
---
# Appendix H. External Knowledge and Versioning
A concrete implementation should record the versions of external resources that materially influence interpretation.
Candidate metadata includes:
```text
UD specification version
UD parser/model version
UCxn schema/rule version
MoCCA comparative-concept database version
FrameNet version
RadLex version
local constructicon version
system semantic-rule version
```
Versioning supports reproducibility and provenance.
---
# Appendix I. Representative Examples
## I.1 Happy Path Measurement
Source:
```text
A pulmonary nodule in the right upper lobe measures 6 mm.
```
Conceptual interpretation:
```text
SOURCE
─────────────────────────────────────
original sentence and spans
MENTIONS
─────────────────────────────────────
pulmonary nodule
right upper lobe
6 mm
CONSTRUCTS
─────────────────────────────────────
Measurement-Predicate
Location
REFERENTS
─────────────────────────────────────
f1 = finding discourse referent
a1 = anatomical discourse referent
FRAMES
─────────────────────────────────────
Measurement(Entity=f1, Value=6, Unit=mm)
Location(Figure=f1, Ground=a1)
GROUNDING
─────────────────────────────────────
f1 → pulmonary nodule
a1 → right upper lobe
OUTPUT RELATIONS
─────────────────────────────────────
measurement_of(q1, f1)
located_in(f1, a1)
```
No token-distance heuristic is required.
## I.2 Cross-Sentence Reference
Source:
```text
There is a nodule in the right upper lobe.
It measures 6 mm.
```
Conceptual interpretation:
```text
MENTIONS
─────────────────────────────────────
m1 = "a nodule"
m2 = "right upper lobe"
m3 = "It"
m4 = "6 mm"
REFERENTS
─────────────────────────────────────
m1 → f1
m3 → f1
m2 → a1
FRAMES
─────────────────────────────────────
Location(Figure=f1, Ground=a1)
Measurement(Entity=f1, Value=6, Unit=mm)
```
The pronoun is a mention.
It is not a second finding referent.
## I.3 Negated Coordination
Source:
```text
No pleural effusion or pneumothorax.
```
Conceptual interpretation:
```text
CONSTRUCTS
─────────────────────────────────────
Negation
Coordination
Medical nominal mentions
SEMANTIC STRUCTURE
─────────────────────────────────────
negative scope applies to:
- pleural effusion
- pneumothorax
```
The system may represent absence assertions.
It should not create positive finding individuals merely because the concepts were mentioned.
## I.4 Ambiguous Attachment
Source:
```text
There is a nodule near the fissure measuring 6 mm.
```
Conceptual interpretation:
```text
KNOWN
─────────────────────────────────────
nodule mention
fissure mention
measurement mention
proximity/location construct
measurement construct
UNRESOLVED
─────────────────────────────────────
measurement target:
- nodule
- fissure
```
Unless permitted structural or domain evidence resolves the ambiguity, both candidates remain represented.
## I.5 Telegraphic Radiology
Source:
```text
Stable 6 mm RUL nodule.
```
Conceptual interpretation:
```text
CONSTRUCT
─────────────────────────────────────
Telegraphic-Finding-Assertion
ELEMENTS
─────────────────────────────────────
Status → stable
Measurement → 6 mm
Location → RUL
Finding → nodule
```
The construction is a property of the radiology reporting sublanguage.
It may be aligned to more general constructional concepts, but its report-specific character remains explicit.
---
# Appendix J. Open Design Questions
The following questions remain intentionally open.
╔════════════════════════════════════════════════════════╗
║ ⚠ OPEN DECISION ║
║ ║
║ Define the exact boundary between Mention grounding ║
║ and Referent grounding. ║
╚════════════════════════════════════════════════════════╝
Known possibilities include:
```text
mention → ontology concept
referent → ontology concept
both, with distinct semantics
```
The decision affects provenance and ambiguity representation.
---
╔════════════════════════════════════════════════════════╗
║ ⚠ OPEN DECISION ║
║ ║
║ Define the exact frame vocabulary used internally. ║
╚════════════════════════════════════════════════════════╝
Possible approaches include:
```text
reuse FrameNet where possible
define application-specific frames
use a hybrid
```
The decision should be driven by empirical radiology cases.
---
╔════════════════════════════════════════════════════════╗
║ ⚠ OPEN DECISION ║
║ ║
║ Define which semantic projections are canonical ║
║ output relations and which remain frame structures. ║
╚════════════════════════════════════════════════════════╝
For example:
```text
LOCATION frame
```
may or may not always project to:
```prolog
located_in(Figure, Ground).
```
The decision should preserve distinctions among linguistic meaning, frame semantics, and domain ontology relations.
---
# Appendix K. Design Conversation Provenance
This appendix is non-normative.
It records selected conceptual pivots that materially shaped the specification.
## K.1 Structured Interpretation Rather Than Clinical Inference
**Design issue**
Scope of the application.
**Context summary**
The system was initially being discussed alongside ontology enrichment and report interpretation, creating a risk that ontology knowledge could be mistaken for case-level clinical inference.
**Design contribution**
Human-led direction. The project scope was explicitly restricted to understanding what the doctor said. Ontology knowledge may enrich meaning, but the system should not infer unstated facts about the patient.
**Resulting specification rule**
No ontology fact alone introduces a discourse or application-level individual.
**Why the interaction was useful**
The correction changed the system boundary rather than merely changing implementation details.
## K.2 Grammar Rather Than Token Distance
**Design issue**
Attachment of measurements and other modifiers.
**Original input**
> “The grammatical attachment is what I was expecting.”
**Design contribution**
Human-led correction. Bounded token windows were rejected in favor of following grammatical relationships.
**Resulting specification rule**
Composition requires structural or semantic evidence. Source proximity alone is insufficient.
**Why the interaction was useful**
A local measurement example became a global architectural principle.
## K.3 Universal Dependencies as Linguistic Authority
**Design issue**
Whether the application should implement English syntax directly.
**Context summary**
APE demonstrated how a Prolog grammar could produce rich linguistic and discourse structure, but building a full English parser would create substantial unnecessary work.
**Design contribution**
Joint refinement. Universal Dependencies was adopted as the standardized morphosyntactic representation, allowing later system logic to operate above raw syntax.
**Resulting specification rule**
Linguistic analysis is an external evidence layer. Later semantic stages interpret rather than reinvent it.
## K.4 Construction Recognition Above UD
**Design issue**
How to obtain larger meaningful grammatical structures.
**Context summary**
Individual dependency relations were useful but too local to express recurring semantic patterns such as measurement, result, location, and comparison.
**Design contribution**
Human-led direction refined through Construction Grammar research. Larger form–meaning pairings should be recognized compositionally over the linguistic representation.
**Resulting specification rule**
Constructs are first-class runtime objects with typed construction elements.
## K.5 UCxn Instead of a Private Construction Annotation System
**Design issue**
How construction instances should be represented.
**Context summary**
A custom Prolog representation was initially considered.
**Design contribution**
Research-led refinement. UCxn was identified as existing prior art specifically for construction annotation atop Universal Dependencies.
**Resulting specification rule**
The conceptual model distinguishes Construction Types, Constructs, and Construction Elements in a way compatible with UCxn.
## K.6 MoCCA and the Separation of Universal Meaning from Language Strategy
**Design issue**
Avoiding accidental English-specific semantics.
**Context summary**
An English dependency pattern such as `X measures Y` could easily be mistaken for the universal definition of a measurement construction.
**Design contribution**
Human-led concern followed by research into MoCCA. The design now distinguishes language-specific constructions from comparative construction concepts and realization strategies.
**Resulting specification rule**
Language-specific realization and language-neutral semantic classification remain distinct.
## K.7 Ambiguity as a Structured Output
**Design issue**
What the deterministic system should do when multiple interpretations remain plausible.
**Original input**
> “Ambiguous structures [are] 100% of the point.”
**Design contribution**
Human-led direction. Correctness was prioritized over forced coverage.
**Resulting specification rule**
Explicit ambiguity is a valid structured result and may not be silently collapsed.
**Why the interaction was useful**
The design objective shifted from maximizing deterministic interpretation to safely reducing ambiguity.
## K.8 The Project Ends at Structured Output
**Design issue**
Whether downstream language-model completion or report generation belonged inside the interpreter.
**Design contribution**
Human-led scope correction. Those activities were removed from the project boundary.
**Resulting specification rule**
The system ends at validated structured semantic output. Downstream consumers are separate systems.
---
# Appendix L. One-Sentence Summary
> **The radiology transcript interpreter progressively transforms source language into a validated semantic representation by identifying mentions, recognizing constructs, forming discourse referents and frames, grounding those objects in established domain concepts, composing compatible interpretations, preserving ambiguity and diagnostics explicitly, and retaining provenance for every derived result.**
Linguistic and semantic refinement specification
The example-driven linguistic profile, construction vocabulary, semantic frames, IR obligations, and source-to-semantics rules.
Authoritative source: RADIOLOGY-TRANSCRIPT-LINGUISTIC-SEMANTIC-REFINEMENT-SPEC.md · Permanent section link
# Radiology Transcript Linguistic and Semantic Refinement Specification
## Status
This document is an example-driven draft.
It is a lower-level refinement of the project-level
`RADIOLOGY-TRANSCRIPT-INTERPRETATION-CONCEPTUAL-SPEC.md`. It assumes the
concepts, boundaries, and invariants established by that specification. If the
two documents conflict, the project-level conceptual specification is
authoritative.
This document begins to define the linguistic annotation profile, initial
construction vocabulary, semantic frame vocabulary, intermediate
representation, and source-to-semantics translation obligations needed for an
implementation.
It is not yet an implementation plan. Names and structures marked
**provisional** are hypotheses to test against the corpus before they become
normative interfaces.
---
# Table of Contents
1. Vision
2. Technical Introduction
3. Survey of Decisions and Translation Rules
4. Reference Appendices
---
# 1. Vision
## 1.1 Purpose of This Refinement
The conceptual specification says what a valid transcript interpretation
means. This refinement describes how representative radiology language is
decomposed into those concepts closely enough to guide implementation.
The refinement proceeds from examples rather than from an attempt to enumerate
English grammar in advance:
```text
representative transcript expression
↓
source-anchored linguistic observations
↓
recognized construction and bound elements
↓
candidate discourse and frame interpretation
↓
domain grounding candidates
↓
validated semantic result, ambiguity, or diagnostic
```
The governing principle is:
> Define only as much linguistic and semantic machinery as is required to
> explain representative corpus examples without losing source evidence or
> inventing transcript-level facts.
## 1.2 Relationship to the Conceptual Specification
This document does not redefine `Source`, `Mention`, `Construct`,
`Construction Element`, `Referent`, `Frame`, `Composition`, `Grounding`,
`Ambiguity`, `Provenance`, `Diagnostic`, or `Validation`.
It refines them by specifying:
- which corpus expressions initially exercise them;
- which linguistic evidence may support them;
- which construction and frame roles are required;
- how objects are represented in an implementation-facing IR;
- which external authority informs each decision;
- which mappings are normative, provisional, or deliberately unresolved.
The conceptual transformation order remains authoritative:
```text
R0 Source Transcript
↓
R1 Linguistically Annotated Source
↓
R2 Construction-Annotated Source
↓
R3 Discourse and Frame Model
↓
R4 Domain-Grounded Semantic Model
↓
R5 Validated Structured Output
```
These are semantic representation levels. An implementation is not required to
materialize five files, make five network calls, or execute five isolated
processes.
## 1.3 Initial Empirical Boundary
This refinement uses only the locally retained generated transcription inputs.
The reports from which those inputs were historically derived are not retained
and are not part of an interpretation execution.
The initial corpus is sufficient for:
- discovering recurring language forms;
- proposing construction and frame vocabularies;
- creating executable interpretation examples;
- testing source preservation, ambiguity, diagnostics, and validation;
- demonstrating architectural viability.
It is not sufficient for claiming production performance on real human
dictation or speech-recognition output.
Real dictation may introduce repairs, hesitations, punctuation commands,
speaker-specific shorthand, abandoned clauses, recognition substitutions, and
other forms that are not adequately represented by the current corpus. Those
phenomena will extend this profile later; they must not silently change the
meaning of existing annotations.
## 1.4 Non-Goals
This draft does not attempt to:
- define a complete grammar of radiology dictation;
- annotate all 3,573 generated inputs before implementation begins;
- treat heuristic corpus labels as gold annotations;
- decide every possible FrameNet or MoCCA alignment;
- infer clinical truth beyond the transcript;
- validate robustness to real human transcription;
- prescribe service boundaries, programming languages, or deployment topology.
---
# 2. Technical Introduction
## 2.1 Corpus Inventory and Evidential Status
The checked-in corpus contains 3,573 generated transcription inputs in JSON
Lines form. The records use two generated surface variants:
| Variant | Records | Meaning |
| --- | ---: | --- |
| `sectionless_dictation` | 1,982 | A deterministic removal of selected section labels. |
| `spoken_punctuation` | 1,591 | A deterministic replacement of selected punctuation with comma-like forms. |
The current artifact was produced by the historical derivation procedure in
`research/radiology-corpus/generated/generate_transcript_corpus.py`. It is a
deterministically generated corpus, not an LLM-generated corpus. The upstream
source material has been removed by project decision. Its historical hash is
retained as provenance, but its content is unavailable to the interpreter.
Future LLM-generated inputs may be added as a distinct provenance tier. Such
records should identify the source report, model, model version, prompt or
prompt version, generation parameters, generation date, and any human review.
The current `phenomena` and `expected_constructs` fields are regular-expression
selection aids. They are neither linguistic analysis nor gold semantic
annotation. In particular, the current heuristic label `ambiguous_attachment`
means only that a measurement and selected spatial language co-occur; it does
not establish actual ambiguity.
## 2.2 Corpus Roles
The project distinguishes two corpus roles:
```text
DEVELOPMENT INPUT CORPUS
─────────────────────────────────────
Generated transcription records, including deterministic variants
now and possible LLM-generated transcriptions later.
Used as executable interpreter input.
VALIDATION CORPUS
─────────────────────────────────────
Future real human transcriptions with appropriate authority and handling.
Used to evaluate generalization to actual dictation.
```
The input boundary is exact:
```text
source(execution) = record.transcript_text
```
Only characters in `transcript_text` may supply linguistic evidence. Historical
lineage fields, generation metadata, and unavailable upstream material may be
used for provenance or test selection, but may not influence interpretation.
Generated text may contain words that resemble report headings or other report
structure. They are ordinary source tokens unless the transcription itself
licenses a spoken discourse function. The system has no hidden Findings or
Impression sections.
Evaluation claims must identify whether their evidence comes from generated or
future human transcription.
## 2.3 Example Selection
The first annotated development set should be small and stratified. It should
contain the simplest positive example and progressively add one linguistic
complication at a time.
The initial selection should cover at least:
| Family | Representative form |
| --- | --- |
| Finding description | `Borderline cardiomegaly.` |
| Normality | `The lungs are clear.` |
| Negation | `No pneumothorax.` |
| Negated coordination | `There is no pneumothorax or pleural effusion.` |
| Location | `opacities in the left lung apex` |
| Finding size | `an 8mm nodule in the left lower lobe` |
| Device distance | `tube tip is 5 cm above the carina` |
| Comparison | `stable from prior radiographs` |
| Uncertainty | `could represent a cavitary lesion` |
| Alternative interpretation | `probably scarring ... difficult to exclude a cavitary lesion` |
| Recommendation | `CT chest with contrast is recommended` |
| Cross-sentence identity | `There is a nodule. It measures 6 mm.` |
| Repeated reference | a later utterance that redescribes an earlier finding |
| Redaction damage | a construction containing `[REDACTED]` |
Heuristic labels may retrieve candidates. A human must inspect each selected
span before it becomes a normative example.
## 2.4 Annotation Units
### 2.4.1 Document and source span
A document is one interpreter input. A source span is a half-open character
interval in the exact input text:
```text
span = [start, end)
```
The source is exactly the record's `transcript_text` value. Neither the record's
historical `source_row` nor any pre-generation document is part of the source.
The stored text for the span must equal the corresponding substring of the
immutable source. Tokens and sentences may be associated with spans, but they
do not replace character anchoring.
### 2.4.2 Linguistic observation
A linguistic observation records imported or derived language analysis such
as tokenization, lemma, part of speech, morphology, dependency relation,
sentence boundary, or candidate normalization.
Universal Dependencies is the initial authority for morphosyntactic labels.
Parser output is evidence, not unquestionable fact. A later rule may disagree
with a parser analysis only by recording an alternative observation or a
diagnostic; it must not silently mutate the imported analysis.
### 2.4.3 Mention
A mention is a source-anchored expression that participates in interpretation.
Initial mention categories are **provisional annotation conveniences**, not new
ontological kinds:
```text
entity expression
anatomical expression
quantity expression
unit expression
state expression
relation trigger
discourse expression
action expression
```
A mention may have more than one applicable category. Mention categorization
does not establish discourse identity, ontology identity, polarity, or patient-
world existence.
### 2.4.4 Construct and construction element
A construct is a recognized form–meaning pattern over source-backed linguistic
material. Every construct binds named construction elements licensed by its
construction type.
UCxn supplies the annotation model for construction instances and elements.
MoCCA may classify or align a construction when an appropriate comparative
concept exists. A radiology-specific construction remains locally defined when
no external category expresses the needed distinction.
### 2.4.5 Referent
A referent records discourse identity. Mentions can introduce, redescribe, or
refer back to a referent.
A referent under the scope of negation or uncertainty remains a discourse
object, not a positive assertion of a patient-world entity. Assertion status is
represented by a frame rather than encoded into referent identity.
### 2.4.6 Frame
A frame represents a semantic situation with named roles. FrameNet is a source
of candidate general frames and role vocabularies. The initial internal frame
profile is a small hybrid: it may reuse FrameNet alignments, but local frames
are normative when radiology examples require distinctions not cleanly supplied
by FrameNet.
### 2.4.7 Grounding
Grounding relates a mention or referent to one or more RadLex concept
candidates. RadLex governs medical concept identity and ontology context. It
does not govern source spans, discourse identity, assertion status, or the
creation of transcript referents.
### 2.4.8 Interpretation alternative
An interpretation alternative is a complete or partial candidate structure
supported by evidence. Alternatives may differ in attachment, referent
identity, frame type, role filler, grounding, scope, or semantic projection.
An ambiguity groups supported alternatives when current rules do not justify a
single choice.
## 2.5 Authority Map
| Question | Primary authority | Local responsibility |
| --- | --- | --- |
| What morphosyntactic relation was observed? | Universal Dependencies | Preserve parser evidence and alternatives. |
| What form–meaning construction occurred? | UCxn conventions | Define the radiology constructicon and recognition rules. |
| How is a construction classified cross-linguistically? | MoCCA where suitable | Record alignment without forcing a match. |
| What semantic situation and roles are expressed? | FrameNet where suitable | Define a minimal radiology frame profile and mappings. |
| Which medical concept is denoted? | RadLex | Generate and constrain grounded candidates. |
| Which mentions share discourse identity? | This specification | Define referent formation and resolution rules. |
| What does polarity, certainty, or comparison scope over? | This specification, informed by linguistic evidence | Define frame composition and ambiguity rules. |
| Which relations appear in final output? | This project | Define canonical projections and validation. |
No authority is allowed to answer a question merely because it has a nearby
concept. Authority follows semantic responsibility.
## 2.6 Initial Construction Families
The initial constructicon is organized by linguistic function rather than by
individual lexical triggers.
| Construction family | Core elements | Initial examples |
| --- | --- | --- |
| `finding_predication` | `finding`, optional `state` | `The lungs are clear.` |
| `telegraphic_finding` | `finding`, optional modifiers | `Borderline cardiomegaly.` |
| `existential_presentation` | `presented` | `There is a nodule.` |
| `negated_finding` | `negator`, `scope` | `No pneumothorax.` |
| `coordination` | `conjuncts`, `coordinator` | `pneumothorax or effusion` |
| `located_finding` | `figure`, `spatial_relation`, `ground` | `opacities in the left apex` |
| `measured_entity` | `entity`, `quantity`, optional `dimension` | `8 mm nodule` |
| `spatial_measurement` | `figure`, `distance`, `relation`, `ground` | `tip 5 cm above the carina` |
| `comparison` | `entity`, `attribute`, `direction`, optional `baseline` | `stable from prior` |
| `epistemic_qualification` | `content`, `cue`, `strength` | `could represent ...` |
| `alternative_characterization` | `subject`, `alternatives`, cues | `probably X ... difficult to exclude Y` |
| `recommendation` | `action`, optional `target`, `rationale` | `CT ... is recommended` |
| `anaphoric_reference` | `anaphor`, candidate `antecedent` | `It measures 6 mm.` |
The names are provisional. Each accepted construction type must eventually
have a definition, licensed elements, recognition tests, counterexamples, and
semantic contribution.
## 2.7 Initial Frame Profile
The first implementation should require only frames demonstrated by accepted
examples.
| Frame | Roles | Purpose |
| --- | --- | --- |
| `FindingAssertion` | `content`, `polarity`, `certainty` | States whether and with what commitment finding content is presented. |
| `PropertyState` | `entity`, `property`, `value` | Represents states such as normal, enlarged, or clear. |
| `Location` | `figure`, `relation`, `ground` | Represents spatial organization. |
| `Measurement` | `entity`, `value`, `unit`, optional `dimension` | Represents an entity attribute measurement. |
| `SpatialMeasurement` | `figure`, `value`, `unit`, `relation`, `ground` | Represents a measured spatial relation. |
| `Comparison` | `entity`, `attribute`, `direction`, optional `baseline` | Represents change or stability relative to a comparison context. |
| `Characterization` | `subject`, `characterization`, `certainty` | Represents an interpretation of an observed finding. |
| `Recommendation` | `action`, optional `target`, `rationale`, `certainty` | Represents a recommended future action. |
`certainty` initially preserves a normalized category and the exact lexical cue.
The first category vocabulary is provisional:
```text
asserted
probable
possible
cannot_exclude
```
These categories must not erase distinctions among source cues. A later corpus
study may require a richer ordered or multidimensional model. This is an
empirical refinement task, not an owner-level design decision: retain the cue,
use the smallest vocabulary that explains accepted examples, and extend it when
a counterexample requires a semantic distinction.
An internal frame directly uses a FrameNet identity only when its meaning and
role constraints match the corpus interpretation. Otherwise the project defines
a local frame and records any useful FrameNet relationship as an alignment.
This rule avoids requiring an advance choice between wholly external and wholly
local frame vocabularies.
## 2.8 Intermediate Representation Shape
The IR is a typed, versioned graph. Its serialization format is secondary to
its concepts and invariants. JSON is the initial external interchange form;
Prolog terms may realize the same model inside the semantic interpreter.
An interpretation execution has the following provisional shape:
```json
{
"ir_version": "draft-0",
"execution_id": "exec-...",
"source": {
"document_id": "kaggle-rad-reports-000048-sectionless_dictation",
"text": "...",
"provenance": {"corpus": "generated-transcript-corpus", "variant": "sectionless_dictation"}
},
"linguistic_observations": [],
"mentions": [],
"constructs": [],
"referents": [],
"frames": [],
"groundings": [],
"ambiguities": [],
"diagnostics": [],
"assertions": [],
"validation": {}
}
```
Every derived object contains:
```text
id
type
status
evidence[]
derived_by
```
where `status` is one of:
```text
accepted
candidate
rejected
unresolved
```
A rejected candidate is retained when its rejection explains a consequential
choice. Implementations need not retain every mechanically generated candidate.
## 2.9 Provenance Graph
Provenance is represented as edges among identified objects rather than as an
unstructured explanation string.
Initial edge types are:
```text
anchored_in(mention, source_span)
observed_in(linguistic_observation, source_span)
recognized_from(construct, linguistic_observation_or_span)
binds(construct, role, object)
evokes(frame, construct)
fills(frame, role, object)
refers_to(mention, referent)
grounded_as(mention_or_referent, ontology_concept)
derived_from(assertion, object)
validated_by(object, validation_rule)
```
An implementation may serialize these relationships inline or as explicit
edges, provided their identity and direction remain recoverable.
---
# 3. Survey of Decisions and Translation Rules
## 3.1 Example Method
Each example distinguishes five things:
```text
SOURCE EXPRESSION
What the transcript contains.
LINGUISTIC EVIDENCE
What observable form supports an interpretation.
CONSTRUCTION
Which conventional form–meaning pattern is recognized.
SEMANTIC CONTRIBUTION
Which candidate referents, frames, roles, or assertions are licensed.
LIMIT
What the example does not license.
```
The examples below specify semantic obligations. They do not prescribe exact
Grew rules, Prolog predicates, parser calls, or JSON layout.
## 3.2 Telegraphic Finding Description
### Source example
From `kaggle-rad-reports-000002-sectionless_dictation`:
```text
Borderline cardiomegaly.
```
### Linguistic interpretation
The expression is a verbless radiology clause. Its head denotes a finding or
state; `borderline` qualifies its degree or category boundary. The absence of a
finite verb is licensed by the radiology dictation sublanguage and is not, by itself, an
incomplete parse diagnostic.
### Design decision
The local `telegraphic_finding` construction licenses a finding assertion from
a nominal or adjectival fragment when transcript context and lexical evidence
support that reading.
Illustrative annotation:
```text
Construct telegraphic_finding
finding → "cardiomegaly"
qualifier → "Borderline"
Frame FindingAssertion
content → cardiomegaly discourse referent
polarity → positive
certainty → asserted
```
`borderline` is preserved as source-backed qualification. Whether it becomes a
`PropertyState`, a degree value, or part of RadLex grounding is open pending
additional examples.
### Formal obligation
```text
telegraphic_finding(c) ∧ binds(c,finding,m)
∧ radiology_transcript_context(c)
→ ∃ r,a : refers_to(m,r) ∧ FindingAssertion(a,r,positive)
```
### Does not entail
The construction does not establish that cardiomegaly is clinically true. It
records that the transcript positively presents that content.
## 3.3 Negation and Coordination
### Source example
From `kaggle-rad-reports-000005-sectionless_dictation`:
```text
There is no pneumothorax or pleural effusion.
```
### Linguistic interpretation
An existential/presentational clause contains a negator whose scope includes a
coordination. The coordination introduces two finding descriptions. The shared
negation distributes to both conjuncts unless syntactic or constructional
evidence supports a narrower scope.
### Design decision
Coordination is represented before polarity is projected. Negation applies to
the coordinated semantic contents, producing two negative finding assertions
with shared scope provenance.
```text
Construct coordination c1
conjunct → "pneumothorax"
conjunct → "pleural effusion"
coordinator → "or"
Construct negated_finding c2
negator → "no"
scope → c1
Frame FindingAssertion a1
content → pneumothorax content
polarity → negative
Frame FindingAssertion a2
content → pleural-effusion content
polarity → negative
```
### Formal obligation
```text
neg_scope(n, coordination(c,{x₁,...,xₙ}))
→ ∀ xᵢ ∈ {x₁,...,xₙ} : negative_assertion(xᵢ,n)
```
This rule applies only to a coordination licensed as wholly inside negation
scope.
### Does not entail
The mentions do not create positive pneumothorax or effusion findings. RadLex
concept matches do not reverse the polarity supplied by the construction.
## 3.4 Finding Measurement and Location
### Source example
From `kaggle-rad-reports-000048-sectionless_dictation`:
```text
There is an 8mm nodule in the left lower lobe.
```
### Linguistic interpretation
The noun phrase contains a measured finding and a prepositional location
modifier. The measurement and location share the nodule as their semantic
participant.
### Design decision
The expression evokes separate `Measurement` and `Location` frames. Composition
unifies their entity/figure roles through one finding referent.
```text
Mentions
m1 → "8mm"
m2 → "nodule"
m3 → "left lower lobe"
Referents
f1 → introduced by m2
a1 → introduced by m3
Frame Measurement
entity → f1
value → 8
unit → mm
dimension → size, unresolved subtype
Frame Location
figure → f1
relation → in
ground → a1
```
The raw quantity text, normalized numeric value, and normalized unit are all
preserved. A normalization is a derived representation, not a replacement for
the source mention.
### Formal obligations
```text
measured_entity(c,m_entity,m_quantity)
→ ∃ r,f : refers_to(m_entity,r) ∧
Measurement(f,entity=r,quantity=m_quantity)
located_finding(c,m_figure,m_relation,m_ground)
→ ∃ r₁,r₂,f : refers_to(m_figure,r₁) ∧
refers_to(m_ground,r₂) ∧
Location(f,figure=r₁,relation=m_relation,ground=r₂)
```
### Does not entail
The preposition `in` does not automatically become a RadLex object property.
The measurement does not establish which anatomical dimension was measured
unless the construction or domain evidence licenses that conclusion.
The working rule is conservative: a dimension is accepted only when it is
explicit in the transcription or licensed by a tested construction rule.
Ontology knowledge alone does not supply a transcript-level dimension.
## 3.5 Spatial Measurement Is Not Entity Size
### Source example
From `kaggle-rad-reports-000057-sectionless_dictation`:
```text
The tracheostomy tube tip is 5 cm above the carina.
```
### Linguistic interpretation
The quantity measures the distance expressed by the spatial relation `above`.
It does not measure the tube tip itself.
### Design decision
This example requires a `spatial_measurement` construction and a
`SpatialMeasurement` frame distinct from `measured_entity` and `Measurement`.
```text
Frame SpatialMeasurement
figure → tube-tip referent
value → 5
unit → cm
relation → above
ground → carina referent
```
### Formal obligation
```text
spatial_measurement(c,figure,q,relation,ground)
→ SpatialMeasurement(figure,q,relation,ground)
∧ ¬ entity_size(q,figure)
```
The final negative term expresses a translation prohibition, not necessarily a
stored negative assertion.
### Does not entail
The tube tip is not five centimetres in size. The carina is not a measured
entity. Linear proximity in the sentence is insufficient to determine the
measurement target.
## 3.6 Comparison and Stability
### Source example
From `kaggle-rad-reports-000057-sectionless_dictation`:
```text
There are prominent diffuse bilateral interstitial opacities, stable from
prior radiographs.
```
### Linguistic interpretation
The participial/adjectival comparison expression predicates stability of the
opacities relative to a prior-study baseline. `prominent`, `diffuse`, and
`bilateral` describe the current finding; `stable` relates an attribute or
overall state across observations.
### Design decision
The comparison is represented independently from the positive finding
assertion:
```text
Frame FindingAssertion
content → interstitial-opacities referent
polarity → positive
Frame Comparison
entity → same referent
attribute → unresolved overall finding state
direction → unchanged
baseline → prior radiographs
```
The exact baseline may remain a discourse description rather than a fully
grounded study referent when redaction or missing context prevents resolution.
### Formal obligation
```text
comparison(c,entity,cue="stable",baseline)
→ Comparison(entity,attribute=?,direction=unchanged,baseline)
```
The unresolved attribute is explicit and valid.
### Does not entail
`stable` does not mean normal, benign, absent, or clinically insignificant. It
does not identify the baseline date when the source does not supply one.
## 3.7 Epistemic Qualification and Alternative Characterization
### Source example
From `kaggle-rad-reports-000004-sectionless_dictation`:
```text
Probably scarring in the left apex, although difficult to exclude a cavitary
lesion.
```
### Linguistic interpretation
The expression offers at least two characterizations of an observed finding
with different epistemic cues. `probably` supports scarring more strongly;
`difficult to exclude` keeps a cavitary lesion as a live alternative. The
second characterization is not negated merely because `exclude` occurs in the
phrase.
### Design decision
Negation detection must operate over constructions and scope, not keyword
presence. The interpretation contains two `Characterization` candidates linked
to the same observed-content referent, preserving the different cues.
```text
Characterization c1
subject → observed apical abnormality
characterization → scarring
certainty → probable
cue → "Probably"
Characterization c2
subject → same observed abnormality
characterization → cavitary lesion
certainty → cannot_exclude
cue → "difficult to exclude"
```
The relationship between these candidates is represented as an alternative-
characterization set. A downstream application may order the alternatives but
must retain both and their source wording.
### Formal obligation
```text
alternative_characterization(subject,{(x,cue₁),(y,cue₂)})
→ Characterization(subject,x,normalize(cue₁))
∧ Characterization(subject,y,normalize(cue₂))
∧ alternatives(x,y)
```
### Does not entail
The transcript does not positively establish either diagnosis as clinical
truth. `difficult to exclude` does not establish absence. An ontology hierarchy
between the candidates does not authorize collapsing the alternatives.
## 3.8 Recommendation Is Not a Finding
### Source example
From `kaggle-rad-reports-000009-sectionless_dictation`:
```text
CT chest with contrast is recommended.
```
### Linguistic interpretation
The passive predicate presents a recommended future imaging action. It does not
state that the CT has occurred.
### Design decision
The `recommendation` construction evokes a `Recommendation` frame. Its action
may be medically grounded, but it is not projected as a current examination or
finding.
```text
Frame Recommendation
action → CT chest
manner_or_protocol → with contrast
rationale → unresolved or linked from discourse context
certainty → asserted recommendation
```
### Formal obligation
```text
recommendation(c,action,target,rationale?)
→ Recommendation(action,target,rationale?)
∧ ¬ performed(action)
```
Again, the final term is a prohibited inference rather than a required stored
negative assertion.
### Does not entail
The recommended examination has not necessarily been ordered, scheduled, or
performed. The recommendation does not itself validate its clinical rationale.
## 3.9 Cross-Sentence Reference
### Canonical example
```text
There is a nodule in the right upper lobe. It measures 6 mm.
```
### Linguistic interpretation
`a nodule` introduces a discourse referent. `It` is a distinct mention whose
candidate antecedent is that referent. The measurement frame uses the resolved
referent as its entity.
### Design decision
Anaphora resolution is candidate-based. Agreement, discourse salience,
constructional role, semantic type, and locality may constrain candidates. No
single token-distance heuristic is authoritative.
```text
Mention m1 → "a nodule"
Mention m2 → "It"
Referent f1
introduced_by → m1
referred_to_by → m2
Frame Measurement
entity → f1
value → 6
unit → mm
```
### Formal obligation
```text
anaphor(m) ∧ candidates(m)={r₁,...,rₙ}
∧ uniquely_preferred(rᵢ)
→ refers_to(m,rᵢ)
anaphor(m) ∧ multiple_undominated_candidates(m)
→ ambiguity(reference,m,candidates(m))
```
### Does not entail
The pronoun does not introduce a second finding merely because it is a second
mention. A nearby noun is not necessarily its antecedent.
## 3.10 Repetition Does Not Supply Hidden Report Identity
The current input may repeat similar expressions, but the interpreter sees
only a transcription character stream. It may not consult a source report or
infer a Findings→Impression relationship from the historical origin of the
record.
Two repeated expressions are distinct mentions. They resolve to one referent
only when transcript-internal discourse evidence uniquely supports that
identity. Otherwise identity remains unresolved.
```text
same wording + compatible grounding
⇏ same referent
```
╔════════════════════════════════════════════════════════╗
║ INPUT BOUNDARY ║
║ ║
║ Historical report structure supplies no evidence ║
║ for transcript mention identity. ║
╚════════════════════════════════════════════════════════╝
An actual generated or human transcription exhibiting repeated reference must
be annotated before stronger identity rules are specified.
## 3.11 Redaction and Damaged Constructions
### Source examples
The corpus preserves `[REDACTED]` markers, sometimes inside expressions needed
for interpretation.
### Design decision
`[REDACTED]` is an opaque source token. It is never normalized into guessed
content. A construction may bind an explicitly unresolved element when the
remaining source supplies enough evidence to recognize the construction.
```text
Construction element
role → baseline
filler → unresolved
evidence → [REDACTED] source span
Diagnostic
type → redacted_required_element
severity → partial_interpretation
```
If the redaction prevents recognition itself, the system emits a diagnostic
rather than fabricating a construction.
### Does not entail
The redaction marker does not denote a person, date, finding, anatomy, or other
domain entity merely because one of those would make the sentence grammatical.
## 3.12 Mention and Referent Grounding
### Upstream meaning
RadLex provides abstract medical concepts, labels, synonyms, hierarchy, and
ontology relations. A source expression may lexically evoke one or more RadLex
concepts. A discourse referent may be characterized by one or more mentions.
### Provisional decision
The IR permits both mention grounding and referent grounding with distinct
meanings:
```text
mention grounding
This expression is a lexical/contextual realization candidate
for this RadLex concept.
referent grounding
The composed discourse interpretation characterizes this
referent using this RadLex concept.
```
Mention grounding supplies evidence for referent grounding; it is not
automatically copied. Composition, polarity, qualification, and competing
mentions may affect the referent-level result.
### Formal obligations
```text
mention_grounding(m,c)
→ Mention(m) ∧ RadLexConcept(c)
referent_grounding(r,c)
→ Referent(r) ∧ RadLexConcept(c)
∧ supported_by_composed_evidence(r,c)
```
### Does not entail
A lexical match does not prove a unique grounding. Neither kind of grounding
creates a referent. Grounding does not change assertion polarity or certainty.
╔════════════════════════════════════════════════════════╗
║ WORKING RULE ║
║ ║
║ Accept grounding only at uniquely supported semantic ║
║ specificity; otherwise preserve the candidates. ║
╚════════════════════════════════════════════════════════╝
The working test combines source-backed lexical or semantic evidence,
construction-role compatibility, composed-context compatibility, and the
absence of an undominated incompatible candidate at the claimed specificity.
Concrete examples may refine this rule without requiring a project-scope
decision.
## 3.13 Candidate Preservation and Resolution
### Design decision
Interpretation is candidate-producing. A pass may:
- introduce a candidate supported by identified evidence;
- accept a candidate because a stated rule is satisfied;
- reject a candidate with a stated reason;
- group undominated candidates into an ambiguity;
- leave a role unresolved with a diagnostic.
A pass may not silently discard a materially supported candidate.
Candidate preference is represented as an evidence-bearing relation:
```text
preferred(candidate_a, candidate_b, rule, evidence)
```
Acceptance requires either a unique supported candidate or an explicit rule
that permits several compatible candidates to coexist.
### Formal obligation
```text
supported(c₁) ∧ supported(c₂)
∧ ¬ dominates(c₁,c₂)
∧ ¬ dominates(c₂,c₁)
∧ incompatible(c₁,c₂)
→ preserve_ambiguity({c₁,c₂})
```
## 3.14 Validation Profile
The initial validator checks at least the following obligations.
### Source integrity
- Every source span is within the document boundary.
- Every stored span text equals the immutable source substring.
- Every mention has at least one source span.
### Construction integrity
- Every construct has exactly one defined construction type.
- Every construction element uses a role licensed by that type.
- Required roles are filled or explicitly unresolved.
- Recognition evidence is retained.
### Discourse and frame integrity
- Every `refers_to` target is a defined referent.
- Every referent is licensed by at least one mention or permitted derivation.
- Every frame role is licensed by its frame type.
- Every frame is evoked by a construct or permitted semantic rule.
- Polarity and certainty attach to semantic content, not ontology concepts.
### Grounding integrity
- Every grounding target exists in the pinned RadLex bundle.
- Candidate and accepted groundings are distinguishable.
- No grounding operation creates a referent.
- Ontology implications do not populate transcript individuals.
### Ambiguity and diagnostic integrity
- Every ambiguity contains at least two supported alternatives.
- Every alternative identifies its distinguishing choice.
- Rejected consequential alternatives retain a reason.
- Every diagnostic identifies a source span or interpretation object.
### Provenance integrity
- Every accepted frame and output assertion has a derivation path to source.
- Normalized values retain the source expression from which they were derived.
- External resource versions used by the execution are recorded.
Validation success means that the representation obeys this contract. It does
not mean every expression was interpreted or every ambiguity resolved.
## 3.15 Annotation Workflow
Examples progress through the following states:
```text
selected
↓
span-annotated
↓
construction-annotated
↓
semantically annotated
↓
reviewed
↓
accepted as executable example
```
Each transition records the annotation-profile version and author or process.
Automated parser and grounding suggestions remain distinguishable from human-
accepted annotations.
Disagreement is represented as alternatives or an adjudication record. It is
not overwritten without history.
## 3.16 Refinement Acceptance Criteria
This draft is ready to become the first implementation contract when:
- an initial stratified set of examples has been selected from the corpus;
- every selected example has exact source-span annotations;
- each accepted construction type has licensed roles and counterexamples;
- each required frame has a defined role inventory;
- at least one complete example traverses R0 through R5;
- mention and referent grounding are tested against concrete examples;
- negation, uncertainty, comparison, recommendation, and redaction remain
semantically distinct;
- ambiguity and partial interpretation have machine-representable examples;
- the IR can represent every accepted example without ad hoc fields;
- validators enforce the conceptual specification's cross-cutting invariants;
- external knowledge and rule versions are recorded in every execution;
- open decisions that block the first vertical slice are resolved, while later
decisions are explicitly deferred.
---
# 4. Reference Appendices
## Appendix A. Provisional Object Schemas
The schemas below define semantic fields, not a required physical
serialization.
### A.1 Source span
```text
SourceSpan
id
document_id
start_character
end_character
text
```
### A.2 Mention
```text
Mention
id
spans[1..n]
categories[0..n]
normalization_candidates[0..n]
evidence[1..n]
```
### A.3 Construct
```text
Construct
id
construction_type
elements[1..n]
recognition_evidence[1..n]
authority_alignment[0..n]
status
ConstructionElement
role
filler
evidence[1..n]
```
### A.4 Referent
```text
Referent
id
introduced_by[1..n]
referred_to_by[0..n]
grounding_candidates[0..n]
status
```
### A.5 Frame
```text
Frame
id
frame_type
roles[1..n]
evoked_by[1..n]
authority_alignment[0..n]
status
```
### A.6 Grounding
```text
Grounding
id
subject
ontology
concept_id
status
lexical_evidence[0..n]
contextual_evidence[0..n]
constraint_evidence[0..n]
resource_version
```
### A.7 Ambiguity
```text
Ambiguity
id
kind
subject
alternatives[2..n]
unresolved_because[1..n]
```
### A.8 Diagnostic
```text
Diagnostic
id
type
severity
subject
evidence[1..n]
detail
```
## Appendix B. Required Counterexample Pairs
Each construction family should be tested with contrasts that prevent shallow
keyword translation.
| Superficially similar forms | Required distinction |
| --- | --- |
| `8 mm nodule` / `tip 5 cm above carina` | Entity measurement / spatial-relation measurement |
| `No pneumothorax` / `difficult to exclude pneumothorax` | Negative assertion / live uncertain alternative |
| `stable opacity` / `normal lung` | Unchanged state / normal state |
| `CT is recommended` / `CT demonstrates` | Future recommended action / evidential examination statement |
| `nodule in the lobe` / `nodule near the fissure measuring 6 mm` | Clear shared participant / potentially ambiguous attachment |
| repeated `nodule` / two explicitly enumerated nodules | Coreferent mentions / distinct same-type referents |
| `[REDACTED] lobe` / `left lobe` | Unresolved anatomy / grounded anatomy |
## Appendix C. Version Metadata
Every interpretation execution should record the materially relevant versions:
```text
IR profile version
source corpus and record version
UD parser and model version
UD specification version
UCxn schema and rule version
local constructicon version
MoCCA database version
FrameNet version
local frame-profile version
RadLex bundle version and checksum
semantic-rule version
validation-rule version
```
## Appendix D. Open Design Decision
╔═══════════════════════════════════════════════════════╗
║ ⚠ OPEN DESIGN DECISION ║
║ ║
║ Define which frames project into canonical R5 output ║
║ predicates and which remain frame structures. ║
╚════════════════════════════════════════════════════════╝
This is genuinely product-defining because it determines the public semantic
contract of validated output. It does not block the first examples: until a
projection is accepted, R5 may preserve the validated frame structure itself.
## Appendix E. Design Provenance
This appendix is non-normative.
### E.1 Refinement Before Implementation
**Joint refinement.** The design conversation identified the need for a layer
between the conceptual specification and an implementation plan. That layer is
example-driven and defines a machine-representable semantic contract by
decomposing corpus expressions through the appropriate linguistic and domain
authorities.
### E.2 Lower-Level Dependency
**Human-led clarification.** This document is explicitly a lower-level
specification that assumes the higher-level conceptual specification. It does
not reopen the established ontology or duplicate its full argument.
### E.3 Initial Corpus Sufficiency
**Human-led scope decision.** The retained generated transcriptions are accepted
as sufficient development input to get the interpreter running, without
productionizing it or making claims about future real human transcriptions.
### E.4 Authorities Have Bounded Roles
**Joint refinement.** The corpus is decomposed using UD, UCxn, MoCCA, FrameNet,
and RadLex where each is authoritative. External vocabulary is reused without
allowing one authority to absorb responsibilities belonging to another layer.
### E.5 Transcription Is the Complete Input
**Human-led correction.** An example incorrectly treated Findings and
Impression sections from a radiology report as transcript structure. The source
reports were removed, normalized report-copy records were removed from the
generated corpus, and the interpretation boundary was restated: only the
generated `transcript_text` character stream supplies linguistic evidence.
Interpreter implementation plan
The executable vertical-slice plan that turns the governing specifications into tested R0-through-R5 behavior.
Authoritative source: RADIOLOGY-TRANSCRIPT-INTERPRETER-IMPLEMENTATION-PLAN.md · Permanent section link
# Radiology Transcript Interpreter Implementation Plan
## Status
This document is the initial executable R&D implementation plan.
It is governed by:
1. `RADIOLOGY-TRANSCRIPT-INTERPRETATION-CONCEPTUAL-SPEC.md`;
2. `RADIOLOGY-TRANSCRIPT-LINGUISTIC-SEMANTIC-REFINEMENT-SPEC.md`.
The conceptual specification defines the meaning and invariants of transcript
interpretation. The refinement specification defines the initial linguistic
and semantic profile. This plan organizes the work required to realize them.
If this plan conflicts with either specification, the specifications are
authoritative in the order above.
This is an R&D plan. Construction definitions, frame alignments, and semantic
rules are expected to improve as examples expose better distinctions. Such
refinement is planned work, not a reason to defer implementation.
---
# 1. Outcome and Execution Strategy
## 1.1 Intended Outcome
The implementation accepts one generated radiology transcription and produces
an immutable, inspectable interpretation execution containing:
```text
source transcription
linguistic observations
mentions
constructs and construction elements
referents
frames and composition
RadLex grounding candidates and accepted groundings
ambiguities
diagnostics
validated structured output
provenance
```
The execution must answer:
> How did this transcription become this structured interpretation?
## 1.2 Governing Implementation Strategy
Development proceeds through vertical semantic slices.
The first slice interprets one useful expression inside one complete retained
transcription, carries it from exact source characters through validated frames,
and explicitly records partial interpretation elsewhere. Later slices expand
the supported linguistic phenomena without replacing the representation model
ad hoc.
Every milestone must leave behind an executable behavior and a regression
example. A milestone is not complete merely because a component API or rule
file exists.
## 1.3 Input Boundary
The interpreter input is exactly:
```text
record.transcript_text
```
The retained local development corpus contains 3,573 generated transcription
records. Historical source reports are not retained and are not available to
the interpreter. Record identifiers, historical row identifiers, heuristic
phenomenon labels, and generation metadata may support provenance and test
selection but may not supply linguistic or semantic evidence.
An independently maintained LLM-generated transcription collection may be
introduced through the same input contract. Creating that collection is not
part of this plan.
Future real human transcription is a later validation source. It is not a
prerequisite for the R&D implementation.
## 1.4 Initial Output Decision
Validated frame structures are valid R5 output for the initial implementation.
Canonical application predicates may be added later when examples and consumers
justify a stable projection. The absence of those predicates does not block an
end-to-end implementation.
## 1.5 Partial Success
The interpreter is not required to understand every expression in a
transcription before it may return a valid result.
A valid partial result:
- preserves the complete source;
- identifies which source regions contributed to accepted interpretations;
- emits diagnostics for consequential unsupported or unresolved material;
- does not manufacture structure to create the appearance of completeness;
- validates every object it does accept.
---
# 2. Existing Baseline
## 2.1 Proven Toolchain
The existing research baseline has already demonstrated:
```text
plain text
→ Stanza
→ Universal Dependencies / CoNLL-U
→ Grew / UCxn annotations
→ SWI-Prolog transport
```
It also provides resident access to MoCCA, FrameNet, and the generated RadLex
runtime bundle.
The setup and infrastructure verification suites are existing prerequisites,
not work to repeat in this plan.
## 2.2 Proven Process Boundaries
The current local topology is retained as the R&D baseline:
| Boundary | Existing responsibility | New application responsibility |
| --- | --- | --- |
| Go hub | Routing, evaluation records, UI, identity checks | Interpretation execution lifecycle, orchestration, persistence, and debugger routes. |
| Python linguistics service | Stanza, Grew/UCxn, MoCCA, FrameNet | Source-preserving linguistic analysis and local construct recognition. |
| SWI-Prolog service | CoNLL-U inspection and RadLex queries | Semantic composition, grounding decisions, ambiguity, diagnostics, and validation. |
No new service boundary is introduced unless an observed limitation requires
one. Internal application modules may remain separately testable without
becoming processes.
## 2.3 Infrastructure/Application Separation
Existing toolchain evaluations and new interpretation executions are distinct:
```text
TOOLCHAIN EVALUATION
Proves that installed components and service seams work.
INTERPRETATION EXECUTION
Records what the application concluded about one transcription and why.
```
Passing infrastructure verification does not imply semantic correctness.
Failing semantic interpretation does not necessarily imply infrastructure
failure.
---
# 3. Target Software Shape
## 3.1 Proposed Repository Layout
The initial application work should use an explicit application area:
```text
interpreter/
README.md
contracts/
interpretation-ir.schema.json
interpretation-request.schema.json
interpretation-result.schema.json
examples/
selected.jsonl
annotations/
expected/
constructicon/
definitions/
rules/
tests/
semantics/
frames.pl
composition.pl
discourse.pl
grounding.pl
diagnostics.pl
validation.pl
tests/
contract/
examples/
counterexamples/
integration/
```
This layout is a working default. Existing infrastructure code remains in
`infrastructure/`; application semantics do not move into setup smoke tests.
## 3.2 Application Capabilities
Three versioned capabilities are added to the existing service model.
### Linguistic analysis
```text
linguistics.analyze
```
Input:
```text
document identity
exact transcription text
analysis profile version
```
Output:
```text
source spans and sentence/token boundaries
UD observations
CoNLL-U representation
UCxn and local construction candidates
component and rule identities
diagnostics
```
### Semantic interpretation
```text
semantics.interpret
```
Input:
```text
versioned linguistic result
interpretation profile version
```
Output:
```text
mentions
constructs
referents
frames
groundings
ambiguities
diagnostics
validation
R5 frame output
```
### Complete execution
```text
interpreter.run
```
The Go hub owns the complete execution, invokes the two capabilities, validates
their envelopes, records artifacts, and publishes the immutable completed
interpretation.
The exact route names may follow existing API conventions. Capability identity
and semantic responsibility are normative; URL spelling is not.
## 3.3 Stable Identity
Every interpretation object receives an execution-local stable identifier.
Identifiers must survive serialization, persistence, hub restart, and UI
navigation.
No persistent object may be identified by:
- process identifier;
- Python object identity;
- Prolog variable name;
- transient Grew graph handle;
- array position without an explicit containing identity.
## 3.4 Source Locations
Character spans in the exact transcription are the canonical source locations.
Sentence and token identifiers are derived indexes.
The linguistic service must prove:
```text
stored_span_text = source_text[start:end]
```
for every emitted span. Tokenization or CoNLL-U serialization must not make it
impossible to recover exact source characters.
## 3.5 Rule and Resource Identity
Every interpretation records the identities of materially relevant resources:
```text
IR contract
linguistic profile
parser and model
UCxn rules
local constructicon
MoCCA database
FrameNet data
RadLex bundle
semantic rules
validation rules
```
An execution produced under changed rule or resource identities is a new
execution. Existing completed executions remain immutable.
---
# 4. Executable Example Method
## 4.1 Selected Example Record
The example catalog contains references to retained transcription records and
human-reviewed source spans. It does not copy facts from unavailable source
reports.
Each selected example records:
```text
example identity
corpus record identity
exact transcript checksum
exact focus spans
phenomenon under examination
expected accepted objects
expected alternatives
expected diagnostics
expected validation result
annotation status and profile version
```
The complete transcription remains the execution input even when an example
focuses on one sentence or fragment.
## 4.2 First Vertical Slice
The first slice uses retained record:
```text
kaggle-rad-reports-000048-sectionless_dictation
```
and focuses initially on:
```text
There is an 8mm nodule in the left lower lobe
```
The expected semantic spine is:
```text
exact source spans
↓
measured-entity and located-finding constructs
↓
nodule and anatomy mentions
↓
finding and anatomical referents
↓
Measurement(Entity=finding, Value=8, Unit=mm)
Location(Figure=finding, Relation=in, Ground=anatomy)
↓
RadLex grounding candidates
↓
validated frame output with complete provenance
```
The slice succeeds even if other portions of the transcription remain
unsupported, provided their status is represented honestly.
## 4.3 Counterexample Obligation
Every accepted construction or semantic rule must have at least one positive
example and one contrastive example capable of detecting a shallow
implementation.
The first required contrast is:
```text
8 mm nodule
versus
tube tip is 5 cm above the carina
```
The first is an entity measurement. The second is a measured spatial relation.
The implementation must not attach both quantities using the same nearest-noun
rule.
## 4.4 Annotation Is Development Work
There is no minimum corpus size gate. Examples are selected and annotated as
needed to drive a semantic slice or investigate a failure.
Annotations may begin as hypotheses. An annotation becomes an executable
expectation after review against the refinement specification and relevant
external authorities.
---
# 5. Milestones and Tickets
## 5.1 Milestone Summary
| Milestone | Ticket | Outcome | Gate |
| --- | --- | --- | --- |
| M0 | `INT-000` | Application skeleton and versioned IR contract | Contract tests pass. |
| M1 | `INT-001` | Executable example catalog | First selected transcription and counterexample are reviewable. |
| M2 | `INT-002` | Source-preserving linguistic analysis | Exact spans, UD, and construction evidence survive transport. |
| M3 | `INT-003` | First semantic vertical slice | Measurement and location frames compile in Prolog. |
| M4 | `INT-004` | RadLex grounding and candidate semantics | Mention and referent grounding retain evidence and ambiguity. |
| M5 | `INT-005` | Semantic validation and R5 frame output | First execution is valid end to end. |
| M6 | `INT-006` | Negation and coordination | Positive and negative content remain distinct. |
| M7 | `INT-007` | Spatial measurement and comparison | Distance, entity size, stability, and baseline remain distinct. |
| M8 | `INT-008` | Uncertainty and recommendation | Epistemic alternatives and future actions remain distinct from findings. |
| M9 | `INT-009` | Discourse identity and ambiguity | Anaphora and unresolved candidates are explicit. |
| M10 | `INT-010` | Durable interpretation executions | Hub runs and persists immutable interpretations. |
| M11 | `INT-011` | Semantic interpretation debugger | One execution is intelligible from source through validation. |
| M12 | `INT-012` | Corpus expansion and final R&D handoff | All selected examples and full verification pass. |
## 5.2 `INT-000` — Application Foundation and IR Contract
### Work
- Create the `interpreter/` application layout.
- Translate the provisional refinement IR into versioned JSON Schemas.
- Define object identifiers, statuses, evidence references, and resource
identities.
- Define interpretation request, in-progress internal record, completed result,
and structured failure envelopes.
- Define forward-compatible extension points without permitting unknown core
object types to pass validation silently.
- Add schema fixtures for minimal valid, full valid, and representative invalid
structures.
### Acceptance
- Every conceptual object required by the first slice is representable.
- Every accepted derived object can reference source evidence and derivation.
- Ambiguity and diagnostics are valid result content rather than transport
failures.
- Invalid references, spans, roles, and statuses fail contract validation.
- Contract tests run without starting resident services.
## 5.3 `INT-001` — Executable Example Catalog
### Work
- Select the first retained transcription and record its checksum.
- Annotate exact focus spans for entity measurement and location.
- Select the spatial-measurement counterexample.
- Store expected objects by semantic identity rather than unstable ordering.
- Build a test loader that verifies record existence, checksum, and exact span
text before semantic tests run.
### Acceptance
- A changed transcription causes an explicit fixture mismatch.
- Expected annotations refer only to characters in `transcript_text`.
- Heuristic corpus labels do not appear as semantic evidence.
- The entity-size/spatial-distance contrast is executable.
## 5.4 `INT-002` — Source-Preserving Linguistic Analysis
### Work
- Add `linguistics.analyze` to the Python boundary.
- Accept exact text and return character-addressable sentences and tokens.
- Preserve Stanza UD observations and CoNLL-U without treating them as final
semantic truth.
- Apply official UCxn rules where relevant.
- Add the first local Grew construction definitions and construction-element
bindings.
- Emit imported, local, and alternative analyses with distinct authority and
rule identities.
- Verify source-span integrity at the service boundary.
### Acceptance
- The first complete transcription parses through the resident service.
- The focus phrase maps back to exact input characters.
- Measurement, finding, and anatomical expressions are recoverable from the
returned analysis.
- Local construction evidence is distinguishable from official UCxn evidence.
- Parser or rule failure produces structured diagnostics.
- Existing infrastructure verification continues to pass.
## 5.5 `INT-003` — First Semantic Vertical Slice
### Work
- Add a separately testable Prolog semantic kernel.
- Import the versioned linguistic result into semantic facts.
- Create mentions from construction elements and source spans.
- Create source-licensed discourse referents.
- Implement the `Measurement` and `Location` frame definitions and role checks.
- Compose both frames through the shared finding referent.
- Retain construct-to-frame and mention-to-referent provenance.
- Return an interpretation graph before grounding.
### Acceptance
- The first focus phrase produces the expected mentions, referents, and frames.
- `8mm` normalizes to value `8` and unit `mm` while preserving its exact span.
- Measurement and location share the nodule referent for stated structural
reasons.
- No RadLex or FrameNet fact creates a transcript referent.
- Removing the construction evidence prevents the semantic result rather than
causing a proximity fallback.
- The Prolog unit suite and service integration test both pass.
## 5.6 `INT-004` — RadLex Grounding
### Work
- Extend RadLex lookup beyond the current exact-label research operation as
examples require, using the generated runtime bundle rather than an RDF
runtime.
- Produce mention grounding candidates with lexical evidence.
- Produce referent grounding only from composed, source-backed evidence.
- Implement the working acceptance rule from the refinement specification:
accept grounding only at uniquely supported semantic specificity; otherwise
preserve candidates.
- Retain ontology and bundle identity with every grounding result.
- Test that ontology existential restrictions constrain abstract knowledge but
never create transcript referents.
### Acceptance
- Finding and anatomy mentions produce inspectable grounding candidates.
- Accepted referent grounding cites its mention and composition evidence.
- Multiple undominated candidates remain explicit.
- Unknown expressions return an empty candidate set plus an appropriate
diagnostic, not a fabricated concept.
- Grounding does not change polarity, certainty, or discourse identity.
## 5.7 `INT-005` — Validation and Initial R5 Output
### Work
- Implement structural, source, construction, discourse, frame, grounding,
ambiguity, diagnostic, and provenance validators.
- Assign stable validation-rule identifiers.
- Distinguish fatal invalidity from a valid partial interpretation containing
unresolved material.
- Emit accepted validated frames as the initial R5 structured output.
- Add deliberately invalid fixtures for each invariant family.
### Acceptance
- The first vertical slice traverses R0 through R5.
- Every accepted frame and grounding has a derivation path to exact source
characters.
- Dangling references, illegal roles, unlicensed referents, invalid groundings,
and missing provenance are rejected.
- Explicit ambiguity and diagnostics can coexist with `valid: true`.
- No canonical application predicate is required to complete the slice.
## 5.8 `INT-006` — Negation and Coordination
### Work
- Add `negated_finding`, `coordination`, and relevant presentational
constructions.
- Represent scope before distributing polarity.
- Add `FindingAssertion` with explicit polarity and source cue.
- Cover finite and telegraphic forms such as `There is no ...` and `No ...`.
- Add counterexamples involving `difficult to exclude` and other forms where a
negation word does not create an absence assertion.
### Acceptance
- `There is no pneumothorax or pleural effusion` yields two negative contents
with shared scope provenance.
- The same grounded concepts in positive contexts do not inherit negative
polarity.
- `difficult to exclude` remains an uncertain live characterization.
- Coordination outside negation scope is not distributed as negative.
## 5.9 `INT-007` — Spatial Measurement and Comparison
### Work
- Add `SpatialMeasurement` distinct from entity `Measurement`.
- Recognize figure, distance, spatial relation, and ground.
- Add the initial `Comparison` frame and unchanged/increased/decreased
directions.
- Preserve explicit or unresolved baselines.
- Infer a measurement dimension only from explicit language or a tested
construction rule.
### Acceptance
- `tube tip is 5 cm above the carina` measures the relation, not tube-tip size.
- `stable from prior radiographs` produces unchanged comparison without
implying normality or benignity.
- Missing or redacted baseline details remain unresolved.
- Nearest-token attachment cannot satisfy the counterexample suite.
## 5.10 `INT-008` — Uncertainty, Characterization, and Recommendation
### Work
- Add epistemic-qualification and alternative-characterization constructions.
- Preserve exact cues alongside the minimal normalized certainty vocabulary.
- Add the `Characterization` and `Recommendation` frames.
- Keep observed content, proposed characterization, and recommended future
action semantically distinct.
- Extend the certainty vocabulary only when a reviewed example requires it.
### Acceptance
- `probably scarring ... difficult to exclude a cavitary lesion` preserves both
characterizations and their different cues.
- `CT chest with contrast is recommended` does not imply that CT occurred.
- An uncertain characterization is not promoted to a certain finding by
grounding.
- A recommendation is not serialized as a present patient finding.
## 5.11 `INT-009` — Discourse Identity and Ambiguity
### Work
- Add candidate-based anaphora and repeated-reference handling.
- Use only transcript-internal evidence: constructional role, semantic type,
agreement, salience, and locality.
- Preserve distinct mentions even when they resolve to one referent.
- Represent attachment, reference, and grounding ambiguities through a common
alternative structure.
- Retain preference and rejection reasons for consequential candidates.
### Acceptance
- `There is a nodule. It measures 6 mm.` uses one referent and two mentions.
- Multiple undominated antecedents yield reference ambiguity.
- Similar wording does not automatically merge referents.
- No historical report section or row information participates in identity.
## 5.12 `INT-010` — Durable Interpretation Executions
### Work
- Add a versioned complete-interpretation request to the Go hub.
- Orchestrate linguistic and semantic capabilities with existing deadline,
identity, and structured-error conventions.
- Persist source, intermediate artifacts, final IR, validation, and component
identities under one execution identity.
- Publish only complete immutable executions as history.
- Keep toolchain evaluation history distinct from interpretation history.
- Define duplicate-request behavior through source and profile identities.
### Acceptance
- One request produces one addressable completed interpretation.
- Restarting the hub does not change completed content or object links.
- Changed rules or resources produce a distinct execution identity or explicit
stale status.
- Partial infrastructure failure cannot publish a semantically complete record.
- Stored artifacts pass digest verification.
## 5.13 `INT-011` — Semantic Interpretation Debugger
### Work
- Implement the execution workspace from
`research/ui-specifications/Radiology Transcript Interpreter Interactive Execution UI Specification.md`.
- Present source, mentions, constructs, referents, frames, grounding, ambiguity,
diagnostics, output, and validation as the primary narrative.
- Make every accepted semantic object navigable to its source evidence and
derivation.
- Keep raw CoNLL-U, JSON, Grew evidence, and Prolog facts available as secondary
implementation evidence.
- Expose domain identities and relationships in a semantic DOM.
- Add accessibility and no-JavaScript tests consistent with the existing UI.
### Acceptance
- An engineer can explain the first vertical slice without reconstructing it
from logs.
- Mention and referent identities are visually distinct.
- Candidate and accepted grounding are visually distinct.
- Ambiguity and diagnostics are not presented as generic crashes.
- Validation displays individual semantic obligations, not only a green badge.
- Every UI claim links to the same immutable execution record exposed by the
API.
## 5.14 `INT-012` — Corpus Expansion and R&D Handoff
### Work
- Add examples opportunistically across the implemented phenomenon families.
- Record newly discovered construction distinctions and counterexamples in the
refinement specification or constructicon documentation.
- Add regression tests for every corrected semantic defect.
- Measure coverage by reviewed phenomenon examples and semantic obligations,
not by an arbitrary corpus annotation quota.
- Run application, service, UI, and existing infrastructure verification from
a stopped state.
- Produce a concise experiment report separating demonstrated behavior from
future production claims.
### Acceptance
- Every implemented construction and frame has positive and contrastive tests.
- Every selected executable example produces its expected valid result,
ambiguity, or diagnostic.
- The complete verification suite runs without accessing historical reports.
- The interpreter consumes only transcription text as semantic input.
- The handoff report identifies unsupported phenomena without treating them as
implementation failures or silently claiming coverage.
---
# 6. Dependency Order
The required dependency spine is:
```text
INT-000 IR contract
↓
INT-001 example catalog
↓
INT-002 linguistic analysis
↓
INT-003 semantic slice
↓
INT-004 grounding
↓
INT-005 validation / R5
↓
INT-010 durable execution
↓
INT-011 debugger
↓
INT-012 final handoff
```
Phenomenon expansions `INT-006` through `INT-009` depend on `INT-005`. They may
proceed independently where their rule and example files do not overlap, but
all must complete before `INT-012`.
The UI may begin as soon as a stable first-slice IR exists. Its final acceptance
depends on durable executions.
---
# 7. Testing Strategy
## 7.1 Contract Tests
JSON Schema and Prolog boundary tests verify valid and invalid IR shapes,
reference integrity, enumeration values, and capability envelopes.
## 7.2 Golden Example Tests
Golden tests compare semantic objects by stable identity and relations, not raw
serialization order. Expected output may deliberately contain ambiguity or
diagnostics.
A golden test must not require every parser detail to remain byte-identical
unless that detail materially supports the semantic expectation.
## 7.3 Counterexample Tests
Counterexamples prevent shallow generalization across superficially similar
forms. They are required for scope, attachment, measurement target,
recommendation, certainty, and referent identity.
## 7.4 Invariant Tests
Each conceptual invariant receives at least one deliberately invalid fixture.
The test asserts both rejection and the appropriate validation diagnostic.
## 7.5 Metamorphic Tests
Where appropriate, controlled source changes verify semantic consequences:
```text
no nodule → negative polarity
nodule → positive polarity
possible nodule → uncertain characterization
8 mm nodule → entity measurement
5 cm above → spatial measurement
```
Metamorphic inputs are explicitly synthetic tests and do not enter the corpus
as empirical observations.
## 7.6 Integration Tests
Integration tests exercise the resident Python, Prolog, and Go boundaries,
including structured error handling, deadlines, component identities, restart
behavior, and immutable artifacts.
## 7.7 Debugger Tests
UI tests verify source links, semantic DOM relationships, ambiguity rendering,
validation detail, raw-evidence access, accessibility, and no-JavaScript
behavior.
---
# 8. Completion Contract
The R&D implementation is complete when:
1. A retained generated transcription traverses R0 through R5.
2. Accepted output consists of validated frames with complete provenance.
3. Measurement, location, negation, coordination, spatial distance, comparison,
uncertainty, recommendation, and basic discourse reference have executable
examples.
4. RadLex grounding preserves candidates and never creates transcript
referents.
5. Ambiguity and diagnostics are first-class valid results.
6. Completed interpretations are immutable, addressable, and reproducible under
recorded rule and resource identities.
7. The semantic debugger explains every accepted object from source evidence.
8. Positive, contrastive, invariant, service, and UI tests pass.
9. Existing setup and infrastructure verification continue to pass.
10. No interpreter behavior depends on historical report content or hidden
report structure.
Completion establishes a working research interpreter. It does not establish
clinical correctness, production readiness, or performance on real human
transcription.
---
# 9. Working Rules for Plan Execution
- Implement the smallest complete semantic slice before broadening coverage.
- Let reviewed examples refine local construction and frame definitions.
- Treat ordinary empirical refinements as engineering work, not owner approval
gates.
- Escalate only choices that change the higher-level conceptual contract or the
public meaning of R5 output.
- Preserve user changes and keep application work separate from setup evidence.
- Update this plan when dependency order or acceptance criteria materially
change; do not rewrite completed evidence to fit a later design.
- Record observed limitations plainly rather than converting them into broad
framework work.
Public demo deployment plan
The complete artifact-demo packaging, VPS provisioning, SSH deployment, hardening, verification, rollback, monitoring, and teardown plan.
Authoritative source: infrastructure/PUBLIC-DEMO-DEPLOYMENT-PLAN.md · Permanent section link
# Public Artifact Demo Deployment Plan
**Status:** Proposed implementation and execution plan
**Target:** `168.235.65.28`, reached first as `$DEMO_BOOTSTRAP_HOST` and then as `$DEMO_HOST`
**Application:** Radiology Transcript Interpreter research proof of concept
**Deployment form:** Artifact-backed public demo, not the live NLP research stack
**Confirmed host:** Debian GNU/Linux 13 (trixie), x86-64, approximately 8 GB RAM and 197 GB disk
## 1. Outcome
This plan creates a public demonstration of the existing interpreter UI using
only the reviewed generated transcription and its immutable checked-in R0–R5
artifacts.
The deployed system permits a visitor to:
1. open the interpreter;
2. load the reviewed generated transcription;
3. run the allowlisted proof-of-concept operation;
4. inspect R0 through R5;
5. inspect approved project documentation; and
6. inspect a truthful, read-only demo health view.
It does not deploy the live Stanza, Grew, UCxn, MoCCA, FrameNet, SWI-Prolog, or
RadLex service processes. It does not accept arbitrary transcription for
interpretation. It contains no historical source reports, production data,
credentials, private corpora, evaluation state, or user-supplied clinical
text.
The governing deployment invariant is:
~~~text
publicly reachable behavior
⊆ reviewed synthetic demo
+ immutable artifact inspection
+ approved documentation
+ read-only demo health
~~~
The deployment must never imply:
~~~text
artifact-backed demonstration = live NLP execution
artifact validity = clinical correctness
public availability = production readiness
~~~
## 2. Why This Is the Fastest Path
The repository already provides:
- the Go hub and UI;
- checked-in POC linguistic and semantic artifacts;
- artifact digest verification;
- the JSON Run operation;
- the Vanilla-JavaScript SPA;
- R0–R5 acceptance tests;
- semantic HTML and security-header tests;
- systemd experience and operational scripts; and
- Make-based build and verification entry points.
The local infrastructure Makefile currently builds and supervises the complete
research stack. Its start target intentionally starts the Python linguistics
and Prolog services before the hub. Its service units also contain
research-machine paths under `/home/raddev`.
Using that full path on a VPS would:
- require at least 4 GB RAM rather than 2 GB;
- install several gigabytes of Python, model, opam, ontology, and research
resources;
- require private or locally pinned dependencies;
- expose unused capability and evaluation operations unless further protected;
and
- take longer while producing no additional behavior in the current UI, whose
Run operation resolves only the reviewed immutable POC.
The shortest sound path is therefore a small public-demo specialization of the
existing Go infrastructure.
## 3. Assumptions and Required Inputs
### 3.1 SSH
The confirmed local private-key path is used by reference and is never copied
into the repository, release bundle, logs, or documentation output. Bootstrap
access and routine administrative access are distinct:
~~~sh
export DEMO_SSH_KEY=/home/raddev/.ssh/id_ed25519
export DEMO_BOOTSTRAP_HOST=root@168.235.65.28
export DEMO_HOST=radnlp-admin@168.235.65.28
export DEMO_ADMIN_SOURCE_IPV4=107.161.20.175
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_BOOTSTRAP_HOST" true
~~~
The root target exists only to establish the named administrator safely. The
bootstrap procedure creates `radnlp-admin` with a locked password, copies the
already-confirmed public key, grants explicit administrative sudo access, and
validates `/etc/sudoers.d/radnlp-admin` with `visudo -c`. It does not expose or
print private-key material.
Before leaving the bootstrap phase, two independent key-authenticated
`radnlp-admin` sessions must succeed and this command must pass without a
prompt:
~~~sh
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_HOST" 'sudo -n true'
~~~
The VPS-observed source address for RADPAIR was independently confirmed on
2026-09-07 as `107.161.20.175`. Host and provider firewalls permit SSH only
from `107.161.20.175/32`. Administrative commands force IPv4 so the selected
path matches that rule. Reconfirm the source through `$SSH_CONNECTION` before
each firewall change. If it differs, stop and review the new address rather
than widening or silently rewriting the allowlist.
The administrator is key-only and has passwordless sudo because the automated
provision, deployment, rollback, and recovery operations require noninteractive
root actions. Compromise of this key therefore means administrative compromise;
the key must remain local and its permissions must remain restricted.
The application runs as the separate unprivileged `radnlp-demo` service
identity and never uses the administrative account.
### 3.2 Domain
Public HTTPS requires a DNS name supplied separately:
~~~sh
export DEMO_DOMAIN=nlp-and-expert.elementsketchpad.com
~~~
DNS inspection on 2026-09-07 found Cloudflare proxy A and AAAA responses for
this name. The adopted minimal deployment does not place Cloudflare in the
request path. Before Caddy starts, change this one record to DNS-only with an A
record for `168.235.65.28`; remove its AAAA record unless the VPS is separately
confirmed and configured for the published IPv6 address. Do not change other
`elementsketchpad.com` records.
Once direct DNS and ports 80/443 reach this VPS, Caddy can obtain and renew a
public certificate and redirect HTTP to HTTPS automatically. Retaining the
Cloudflare proxy would add a CDN/TLS/operator boundary and requires a separate
recorded architecture decision rather than an incidental DNS setting.
### 3.3 Release identity
The deployment uses an immutable committed revision:
~~~sh
export DEMO_RELEASE=v0.1.1
export DEMO_ARCH=amd64
~~~
The existing `v0.1.0` tag is not moved. Public-demo implementation changes
must be committed as `v0.1.1` before promotion. A different later identity
requires an explicit orchestration decision; it is never inferred from a dirty
worktree.
### 3.4 Host baseline
Read-only preflight on 2026-09-07 confirmed:
- Debian GNU/Linux 13 (trixie);
- x86-64 architecture;
- approximately 8 GB RAM with no swap;
- approximately 197 GB disk with more than 180 GB free;
- SSH listening publicly on TCP 22;
- LLMNR listeners on TCP/UDP 5355, which the host firewall will not expose;
- outbound HTTPS for operating-system and Caddy installation;
- inbound SSH during provisioning.
These observations are not permanent assumptions. Preflight rechecks them
before any mutation. The chosen recovery model does not depend on a provider
console: it retains the current root session, retains key-only root login from
RADPAIR, tests fresh administrator sessions, and automatically rolls back each
firewall change unless the new path is explicitly confirmed.
The plan does not assume Docker, Kubernetes, a database, object storage, a
managed load balancer, or a secrets manager.
## 4. Target Architecture
~~~text
Internet
│
│ TCP 80/443
▼
┌───────────────────────────────────────┐
│ Caddy │
│ public TLS · HTTP→HTTPS · proxy │
└───────────────────┬───────────────────┘
│ loopback HTTP
▼
┌───────────────────────────────────────┐
│ rad-nlp Go hub │
│ public-demo route profile │
│ 127.0.0.1:8170 │
└───────────────────┬───────────────────┘
│ read-only files
▼
┌───────────────────────────────────────┐
│ reviewed POC artifacts │
│ approved Markdown documentation │
│ release manifest and identities │
└───────────────────────────────────────┘
~~~
Only Caddy binds public interfaces. The Go process binds
`127.0.0.1:8170`. No Python or Prolog service is installed or started.
## 5. Public-Demo Application Profile
### 5.1 Profile selection
Add an explicit deployment profile to the hub:
~~~text
research
public-demo
~~~
`research` remains the default for local compatibility. The public service
must start with an explicit argument such as:
~~~sh
--deployment-profile public-demo
~~~
Route registration is selected by profile. Public safety must not depend on
registering every research route and rejecting it later in middleware.
### 5.2 Public route allowlist
The public-demo profile registers only these operations:
| Method | Route | Purpose |
|---|---|---|
| GET | `/` | Redirect to the interpreter |
| GET | `/livez` | Process liveness |
| GET | `/readyz` | Demo artifact/document readiness |
| GET | `/assets/basic-web-theme.css` | Local UI stylesheet |
| GET | `/assets/interpreter-app.js` | Local SPA application |
| GET | `/interpretations/new` | Draft/test-data view |
| POST | `/api/v1/interpretations` | Exact allowlisted POC Run |
| GET | `/interpretations/{execution}` | Stable R0–R5 execution view |
| GET | `/interpretations/{execution}/artifacts/{artifact}` | Reviewed synthetic artifacts |
| GET | `/documentation` | Approved documentation index |
| GET | `/documentation/{document}` | Stable documentation section |
| GET | `/toolchains/rad-nlp-research` | Read-only public-demo health |
Every other route returns 404 or 405. In particular, the public profile does
not register:
- capability proxies;
- Stanza, Grew, UCxn, MoCCA, FrameNet, Prolog, or RadLex API routes;
- evaluation creation;
- evaluation records or artifacts;
- generic filesystem or document paths;
- generic Prolog, graph-rule, or model operations; or
- operational mutation endpoints.
### 5.3 Run boundary
The current Run endpoint already:
- requires JSON;
- requires the same-origin SPA header;
- uses a bounded request body;
- accepts only the two allowlisted profiles;
- resolves only the exact reviewed transcription; and
- rejects other transcription with a structured 422 response.
Public-demo acceptance tests preserve all of those obligations. No future
arbitrary-input interpreter is enabled automatically in this profile.
### 5.4 Public readiness
Public `/readyz` must mean:
~~~text
hub responds
∧ POC manifest loads
∧ artifact digests match
∧ approved documentation loads
∧ UI assets are embedded
~~~
It must not contact absent research services.
The Toolchain health page must state:
- deployment profile: artifact-backed public demo;
- application version and build revision;
- POC artifact identity and digest status;
- documentation status;
- live NLP toolchain: not deployed in this profile; and
- research/clinical scope boundary.
It must not display a false full-toolchain READY state.
### 5.5 State and cookies
The public-demo profile has no evaluation mutation and does not require a CSRF
secret or CSRF cookie. Avoid creating either in this profile.
The application may keep a private state directory for runtime compatibility,
but successful operation should require no mutable application data. A restart
must reconstruct all public truth from the release bundle.
## 6. Public Documentation Boundary
The public documentation bundle is an explicit allowlist. It initially
contains:
1. the original RadLex-to-Prolog compiler specification;
2. the radiology transcript conceptual specification;
3. the linguistic-semantic refinement specification;
4. the interpreter implementation plan;
5. the Interpreter UI specification;
6. a concise public project and scope overview.
The detailed deployment and orchestration plans remain available in the local
research documentation UI but are not placed in the public release bundle.
They contain host identifiers, administrative paths, recovery procedures, and
other operational detail that a visitor does not need.
The public profile does not automatically publish every Markdown file in the
repository. In particular, exclude:
- machine-specific operator notes;
- absolute development-machine paths;
- internal evaluation artifacts;
- orchestration scratch state;
- credentials or environment files;
- private-source acquisition instructions; and
- documents not reviewed for public release.
Documentation remains rendered as escaped text. It does not execute embedded
HTML, JavaScript, remote images, or third-party assets.
## 7. Release Bundle
### 7.1 Required Make targets
Extend `infrastructure/Makefile` with:
~~~text
demo-check
demo-build
demo-bundle
demo-smoke
demo-bootstrap-admin
demo-harden-host
demo-provision
demo-deploy
demo-activate-public
demo-status
demo-rollback
~~~
Their intended contracts are:
| Target | Contract |
|---|---|
| `demo-check` | Validate release identity, public route registration, document allowlist, and source/artifact digests |
| `demo-build` | Build a static Linux hub binary for `DEMO_ARCH` |
| `demo-bundle` | Create the explicit deployment tree, manifest, archive, and checksum |
| `demo-smoke` | Exercise a deployed base URL without SSH |
| `demo-bootstrap-admin` | Idempotently establish and verify `radnlp-admin` through the temporary root bootstrap target |
| `demo-harden-host` | Audit, apply the SSH-only nftables policy, patch Debian, configure security updates, and verify any reboot |
| `demo-provision` | Install host prerequisites and validated inactive service configuration without opening web ports |
| `demo-deploy` | Upload, verify, unpack, promote, restart, and smoke one release over loopback |
| `demo-activate-public` | Validate DNS/Caddy, open 80/443, and run public HTTPS acceptance with fail-closed rollback |
| `demo-status` | Read remote unit status and public readiness |
| `demo-rollback` | Promote an explicitly named prior installed release |
The local interpreter and infrastructure final gates remain prerequisites.
### 7.2 Static build
The Go hub should be built with an explicit target:
~~~sh
CGO_ENABLED=0 GOOS=linux GOARCH="$DEMO_ARCH" go build -trimpath -o dist/demo-root/bin/radnlp-toolchain-hub ./cmd/hub
~~~
The build embeds:
- UI CSS;
- UI JavaScript;
- application version; and
- a trustworthy commit/build identity supplied from the committed release.
The build must not fabricate a clean release identity from a dirty worktree.
### 7.3 Bundle layout
The archive expands to:
~~~text
rad-nlp-demo-$DEMO_RELEASE/
├── bin/
│ └── radnlp-toolchain-hub
├── config/
│ └── public-demo.json
├── interpreter/
│ └── artifacts/
│ ├── poc-linguistic.json
│ ├── poc-manifest.json
│ └── poc-result.json
├── documentation/
│ └── approved source documents
├── share/
│ ├── Caddyfile.example
│ └── radnlp-public-demo.service
├── RELEASE
└── MANIFEST.sha256
~~~
The implementation may preserve selected repository-relative paths internally
if that materially simplifies the first bundle, but the archive remains an
explicit allowlist.
The bundle must not contain:
- `.git`;
- `setup/.venv`;
- `setup/cache`;
- research corpora;
- historical report data;
- the UCxn source worktree;
- FrameNet or MoCCA databases;
- the RadLex OWL source or full generated runtime;
- infrastructure evaluation state;
- CSRF secrets;
- SSH material;
- environment files; or
- logs.
### 7.4 Local release gate
Before packaging:
~~~sh
make -C interpreter verify-poc
make -C infrastructure test-interpreter-ui
make -C infrastructure test-ui
make -C infrastructure test-ui-operations
make -C infrastructure demo-check
~~~
After packaging:
1. enumerate every archive member and compare it to the allowlist;
2. verify `MANIFEST.sha256`;
3. scan the expanded bundle for known secret formats and forbidden paths;
4. assert no `/home/raddev` path occurs;
5. run the binary from the expanded bundle in a temporary directory;
6. run `demo-smoke` against that temporary instance; and
7. record the archive SHA-256.
## 8. VPS Provisioning and Initial Hardening
### 8.1 Preflight
From the development machine:
~~~sh
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_BOOTSTRAP_HOST" 'set -eu; uname -m; . /etc/os-release; printf "%s %s\n" "$ID" "$VERSION_ID"; printf "SSH_CONNECTION=%s\n" "$SSH_CONNECTION"; free -h; df -h /'
~~~
Confirm:
- expected architecture;
- Debian 13;
- at least 2 GB RAM;
- at least 10 GB free disk;
- correct system clock;
- working DNS;
- the effective SSH configuration;
- installed firewall tooling and current nftables rules;
- all users with UID 0 or sudo-equivalent access;
- enabled services and public listeners;
- pending package upgrades and whether a reboot is already required;
- the VPS-observed SSH source is exactly `107.161.20.175`; and
- no existing listeners that conflict with ports 80, 443, or loopback 8170.
Record this baseline before changing the host. Unexpected administrators,
firewall rules, repositories, or services are a stop condition for diagnosis;
they are not silently overwritten.
### 8.2 Establish the named administrator
Use the confirmed root session only to create `radnlp-admin`, install the
confirmed public key with mode `0600`, grant noninteractive sudo through a
root-owned mode-`0440` sudoers fragment, and validate the result. Install the
Debian `sudo` package first if this minimal image does not already contain it.
Keep the original root session open while two new administrator sessions are
tested. Verify login, `sudo -n true`, distribution identity, and a harmless
privileged read. Do not change the SSH daemon policy yet.
Root SSH remains a key-only recovery path restricted by firewall to RADPAIR.
The administrator must also survive the patched-host reboot.
### 8.3 SSH-only firewall
Debian's native nftables service is the host-firewall authority. Do not layer
UFW, firewalld, and hand-written nftables rules on the same host.
Install the Debian `nftables` package if absent, without enabling an unreviewed
default ruleset. Save the effective pre-change rules before installing the
reviewed configuration.
The initial ruleset must:
- accept loopback traffic;
- accept established and related traffic;
- accept the confirmed SSH port only when the IPv4 source is
`107.161.20.175/32`;
- accept the ICMP and ICMPv6 traffic required for correct networking;
- default-drop unsolicited inbound traffic for both IPv4 and IPv6;
- leave outbound traffic allowed;
- omit TCP 80 and 443; and
- omit TCP/UDP 5355 and port 8170.
Validate the ruleset syntax before loading it. Before each live firewall
change, save the current rules and schedule a two-minute automatic restoration
of that exact saved ruleset. Load the candidate while the original root session
remains open, confirm fresh `radnlp-admin` and root connections from RADPAIR,
inspect the effective rules, and cancel the rollback only after both pass. If a
new session fails, allow the timed restoration to run or restore immediately
through the still-open session.
Apply the equivalent SSH-only policy at the VPS provider firewall when that
facility is available: TCP 22 from `107.161.20.175/32`, with no broader SSH
source. Provider-firewall changes remain an external operator step unless its
API is explicitly placed in scope.
### 8.4 Operating-system patching
After the administrator and SSH-only firewall pass:
1. refresh package metadata from the already-configured Debian repositories;
2. apply the current Debian 13 security and stable updates;
3. install and enable the Debian `unattended-upgrades` package for security
updates;
4. inspect conffile decisions rather than overwriting local configuration
blindly;
5. reboot if required; and
6. re-verify the named administrator, sudo, nftables, clock, disk, listeners,
and package state after reboot.
The upgrade/reboot gate must pass before application packages are installed.
### 8.5 Application-host packages
Install only:
- CA certificates;
- curl;
- GnuPG/keyring support required by the Caddy repository;
- Caddy;
- standard systemd tooling.
Use the official Caddy Debian/Ubuntu package instructions rather than a
third-party script. The official package supplies and runs Caddy as a systemd
service. Because the official package may start Caddy immediately, install it
only after the SSH-only firewall is active. Replace its default configuration
before any web port is opened.
Do not install Python, PyTorch, Stanza, opam, OCaml, Grew, or SWI-Prolog for the
artifact demo.
### 8.6 Service account and directories
Create a non-login system identity and explicit filesystem ownership:
~~~text
user/group: radnlp-demo
release root: /opt/radnlp-demo/releases
current symlink: /opt/radnlp-demo/current
runtime state: /var/lib/radnlp-demo
unit: /etc/systemd/system/radnlp-public-demo.service
Caddy config: /etc/caddy/Caddyfile
~~~
Release directories are owned by root and read-only to the application.
Runtime state is owned by `radnlp-demo`. The application user has no shell,
sudo rights, or write access to its binary, configuration, artifacts, or
documentation.
### 8.7 Public web-port activation
TCP 80 and 443 are deliberately absent throughout host hardening, package
installation, application deployment, and loopback verification. Add them to
the nftables and provider-firewall allowlists only after all of the following
are true:
1. the exact release is committed, tagged, bundled, and locally accepted;
2. the application runs as `radnlp-demo` on `127.0.0.1:8170`;
3. loopback liveness, readiness, Run, documentation, and route-denial tests
pass on the VPS;
4. the Caddyfile passes `caddy validate`;
5. `$DEMO_DOMAIN` resolves to `168.235.65.28` and any AAAA record resolves to
the same host's configured IPv6 address;
6. Caddy is ready to proxy only to loopback; and
7. fresh administrator and key-only root sessions from RADPAIR, sudo, and the
nftables rollback path remain verified.
Open 80 and 443, start or reload Caddy, and immediately run public TLS and
application acceptance. If activation fails, close 80/443 again while leaving
SSH available for recovery.
Port 8170 is never opened in either firewall. The Python and Prolog ports are
absent.
### 8.8 Final SSH policy
Retain key-based SSH authentication. Do not automate disabling alternative
authentication until:
- a second key-authenticated session is open; and
- the exact Debian 13 SSH defaults have been inspected;
- the named administrator has survived a reboot; and
- deployment and rollback administration work through `$DEMO_HOST`.
At that final gate, install a small validated SSH configuration fragment that
disables password authentication while retaining key-only login for
`radnlp-admin` and root. Validate with `sshd -t`, reload rather than restart
SSH, and prove fresh connections to both accounts before closing existing
sessions. The firewall remains the source boundary: TCP 22 accepts only
`107.161.20.175/32`. Root recovery is an intentional part of this no-console
model, not a temporary exception.
## 9. Service Configuration
### 9.1 Application unit
The installed systemd service should have the following effective shape:
~~~ini
[Unit]
Description=rad-nlp public artifact demo
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=radnlp-demo
Group=radnlp-demo
WorkingDirectory=/opt/radnlp-demo/current
ExecStart=/opt/radnlp-demo/current/bin/radnlp-toolchain-hub --host 127.0.0.1 --port 8170 --deployment-profile public-demo --config /opt/radnlp-demo/current/config/public-demo.json --state-dir /var/lib/radnlp-demo
Restart=on-failure
RestartSec=2
TimeoutStartSec=30
TimeoutStopSec=15
KillMode=control-group
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadWritePaths=/var/lib/radnlp-demo
MemoryMax=384M
TasksMax=64
[Install]
WantedBy=multi-user.target
~~~
The actual unit must be tested with the target Debian 13 systemd release.
Hardening options are retained only when compatible with the static Go binary
and required DNS/network behavior.
### 9.2 Caddy
The production Caddyfile is deliberately small:
~~~caddyfile
$DEMO_DOMAIN {
encode zstd gzip
reverse_proxy 127.0.0.1:8170
}
~~~
Before a domain is available, provisioning validates this template with the
reserved placeholder `demo.invalid` and leaves Caddy stopped. Public activation
substitutes the validated domain, validates the exact production file again,
and only then starts or reloads Caddy.
Caddy owns public TLS. The application continues to emit its CSP,
X-Content-Type-Options, X-Frame-Options, and Referrer-Policy headers.
Enable HSTS only after:
- HTTPS succeeds publicly;
- certificate renewal is healthy;
- the domain is intended to remain HTTPS-only; and
- rollback does not require serving the domain over HTTP.
### 9.3 Logs
The Go process writes operational errors to the system journal. It must not log
request bodies or transcription text.
Caddy access logging is initially disabled unless there is a concrete
operational need. If enabled later:
- do not log request or response bodies;
- use short retention;
- restrict journal/file access;
- account for visitor IP addresses as data; and
- document the retention decision.
No third-party browser analytics, fonts, scripts, error collectors, or content
services are introduced.
## 10. Deployment Procedure
### 10.1 Build
From the repository root:
~~~sh
make -C infrastructure demo-bundle DEMO_RELEASE="$DEMO_RELEASE" DEMO_ARCH="$DEMO_ARCH"
~~~
Expected outputs:
~~~text
dist/rad-nlp-demo-$DEMO_RELEASE-$DEMO_ARCH.tar.gz
dist/rad-nlp-demo-$DEMO_RELEASE-$DEMO_ARCH.tar.gz.sha256
~~~
### 10.2 Harden and provision once
~~~sh
make -C infrastructure demo-bootstrap-admin DEMO_BOOTSTRAP_HOST="$DEMO_BOOTSTRAP_HOST" DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY"
make -C infrastructure demo-harden-host DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY" DEMO_ADMIN_SOURCE_IPV4="$DEMO_ADMIN_SOURCE_IPV4"
make -C infrastructure demo-provision DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY"
~~~
These targets are idempotent and have distinct safety boundaries. Bootstrap
creates and verifies the named administrator. Host hardening installs the
SSH-only nftables policy, patches Debian, enables security updates, and verifies
the rebooted host. Provision installs application prerequisites, creates
identities and directories, installs the service unit and inactive Caddy
configuration, validates both configurations, and leaves the prior application
release untouched.
They do not modify DNS or open TCP 80/443.
### 10.3 Deploy a release
~~~sh
make -C infrastructure demo-deploy DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY" DEMO_RELEASE="$DEMO_RELEASE" DEMO_ARCH="$DEMO_ARCH"
~~~
The target performs these operations:
1. upload archive and checksum to an explicit temporary filename;
2. verify the archive checksum remotely;
3. create a new release directory;
4. extract without overwriting another release;
5. verify the internal manifest;
6. run the new binary's local readiness smoke on an unused loopback port;
7. atomically update `/opt/radnlp-demo/current`;
8. restart `radnlp-public-demo.service`;
9. wait for loopback readiness;
10. keep Caddy and public web ports inactive;
11. run the complete loopback acceptance suite; and
12. remove only the explicitly uploaded temporary files.
If loopback smoke fails, the target restores the prior current symlink and
restarts the prior release. A separate `demo-activate-public` target validates
DNS and Caddy, opens 80/443, reloads Caddy, and runs public HTTPS smoke. If
public activation fails, it closes 80/443 again and reports the exact failure.
### 10.4 Activate public HTTPS
~~~sh
make -C infrastructure demo-activate-public DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY" DEMO_DOMAIN="$DEMO_DOMAIN"
~~~
This is the first operation permitted to open TCP 80/443 or start Caddy with
the production site. It verifies DNS first and closes the web ports again if
public acceptance fails.
### 10.5 Verify
~~~sh
make -C infrastructure demo-smoke DEMO_BASE_URL="https://$DEMO_DOMAIN"
~~~
Then inspect:
~~~sh
make -C infrastructure demo-status DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY"
~~~
## 11. Public Acceptance Matrix
### 11.1 Network and TLS
- DNS resolves to the intended VPS.
- TCP 80 redirects to HTTPS.
- TCP 443 serves a trusted certificate for `$DEMO_DOMAIN`.
- TCP 22 is reachable only from `107.161.20.175/32`; TCP 80 and 443 are
publicly reachable.
- Port 8170 accepts loopback connections only.
- No Python, Prolog, database, or model port is listening.
### 11.2 Application truth
- `/livez` returns live.
- `/readyz` returns ready only after artifact and documentation checks pass.
- The visible UI version matches its DOM version and asset keys.
- The health page identifies the deployment as an artifact-backed public demo.
- The health page explicitly states that the live NLP toolchain is not
deployed.
- Refresh and deep links restore R0–R5 truthfully.
### 11.3 Run behavior
- The reviewed generated transcription produces the expected stable execution.
- The Run response is JSON.
- Edited or arbitrary transcription is rejected with 422.
- Missing SPA proof is rejected.
- Non-JSON input is rejected.
- Cross-origin Run attempts are not allowed.
- Request size and timeout bounds remain active.
### 11.4 Route denial
The following are absent in public-demo mode:
~~~text
/api/v1/stanza/*
/api/v1/grew/*
/api/v1/ucxn/*
/api/v1/mocca/*
/api/v1/framenet/*
/api/v1/conllu/*
/api/v1/radlex/*
/api/v1/evaluations/*
/toolchains/*/evaluations/*
~~~
Evaluation POST, raw research evaluation artifacts, and arbitrary capability
operations must not become reachable through method changes or alternate path
forms.
### 11.5 Data boundary
- The archive inventory exactly matches the release allowlist.
- No historical report archive or CSV is present.
- No full generated corpus is present.
- No credential, key, token, cookie secret, or environment file is present.
- No development-machine absolute path is rendered publicly.
- The only transcription and IR artifacts are the reviewed no-PII POC.
- Documentation is the reviewed public allowlist.
- Application and proxy logs contain no transcription bodies.
### 11.6 Reliability
- The application recovers after a process kill.
- The service starts after reboot.
- A corrupt artifact prevents readiness.
- A missing document prevents readiness or removes only the explicitly
optional document according to the documented policy.
- Twenty concurrent UI reads do not breach the 384 MB service limit.
- Repeated exact Run requests remain stable and bounded.
### 11.7 Accessibility and UI
- Draft, Run, R0–R5, documentation, and health acceptance suites pass through
the public HTTPS origin.
- Keyboard interaction remains complete.
- No third-party frontend request occurs.
- The CSP allows only the intended local application behavior.
## 12. Monitoring and Routine Operation
### 12.1 External monitoring
An optional uptime monitor may call only:
~~~text
GET https://$DEMO_DOMAIN/livez
GET https://$DEMO_DOMAIN/readyz
~~~
It does not submit transcription or fetch raw artifacts.
### 12.2 Operator checks
~~~sh
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_HOST" 'systemctl is-active radnlp-public-demo.service caddy'
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_HOST" 'curl --fail --silent http://127.0.0.1:8170/readyz'
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_HOST" 'journalctl -u radnlp-public-demo.service -u caddy --since today --no-pager'
~~~
### 12.3 Updates
Operating-system security updates are applied through Debian's configured
security repositories and `unattended-upgrades`. Caddy is updated from its
official stable repository.
Application updates always use a new immutable release directory. No deployed
release is edited in place.
## 13. Rollback
List installed releases and identify the exact target:
~~~sh
ssh -4 -i "$DEMO_SSH_KEY" -o IdentitiesOnly=yes "$DEMO_HOST" 'find /opt/radnlp-demo/releases -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | sort'
~~~
Rollback is explicit:
~~~sh
make -C infrastructure demo-rollback DEMO_HOST="$DEMO_HOST" DEMO_SSH_KEY="$DEMO_SSH_KEY" DEMO_RELEASE="<installed-prior-release>"
~~~
The rollback target:
1. verifies the named release and manifest;
2. records the current target;
3. atomically changes the current symlink;
4. restarts the application;
5. waits for loopback readiness;
6. runs public smoke tests; and
7. restores the original target if rollback verification fails.
Rollback never deletes a release.
## 14. Teardown
Teardown is a separate, explicitly invoked operation. It:
1. disables and stops `radnlp-public-demo.service`;
2. removes the Caddy site configuration and reloads Caddy;
3. leaves release directories intact by default;
4. leaves DNS unchanged;
5. leaves the service account intact unless explicitly requested; and
6. reports the remaining paths.
Removal of `/opt/radnlp-demo` or `/var/lib/radnlp-demo` is never implicit in
a stop or uninstall command.
## 15. Later Full-Stack Demonstration
A live NLP demonstration is a separate deployment:
~~~text
public artifact demo ≠ live research toolchain
~~~
It would require:
- at least 4 GB RAM, with 8 GB preferred;
- a CPU-only Python/PyTorch installation;
- Stanza models;
- Grew and UCxn resources;
- SWI-Prolog and the generated RadLex runtime bundle;
- authentication or a private operator boundary;
- request queuing and concurrency limits;
- stronger abuse controls;
- durable execution storage;
- an explicit sensitive-input policy; and
- a new security review.
The current public-demo plan does not silently evolve into that topology.
## 16. Implementation Sequence
| Order | Work item | Completion evidence |
|---|---|---|
| 1 | Freeze the deployment contract and establish local/remote read-only baselines | Orchestration, regression, host inventory, and recovery prerequisites are recorded |
| 2 | Add Debian 13 administrator, nftables, patching, and SSH-hardening automation | Scripts are idempotent, syntax-checked, and fail closed |
| 3 | Establish `radnlp-admin` and harden the host with SSH only exposed | Fresh login, firewall, update, and post-reboot gates pass |
| 4 | Introduce deployment-profile configuration | Unit tests prove research and public route sets differ |
| 5 | Implement public readiness, health truth, and documentation allowlist | Corrupt/missing artifact tests, public health assertions, and forbidden-document tests pass |
| 6 | Add relocatable bundle layout and `demo-check`/`demo-build`/`demo-bundle` | Bundle runs outside the checkout; archive and manifest gates pass |
| 7 | Add hardened systemd/Caddy configuration and idempotent provision/deploy/rollback scripts | Local tests and Debian 13 configuration validation pass |
| 8 | Add loopback and public-origin smoke/denial tests | Full acceptance is executable in both phases |
| 9 | Commit and tag the public-demo release | Clean committed identity matches bundle and visible UI version |
| 10 | Provision and deploy through `$DEMO_HOST` behind closed web ports | VPS loopback acceptance passes with only SSH public |
| 11 | Activate DNS, TLS, and public web ports | Public HTTPS acceptance passes; only SSH/80/443 are exposed |
| 12 | Reboot, rollback, restore, and finalize SSH policy | Recovery evidence and final operational handoff are recorded |
## 17. Definition of Done
The public demo is complete only when:
1. every public route is explicitly allowlisted;
2. the bundle contains only approved files;
3. the application runs without the full research toolchain;
4. no arbitrary transcription can be interpreted;
5. no sensitive or machine-private material is deployed;
6. TLS, firewall, systemd hardening, readiness, and rollback are verified;
7. local interpreter/infrastructure regressions pass;
8. public HTTPS acceptance and denial tests pass;
9. the release is committed and tagged without moving `v0.1.0`; and
10. the health view describes exactly what is and is not running.
## 18. Authoritative External References
- [Caddy installation](https://caddyserver.com/docs/install)
- [Caddy automatic HTTPS](https://caddyserver.com/docs/automatic-https)
- [Caddy reverse proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy)
- [Running Caddy with systemd](https://caddyserver.com/docs/running)
- [Debian security information](https://www.debian.org/security/)
- [Debian firewall and nftables guidance](https://www.debian.org/doc/manuals/debian-handbook/sect.firewall-packet-filtering.en.html)
- [Debian package-management and unattended-upgrades guidance](https://www.debian.org/doc/manuals/debian-reference/ch02.en.html)
- [systemd execution sandboxing](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html)
- [systemd resource controls](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)
Public demo deployment orchestration
The resumable GO protocol, safety gates, ticket sequence, evidence discipline, and completion contract for deploying the public artifact demo.
Authoritative source: infrastructure/public-demo-orchestration/GO.md · Permanent section link
# GO! — Public Artifact Demo Deployment Protocol
## Activation
This package makes the public-demo deployment resumable. Its existence is not
authorization to change the repository, VPS, DNS, or provider firewall.
The exact instruction `GO`, when it refers to deploying the rad-nlp public
demo, adopts and activates `DEP-000` through `DEP-006`. After activation,
continue through every ready ticket without asking for routine supervision.
The adopted target is the artifact-backed demonstration on `168.235.65.28`.
It does not authorize deploying the live Python/Prolog NLP stack, accepting
arbitrary transcription, moving the existing `v0.1.0` tag, or publishing
material outside the documented allowlist.
## Required reading
At activation or resumption, read the durable sources rather than relying on a
conversation summary:
1. the applicable machine and project agent instructions;
2. `../PUBLIC-DEMO-DEPLOYMENT-PLAN.md`;
3. `STATE.md`, `DECISIONS.md`, and `ACCEPTANCE-MATRIX.md`;
4. the active ticket, or the lowest-numbered ready ticket;
5. the ticket's cited deployment-plan sections; and
6. the current implementation and tests in every area the ticket will change.
## Adopted execution boundary
~~~text
DEP-000 freeze authority and establish baselines
↓
DEP-001 establish named administration and harden Debian
↓
DEP-002 implement the allowlisted public-demo application profile
↓
DEP-003 build, inspect, and verify an immutable release bundle
↓
DEP-004 deploy and accept the release on VPS loopback
↓
DEP-005 activate DNS, TLS, and public web ports
↓
DEP-006 prove restart/rollback/recovery and complete the handoff
~~~
Only the final two phases make the application publicly reachable. TCP 80 and
443 remain closed through DEP-004.
## Required operator inputs
The execution uses these explicit values:
~~~sh
export DEMO_SSH_KEY=/home/raddev/.ssh/id_ed25519
export DEMO_BOOTSTRAP_HOST=root@168.235.65.28
export DEMO_HOST=radnlp-admin@168.235.65.28
export DEMO_ADMIN_SOURCE_IPV4=107.161.20.175
export DEMO_ARCH=amd64
export DEMO_RELEASE=v0.1.1
export DEMO_DOMAIN=nlp-and-expert.elementsketchpad.com
~~~
The SSH key is operated on by path. Its private contents are never printed,
embedded, copied to the VPS, or placed in an artifact.
Control of the supplied domain's DNS record is the remaining external fact
required before DEP-005.
The domain currently returns Cloudflare proxy addresses, not the VPS address.
That does not block DEP-000 through DEP-004. DEP-005 requires changing only
this record to DNS-only A `168.235.65.28` and removing AAAA unless origin IPv6
is confirmed. Provider-console recovery is not part of the adopted model.
DEP-001 instead preserves the current root session and key-only root login,
restricts SSH to RADPAIR's confirmed `107.161.20.175/32`, and wraps every live
firewall change in a timed automatic rollback.
## Execution loop
1. Confirm `STATE.md` records adoption after the deployment `GO`.
2. Resume the one `in_progress` ticket, or select the lowest ready ticket.
3. Update the ticket and `STATE.md` to `in_progress` together.
4. Establish the ticket's narrow baseline before changing anything.
5. Preserve unrelated user changes and the dirty UCxn source submodule.
6. Implement the complete ticket obligation.
7. Run narrow tests first, then the ticket gate, then inherited regressions.
8. Record exact commands, outcomes, digests, service state, and deviations.
9. Mark acceptance rows passed only from named executable or observed evidence.
10. Update the ticket, state, decisions, and acceptance matrix together.
11. Continue immediately to the next ready ticket.
Only one ticket may be `in_progress`.
## State machine
~~~text
planned → ready → in_progress → complete
└────────→ blocked
~~~
`blocked` means that safe progress requires an unavailable external input,
provider action, or authority outside this protocol. A failing test, package
surprise, configuration error, or difficult implementation problem is not a
blocker while safe diagnostic and corrective work remains.
## Host mutation discipline
- Start every mutating host ticket with a fresh read-only inventory.
- Save the prior configuration before replacing a firewall, SSH, systemd, or
Caddy file.
- Resolve destructive targets to explicit paths; do not use broad globs.
- Keep an existing root session open until two named-administrator sessions
and noninteractive sudo pass.
- Validate nftables and SSH syntax before loading or reloading them.
- Reload SSH, never terminate the last verified session during a policy change.
- Force administrative SSH over IPv4 and verify that the VPS sees RADPAIR as
`107.161.20.175` before applying an SSH allowlist.
- Permit TCP 22 only from `107.161.20.175/32`.
- Schedule an automatic restoration of the prior firewall rules before every
live firewall change and cancel it only after fresh administrator and root
sessions pass.
- Keep key-only root login from RADPAIR as the no-console recovery path.
- Keep TCP 80/443 closed until VPS loopback acceptance and Caddy validation
pass.
- If public activation fails, close 80/443 and retain SSH recovery.
- Never expose 8170, 5355, Python, Prolog, model, or database ports.
## Application and release discipline
- Select routes at registration time from an explicit `research` or
`public-demo` profile.
- The public profile contains only the reviewed transcription and immutable
R0–R5 artifacts.
- Do not deploy the full corpus, historical reports, evaluation state,
credentials, private resources, or machine-specific operational documents.
- A dirty worktree cannot produce a promotable release identity.
- The release archive is allowlisted, checksummed, scanned, and run outside the
checkout before upload.
- Releases are installed in immutable directories and promoted atomically.
- `v0.1.0` is never moved. The adopted public-demo release is `v0.1.1` unless
the human changes that identity before activation.
## Verification hierarchy
Where applicable, verify in this order:
~~~text
unit and route-registration tests
→ public-profile application tests
→ local bundle inventory and digest checks
→ unpacked-bundle smoke outside the checkout
→ Debian configuration syntax checks
→ VPS loopback acceptance with web ports closed
→ public HTTPS acceptance and route denial
→ process restart and host reboot
→ rollback and restoration
~~~
The broad final gate includes existing interpreter and infrastructure
regressions. Deployment success may not be obtained by weakening current R0–R5,
security-header, SPA, accessibility, or documentation behavior.
## Decision discipline
Record durable choices affecting public routes, data inventory, host access,
firewall policy, release identity, TLS, rollback, logging, or truthfulness in
`DECISIONS.md`. Small implementation choices that preserve the plan do not
require human approval.
If evidence contradicts the deployment plan, stop the contradictory mutation,
record the evidence, and surface the mismatch. Do not silently reinterpret a
security or data boundary to keep moving.
## External side-effect boundary
The deployment `GO` authorizes repository implementation, new commits and the
`v0.1.1` tag, and SSH changes on the named VPS within these tickets. It does not
authorize purchasing services, changing unrelated DNS records, changing a
provider account, or pushing to an external Git remote.
DNS and provider-firewall changes are performed by the human unless the
specific control interface is later supplied and explicitly placed in scope.
The agent prepares exact required values, verifies the observed result, and
continues once the external state is correct.
## Stop conditions
Continue until one of these conditions holds:
1. **Complete:** DEP-000 through DEP-006 and every acceptance row pass, the
public HTTPS URL is healthy, restart and rollback are proven, and the final
deployment report is recorded.
2. **Externally blocked:** DNS control or another required external action is
unavailable after all safe independent work is complete.
3. **Unsafe or outside scope:** continuation would risk lockout, publish
unapproved data, deploy arbitrary-input NLP, or mutate an unrelated system.
When blocked, update `STATE.md` and the active ticket with the exact condition,
evidence, completed safe work, and first action required to resume.
## Completion handoff
Completion records:
- the public URL and resolved address;
- application version, commit, tag, archive digest, and artifact digests;
- effective public route and port inventories;
- Debian, nftables, SSH, systemd, and Caddy verification evidence;
- public acceptance results;
- restart, reboot, rollback, and restoration results;
- monitoring and update commands;
- any explicit temporary security exception; and
- a statement that this is an artifact-backed research demo, not a clinical or
live-NLP service.
Interpreter UI specification
The Draft, Run, enrichment-stage, stable-focus, visual-representation, and accessibility contract for this interface.
# Radiology Transcript Interpreter
# Interactive Execution UI Specification
**Status:** Normative design draft
**Specification version:** 0.1.0
**Target UI version:** 0.1.1
**Supersedes:** *Radiology Transcript Interpreter — Debug UI Design Specification*
**Basis:** The conceptual interpretation specification, linguistic-semantic refinement specification, `interpreter.ir.v1`, and the completed first proof of concept
**Primary interaction:** Draft transcription → Run → Step through interpretation depth → Inspect a focused object
**Visual direction:** Clear, restrained application interface with contextual detail and progressive disclosure
## Contents
1. Vision
2. Technical Introduction
3. Survey of Decisions and Interaction Rules
4. Reference Appendices
---
# 1. Vision
## 1.1 Purpose
The interface exists to let a researcher provide a transcription, run the
radiology transcript interpreter, move forward and backward through the
resulting representations, and inspect any semantic object in context.
Its central interaction is:
```text
write or load transcription
│
▼
Run
│
▼
R0 Source ⇄ R1 Linguistic ⇄ R2 Constructs
⇄ R3 Frames ⇄ R4 Grounding ⇄ R5 Validated
│
▼
select an object and inspect its local explanation
```
The interface is not primarily a long report about an execution. It is an
interactive environment for examining one interpretation at different degrees
of enrichment.
## 1.2 Governing Principle
> **Hold the execution and subject stable while changing how deeply the
> interpretation is viewed.**
The user should be able to begin with the exact source, move toward the
validated result one enrichment step at a time, and then move backward without
losing the object or question under investigation.
## 1.3 Design Correction
The earlier UI draft made the source transcript the permanent visual anchor and
organized the execution as a vertically ordered narrative with a Tufte-inspired
evidence margin. That draft established valuable semantic and evidentiary
principles, but its page geometry is no longer normative.
The new design distinguishes:
```text
epistemic anchor interaction anchor
──────────────────────────────────── ────────────────────────────────────
exact source characters interpretation depth
plus subject under inspection
```
The source remains authoritative. It does not have to remain the largest or
most persistent visual region at every depth.
Tufte remains an influence on restraint, typography, comparison, and the
adjacency of claims and evidence. Tufte-derived preferences do not determine
the application structure, prohibit useful controls or panels, or require a
document-and-margin layout.
## 1.4 Desired Experience
The interface should feel clean, direct, and conceptually stable.
The user should be able to:
1. enter text or load a reviewed test transcription into the same textarea;
2. run the complete interpreter against the exact submitted text;
3. begin at the source representation;
4. move toward more enriched IR or back toward less enriched IR;
5. select a span, mention, construct, referent, frame, grounding, diagnostic,
or validation result;
6. retain that subject while moving across interpretation depth;
7. expose related evidence, relationships, provenance, candidates, and raw
artifacts as needed; and
8. edit the transcription and deliberately create a new execution.
The normal workflow should not require reconstructing the interpretation from
JSON, logs, endpoint responses, Prolog terms, or implementation topology.
## 1.5 Scope
This specification governs:
- transcription drafting and test-data loading;
- starting an interpretation;
- execution status and completion;
- R0–R5 navigation;
- object focus and cross-depth explanation;
- contextual peripheral information;
- semantic HTML, addressability, accessibility, and progressive enhancement;
- access to raw evidence; and
- the relationship between the interpreter UI and the existing toolchain UI.
It does not define:
- new interpretation semantics;
- new R0–R5 boundaries;
- clinical workflow or clinical correctness;
- production authentication or authorization;
- collaborative editing;
- arbitrary code, rule, query, command, or service execution;
- the durable-execution storage design owned by the interpreter implementation
plan; or
- a general ontology browser.
---
# 2. Technical Introduction
## 2.1 Existing System Boundary
The current research system already contains:
- a Go hub and server-rendered Toolchain Debug UI on loopback port `8170`;
- a Python linguistic service that preserves exact source characters and emits
linguistic and construction evidence;
- an SWI-Prolog semantic service that creates mentions, referents, frames,
grounding, diagnostics, provenance, and validation;
- an `interpreter.ir.v1` contract; and
- a deterministic first proof-of-concept result artifact.
The existing Toolchain Debug UI answers whether the research machinery is
available and verified. The UI specified here answers what one transcription
means according to one interpreter execution. These remain distinct
applications even when the Go hub serves and links both.
The Go hub remains bound to `127.0.0.1:8170`. Tailscale Serve may expose that
loopback service to the tailnet. The interpreter services do not bind directly
to a Tailscale address.
## 2.2 Empirical IR Shape
The current complete POC result contains the following primary collections:
```text
source
source_spans
linguistic_observations
mentions
constructs
referents
frames
groundings
ambiguities
diagnostics
provenance_edges
validation
output
resource_identities
```
The first retained execution currently demonstrates 145 source spans, 130
linguistic observations, six mentions, three constructs, three referents, three
frames, six grounding records, one diagnostic, 25 provenance edges, and eight
validation checks.
These counts describe the current fixture. They are not UI limits and should
not become layout assumptions.
## 2.3 Core UI Concepts
The interface introduces a small application vocabulary over the interpreter
model.
### Draft
A mutable candidate transcription and its drafting provenance. A Draft is not
an Interpretation Execution.
### Test Example
A reviewed source record that may populate a Draft. Test-example metadata may
identify the source of the draft, but it is not semantic evidence.
### Interpretation Execution
An immutable attempt to interpret one exact source snapshot under recorded
profiles, rules, and resources.
### Interpretation Depth
One of the named conceptual levels R0 through R5.
### Interpretation Projection
The view of an execution at one interpretation depth. This is sometimes called
the “IR at R3” in ordinary conversation, although R0 begins with source rather
than a derived IR object.
### Subject Under Inspection
The stable object or source region currently being examined.
### Peripheral Detail
Information that explains or contextualizes the current subject without
replacing the interpretation projection: evidence, relationships, provenance,
candidates, diagnostics, identities, and raw representations.
## 2.4 Interpretation Depth
The UI uses the conceptual sequence already established by the interpreter:
| Depth | Name | Newly emphasized material |
| --- | --- | --- |
| R0 | Source | Exact submitted transcription |
| R1 | Linguistic | Sentences, tokens, UD observations, and imported linguistic evidence |
| R2 | Constructs | Mentions, constructs, construction elements, and licensed source roles |
| R3 | Discourse and Frames | Referents, frame instances, role bindings, and composition |
| R4 | Grounding | RadLex candidates, accepted groundings, ambiguity, and domain context |
| R5 | Validated | Validation outcomes and accepted validated-frame output |
The levels are conceptual projections, not claims that the runtime executes as
six isolated sequential programs.
## 2.5 UI State
For a completed execution, the essential UI state is:
```text
UIState = (execution, depth, subject)
```
where:
```text
execution ∈ InterpretationExecution
depth ∈ {R0, R1, R2, R3, R4, R5}
subject ∈ ExecutionObject ∪ SourceRegion ∪ {none}
```
Changing depth does not implicitly change execution or subject.
Before execution, the essential state is:
```text
DraftState = (text, origin, dirty)
```
Draft state and completed-execution state must not be conflated.
## 2.6 Execution Lifecycle
The visible lifecycle is:
```text
Draft ──Run──► Submitted ──► Running ──► Completed
│
└────────► Failed
```
A Completed execution owns immutable source, intermediate representations,
final IR, validation, and resource identities.
A Failed run may expose a stable failure record and structured diagnostics. It
must not masquerade as a completed interpretation or publish R5 output.
## 2.7 Application Architecture
The intended responsibility boundary is:
```text
Browser
│
│ draft form, run request, navigation, object links
▼
Go hub
│
│ complete interpretation operation and immutable execution record
├──────────────► Python linguistic service
└──────────────► SWI-Prolog semantic service
│
▼
Interpretation execution
│
├── R0–R5 projections
├── object and relationship routes
└── raw immutable artifacts
```
The browser does not orchestrate the Python and Prolog services directly. The
hub owns the complete run and publishes the execution that the UI inspects.
## 2.8 Terminology
“More enriched” means moving toward a greater interpretation depth.
“Less enriched” means moving toward source evidence.
“Step” means changing the inspected projection of an existing execution. It
does not mean invoking one backend stage unless a future specification
explicitly introduces live staged execution.
---
# 3. Survey of Decisions and Interaction Rules
## 3.1 The Execution Workspace Is the Primary Interface
### Existing meaning
The earlier design treated one Interpretation Execution as the primary object
but rendered it principally as a long explanatory document.
### Design decision
The primary execution view is an interactive workspace. Its stable center is
the current Interpretation Projection. Its stable contextual object is the
Subject Under Inspection.
The Draft preserves a simple conceptual reading order:
```text
submitted input → complete R0–R5 stage map → selected-stage output
```
Before Run, the same location displays a preview of the complete stage map and
an explicit empty-output state. After Run, the editable input disappears and
the execution uses this reading order:
```text
complete R0–R5 stage map → selected-stage visual representation
└→ peripheral object detail
```
The exact submitted text remains the R0 representation and is linked from the
execution header at every depth. It is not repeated in a read-only textarea.
The long-form narrative remains useful as a printable or overview
representation, but it is secondary to the workspace.
### Entails
- R0–R5 navigation is visible without scrolling through every level.
- The current depth is always apparent.
- Object selection reorganizes contextual detail around that object.
- The user may inspect an execution without reading every preceding section.
### Does not entail
- The interface is a free-form graph canvas.
- Every IR object is displayed simultaneously.
- Implementation subsystems become primary navigation categories.
## 3.2 One Textarea Owns Draft Input
### Design decision
The New Interpretation view contains one primary textarea for transcription
text. The user may type, paste, edit, or populate that textarea from a reviewed
Test Example.
Test data enters through the same Draft model as manually entered text:
```text
Manual entry ───────┐
├──► Draft.text ──► Run
Load test example ──┘
```
Loading a test example does not run the interpreter. It replaces the mutable
Draft text and records the example identity as drafting provenance.
### Required controls
The initial form provides:
- the transcription textarea;
- a small named test-example selector or “Load test data” control;
- the active linguistic and semantic profile identities, normally using safe
defaults rather than editable arbitrary strings;
- a Run action; and
- concise input validation or run failure feedback.
### Invariants
- `Draft.text` is the only semantic language input.
- Test-example annotations, expected constructs, source-row lineage, or hidden
report material are never submitted as semantic evidence.
- The server interprets the exact received text without trimming, correcting,
normalizing, or replacing it.
- The source snapshot displayed after completion is the server-recorded input,
not an assumed copy of browser state.
## 3.3 Run Creates an Immutable Source Snapshot
### Design decision
Run submits the Draft to the complete interpretation operation. A successful
run creates a new immutable Interpretation Execution.
Formally:
```text
run(Draft, Profiles, Resources) = Execution
Execution.source.text = submitted(Draft.text)
```
The UI initially opens a newly completed execution at R1, the first visibly
enriched representation. R0 remains directly selectable as the exact immutable
source anchor.
### Entails
- The textarea is an editor before Run, not a live editor of completed source.
- A completed Execution contains no textarea; its central object is the
selected enrichment representation.
- Profiles, rules, models, and ontology identities belong to the execution.
- Refreshing or revisiting the execution does not recompute it silently.
- A shareable execution URL refers to one stable result.
### Does not entail
- Every keystroke invokes analysis.
- Editing a prior Draft mutates a completed execution.
- A failed run creates valid R5 output.
## 3.4 Step Through Enrichment, Not Runtime Calls
### Design decision
Run computes the complete interpretation. Previous, Next, and direct depth
selection change only the inspected projection.
```text
Run : Draft → Execution
Next : (E, Rᵢ, S) → (E, Rᵢ₊₁, S)
Previous : (E, Rᵢ, S) → (E, Rᵢ₋₁, S)
```
The initial interface must not require the user to invoke linguistic,
construction, semantic, grounding, and validation operations separately.
### Rationale
This interaction presents the conceptual enrichment process without falsely
claiming that the runtime is manually stepped or that each representation is
computed only when its button is pressed.
## 3.5 Projections Are Cumulatively Intelligible
### Design decision
Moving toward R5 adds semantic interpretation without making earlier evidence
unavailable. Moving toward R0 removes higher-order overlays and returns toward
the exact source.
At the UI level:
```text
Visible(E,R0) ⊆ Visible(E,R1) ⊆ ... ⊆ Visible(E,R5)
```
This relation describes conceptual availability in the workspace. It does not
require backend JSON objects to be physically nested or monotonically
serialized.
Each depth should visually emphasize what is introduced there while retaining
local routes to the earlier objects that support it.
### Does not entail
- R5 visually overlays all 145 spans and 130 observations at once.
- Later representations may silently rewrite or erase earlier evidence.
- An object rejected or unresolved at a later depth should be presented as
accepted merely because it appeared earlier.
## 3.6 Subject Focus Persists Across Depth
### Design decision
Object selection establishes a Subject Under Inspection. Depth navigation
preserves that subject.
Every object has an introduction depth:
```text
birth(o) = least Rᵢ at which o is represented
```
If the current depth is at or beyond `birth(o)`, the projection displays and
highlights the object directly.
If the user moves to a depth earlier than `birth(o)`, the subject remains
pinned and the projection shows its provenance antecedents at that depth:
```text
evidenceAt(o, Rᵢ) =
objects at Rᵢ reachable backward through provenance from o
```
For example, a selected Location frame remains the subject when the user moves
from R5 to R2. At R2, the central view highlights its evoking located-finding
construct and role-filling mentions. At R0, it highlights the exact source
spans supporting those objects.
If no provenance path exists, the interface states that the subject has no
representation at the selected depth. It does not select a nearby object by
position or guess a relationship.
## 3.7 Central Projection and Contextual Periphery
### Design decision
The normal wide-screen geometry is:
```text
┌──────────────────────────────────────────────────────────────────────┐
│ Execution identity R0 R1 R2 R3 R4 R5 Less More │
├───────────────────────────────────────────────┬──────────────────────┤
│ │ Subject │
│ Current interpretation projection │ │
│ │ relationships │
│ source / annotation / semantic objects │ evidence │
│ appropriate to the selected depth │ provenance │
│ │ candidates │
│ │ diagnostics │
│ │ raw details │
└───────────────────────────────────────────────┴──────────────────────┘
```
The periphery is contextual, not a permanent table of every fact. It changes
with the selected subject and current depth.
The initial inspector should organize detail into a small number of semantic
groups such as:
- identity and status;
- roles and relationships;
- source evidence;
- derivation and provenance;
- candidates, diagnostics, and validation; and
- raw representations.
The exact disclosure mechanism may use sections, tabs, drawers, or another
accessible control. No particular widget is mandated by this specification.
## 3.8 Source Authority Does Not Require Permanent Source Geometry
### Design decision
The exact transcription remains the canonical evidentiary source. The source
may occupy the central projection at R0, appear as annotated text at R1 and R2,
and appear as focused excerpts or evidence links at later depths.
Selecting any source-backed object must provide a route to its exact full
source context and offsets.
### Invariant
```text
stored span text = execution source[start:end]
```
### Does not entail
- The complete transcript remains fixed beside every later view.
- Normalized quantities or labels replace source wording.
- Source adjacency is evidence of semantic composition.
## 3.9 Depth-Specific Presentation
### R0 — Source
The central view presents the exact immutable source as a readable source
document with minimal execution metadata. Exact source spans remain selectable.
When a later subject is pinned, supporting source ranges are highlighted and
distinguishable when they overlap.
### R1 — Linguistic
The source becomes an interlinear token stream grouped by sentence. Each token
presents its surface form with a compact lemma, part-of-speech, and dependency
line. Selecting a token reveals its broader object detail, local linguistic
neighborhood, evidence, and imported authority.
### R2 — Constructs
The view first exposes recognized source phrases as labelled Mention chips,
then presents each Construct as a role-oriented card connecting named
construction elements to their exact fillers. It must distinguish construct
type, construct instance, role, and source material.
### R3 — Discourse and Frames
The view presents discourse Referents as entity chips and Frame instances as
role-oriented semantic cards. Referenced role values link back to the same
Referent identity. Shared identity—such as Measurement.entity and
Location.figure referring to the same finding—must therefore be immediately
visible.
### R4 — Grounding
The view presents explicit subject-to-concept mapping rows. Each row identifies
whether its subject is a Mention or Referent and whether the mapping is a
candidate or accepted Grounding. Mention, Referent, and Ontology Concept remain
distinct objects. Multiple undominated candidates are comparable without
repeated navigation.
### R5 — Validated
The view assembles accepted frames into readable structured Finding cards with
entity, measurement, location, ontology grounding, and unresolved fields. It
also exposes the individual validation rules that licensed the output.
Ambiguity and diagnostics may remain visible in a valid result.
## 3.10 Peripheral Detail Is Progressive Disclosure
### Design decision
The interface initially displays the semantic facts required to identify the
subject and understand its immediate role. Deeper evidence is disclosed in
place.
Examples include:
```text
Frame
roles
evoking construct
source evidence
why this exists
raw JSON
Prolog derivation
```
Raw evidence remains locally reachable from the object it explains. A global
raw-artifact index may exist, but it is not the ordinary inspection path.
Progressive disclosure must not hide status, ambiguity, unresolved roles, or
failed validation merely to simplify the page.
## 3.11 Visual Direction and the Tufte Override
### Design decision
The visual language remains restrained, but the interface is permitted to use
application controls and bounded regions when they clarify state and
interaction.
### Basic Web Theme baseline and restrained customization
The initial implementation begins with Basic Web Theme as its visual and
technical starting point:
```text
https://raw.githubusercontent.com/mdashx/basicwebtheme/
46fe7fcbff91d766a9aca040adf4aec3de26659c/static/assets/css/style.css
```
The source and license remain recorded, but the upstream file is not a
pixel-perfect or source-text conformance target. CSS may be added, removed,
reorganized, or rewritten when doing so improves the specified interaction.
The intended “ten percent” limit is a design guardrail, not arithmetic over
bytes, lines, declarations, selectors, or syntax-tree nodes. Approximately
ninety percent of the visual language should still feel like Basic Web Theme:
semantic HTML, system typography, ordinary controls, readable prose and data,
minimal chrome, automatic dark mode, and no dependency on JavaScript for basic
presentation. The remaining custom layer may establish the application
workspace, stage navigation, focus, comparison, and semantic status needed by
this interface.
The implementation should retain one compact local author stylesheet and must
not introduce a CSS framework, generic component system, utility-class layer,
third-party visual dependency, or inline-style sprawl. Compliance is evaluated
through design review and the resulting interface, not a mechanical CSS-diff
score.
The design should prefer:
- strong typographic hierarchy;
- generous but not wasteful spacing;
- a small neutral palette with semantic status accents;
- minimal borders and backgrounds;
- legible identifiers and source text;
- stable placement of depth controls;
- comparison by adjacency; and
- motion only when it preserves orientation.
Cards, panels, tabs, sticky controls, and drawers are not prohibited. They must
correspond to real concepts or interaction state rather than supply generic
application decoration.
The following earlier inferences are explicitly rejected:
- that a narrative-plus-margin page is the preferred desktop geometry;
- that a long document is inherently more intelligible than an interactive
workspace;
- that avoiding common UI controls is itself a mark of conceptual purity; and
- that source authority requires source dominance at every depth.
## 3.12 Ambiguity, Diagnostics, and Validation
Ambiguity is a supported semantic outcome, not a generic error state.
Diagnostics belong both to their affected subject and to an execution-level
summary. They must not be exiled to logs.
Validation is a collection of named semantic checks. A green execution-level
status may summarize them, but the user must be able to inspect each check and
its subjects.
The UI must preserve:
```text
valid ≠ completely resolved
candidate ≠ accepted
unresolved ≠ failed execution
diagnostic ≠ crash
```
## 3.13 Editing and Re-running
### Design decision
A completed execution is immutable. “Edit and run again” copies its source into
a new Draft.
```text
Execution E₁.source
│ copy
▼
Draft D₂ ──Run──► Execution E₂
```
Changing the Draft does not change E₁. Changed rules, resources, profiles, or
source create a new execution identity or an explicit duplicate/stale outcome
according to the durable execution contract.
The UI must never make an old R5 result appear to belong to newly edited text.
## 3.14 Running and Failure States
While a run is active, the interface should show:
- the immutable submitted source identity;
- the operation status;
- the profiles and execution identity when assigned;
- elapsed time or last update when available; and
- structured diagnostics when a stage fails.
Refresh must reveal the true current state. Client polling or server-sent
events may improve responsiveness but must not own hidden execution truth.
On failure, the UI offers a route back to an editable copy of the submitted
text. It does not fabricate partial R5 output.
## 3.15 Addressability
The initial route vocabulary should support:
```text
/interpretations/new
/interpretations/{execution}
/interpretations/{execution}?depth=R3
/interpretations/{execution}?depth=R3&focus={object}
/interpretations/{execution}/artifacts/{artifact}
```
Equivalent path-based object routes may also exist, but depth and focus must be
representable in a shareable URL.
Following a shared URL should restore the same execution, depth, and subject or
return an explicit not-found/stale response.
## 3.16 Semantic DOM
The rendered HTML must expose the domain state that the visual interface
already knows.
At minimum, the document identifies:
- execution identity and execution status;
- current interpretation depth;
- subject identity and type;
- every rendered object's stable identity, type, and status;
- source offsets for rendered source spans;
- important relationships such as evidence, reference, evocation, role
filling, grounding, and validation; and
- the available depth and object navigation actions.
These relationships must not exist exclusively in opaque client state or CSS
class names.
## 3.17 Visible Version Identity
Every primary Draft and Execution view visibly identifies the application as
`UI v0.1.1` in a stable header location. The same value is exposed on the
application shell as `data-application-version`.
An Execution view additionally displays and exposes these distinct identities:
- interpretation contract version, such as `interpreter.v1`; and
- IR schema version, such as `interpreter.ir.v1`.
Profile, model, ontology, resource, artifact, and build identities remain
separately labelled. None of them substitutes for the UI version. The
application version has one source in the implementation and is copied neither
into templates nor client code as an independent value.
Before 1.0, a change to specified user-visible interaction or interpretation
presentation increments the minor version; a compatible correction increments
the patch version. A build or commit identity may be shown in addition when it
is trustworthy, but an uncommitted or unknown build must not fabricate one.
## 3.18 Vanilla-JS SPA and Accessibility
The browser experience is a single-page application implemented with a small,
dependency-free vanilla-JavaScript module. It intercepts Draft loading, Run,
depth selection, object focus, and Previous/Next navigation; replaces the
application workspace in place; updates the document title and address bar;
and restores addressable state through browser Back and Forward navigation.
The SPA uses the server-rendered document routes as its state and rendering
contract. It must not maintain a competing browser-only interpretation model,
invent client-only execution identities, or make a refresh less truthful.
The vanilla-JS layer provides in-place depth transitions, inspector updates,
Run feedback, history integration, focus management, and live navigation
status. The interactive workflow requires JavaScript. Server-rendered GET
routes bootstrap the application and restore deep-linked or refreshed state;
they are not a parallel non-JavaScript interaction implementation.
Run is a JSON application operation. The SPA sends only the exact transcription
and the two allowlisted profile identities to `POST /api/v1/interpretations`.
That endpoint returns a JSON execution location or a structured JSON error.
It does not return an HTML document. Server-rendered HTML remains the document
and projection representation used by stable GET routes.
Required keyboard behavior includes:
- normal sequential focus order;
- operable Run and test-data controls;
- operable Previous and Next controls;
- operable direct depth selection;
- visible focus indication; and
- no requirement for pointer-only graph interaction.
Previous/Next keyboard shortcuts may be added, but they must not interfere with
typing in the Draft textarea.
Color, position, and animation must not be the sole carriers of object type,
status, selection, or validation state.
## 3.19 Narrow Displays
On narrow displays, the current projection remains primary. Contextual
peripheral detail moves after the projection or into an accessible bottom
drawer associated with the subject.
The depth navigator may become horizontally scrollable or use compact
Previous/Next controls, but the current named depth remains visible.
Peripheral detail must not collapse into an unrelated generic menu.
## 3.20 Security and Source Handling
The current reviewed test corpus contains no PII, but future real human
transcription may contain sensitive clinical language. The UI therefore must:
- avoid third-party scripts, fonts, analytics, or content services;
- escape all submitted and interpreted text in HTML;
- require JSON content and `X-Rad-NLP-Navigation: spa` on the SPA Run endpoint;
a cross-origin script cannot send that custom header without a CORS
preflight, and the application grants no cross-origin access;
- expose only allowlisted interpretation actions;
- avoid embedding source text in logs unnecessarily; and
- treat tailnet exposure as research-machine access, not as a production
security boundary or clinical deployment claim.
## 3.21 Relationship to the Toolchain UI
The Toolchain UI and Interpreter UI may link to one another through resource and
execution identities.
Every Draft and Execution header includes a prominent Documentation action.
The Documentation view begins with the original RadLex-to-Prolog compiler
specification, then renders the checked-in interpreter conceptual
specification, linguistic-semantic refinement specification, implementation
plan, Interpreter UI specification, Toolchain UI specification, and operator
manual as authoritative source-backed sections. It also provides a prominent
route to the Toolchain UI for system health, monitoring, verification evidence,
and further operational documentation.
They must retain separate primary concepts:
```text
Toolchain UI Interpreter UI
────────────────────────────── ──────────────────────────────
Evaluation Interpretation Execution
Service / Component Source / Mention / Construct
Capability / Seam Referent / Frame / Grounding
Verification Validation / Output
```
An interpreter execution may link to the toolchain evaluation or component
identities that support it. Infrastructure tables and service controls do not
belong in the normal interpretation workspace.
## 3.22 Cross-Cutting Invariants
1. The exact submitted transcription remains recoverable at every depth.
2. A Test Example populates a Draft but contributes no hidden semantic evidence.
3. Run creates a new immutable execution; stepping does not recompute it.
4. Depth navigation preserves the Subject Under Inspection.
5. Earlier-depth evidence remains reachable from every derived object.
6. Mention, Referent, and Ontology Concept remain distinct.
7. Candidate, accepted, rejected, and unresolved states remain distinct.
8. An ontology class never appears visually as a transcript individual.
9. Source proximity is never presented as semantic justification without a
licensed relationship.
10. A valid interpretation may contain ambiguity and diagnostics.
11. R5 contains validated structured output and does not require canonical
predicate projection.
12. Raw evidence is available but does not define the primary information
architecture.
13. The DOM identifies the concepts and relationships rendered to the user.
14. Stable server-rendered GET routes restore the SPA at an addressed
execution, depth, and subject after refresh or direct navigation.
## 3.23 Acceptance Criteria
The initial UI satisfies this specification when executable tests demonstrate
the following behavior.
### Draft and Run
- A user can enter arbitrary nonempty transcription text in the textarea.
- A user can load the reviewed POC record into that same textarea and edit it.
- Loading test data does not automatically run the interpreter.
- Run submits only the exact text and allowlisted profile choices as semantic
input.
- A successful Run creates an addressable immutable execution and opens R1.
- Editing and running again creates or resolves to a distinct execution without
changing the prior result.
- A completed execution contains no textarea; the selected enrichment layer
replaces the Draft editor.
### Interpretation Depth
- Previous, Next, and direct depth controls cover R0 through R5.
- The current depth is visible and addressable.
- R0 reproduces the exact submitted source.
- R1 exposes linguistic observations.
- R2 exposes mentions, constructs, elements, and exact fillers.
- R3 exposes referents, frames, roles, and shared identity.
- R4 exposes candidate and accepted RadLex grounding distinctly.
- R5 exposes individual validation results and accepted validated frames.
- R0 through R5 each expose one depth-specific visual representation rather
than using an object table or raw JSON as the primary output.
### Subject Inspection
- Selecting a frame establishes a stable Subject Under Inspection.
- Moving from that frame toward R2 and R0 highlights its provenance
antecedents without changing the subject.
- Moving forward restores the frame when its introduction depth is reached.
- Missing ancestry is stated explicitly rather than guessed.
- Peripheral detail identifies relationships, evidence, provenance,
diagnostics, validation, resource identities, and raw evidence as available.
### Semantic Integrity
- Mention and Referent are visually and structurally distinguishable.
- Referent and Ontology Concept are visually and structurally distinguishable.
- Unresolved roles remain present.
- Ambiguity is not styled as a crash.
- Partial interpretation can coexist with a valid result.
- Every accepted frame and grounding exposes a path to exact source evidence.
### Web Interface
- Execution, depth, focus, object identities, and important relationships are
machine-discoverable in the DOM.
- Every primary view visibly exposes UI version `0.1.1` and carries the same
value as `data-application-version` on its semantic application shell.
- Execution views visibly and structurally distinguish the interpretation
contract version from the IR schema version.
- Run, depth, focus, and Previous/Next transitions occur in place through the
dependency-free vanilla-JS SPA layer.
- The SPA updates stable URLs and correctly restores them through browser Back
and Forward navigation.
- JavaScript is served as a local external asset allowed by the page CSP; the
interface contains no inline executable script or event-handler attributes.
- All controls have accessible names and keyboard behavior.
- Stable URLs restore execution, depth, and subject.
- Draft and Execution views expose a prominent stable Documentation route.
- Documentation exposes the conceptual and refinement specifications and a
direct Toolchain health and monitoring route.
- Raw artifacts retain their immutable identities and digest checks.
- The application remains available through the existing loopback hub and its
configured Tailscale Serve proxy without exposing internal services directly.
## 3.24 Deliberately Experimental Presentation Questions
The following choices should continue to be refined with additional IR
examples rather than prematurely frozen:
- whether R1 should add a focused dependency-neighborhood view alongside the
sentence-grouped interlinear token stream;
- whether R3 should add a compact relation diagram alongside its role-oriented
semantic cards;
- the best compact representation for overlapping source spans;
- whether the contextual inspector uses vertically stacked sections or a small
tab set on wide displays; and
- how much of a very long transcription remains in the central viewport while
a later semantic subject is selected.
These experiments may change presentation geometry. They may not change the
Draft/Execution boundary, interpretation-depth model, stable subject focus, or
source/provenance invariants without revising this specification.
---
# 4. Reference Appendices
## Appendix A — Initial Workflow
```text
NEW INTERPRETATION
Test data: [POC measured and located nodule ▾] [Load]
┌──────────────────────────────────────────────────────────────┐
│ There is an 8mm nodule in the left lower lobe ... │
│ │
│ │
└──────────────────────────────────────────────────────────────┘
Profiles: linguistic.poc.v1 · semantic.poc.v1
[Run interpretation]
Interpretation stages
[R0 Source] [R1 Linguistic] [R2 Constructs]
[R3 Frames] [R4 Grounding] [R5 Validated]
Current selected stage output
No execution yet. Run the Draft to begin at R1.
```
After completion:
```text
INTERPRETATION exec-poc-4cd7522b679092d7
Submitted transcription
┌──────────────────────────────────────────────────────────────┐
│ There is an 8mm nodule in the left lower lobe ... │
└──────────────────────────────────────────────────────────────┘
[R0 Source] [R1 Linguistic] [R2 Constructs]
[R3 Frames] [R4 Grounding] [R5 Validated]
[← Less enriched] [More enriched →]
Current selected stage output: R1 Linguistic
Current projection Subject
──────────────────────────────────────────── ───────────────────────
There is an 8mm nodule in the no object selected
left lower lobe ...
```
## Appendix B — Example Cross-Depth Focus
Suppose `f-cxn-location-s6-6` is the selected Location frame.
| Depth | Central emphasis while the frame remains the subject |
| --- | --- |
| R5 | The accepted Location frame and its passed validation |
| R4 | The grounded finding and anatomy referents participating in the frame |
| R3 | Location roles and the shared finding referent |
| R2 | The located-finding construct and its figure, relation, and ground mentions |
| R1 | Tokens and dependencies supporting `nodule in … lobe` |
| R0 | Exact `nodule`, `in`, and `left lower lobe` source spans |
The inspector continues to identify the selected frame at all six depths. It
also identifies the current antecedents being displayed.
## Appendix C — Semantic DOM Sketch
```html
<article
id="interpretation-exec-poc-4cd7522b679092d7"
data-concept="interpretation-execution"
data-execution-id="exec-poc-4cd7522b679092d7"
data-execution-status="completed"
data-depth="R3"
data-subject-id="f-cxn-location-s6-6">
<nav aria-label="Interpretation depth" data-concept="depth-navigator">
<a href="?depth=R2&focus=f-cxn-location-s6-6">R2 Constructs</a>
<a aria-current="step" href="?depth=R3&focus=f-cxn-location-s6-6">
R3 Frames
</a>
<a href="?depth=R4&focus=f-cxn-location-s6-6">R4 Grounding</a>
</nav>
<main data-concept="interpretation-projection" data-depth="R3">
<section
id="f-cxn-location-s6-6"
data-concept="frame"
data-frame-type="Location"
data-status="accepted">
...
</section>
</main>
<aside
aria-label="Subject under inspection"
data-concept="subject-inspector"
data-subject-id="f-cxn-location-s6-6">
...
</aside>
</article>
```
This markup is illustrative. The required semantics are the stable execution,
depth, subject, object types, statuses, source locations, and relationships.
## Appendix D — Design Provenance
### Interpretation depth as the interaction anchor
**Original input**
> “Hit a button and flip through the enriched or less enriched IR from my
> source to end.”
**Context summary**
The earlier draft used a Tufte-inspired long narrative with source as the
dominant visual anchor.
**Design contribution**
**Human-led correction.** The author replaced static page geometry with a
depth-oriented interaction model. The source remains authoritative, while
R0–R5 navigation becomes the principal way of understanding the execution.
**Resulting specification rule**
```text
UIState = (execution, depth, subject)
```
Depth may change without changing execution or subject.
### Draft, Run, and inspect
**Original input**
> “Provide in a text area or have the area populated with test data, and then
> run and step through the IR.”
**Context summary**
The design had described completed execution inspection but had not made the
creation workflow its central interaction.
**Design contribution**
**Human-led direction.** The author established the complete interaction spine:
one editable Draft, optional reviewed test-data population, one atomic Run, and
stepwise inspection of the completed representations.
**Resulting specification rule**
```text
Draft ──Run──► immutable Execution ──inspect──► R0 ⇄ ... ⇄ R5
```
Run computes the execution. Stepping changes its inspected projection.
## Appendix E — Superseded and Retained Principles
The previous interpreter UI draft remains useful design history. The new
specification retains its requirements for:
- domain-first concepts;
- exact source preservation;
- Mention/Referent/Ontology Concept separation;
- explicit construct elements and frame roles;
- ambiguity and diagnostics as first-class results;
- provenance and individual validation checks;
- semantic HTML;
- stable object addressability; and
- locally reachable raw evidence.
It supersedes the previous draft's normative preference for:
- a long vertically ordered execution narrative;
- permanent source dominance;
- an asymmetric narrative-and-margin desktop layout; and
- a restricted visual grammar that discourages ordinary interactive
application structures.
Toolchain UI specification
The research design for the Toolchain Debug UI, its concepts, views, evidence model, and scope boundary.
# Toolchain Debug UI
# Design Specification
**Status:** Research Draft — Unapproved
**Application:** Toolchain
**Scope:** Installation, capability, interoperability, and evidence inspection for the research toolchain
**Design basis:** *Debug Interface Design Philosophy*
**Current empirical basis:** `setup/PLAN.md`, `setup/ACCEPTANCE-MATRIX.md`, and `setup/STATE.md`
This document records a candidate design. Its presence under `research/` does not approve an architecture or authorize implementation. Requirements language describes the proposed design if adopted. Planning assumptions are called out separately and remain revisable until explicitly accepted.
---
# 1. Vision
The Toolchain Debug UI is a separate technical application for understanding whether the research toolchain is present, operable, and interoperable.
Its central question is:
> **Is this toolchain ready for research, what capabilities were demonstrated, and what evidence proves it?**
The application does not explain a radiology transcript interpretation. It does not present mentions, constructs, referents, frames, groundings, or clinical meaning. Those belong to the Radiology Transcript Interpreter and its own debug application.
The Toolchain application instead presents the domain of research infrastructure:
```text
declared toolchain
│
▼
components and identities
│
▼
required capabilities and seams
│
▼
version-bound evaluation
│
▼
verifications
│
▼
inspectable evidence and diagnostics
```
The interface is successful when an engineer can determine, without reading setup scripts or inferring meaning from logs:
- which executable tools and knowledge resources constitute the toolchain;
- which capabilities each component is expected to provide;
- which artifacts cross component boundaries;
- which seams have actually been exercised;
- which claims passed, failed, were blocked, or have not been attempted;
- whether prior evidence still applies to the selected versions and environment;
- how to inspect and reproduce every readiness claim; and
- what the readiness claim explicitly does **not** establish.
## 1.1 Boundary with the interpreter application
Toolchain and Radiology Interpreter are separate applications with separate concepts and separate primary objects of inspection.
```text
TOOLCHAIN DEBUG UI RADIOLOGY INTERPRETER DEBUG UI
Toolchain Interpretation Execution
Component Source
Capability Mention
Artifact Construct
Seam Referent
Service —
Endpoint —
Service Instance —
Environment Frame
Evaluation Grounding
Verification Validation
Evidence Provenance
Diagnostic Diagnostic
"Can the machinery work together?" "How did this text become this meaning?"
```
The applications may link to one another by stable URL when useful. Neither should embed the other's domain as a subordinate dashboard.
Toolchain readiness is a prerequisite claim about research machinery. It is not evidence that the radiology interpretation model is implemented correctly, that a clinical interpretation is valid, or that an end-to-end product is ready.
## 1.2 Governing principles
This application follows the general debug-interface philosophy, with one important domain-specific consequence:
> In a toolchain application, component boundaries and interoperability seams are domain concepts, not incidental implementation telemetry.
Even so, a process diagram or package inventory is not sufficient. The interface is organized around **capabilities that have been demonstrated**, with versions, commands, logs, and artifacts serving as evidence.
The following propositions organize the current research draft:
1. Toolchain is a distinct application, not a section of the Radiology Interpreter UI.
2. Readiness is derived from current verification evidence; it is never a manually assigned green state.
3. Installation and version discovery are evidence about a component, not proof of its behavior.
4. Independent component checks and cross-component seam checks are both required.
5. Evidence is bound to exact component identities and an environment.
6. Raw evidence is directly reachable but subordinate to the explanation it supports.
7. Observation is safe by default; rerunning a check is an explicit operation.
8. The rendered DOM is a stable, semantic, machine-readable inspection surface.
---
# 2. Technical Introduction
## 2.1 Primary object of inspection
The durable domain object is a **Toolchain**: a declared composition of components, required capabilities, and required seams.
The primary inspectable snapshot is an **Evaluation**: one bounded assessment of a toolchain in a particular environment against particular component identities.
This distinction matters because the toolchain can remain conceptually stable while its installed versions, generated resources, host environment, or test results change.
The default page presents the selected Toolchain through its latest Evaluation. Historical evaluations remain stable and addressable.
## 2.2 Core concepts
### Toolchain
A declared composition of components and research-readiness requirements.
A toolchain defines what is required. It does not acquire readiness merely because its components have been named or installed.
### Component
An independently identifiable constituent of the toolchain.
The initial application distinguishes at least two component kinds:
- **Tool** — executable machinery that transforms, queries, validates, or transports artifacts.
- **Knowledge Resource** — versioned declarative data, schemas, models, rules, or vocabularies used by tools.
A distribution such as UCxn may expose several independently identified constituents—adapter, rules, corpus, or generated annotations—rather than being forced into one kind.
Every component identity should include the strongest practical identity available, such as package version, source revision, model name, database release, generated-bundle digest, or local artifact path.
### Service
A durable operational boundary that hosts one or more executable Components and exposes their Capabilities to another program.
A Service is not synonymous with a Component. One Python Service may host Stanza, the UCxn adapter, MoCCA, and FrameNet while those remain separately identified Components with separately verified Capabilities.
### Endpoint
A versioned callable operation through which a Service exposes a Capability.
An Endpoint defines an input contract, output contract, error vocabulary, timeout behavior, and identity. It does not expose arbitrary execution merely because its underlying runtime can execute arbitrary Python, Grew, or Prolog code.
### Service Instance
One running realization of a Service in an Environment.
Its process identity, start time, readiness, resource observations, and restart history are operational facts. Clients must not depend on its process ID or on ephemeral in-memory handles surviving a restart.
### Capability
A behavior that a component is required or expected to demonstrate.
Examples include:
```text
parse English text into valid CoNLL-U
mutate a dependency graph using a Grew rule
load and query a construction graph
index FrameNet frames and lexical units
execute a Prolog transport query over CoNLL-U
resolve RadLex concepts through the generated consumer bundle
```
A capability is a claim in the domain model. A version string, import statement, process exit code, or log line may support the claim but is not the claim itself.
### Artifact
A typed, inspectable object consumed, produced, or retained by a component.
Examples include text, a Stanza document, CoNLL-U, a Grew graph, construction annotations, FrameNet XML, a MoCCA graph, a RadLex bundle, a Prolog term, or a verification report.
An artifact may also serve as evidence, but the concepts are not identical:
- artifact describes the role of data in the toolchain;
- evidence describes the role of an observation in supporting a claim.
### Seam
A declared interoperability boundary through which one component's artifact becomes usable by another component.
A seam identifies:
- producing component;
- consuming component;
- transported artifact kind;
- representation or contract;
- any adapter or transformation;
- required invariants; and
- the verification that exercises the boundary.
A seam is not proven by the independent health of its endpoints. It must be exercised across the boundary.
### Environment
The execution context in which an evaluation is performed.
It records only facts material to interpreting or reproducing results: operating system and architecture, relevant runtimes, accelerator availability, selected environment or package roots, and other declared compatibility dimensions.
### Evaluation
One bounded assessment of one Toolchain under one Environment and one set of component identities.
An evaluation collects verifications and derives the readiness state. It records start and completion times, but chronological ordering does not define conceptual structure.
### Verification
One execution of a prescribed check against a Capability or Seam.
A verification records:
```text
subject
requirement checked
command or procedure
inputs
environment
component identities
outcome
measurements
evidence
diagnostics
time
```
### Evidence
An inspectable observation that supports or contradicts a verification claim.
Evidence includes structured assertions, counts, selected output, hashes, paths, generated artifacts, logs, and commands. Evidence must remain connected to the claim it supports.
### Diagnostic
A structured explanation of an incomplete, blocked, stale, or failed verification.
A diagnostic should identify the affected concept, failure phase, observed condition, available evidence, and likely reproduction step. A stack trace can be attached as evidence; it is not the complete diagnostic by itself.
## 2.3 Concept relations
```text
Toolchain contains Component
Toolchain requires Capability
Toolchain requires Seam
Component provides Capability
Component consumes Artifact
Component produces Artifact
Service hosts Component
Service exposes Endpoint
Endpoint makes-callable Capability
Service Instance realizes Service
Service Instance runs-in Environment
Seam connects Component to Component
Seam transports Artifact
Evaluation evaluates Toolchain
Evaluation occurs-in Environment
Evaluation identifies Component
Evaluation includes Verification
Verification checks Capability or Seam
Verification yields Evidence
Verification may-yield Diagnostic
```
The corresponding high-level technical structure is:
```text
┌──────────────────────┐
│ TOOLCHAIN │
│ requirements + parts │
└──────────┬───────────┘
│ evaluated as
▼
┌──────────────────────┐
│ EVALUATION │
│ identities + env │
└──────────┬───────────┘
│ contains
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
component verification seam verification diagnostic
│ │ │
└──────────────┬──────┴─────────────────────┘
▼
evidence bundle
command · output · artifact · hash
```
## 2.4 Formal readiness model
Let:
```text
Req(T) = required capabilities and seams of toolchain T
checks(v, r) = verification v checks requirement r
passed(v) = v completed with the outcome passed
current(v,E) = v's component identities and relevant environment facts
agree with evaluation E
```
A requirement is satisfied only by current passing evidence:
```text
satisfied(r, E)
iff ∃ v ∈ verifications(E):
checks(v, r) ∧ passed(v) ∧ current(v, E)
```
Toolchain readiness is derived:
```text
ready(T, E)
iff completed(E)
∧ evaluation-of(E, T)
∧ ∀ r ∈ Req(T): satisfied(r, E)
```
Consequences:
- Installed does not imply passed.
- A passing component check does not imply a passing seam check.
- A historical pass does not imply a current pass after an identity changes.
- Optional or exploratory checks may inform the interface but do not block readiness.
- Overall readiness cannot contradict the underlying required verifications.
## 2.5 State vocabulary
State must preserve meaningful distinctions.
For a verification:
```text
not attempted
running
passed
failed
blocked
```
For previously obtained evidence:
```text
current
stale
```
For a component:
```text
unavailable
identified
installed
```
For a toolchain evaluation:
```text
not evaluated
evaluating
ready
not ready
incomplete
```
These vocabularies must not be collapsed into generic green, yellow, and red labels. Human-readable labels must remain present even when color is used redundantly.
The system must also preserve `unknown`, `not applicable`, and `not observed` where those are facts rather than errors.
## 2.6 Current empirical toolchain
The first Toolchain represented by the application is the `rad-nlp` research toolchain established by the setup plan.
Its current executable path is:
```text
source text
│
▼
Stanza 1.14.0 / torch 2.14.0
│ dependency parse
▼
CoNLL-U
│
▼
official UCxn adapter + Grew 1.21.0
│ construction matching and annotation
▼
annotated CoNLL-U
│
▼
SWI-Prolog 9.2.9
transport and existential query checks
```
The current knowledge-resource capabilities branch from that executable path rather than pretending to form one linear runtime pipeline:
```text
UCxn pinned source and official rules ──► construction rules and corpus adapter
MoCCA DB 1.0 ────────► construction graph queries
FrameNet 1.7 XML ────────► frames, FEs, LUs, and relations
RadLex generated bundle ────────► ontology consumer queries
```
The initial evaluation is backed by ten setup obligations, S-01 through S-10. Existing evidence includes:
| Area | Demonstrated evidence |
|---|---|
| Stanza | 10 documents, 12 dependency trees, 125 tokens, valid CoNLL-U |
| Grew | graph mutation emitting `Smoke=grew-ok` |
| UCxn | official adapter over 500 EWT sentences and 7,275 tokens, producing 61 `Cxn` and 91 `CxnElt` rows |
| MoCCA | graph load and query over 1,278 nodes and 3,049 edges |
| FrameNet | 1,221 frames, 11,428 frame elements, 13,572 indexed lexical units, and relation indexes |
| SWI-Prolog | three passing `plunit` CoNLL-U transport tests |
| RadLex | six consumer tests against a generated bundle with recorded digest |
| Assembly seam | Text → Stanza → CoNLL-U → UCxn/Grew → SWI-Prolog with an exact existential anchor/pivot assertion |
These numbers are baseline evidence from the current setup, not constants in the design. The UI must read the current evaluation record and never hard-code them as permanent truths.
---
# 3. Survey of Design Decisions and Translation Rules
## 3.1 Primary narrative
The default Toolchain page should read as a compact technical explanation, in this order:
1. **Identity and boundary** — which declared toolchain and environment are being inspected.
2. **Readiness statement** — whether it is ready, why, when evaluated, and what the statement excludes.
3. **Executable transport path** — the main artifacts and seams exercised end to end.
4. **Knowledge-resource capabilities** — independently queryable resources and demonstrated operations.
5. **Verification ledger** — every required and optional check with exact state.
6. **Diagnostics and drift** — failures, blocked work, stale results, or changed identities.
7. **Reproduction** — commands and retained evidence sufficient to inspect or rerun the evaluation.
This order presents the conclusion first, then its structured proof.
## 3.2 Page geometry
The default desktop layout uses one dominant narrative column and one narrower evidence margin.
```text
┌────────────────────────────────────────────────────────────────────────────┐
│ Toolchain: rad-nlp research READY │
│ Evaluation identity · environment · completed time · scope boundary │
├───────────────────────────────────────────────────┬────────────────────────┤
│ │ │
│ READINESS EXPLANATION │ EVIDENCE MARGIN │
│ │ │
│ EXECUTABLE TRANSPORT PATH │ selected claim │
│ text → Stanza → CoNLL-U → UCxn/Grew → Prolog │ versions │
│ │ source revisions │
│ KNOWLEDGE-RESOURCE CAPABILITIES │ command │
│ MoCCA · FrameNet · RadLex │ measurements │
│ │ artifact links │
│ VERIFICATION LEDGER │ raw output │
│ S-01 … S-10 │ reproduction │
│ │ │
│ DIAGNOSTICS AND DRIFT │ │
│ │ │
└───────────────────────────────────────────────────┴────────────────────────┘
```
On narrow screens, the evidence margin follows the selected claim in document order. The conceptual hierarchy must survive without CSS or JavaScript.
The initial interface should not introduce a dashboard of equal-weight cards, tabbed subsystems, a permanent icon sidebar, or a node-link graph as the only account of the pipeline.
## 3.3 Readiness explanation
The readiness statement must be a sentence with inspectable support, not merely a badge.
Example:
> Ready for research experiments: all 10 required component and seam verifications passed for the identified local versions in this CPU environment. This does not establish radiology interpretation correctness or clinical validity.
If the toolchain is not ready, the statement should name the minimal blocking set:
> Not ready: 8 of 10 requirements pass; the UCxn-to-Prolog seam failed and the RadLex consumer verification has not been attempted for the current bundle digest.
Every clause links to the verification or identity that justifies it.
## 3.4 Pipeline representation
The transport path is an ordered relation among components, seams, and artifacts. It must not be rendered as decorative boxes detached from evidence.
Each step exposes:
```text
component identity
capability exercised
input artifact
output artifact
outcome
verification link
```
Each connector exposes:
```text
seam identity
artifact contract
adapter, if any
invariants checked
verification link
```
The visual path is a summary of those semantic relations. A text or table representation must remain available in the DOM.
## 3.5 Verification ledger
The ledger is the complete accounting surface for readiness.
Each row presents:
| Field | Meaning |
|---|---|
| Requirement | Stable capability or seam identifier and name |
| Kind | Component capability or interoperability seam |
| Required | Whether failure blocks readiness |
| Subject | Component or seam checked |
| Outcome | Exact verification state |
| Currentness | Whether evidence matches selected identities and environment |
| Measurement | Compact result that demonstrates useful work |
| Evidence | Stable link to the verification explanation and raw artifacts |
Filtering may reduce what is visible, but the document must state that a filter is active and preserve the complete evaluation count.
## 3.6 Evidence presentation
Evidence should be progressively disclosed in three layers:
1. **Claim** — the capability or seam result in domain language.
2. **Structured evidence** — identities, command, assertions, measurements, and artifact references.
3. **Raw evidence** — complete output, log, serialized artifact, or retained report.
The interface must not require a user to search an undifferentiated log for the fact that supports a passing claim.
Raw outputs should use native `<details>` disclosure where practical. Commands and short artifacts should be copyable as text. Large retained artifacts should be linked with type, size, digest, and availability state.
## 3.7 Provenance and freshness
Every verification carries provenance sufficient to answer:
```text
What ran?
Against which component identities?
In which environment?
Using which inputs?
At what time?
What exact observations determined the outcome?
Where is the retained evidence?
```
A change to a relevant identity does not rewrite a historical evaluation. It causes prior evidence to be marked stale relative to a new evaluation.
Freshness must be semantic, not merely chronological. A result is stale because a declared dependency or compatibility dimension changed, not simply because an arbitrary number of days elapsed.
## 3.8 Diagnostics
Diagnostics are attached to the capability, seam, component, artifact, or verification they explain.
A diagnostic contains:
```text
stable identity
severity
affected concept
phase
summary
observed condition
expected condition
evidence references
reproduction command or procedure
```
The interface preserves the difference between:
- failed — the check ran and contradicted its acceptance condition;
- blocked — the check could not run because a prerequisite was absent;
- not attempted — no check was run;
- stale — evidence exists but does not apply to the selected identities; and
- unavailable — a component or retained artifact cannot be reached.
## 3.9 Safe interaction model
The default application is observational.
Ordinary interactions include:
```text
inspect
follow
filter
compare
copy
download retained evidence
```
Rerunning verification changes machine state by starting processes and producing artifacts. It is therefore an explicit operation presented as a semantic form or button whose label states the action and scope, such as:
```text
Run verification S-08
Run failed required verifications
Start new full evaluation
```
Before submission, the interface shows the target toolchain, selected checks, environment, and command or procedure. The new run creates a new verification or evaluation record; it does not overwrite historical evidence.
## 3.10 Semantic DOM contract
The rendered document is a public inspection surface for humans, browser tools, tests, and local agents.
Core concepts require stable IDs and explicit semantic relationships. A representative structure is:
```html
<article id="toolchain-rad-nlp-research"
data-concept="toolchain"
data-toolchain-id="rad-nlp-research"
data-readiness="ready">
<header>
<h1>rad-nlp research toolchain</h1>
<p id="readiness-statement">…</p>
</header>
<section id="transport-path" aria-labelledby="transport-path-heading">
<h2 id="transport-path-heading">Executable transport path</h2>
<ol data-relation="artifact-transport">…</ol>
</section>
<section id="verification-ledger" aria-labelledby="verification-heading">
<h2 id="verification-heading">Verification ledger</h2>
<table>…</table>
</section>
</article>
```
Concept instances should use a consistent vocabulary such as:
```text
data-concept="component"
data-component-kind="tool"
data-concept="capability"
data-concept="artifact"
data-concept="seam"
data-concept="evaluation"
data-concept="verification"
data-concept="evidence"
data-concept="diagnostic"
```
Relations should be discoverable through links, IDs, and attributes rather than inferred from visual proximity alone.
The essential page must remain readable and navigable with JavaScript disabled. Native HTML links, tables, forms, headings, lists, and disclosure controls are preferred.
## 3.11 Stable routes and identity
The application should provide meaningful, bookmarkable routes:
```text
/toolchains/{toolchain-id}
/toolchains/{toolchain-id}/evaluations/{evaluation-id}
/toolchains/{toolchain-id}/components/{component-id}
/toolchains/{toolchain-id}/capabilities/{capability-id}
/toolchains/{toolchain-id}/seams/{seam-id}
/toolchains/{toolchain-id}/verifications/{verification-id}
```
The first route resolves to the current selected evaluation while making that selection explicit. Historical evaluation URLs remain immutable.
Fragments should deep-link to specific evidence, diagnostics, artifacts, and verification rows.
## 3.12 Visual language
The visual implementation begins with Basic Web Theme and the conventions of the general debug-interface philosophy:
- native typography and controls;
- high information density without crowding;
- restrained borders and color;
- sentence-like status explanations;
- aligned measurements where comparison matters;
- no icon-only concepts;
- no animation required to understand state; and
- no decorative system diagram competing with the evidence.
Color may reinforce outcome, currentness, or severity. It may not carry those distinctions alone.
## 3.13 Candidate invariants
An implementation of this draft would preserve these invariants:
1. Every readiness-blocking requirement is represented by a stable Capability or Seam.
2. Every required Capability or Seam has a Verification in a completed Evaluation, or is explicitly shown as unsatisfied.
3. Every passing Verification exposes positive evidence beyond process exit status.
4. Every failed or blocked Verification exposes at least one Diagnostic.
5. Every Verification identifies its relevant components, inputs, environment, procedure, and time.
6. Every Seam names its producer, consumer, artifact contract, and exercising Verification.
7. Overall readiness is derived from required verification state and currentness.
8. Historical evaluations are not silently mutated when versions or environments change.
9. Missing, false, empty, unknown, unavailable, not attempted, not applicable, blocked, failed, and stale remain distinguishable.
10. Raw evidence is reachable from the claim it supports.
11. The default page states the boundary of the readiness claim.
12. No Toolchain state is presented as proof of radiology interpretation or clinical correctness.
13. The UI distinguishes a Component from the Service that hosts it.
14. Every callable Endpoint identifies the Capability it exposes and the Service that owns it.
15. No durable URL, evaluation record, or client contract depends on an ephemeral process ID or in-memory backend handle.
## 3.14 Initial implementation slice
The first useful UI need not be a general toolchain platform. It should render the current `rad-nlp` setup state faithfully.
The initial slice should support:
1. one declared toolchain, `rad-nlp-research`;
2. the current local environment and component identities;
3. all setup obligations S-01 through S-10;
4. the executable assembly seam and independent knowledge-resource checks;
5. structured summaries of the existing heavy smoke evidence;
6. stable links to commands, reports, logs, and retained artifacts;
7. exact readiness derivation;
8. diagnostics for absent or failed evidence; and
9. reproduction through the existing `make -C setup verify` entry point and narrower check commands.
Comparison across evaluations, remote execution, arbitrary toolchain editing, service restart controls, and generalized plugin discovery are later concerns. Live progress may be added as a small progressive enhancement for an explicitly started verification run.
## 3.15 Acceptance criteria
The initial interface is acceptable when an engineer can answer all of the following from the page and its directly linked evidence:
- What is the current toolchain identity?
- Which exact tool and resource versions are selected?
- Which capabilities are required for readiness?
- Which component produced and consumed each transported artifact?
- Which seams were exercised rather than merely configured?
- What useful work did each heavy smoke check perform?
- Which checks block readiness, and why?
- Is each result current for this environment and these identities?
- How was the overall readiness state derived?
- How can a particular check or the complete evaluation be reproduced?
- What is not established by this readiness result?
Machine-facing acceptance additionally requires:
- semantic headings and landmarks;
- stable concept IDs;
- explicit status text;
- discoverable concept relations;
- ordinary links for navigation;
- native controls for disclosure and operations; and
- a complete useful document without client-side JavaScript.
## 3.16 Open decisions
The following decisions remain provisional and should be resolved against the setup implementation rather than guessed in the UI:
1. **Evaluation record format** — whether setup emits one canonical JSON document, a directory of per-check records, or both.
2. **Compatibility dimensions** — which environment facts make evidence stale for each requirement.
3. **UCxn component boundaries** — whether distribution, adapter, rules, and corpus should appear as one compound component or several related components.
4. **Artifact retention** — which raw artifacts are retained permanently and which can be reproduced on demand.
5. **Execution boundary** — whether the initial UI may start checks directly or only present copyable commands.
6. **Evaluation comparison** — the smallest useful comparison between two version-bound evaluations.
These are implementation decisions within the Toolchain application. None changes the separation between Toolchain and Radiology Interpreter.
## 3.17 Infrastructure planning assumptions
The proposed Toolchain Service Infrastructure orchestration plan currently uses the following unapproved assumptions to make the UI work concrete:
1. A Go hub serves the Toolchain HTML, owns evaluation records, and invokes capability endpoints.
2. The first UI is server-rendered with Go templates, native HTML, and one small stylesheet rather than a separate single-page application.
3. A local Python Service hosts the Python-facing Components and owns the private `grewpy_backend` child process.
4. A local SWI-Prolog Service loads the generated RadLex bundle and exposes named ontology and transport operations.
5. Services expose versioned HTTP/JSON operations on loopback interfaces plus liveness, readiness, and identity documents.
6. A user-level process supervisor, provisionally systemd, owns service lifetimes; the Go hub reports availability but does not act as PID 1.
7. The UI begins read-only. A later ticket adds explicit forms to start named verification runs and optional server-sent progress events.
8. The browser never calls the bare services directly. It calls the Go hub, which preserves timeouts, evidence, artifact identity, and a single public contract.
These assumptions exist to support executable research. Evidence obtained during service experiments may refine or reject them through an explicit decision record.
---
# 4. Reference Appendices
## Appendix A. Initial component map
| Component | Kind | Identity basis | Principal demonstrated capability |
|---|---|---|---|
| Python | Tool/runtime | runtime version | execute Python verification programs |
| Stanza | Tool | package and model versions | produce dependency parses and valid CoNLL-U |
| PyTorch | Tool/runtime | package version and accelerator state | execute Stanza model inference |
| OCaml | Tool/runtime | compiler version | support Grew ecosystem runtime |
| opam | Tool/package manager | client and switch identity | resolve the OCaml tool environment |
| Grew | Tool | package version | load, query, and mutate dependency graphs |
| grewpy / backend | Tool/adapter | package versions | bridge Python checks to Grew |
| UCxn | Mixed distribution | pinned source revision and resource identities | adapt UD corpora and run official construction rules |
| MoCCA | Knowledge Resource | DB release and source revision | load and query a construction graph |
| FrameNet | Knowledge Resource | FrameNet release and local XML identity | query frames, FEs, lexical units, and relations |
| SWI-Prolog | Tool | runtime version | load transported facts and prove queries/tests |
| RadLex bundle | Knowledge Resource | source identity and generated-bundle digest | serve application-shaped ontology consumer queries |
This table is an initial decomposition, not a substitute for the version-bound identities in an Evaluation.
## Appendix B. Initial requirement families
The setup obligations can be presented under conceptual families while retaining their stable S-01 through S-10 identities:
```text
Environment identity
runtimes and package roots are explicit
Component operation
Stanza parses nontrivial input
Grew mutates graphs
MoCCA answers graph queries
FrameNet loads and indexes its relations
SWI-Prolog executes transport tests
RadLex serves consumer-shaped queries
Official-resource fidelity
UCxn official adapter and rules run against pinned upstream material
Interoperability
serialized artifacts survive each declared seam
assembled Text → Stanza → UCxn/Grew → Prolog path proves an exact assertion
Reproducibility
verification succeeds from installed local artifacts through the declared setup entry point
```
The UI should not invent a different source of truth for these requirements. It should consume or faithfully translate the setup plan's declared acceptance model.
## Appendix C. Source documents
This specification is governed by:
- [Debug Interface Design Philosophy](<./Debug Interface Design Philosophy _ Draft Specification.md>)
- [`setup/PLAN.md`](../../setup/PLAN.md)
- [`setup/ACCEPTANCE-MATRIX.md`](../../setup/ACCEPTANCE-MATRIX.md)
- [`setup/STATE.md`](../../setup/STATE.md)
The [Radiology Transcript Interpreter Debug UI specification](<./Radiology Transcript Interpreter _ Debug UI Design Specification.md>) was consulted to establish and preserve the application boundary. It is not the domain model for this application.
## Appendix D. Design provenance
The separation of Toolchain from Radiology Interpreter is a human-led architectural decision established during design discussion. The Toolchain concept model and this UI specification translate that decision into an independent application boundary, readiness semantics, evidence model, DOM contract, and initial implementation slice.
Operator manual
The working guide for starting, testing, observing, troubleshooting, and stopping the resident toolchain services.
# Toolchain Service Infrastructure
This directory implements the adopted infrastructure experiment in
`../research/toolchain-service-infrastructure/PLAN.md`.
It keeps the installed research tools resident behind local capability
services, routes them through a Go hub, and exposes their verification evidence
through the Toolchain Debug UI. It does not implement radiology interpretation
semantics.
## Operator interface
```sh
make -C infrastructure doctor
make -C infrastructure start
make -C infrastructure status
make -C infrastructure smoke-services
make -C infrastructure smoke-hub
make -C infrastructure smoke-assembly
make -C infrastructure test-ui
make -C infrastructure test-interpreter-ui
make -C infrastructure verify
make -C infrastructure stop
```
`start` links the three checked-in user units and starts them, but does not
enable them at login. All services bind only to loopback:
| Process boundary | Address | Responsibility |
|---|---|---|
| Go Toolchain hub | `http://127.0.0.1:8170` | caller API, evaluation records, and web UI |
| Python linguistics service | `http://127.0.0.1:8171` | Stanza, Grew/UCxn, MoCCA, and FrameNet |
| SWI-Prolog service | `http://127.0.0.1:8172` | CoNLL-U inspection and the resident RadLex bundle |
The public research host uses the same user units with lingering and login
enablement so they return after reboot. Its accepted installation and recovery
details are recorded in `FULL-TOOLCHAIN-DEPLOYMENT-REPORT.md`. The retired
artifact-only deployment remains available as an explicit rollback service.
The primary interpreter UI and supporting Toolchain UI are:
```text
http://127.0.0.1:8170/interpretations/new
http://127.0.0.1:8170/toolchains/rad-nlp-research
```
The interpreter UI is the UI-only first slice: it loads and resolves the
reviewed POC transcription to its immutable checked-in R0–R5 artifact. It does
not yet run edited or arbitrary text through a durable interpretation
operation. The interface states that boundary explicitly instead of presenting
an edited Draft as a completed interpretation. A dependency-free vanilla-JS
SPA layer performs Run, depth, focus, and history transitions in place; the
same server-rendered GET URLs bootstrap refreshes and deep links. The
interactive workflow intentionally has no parallel non-JavaScript fallback.
After Run, the Draft textarea is replaced by depth-specific visual
representations: source text, linguistic tokens, constructions, semantic
frames, ontology groundings, and validated structured findings. Object indexes
and raw JSON remain secondary inspection details.
## Configuration and evidence
`config/services.json` is the operational inventory. It fixes service IDs,
loopback addresses, user-unit names, limits, and the component/resource
identities required for hub readiness. `config/environment` is an optional,
untracked operator override; `config/environment.example` documents supported
non-secret values.
Runtime evidence is written beneath `infrastructure/var/evaluations/`, which is
not version controlled. Each completed evaluation has a read-only JSON record
and content-addressed artifacts. The UI and `/api/v1/evaluations/{id}` expose
the same durable truth; browser connection state is not authoritative.
## Operation and troubleshooting
Use `make -C infrastructure status` for unit and readiness state. Logs remain
in the user journal:
```sh
infrastructure/scripts/manage-services.sh logs
journalctl --user -u radnlp-linguistics.service -f
journalctl --user -u radnlp-prolog.service -f
journalctl --user -u radnlp-toolchain-hub.service -f
```
If the hub reports `not_ready`, inspect `/readyz` and `/v1/manifest` on the two
bare services. A component identity that differs from the checked-in inventory
is intentionally treated as stale rather than silently accepted. Rebuild and
restart only the Go boundary with:
```sh
make -C infrastructure build
systemctl --user restart radnlp-toolchain-hub.service
```
`make -C infrastructure stop` cleanly stops all three project units and the
Python-owned Grew child. The direct heavy smokes use separate ports 18171 and
18172, so they can validate clean resident instances independently.
Public project and scope overview
A concise guide to what this artifact-backed research demonstration does and does not claim.
# rad-nlp Public Research Demonstration
This site demonstrates how one reviewed, generated radiology transcription can
be represented through progressively enriched intermediate representations.
The interface lets a visitor run that exact example and move from preserved
source text through linguistic observations, constructions, discourse frames,
ontology grounding, and validated structured output.
The public host now runs the research toolchain behind the Go hub: Stanza,
Grew, UCxn, MoCCA, FrameNet, SWI-Prolog, and the compiled RadLex knowledge
base. The Toolchain UI reports their live identities and readiness, and the
allowlisted capability API routes execute those resident services.
The interpreter's R0-through-R5 visual example remains artifact-backed. It
reads the immutable checked-in proof-of-concept result; this release does not
yet turn edited or arbitrary transcription text into a new durable R0-through-
R5 interpretation. Live tool availability and the completed interpreter
workflow are separate boundaries.
The example and research inputs are generated transcriptions reviewed for this
demonstration. Historical source reports are not retained. The host contains
no patient data or application credentials; evaluation records are mutable
operational evidence generated by toolchain checks.
This is research software. Its output is not medical advice, is not clinically
validated, and must not be used for diagnosis, treatment, or patient care.