Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 32 additions & 30 deletions src/core/weave/mesh_support_pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,11 @@ function planInitialMeshSupportResourcePageWeave(input: {
const versionedInventory = versionedSupportResources.find((support) =>
support.path === "_mesh/_inventory"
);
const updatedMeshMetadataTurtle = versionedInventory === undefined
const updatedMeshMetadataTurtle = versionedSupportResources.length === 0
? input.currentMeshMetadataTurtle
: renderInitialMeshMetadataWithMeshInventoryProgression(
: renderInitialMeshMetadataWithSupportProgression(
input.currentMeshMetadataTurtle,
versionedInventory,
versionedSupportResources,
);

return {
Expand All @@ -457,7 +457,7 @@ function planInitialMeshSupportResourcePageWeave(input: {
}]),
],
updatedFiles: [
...(versionedInventory === undefined ? [] : [{
...(versionedSupportResources.length === 0 ? [] : [{
path: "_mesh/_meta/meta.ttl",
contents: updatedMeshMetadataTurtle,
}]),
Expand All @@ -469,41 +469,45 @@ function planInitialMeshSupportResourcePageWeave(input: {
};
}

function renderInitialMeshMetadataWithMeshInventoryProgression(
function renderInitialMeshMetadataWithSupportProgression(
currentMeshMetadataTurtle: string,
versionedInventory: MeshSupportResource,
versionedSupportResources: readonly MeshSupportResource[],
): string {
const metadataWithPrefixes = ensureXsdPrefix(currentMeshMetadataTurtle);
let blocks = splitTurtleBlocks(metadataWithPrefixes);
blocks = upsertSubjectBlockAfter(
blocks,
"_mesh",
"_mesh/_inventory",
renderInitialMeshInventoryMetaProgressionBlock(versionedInventory),
);
blocks = upsertSubjectBlockAfter(
blocks,
"_mesh/_inventory",
versionedInventory.historyPath!,
renderInitialMeshInventoryHistoryMetaProgressionBlock(versionedInventory),
);
let anchorPath = "_mesh";
for (const support of versionedSupportResources) {
blocks = upsertSubjectBlockAfter(
blocks,
anchorPath,
support.path,
renderInitialMeshSupportMetaProgressionBlock(support),
);
blocks = upsertSubjectBlockAfter(
blocks,
support.path,
support.historyPath!,
renderInitialMeshSupportHistoryMetaProgressionBlock(support),
);
anchorPath = support.historyPath!;
}

return `${blocks.join("\n\n")}\n`;
}

function renderInitialMeshInventoryMetaProgressionBlock(
versionedInventory: MeshSupportResource,
function renderInitialMeshSupportMetaProgressionBlock(
support: MeshSupportResource,
): string {
return `<_mesh/_inventory> a sflo:MeshInventory, sflo:DigitalArtifact, sflo:RdfDocument ;
sflo:currentArtifactHistory <${versionedInventory.historyPath!}> ;
return `<${support.path}>
sflo:currentArtifactHistory <${support.historyPath!}> ;
sflo:nextHistoryOrdinal "2"^^xsd:nonNegativeInteger .`;
}

function renderInitialMeshInventoryHistoryMetaProgressionBlock(
versionedInventory: MeshSupportResource,
function renderInitialMeshSupportHistoryMetaProgressionBlock(
support: MeshSupportResource,
): string {
return `<${versionedInventory.historyPath!}> a sflo:ArtifactHistory ;
sflo:latestHistoricalState <${versionedInventory.statePath!}> ;
return `<${support.historyPath!}>
sflo:latestHistoricalState <${support.statePath!}> ;
sflo:nextStateOrdinal "2"^^xsd:nonNegativeInteger .`;
}

Expand Down Expand Up @@ -720,7 +724,7 @@ function appendInitialSupportHistoryFactsToBlock(
block: string,
historyPath: string,
): string {
if (block.includes("sflo:currentArtifactHistory")) {
if (block.includes("sflo:hasArtifactHistory")) {
return block;
}
if (!block.endsWith(" .")) {
Expand All @@ -730,7 +734,7 @@ function appendInitialSupportHistoryFactsToBlock(
}
return `${
block.slice(0, -2)
} ;\n sflo:hasArtifactHistory <${historyPath}> ;\n sflo:currentArtifactHistory <${historyPath}> ;\n sflo:nextHistoryOrdinal "2"^^xsd:nonNegativeInteger .`;
} ;\n sflo:hasArtifactHistory <${historyPath}> .`;
}

function renderInitialSupportHistoryBlock(
Expand All @@ -740,8 +744,6 @@ function renderInitialSupportHistoryBlock(
return `<${historyPath}> a sflo:ArtifactHistory ;
sflo:historyOrdinal "1"^^xsd:nonNegativeInteger ;
sflo:hasHistoricalState <${statePath}> ;
sflo:latestHistoricalState <${statePath}> ;
sflo:nextStateOrdinal "2"^^xsd:nonNegativeInteger ;
sflo:hasResourcePage <${historyPath}/index.html> .`;
}

Expand Down
116 changes: 115 additions & 1 deletion src/core/weave/mesh_support_pages_test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { assert, assertEquals, assertThrows } from "@std/assert";
import {
assert,
assertEquals,
assertFalse,
assertStringIncludes,
assertThrows,
} from "@std/assert";
import { compareRdfContent } from "../../../dependencies/github.com/spectacular-voyage/accord/src/checker/compare_rdf.ts";
import { planMeshSupportResourcePages } from "./mesh_support_pages.ts";
import { WeaveInputError } from "./errors.ts";
Expand Down Expand Up @@ -51,6 +57,77 @@ Deno.test("mesh-support page-only append rejects a missing support subject", ()
);
});

Deno.test("initial mesh-support history keeps mutable progression in MeshMetadata only", () => {
const plan = planMeshSupportResourcePages({
meshBase,
currentMeshInventoryTurtle: initialSupportInventoryTurtle(),
currentMeshMetadataTurtle: initialMeshMetadataTurtle(),
currentMeshConfigTurtle: "# current config bytes\n",
supportHistoryPolicies: {
meshMetadata: "versioned",
meshInventory: "versioned",
config: "versioned",
},
});
const updatedInventory =
plan.updatedFiles.find((file) =>
file.path === "_mesh/_inventory/inventory.ttl"
)?.contents ?? "";
const updatedMetadata =
plan.updatedFiles.find((file) => file.path === "_mesh/_meta/meta.ttl")
?.contents ?? "";

for (
const mutablePredicate of [
"sflo:currentArtifactHistory",
"sflo:nextHistoryOrdinal",
"sflo:latestHistoricalState",
"sflo:nextStateOrdinal",
]
) {
assertFalse(
updatedInventory.includes(mutablePredicate),
"MeshInventory retained mutable predicate " + mutablePredicate,
);
}
for (
const supportPath of [
"_mesh/_meta",
"_mesh/_inventory",
"_mesh/_config",
]
) {
const historyPath = supportPath + "/_history001";
assertStringIncludes(
updatedInventory,
"sflo:hasArtifactHistory <" + historyPath + ">",
);
assertStringIncludes(
updatedInventory,
"sflo:hasHistoricalState <" + historyPath + "/_s0001>",
);
assertStringIncludes(updatedMetadata, "<" + supportPath + ">");
assertStringIncludes(
updatedMetadata,
"sflo:currentArtifactHistory <" + historyPath + ">",
);
assertStringIncludes(
updatedMetadata,
"<" + historyPath + ">",
);
assertStringIncludes(
updatedMetadata,
"sflo:latestHistoricalState <" + historyPath + "/_s0001>",
);
}
assertEquals(
plan.createdFiles.find((file) =>
file.path === "_mesh/_meta/_history001/_s0001/ttl/meta.ttl"
)?.contents,
updatedMetadata,
);
});

function planCurrentOnlyMeshSupportPages(
currentMeshInventoryTurtle: string,
) {
Expand Down Expand Up @@ -110,6 +187,43 @@ function requestedSupportPageFactsTurtle(): string {
`;
}

function initialSupportInventoryTurtle(): string {
return [
"@base <" + meshBase + "> .",
"@prefix sflo: <https://semantic-flow.github.io/sflo/ontology/> .",
"",
"<_mesh> a sflo:SemanticMesh .",
"",
"<_mesh/_meta> a sflo:MeshMetadata, sflo:DigitalArtifact, sflo:RdfDocument ;",
" sflo:hasWorkingLocatedFile <_mesh/_meta/meta.ttl> .",
"",
"<_mesh/_inventory> a sflo:MeshInventory, sflo:DigitalArtifact, sflo:RdfDocument ;",
" sflo:hasWorkingLocatedFile <_mesh/_inventory/inventory.ttl> .",
"",
"<_mesh/_config> a sflo:DigitalArtifact, sflo:RdfDocument ;",
" sflo:hasWorkingLocatedFile <_mesh/_config/config.ttl> .",
"",
"<_mesh/_meta/meta.ttl> a sflo:LocatedFile, sflo:RdfDocument .",
"",
"<_mesh/_inventory/inventory.ttl> a sflo:LocatedFile, sflo:RdfDocument .",
"",
"<_mesh/_config/config.ttl> a sflo:LocatedFile, sflo:RdfDocument .",
"",
].join("\n");
}

function initialMeshMetadataTurtle(): string {
return [
"@base <" + meshBase + "> .",
"@prefix sflo: <https://semantic-flow.github.io/sflo/ontology/> .",
"",
"<_mesh> a sflo:SemanticMesh .",
"",
"<_mesh/_meta> a sflo:MeshMetadata, sflo:DigitalArtifact, sflo:RdfDocument .",
"",
].join("\n");
}

function encode(value: string): Uint8Array {
return new TextEncoder().encode(value);
}
38 changes: 33 additions & 5 deletions src/core/weave/weave_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,22 @@ Deno.test("planMeshSupportResourcePages adds current support ResourcePages inclu
);
assertEquals(
plan.updatedFiles.map((file) => file.path),
["_mesh/_inventory/inventory.ttl"],
["_mesh/_meta/meta.ttl", "_mesh/_inventory/inventory.ttl"],
);
const inventory = plan.updatedFiles[0]?.contents ?? "";
const inventory =
plan.updatedFiles.find((file) =>
file.path === "_mesh/_inventory/inventory.ttl"
)?.contents ?? "";
const metadata =
plan.updatedFiles.find((file) => file.path === "_mesh/_meta/meta.ttl")
?.contents ?? "";
assertStringIncludes(
inventory,
"sfcfg:hasConfig <_mesh/_config> ;\n sflo:hasResourcePage <_mesh/index.html> .",
);
assertStringIncludes(
inventory,
"sflo:hasWorkingLocatedFile <_mesh/_config/config.ttl> ;\n sflo:hasResourcePage <_mesh/_config/index.html> ;\n sflo:hasArtifactHistory <_mesh/_config/_history001> ;",
"sflo:hasWorkingLocatedFile <_mesh/_config/config.ttl> ;\n sflo:hasResourcePage <_mesh/_config/index.html> ;\n sflo:hasArtifactHistory <_mesh/_config/_history001> .",
);
assertStringIncludes(
inventory,
Expand All @@ -245,6 +251,19 @@ Deno.test("planMeshSupportResourcePages adds current support ResourcePages inclu
"sflo:currentArtifactHistory <_mesh/_meta/_history001>",
),
);
assertFalse(
inventory.includes(
"sflo:currentArtifactHistory <_mesh/_config/_history001>",
),
);
assertStringIncludes(
metadata,
"sflo:currentArtifactHistory <_mesh/_config/_history001> ;",
);
assertStringIncludes(
metadata,
"sflo:latestHistoricalState <_mesh/_config/_history001/_s0001> ;",
);
assertStringIncludes(
inventory,
"<_mesh/_config/_history001/_s0001/ttl> a sflo:ArtifactManifestation, sflo:RdfDocument ;",
Expand Down Expand Up @@ -321,7 +340,10 @@ Deno.test("planMeshSupportResourcePages keeps support ResourcePage facts when pa
},
});

const inventory = plan.updatedFiles[0]?.contents ?? "";
const inventory =
plan.updatedFiles.find((file) =>
file.path === "_mesh/_inventory/inventory.ttl"
)?.contents ?? "";
assertStringIncludes(
inventory,
"sflo:hasResourcePage <_mesh/_config/index.html>",
Expand All @@ -340,7 +362,7 @@ Deno.test("planMeshSupportResourcePages keeps support ResourcePage facts when pa
);
assertStringIncludes(
inventory,
"sflo:hasArtifactHistory <_mesh/_config/_history001> ;",
"sflo:hasArtifactHistory <_mesh/_config/_history001> .",
);
assertStringIncludes(
inventory,
Expand Down Expand Up @@ -4215,6 +4237,12 @@ Deno.test("planWeave renders an extracted term from a nested source without a ro
const input = await createExtractedBobWeaveInput();
input.currentMeshInventoryTurtle = input.currentMeshInventoryTurtle
.replace(" sflo:hasKnop <alice/_knop> ;\n", "")
.replace(
`<_mesh> sflo:hasKnop <alice/_knop> .

`,
"",
)
.replace(
`<alice/_knop> a sflo:Knop ;
sflo:hasWorkingKnopInventoryFile <alice/_knop/_inventory/inventory.ttl> ;
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/weave/page_model_assembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ export async function visitResourcePageModels(
() =>
collectHistoryGroupsByResourcePath(
meshState.meshBase,
meshState.currentMeshInventoryTurtle,
"Could not parse the current MeshInventory while collecting ResourcePage histories.",
`${meshState.currentMeshInventoryTurtle}\n${meshState.currentMeshMetadataTurtle}`,
"Could not parse the current MeshInventory and MeshMetadata while collecting ResourcePage histories.",
),
);
const meshInventoryPagePaths = await timeOptional(
Expand Down
8 changes: 7 additions & 1 deletion src/runtime/weave/raw_source_panels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,17 @@ export async function collectMeshSupportRawSourcePanels(
string,
readonly ResourcePageRawSourcePanelModel[]
>();
const quads = parseInventoryQuads(
const inventoryQuads = parseInventoryQuads(
meshState.meshBase,
meshState.currentMeshInventoryTurtle,
"Could not parse the current MeshInventory while collecting mesh support source panels.",
);
const metadataQuads = parseInventoryQuads(
meshState.meshBase,
meshState.currentMeshMetadataTurtle,
"Could not parse the current MeshMetadata while collecting mesh support source panels.",
);
const quads = [...inventoryQuads, ...metadataQuads];

if (
!(await addLatestHistoricalRawSourcePanelForCurrentArtifact(
Expand Down
Loading