Keep one reading of a source and render from it
Validate a hand-written semantic record against its source, watch three direct renderings drift apart, and walk every element back to the words it came from.
If a source can be rendered many ways, each rendering re-reads it. The chapter’s proposal is to keep one structured reading and draw the renderings from that, so that what the reader sees cannot drift apart silently. The program below takes a constructed payments policy, three constructed direct renderings, and one hand-written record, and shows what each approach costs.
No model is called. The record is written by hand, and the three direct renderings are built by hand to make the drift visible; they are not model output.
Run it
git clone https://github.com/ernanhughes/project-language.git
cd project-language
git checkout 329660f679a5a87831f91fe1430c20ac9360dda8
npm ci
npm run example:ch07Node 22.19 or later; the project was developed on Node 25.8. The record module
itself imports nothing, so core/record/src/index.ts can be read on its own.
Expected outcome
Three renderings written straight from the prose carry between one and two of the policy’s three exceptions. The renderings drawn from the record carry all three — by construction, because they are the same reading:
...
Monday: diagram carries 2 of 3 exceptions; missing: final
Wednesday: timeline carries 1 of 3 exceptions; missing: partition, idempotent
Friday: table carries 1 of 3 exceptions; missing: partition, final
Each is plausible alone. Together they describe three slightly different systems: 3 of 3 exceptions are carried by some and not by others.The traceability check reports no problems for the hand-written record, and every element can be located in the source by character offset:
...
9 claims, 3 relations with direction, 0 qualifiers; each cites the source verbatim.
traceability problems: []
...
partition chars 143-245 "If the failure is a network partition, the payment is not retried and is sent to the dead-letter queue"
x3 chars 330-368 "unless the partition exception applies"
final chars 305-368 "The third retry is final unless the partition exception applies"And the record is not the source of truth. The source asserts a causal link and cites nothing for it; the record keeps the claim and records that nothing backs it, rather than correcting it:
...
source asserts: "Retries cause queue backlogs during outages."
record keeps: standing=stated, evidence=none_citedThe check that makes it a record
The traceability check is the whole mechanism. It holds for any record, not only the fixture, and it is the reason a record is a reading rather than a paraphrase. This is the check, in full:
export function validateRecord(source: Source, record: DocumentRecord): { problem: RecordProblem; id: string }[] {
const out: { problem: RecordProblem; id: string }[] = [];
const ids = new Set<string>();
const claimIds = new Set(record.claims.map((c) => c.id));
const targetIds = new Set([...claimIds, ...record.relations.map((r) => r.id)]);
const add = (problem: RecordProblem, id: string) => out.push({ problem, id });
if (record.source_id !== source.id) add("SOURCE_MISMATCH", record.source_id);
const kinds: [string, readonly { id: string; passage: string }[], ReadonlySet<string>][] = [
["claim", record.claims, ALLOWED_FIELDS.claim],
["relation", record.relations, ALLOWED_FIELDS.relation],
["qualifier", record.qualifiers, ALLOWED_FIELDS.qualifier],
];
for (const [, entries, allowed] of kinds) {
for (const entry of entries) {
if (ids.has(entry.id)) add("DUPLICATE_ID", entry.id);
ids.add(entry.id);
if (typeof entry.passage !== "string" || entry.passage.trim() === "") add("EMPTY_PASSAGE", entry.id);
else if (!source.text.includes(entry.passage)) add("PASSAGE_NOT_IN_SOURCE", entry.id);
for (const key of Object.keys(entry)) if (!allowed.has(key)) add("UNKNOWN_FIELD", entry.id + "." + key);
}
}
for (const r of record.relations) {
if (!claimIds.has(r.from) || !claimIds.has(r.to)) add("UNKNOWN_CLAIM", r.id);
if (r.from === r.to) add("SELF_RELATION", r.id);
}
for (const q of record.qualifiers) {
if (!targetIds.has(q.applies_to)) add("UNKNOWN_CLAIM", q.id);
const passage = q.passage.toLowerCase();
if (!passage.includes(q.condition.toLowerCase())) add("CONDITION_NOT_IN_PASSAGE", q.id);
if (q.status === "unknown" && (!q.gap || !passage.includes(q.gap.toLowerCase()))) add("GAP_WITHOUT_PASSAGE", q.id);
}
for (const c of record.claims) if (c.kind === "conclusion" && c.standing === "disputed" && !c.holder) add("DISPUTE_WITHOUT_HOLDER", c.id);
return out;
}The same module answers “where did this come from,” which is what makes a rendering traceable rather than merely tidy:
export function locate(record: DocumentRecord, source: Source, id: string): Located | undefined {
const entry = [...record.claims, ...record.relations, ...record.qualifiers].find((e) => e.id === id);
if (!entry) return undefined;
const start = source.text.indexOf(entry.passage);
return start < 0 ? undefined : { id, passage: entry.passage, start, end: start + entry.passage.length };
}Mechanism and limitations
Documented: the record’s shape — claims, directed relations, qualifiers, each
citing a passage — and the rule that a reading can be wrong, are in the module’s
own header comment and in core/record/src/index.ts. The rule that the record
stores what the source said rather than a corrected fact is the standing and
evidenceStatus pair.
Observed: the run above. validateRecord returned [] for the hand-written
record; the three direct renderings carried 2, 1 and 1 of the 3 exceptions; the
record-drawn renderings carried 3, 3 and 3; and the record kept
evidence=none_cited for the causal claim the source does not support.
Not shown. The chapter’s bet is that renderings made through a record agree more, contradict less and trace back further than renderings made directly. The “direct” renderings here are constructed, and the agreement check is phrase presence, so agreement is true by construction. The bet is untested by this program. Whether a model can build a record that passes the traceability check is also untested: this one is written by hand. Nothing here measures a reader, and the record’s own costs — a wrong record, omitted information, over-specified vague prose, false authority — are not exercised.
The traceback is a repeated quotation resolving to its first occurrence, nothing checks that a label means what its passage means, and there is no concepts field, extraction or revision log.
Understand this example
Copy this prompt into your AI tool. No code runs here.
Apply this example
Copy this prompt into your AI tool. No code runs here.