DisclosureOS documentation · v2 Beta
Event and setting
Add sourced descriptions of a place, event and surrounding conditions to an observation.
An observation holds the source inventory and measured values. An event and setting document adds descriptions of what happened, where it happened and the surrounding conditions. Its technical name is observation_context. It points to one exact observation snapshot instead of copying the source inventory into a second record.
This guide continues Observation records. You will add the fictional location named in the same station log, connect the session to it, and test a broken place reference. You will then check those links against the saved observation bytes.
Requirements: Node.js 22 and the source-observation.json produced by the Observation guide. Run its script successfully before continuing. Install the published packages in that same project:
npm install --save-exact @disclosureos/records@2.0.0-beta.4 @disclosureos/schema@2.0.0-beta.4The context document version is 0.1.0. It identifies the document format and is separate from the npm package version.
1. Decide what belongs in context
The example station log says:
Meridian Basin is a fictional location.
The observation already holds the session time and identifies the log as station-log. We will add a place named Meridian Basin and an event that links the session to that place. We will not add coordinates: the log does not supply them.
An entity is one described event, object, place, platform, environment, time context or collection. Each entity has an ID and fields. A field holds a list of source-attributed assertions so different descriptions can coexist.
| Layer | In this example |
|---|---|
| Observation | The session time and the station-log source entry. |
| Context document | An exact reference to that observation, plus the event and place entities. |
| Field assertion | The reported place name, with the source and the person or document it is attributed to. |
| Claim history, when needed | A separate review of a description, with its reviewer, method and outcome. |
The context assertion records what the source supplies. It does not decide whether a reported characteristic is anomalous or which explanation is correct.
2. Build and save the context
Save this as setting.mjs beside source-observation.json. It reads and hashes the saved file's exact bytes, checks the observation, then creates the two context entities.
import { readFileSync, writeFileSync } from "node:fs";
import { createHash } from "node:crypto";
import {
parseExperimentalObservation,
parseObservationContext,
} from "@disclosureos/records/experimental/v2";
const observationBytes = readFileSync("source-observation.json");
const observation = JSON.parse(observationBytes.toString("utf8"));
const checked = parseExperimentalObservation(observation);
if (!checked.success)
throw new Error("Fix the observation before adding context.");
const sourced = (id, value) => [
{
id,
content: {
state: "known",
value,
provenance: {
sourceRef: "source:station-log",
attributedTo: "Synthetic field session log",
},
},
},
];
const context = {
kind: "observation_context",
schemaVersion: "0.1.0",
id: "docs-field-setting",
observationRef: {
documentId: observation.id,
schemaId: "urn:disclosureos:experimental:observation:0.1.0",
sha256: createHash("sha256").update(observationBytes).digest("hex"),
},
recordedAt: "2026-10-16T00:00:00Z",
recordedBy: "DisclosureOS documentation example",
entities: [
{
kind: "event",
id: "session",
fields: { placeIds: sourced("site", ["basin"]) },
},
{
kind: "place",
id: "basin",
fields: { name: sourced("name", "Meridian Basin") },
},
],
};
const result = parseObservationContext(context);
console.log(
JSON.stringify({ success: result.success, checks: result.checks }, null, 2),
);
if (!result.success) {
console.error(JSON.stringify(result.issues, null, 2));
process.exitCode = 1;
} else {
writeFileSync(
"source-context.json",
JSON.stringify(result.data, null, 2) + "\n",
);
console.log("Saved source-context.json");
}Run it:
node setting.mjsThe result is followed by Saved source-context.json:
{
"success": true,
"checks": {
"structural": "passed",
"semantic": "passed",
"profile": "not_checked",
"external": "not_checked"
}
}The parser checks the document shape and local relationships, including that placeIds resolves to a place entity. It has not opened the referenced observation or station log. The snapshot and source references remain in result.uncheckedRefs; we check the observation connection in step 4.
Notice the different identities:
observationRefidentifies the observation by document ID, schema ID and SHA-256 of the exact saved bytes. Reformatting the JSON changes that digest.sessionandbasinare entity IDs inside this context document.placeIdsuses the bare place ID, notsource:basin.siteandnameidentify individual assertions. Assertion IDs must be unique across the fields of their entity.source:station-logrefers to the source inventory in the referenced observation. It is not a URL.
known means that a value is supplied, not independently verified. recordedAt dates the context document; it is not the event time. We omit acquisitionRef because this example does not refer to instrument captures.
3. Try a broken place reference
Change sourced("site", ["basin"]) to sourced("site", ["missing-place"]), leaving the place entity unchanged. Run node setting.mjs again.
The structure still passes, but success becomes false and semantic becomes failed. The script exits with status 1 and prints:
[
{
"code": "REF.LOCAL_RESOLUTION",
"stage": "semantic",
"pointer": "/entities/0/fields/placeIds",
"message": "Place reference does not resolve."
}
]The pointer identifies the field containing the broken link. A failed run does not overwrite an existing source-context.json; use the exit status to decide whether the current run succeeded. Restore basin and rerun before continuing.
4. Check the observation connection
The published cross-document checker accepts a context-aware claim history. We can use an empty claim list to check the context and observation snapshots without inventing an assessment. Later, the same history can hold attributed claims about these descriptions.
Save this as check-setting.mjs. The map contains the original file bytes, keyed by their SHA-256. The checker fetches nothing.
import { readFileSync } from "node:fs";
import { createHash } from "node:crypto";
import { evaluateContextClaimHistory } from "@disclosureos/schema/experimental/v2";
const observationBytes = readFileSync("source-observation.json");
const contextBytes = readFileSync("source-context.json");
const observation = JSON.parse(observationBytes.toString("utf8"));
const context = JSON.parse(contextBytes.toString("utf8"));
const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
const history = {
kind: "claim_history",
schemaVersion: "0.2.0",
id: "docs-setting-check",
observation,
contextRefs: [
{
documentId: context.id,
schemaId: "urn:disclosureos:experimental:observation-context:0.1.0",
sha256: digest(contextBytes),
},
],
claims: [],
};
const documents = new Map([
[digest(observationBytes), observationBytes],
[digest(contextBytes), contextBytes],
]);
const result = await evaluateContextClaimHistory(history, { documents });
console.log(
JSON.stringify({ success: result.success, checks: result.checks }, null, 2),
);
if (!result.success) {
console.error(JSON.stringify(result.issues, null, 2));
process.exitCode = 1;
}Run node check-setting.mjs. You should see:
{
"success": true,
"checks": {
"structural": "passed",
"semantic": "passed",
"profile": "not_checked",
"external": "passed"
}
}Here, external: "passed" means the required context and observation snapshots were supplied and their connections checked. The checker verifies their digests, identities and declared contracts, then resolves the source references against the observation. It does not open the station log or certify its wording, authenticity or scientific meaning. Profile checks, source-artifact integrity, temporal normalization and sensor fusion remain not_checked.
If you change the observation file afterward, regenerate the context reference from the new bytes and rerun the checks. Missing or altered snapshots cannot pass against the old reference. Do not reuse an earlier successful result for changed input.
Choose an entity type
Use only the entities your material needs. The seven types are alternatives within the entities list, not seven required sections.
| Type | Use it for |
|---|---|
| Event | Event descriptions and connections to places and time. |
| Reported object | Reported shape, appearance, maneuvers, sound and contacts. This is a description, not an established object identity. |
| Place | Location names, positions, terrain, airspace and proximity. |
| Platform | Observer, station, aircraft or vessel context. |
| Environment | Weather, visibility, celestial conditions and links to ambient measurements. |
| Temporal | Calendar periods, ranges, relative dates and local clock declarations. |
| Collection | Capture references, retention and declared alignment or correlation. |
The field reference has direct entrances to each type, nested search and a separate document choice for context-aware claims.
Preserve uncertainty and disagreement
Fields hold assertion lists, so competing descriptions remain separate. approximate preserves a qualified value; unknown and redacted retain a reason; unmapped retains source wording that has not been mapped to a supported value. An absent field means it was not supplied. Zero and false are actual values, not substitutes for missing information.
An optional selections entry records which assertion a reviewer selected, the alternatives considered, method, time and rationale. It points to an assertion; it does not create another value or prove that account correct. Keep those selections distinct from claims that assess a description.
Calendar quarters and ranges must not become invented instants. Relative temporal anchors must resolve locally without cycles. A declared timezone does not automatically normalize a date or settle a daylight-saving ambiguity.
Connect measurements and captures
Keep quantities, units and uncertainty in the observation's measurements. An entity can link to a measurement ID through a defined role. For example, ambient_temperature belongs to an environment entity and accepts the documented temperature quantities and units. The checker does not guess quantities or convert units.
Add an exact acquisitionRef when collection descriptions cite acquisition IDs, and supply those acquisition bytes to the checker. Sharing a collection does not establish that channels are synchronized or have a common cause. Instrument capture and measurement links are covered in Bindings.
Add an attributed review
Use a context-aware claim history (0.2.0) when a reviewer assesses an entity or field. Its contextRefs declare the exact snapshots in scope. A context subject identifies that snapshot and a target { kind, id, field? }; supporting contextInputRefs can identify particular assertions by entity, field and assertion ID.
Use parseContextClaimHistory for the local parse and evaluateContextClaimHistory with the exact bytes for cross-document checks. parseExperimentalClaimHistory and the default claims schema export still describe the 0.1.0 history. Profile support is explicit; a profile accepting 0.1.0 does not automatically accept 0.2.0.
A changed context snapshot is a different subject. A review may cite a prior claim, but cannot supersede it as if it examined the same snapshot. A current claim is one that has not been superseded; it is not necessarily accepted or confirmed. Continue with Claims for the review model.
For a larger runnable exercise, download the context review example, extract it and run:
cd context
npm install --ignore-scripts
npm startThe download and walkthrough both use the published 2.0.0-beta.4 packages. This separate synthetic control demonstrates conflicting triangle/oval descriptions, an ambient measurement and independent optical/radio captures. It uses its own source files and timestamps, not the station-log snapshot built above. The runner supplies exact local snapshot bytes; a passing result does not establish a common source for the captures. None of these examples is ELDÆON data.
Continue exploring
- Event and setting fields: search the complete context and context-aware claim structures, including exact schema exports.
- Places and history in the showcase: inspect the full fictional case's positions and chronology. This guide retains only its station-log location name.
- Witnesses and accounts: add detailed accounts and the circumstances in which they were recorded.
The schema exports are @disclosureos/records/experimental/v2/context/schema/0.1.0 and @disclosureos/records/experimental/v2/claims/schema/0.2.0. Their URNs identify contracts; they are not downloadable HTTP endpoints.