q / core /semantic.js
Humuhumu33's picture
Upload folder using huggingface_hub
3365e13 verified
Raw
History Blame Contribute Delete
5.74 kB
// core/semantic.js — the SEMANTIC SKIN (gap C2): every κ-object the substrate produces carries an
// open-semantic-web type, so humans, agents, and W3C validators all read it the same way. Closes the
// weakest audit axis (κ names objects, but few declared a W3C @type). Two W3C standards, both native:
// • JSON-LD / schema.org — WHAT a thing is (a skill is a schema:HowTo; a file is a schema:DigitalDocument)
// • PROV-O — HOW it came to be (the κ-chain becomes prov:wasRevisionOf links)
// Pure, dependency-free, browser+node. The result round-trips through any JSON-LD/RDF tool.
export const HOLO_CONTEXT = {
schema: "https://schema.org/",
prov: "http://www.w3.org/ns/prov#",
holo: "https://hologram.foundation/ns/",
"@vocab": "https://schema.org/",
};
// schema.org type for a substrate object kind (the canonical mapping, L2 — fixed at the ingest boundary)
const TYPE_FOR = {
skill: "HowTo", // a reusable procedure = schema:HowTo (steps + when-to-use)
file: "DigitalDocument",
app: "SoftwareApplication",
model: "SoftwareSourceCode",
conversation: "Conversation",
receipt: "CreativeWork", // a sealed work record: schema:CreativeWork that is also a prov:Entity
};
// wrap any object as a typed, content-addressed JSON-LD node. `kappa` is its did:holo (the @id —
// content IS the identity, Law L1). `prov` is the κ-chain → prov:wasRevisionOf links (PROV-O).
export function asLinkedData({ kind, kappa, props = {}, prov = [] }) {
const t = TYPE_FOR[kind] || "Thing";
const node = {
"@context": HOLO_CONTEXT,
"@id": kappa, // content-derived identity (no location — Law L1)
"@type": Array.isArray(t) ? t : ["schema:" + t, "prov:Entity"], // schema kind + PROV entity
...props,
};
if (prov.length >= 2) { // the version chain → PROV-O revision links
const cur = prov[prov.length - 1], parent = prov[prov.length - 2];
node["prov:wasRevisionOf"] = { "@id": parent.kappa };
node["holo:version"] = cur.v;
}
node["prov:wasDerivedFrom"] = prov.length ? prov.map((p) => ({ "@id": p.kappa })) : undefined;
return node;
}
// a skill → schema:HowTo (steps become schema:HowToStep), with its PROV-O revision chain.
export function skillAsHowTo({ name, description, instructions, kappa, prov = [] }) {
const steps = String(instructions || "").split("\n").map((s) => s.trim()).filter(Boolean)
.map((text, i) => ({ "@type": "schema:HowToStep", "schema:position": i + 1, "schema:text": text.replace(/^\d+[.)]\s*/, "") }));
return asLinkedData({ kind: "skill", kappa, prov, props: { "schema:name": name, "schema:description": description, "schema:step": steps } });
}
// extension → IANA media type (schema:encodingFormat). Small, common set; default text/plain.
const MEDIA = { html: "text/html", htm: "text/html", js: "text/javascript", mjs: "text/javascript", json: "application/json", jsonld: "application/ld+json", css: "text/css", md: "text/markdown", txt: "text/plain", py: "text/x-python", svg: "image/svg+xml", wasm: "application/wasm", gz: "application/gzip" };
const mediaOf = (name) => MEDIA[String(name).toLowerCase().split(".").pop()] || "text/plain";
// a workspace file → schema:DigitalDocument (name + media type + byte size), content-addressed (L1).
export function fileAsDocument({ path, kappa, bytes = 0, mediaType, prov = [] }) {
const name = String(path).split("/").filter(Boolean).pop() || String(path);
return asLinkedData({ kind: "file", kappa, prov, props: {
"schema:name": name, "schema:identifier": kappa,
"schema:encodingFormat": mediaType || mediaOf(name), "schema:contentSize": bytes } });
}
// a built app → schema:SoftwareApplication (a self-contained WebGPU/Web app object).
export function appAsSoftware({ name, kappa, bytes = 0, prov = [] }) {
return asLinkedData({ kind: "app", kappa, prov, props: {
"schema:name": String(name).replace(/\.html$/i, ""), "schema:identifier": kappa,
"schema:applicationCategory": "WebApplication", "schema:operatingSystem": "Any (WebGPU/Web)",
"schema:fileSize": bytes } });
}
// a loaded model → schema:SoftwareSourceCode (the κ-object that runs on the GPU).
export function modelAsSource({ name, kappa, family, params, format, prov = [] }) {
return asLinkedData({ kind: "model", kappa, prov, props: {
"schema:name": name, "schema:identifier": kappa, "schema:programmingLanguage": "WGSL/WebGPU",
"holo:family": family, "holo:parameters": params, "holo:format": format } });
}
// one dispatcher so any producer can type any κ-object: linkedDataFor("app", {...}) etc.
export function linkedDataFor(kind, props = {}) {
switch (kind) {
case "skill": return skillAsHowTo(props);
case "file": return fileAsDocument(props);
case "app": return appAsSoftware(props);
case "model": return modelAsSource(props);
default: return asLinkedData({ kind, kappa: props.kappa, prov: props.prov || [], props: props.props || props });
}
}
// VERIFY (the gate): an object is semantically valid iff it has @context, an @id (κ), and a @type
// carrying both a schema.org kind and PROV-O lineage. Returns { ok, types, hasId, hasContext }.
export function verifySemantic(node) {
const types = [].concat(node && node["@type"] || []);
const hasSchema = types.some((t) => /^schema:|^https:\/\/schema\.org\//.test(t));
const hasProv = types.some((t) => /^prov:/.test(t)) || !!node["prov:wasDerivedFrom"];
const hasId = typeof node?.["@id"] === "string" && node["@id"].startsWith("did:holo:");
const hasContext = !!node?.["@context"];
return { ok: hasSchema && hasId && hasContext, hasSchema, hasProv, hasId, hasContext, types };
}