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
2 changes: 1 addition & 1 deletion documentation/notes/wd.codebase-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Core owns portable Semantic Flow behavior: request/result types, RDF/Turtle help
- `src/core/weave` owns shared weave/version/generate contracts and planner helpers.
- `src/core/weave/inventory_append_planner.ts` prepares current inventory bytes and parsed default-graph quads as one opaque value, plans append/no-op/conflict outcomes, and renders planner-approved append facts through one shared compact renderer. The prepared current bytes remain the exact output prefix; a self-contained suffix-only proof checks rendered facts against `plan.missing`, avoiding a second parse of carried blank nodes. `knop.create` MeshInventory growth, FoundingReferentData settlement, current-only ReferenceCatalog and PageDefinition weave, current-shape extract and integrate, import source-registry insertion, first `knop add-reference` catalog registration, extracted-term versioned MeshInventory growth, and shared current-only payload-like page claims use the planner.
- `src/core/knop/add_reference.ts` retains its unwoven/current-only/versioned shape validation and known support-family consistency checks, but treats the shape renderer only as the requested ReferenceCatalog fact set. The original KnopInventory is the append planner's prepared input and exact output prefix, so unknown facts, comments, prefixes, and carried blank nodes survive; single-valued conflicts refuse before the runtime stages writes.
- `src/core/weave/mesh_inventory_renderers.ts` builds only the term, Knop, page, membership, and optional history/state facts owned by each migrated path, then appends them against the original MeshInventory. Homogeneous extracted batches, versioned sequential extracted weave, and the shared current-only first-payload/extracted helper preserve carried bytes and graph; current-only semantic no-ops return exact input bytes and create no history progression.
- `src/core/weave/mesh_inventory_renderers.ts` builds only the term, Knop, page, membership, and optional history/state facts owned by each migrated path, then appends them against the original MeshInventory. Versioned first-Knop weave, homogeneous extracted batches, versioned sequential extracted weave, and the shared current-only first-payload/extracted helper preserve carried bytes and graph. First-Knop weave rejects legacy inventory-owned mutable progression before planning instead of silently deleting or retaining it; current-only semantic no-ops return exact input bytes and create no history progression.
- `src/core/weave/mesh_support_pages.ts` keeps initial support-history construction separate. Initial versioned support history writes only settled artifact/history/state/manifestation membership into MeshInventory and writes current/latest/next progression for every versioned mesh-owned support artifact into MeshMetadata. Its no-initial-history page-only arm prepares the carried MeshInventory and appends only named support-page claims/types. Runtime ResourcePage history/raw-source assembly combines inventory structure with metadata progression. Exact page-claim duplicates produce no inventory update; comments, repeated blocks, opaque facts, trailing bytes, and carried blank nodes remain untouched prefix data.
- `src/core/weave/knop_inventory_renderers.ts` uses the same append path for current-only ReferenceCatalog and ResourcePageDefinition page claims. PageDefinition working-file validation is RDF-semantic rather than substring/block based, so unrelated mentions cannot hide a conflicting locator; exact duplicates return the original KnopInventory bytes.
- `src/core/extract/extract.ts` keeps its legacy-carried-shape renderer separate, but normal current-shape MeshInventory registration prepares and preserves the original bytes before appending only `_mesh` membership, Knop type/working-inventory, and inventory-file facts. Carried source-locator blank nodes remain prefix data and are not part of the named-node-only append request.
Expand Down
1 change: 1 addition & 0 deletions documentation/notes/wd.todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Groomed on 2026-05-27 from all `wa.task.*` notes in the Weave archive. Updated a

- [ ] Keep Stagecraft's persisted roleplaying-data use case in view when prioritizing runtime work: prefer slices that improve stable identifiers, exact state citation, append-onlyish histories, source provenance, and generated inspection pages for ordinary application data.- [ ] Remove the remaining first-payload planner blockers from [[wa.task.2026.2026-05-04-refactor-planFirstPayloadWeave]]. Multi-pending first-payload weave shipped in `v0.7.0` (PR #33), extracted-term sets joined the batch path post-regroom (PR #41), and condition-specific diagnostics landed (PR #42). Still open: current-mode extracted-term weave, and the SFLO/URPX docs pass to drop the old failure-mode warnings.
- [ ] Implement append-onlyish inventory writes through [[wa.plan.2026.2026-05-17-append-onlyish-inventory]]: normal inventory operations append new settled facts, no-op existing facts, and fail closed on conflicts; current/latest/next progression belongs in metadata or explicit repair/regeneration/retraction modes. `planInventoryAppend` now has consistency-by-construction prepared current input and one exactness-checked shared append renderer; current-only ReferenceCatalog and PageDefinition, first/later `knop.create`, FoundingReferentData, import source-registry insertion, first `knop add-reference` catalog registration, extracted/current-only MeshInventory weave growth, current-shape extract/integrate, and mesh-support page-only growth use it, while ResourcePage policy deletion is fixed. Mesh-support progression producers and affected fixture tails are corrected. Remaining in sequence: first-Knop append, other versioned/KnopInventory writers, then fixture/docs closure.
- [ ] In the next Weave release notes, call out the first-Knop MeshInventory output change from [[wa.task.2026.2026-08-31_1111-versioned-first-knop-mesh-inventory-append]]: carried bytes/facts now survive as the exact prefix, stale inventory-owned progression refuses pending explicit repair, and the affected live fixture refs were regenerated.
- [ ] Harden the shared append renderer against an internally mismatched prepared-inventory/plan pair, even though current production callers construct and pass the pair together and the final G1 review found no public reachability. Keep this separate from FoundingReferentData unless that work touches the renderer.
- [ ] Stop reusing one stateful N3 Parser across multiple planned Turtle files in import, integrate, version execution, and payload update validators; instantiate per document so `@base`/`@prefix` state cannot leak between files. Found by [[wa.review.2026-08-22_2303-stagecraft-phase1-g1-claude]], outside G1.
- [ ] Replace FoundingReferentData history progression's compact-`sflo:` regex rewrite with the shared subject-block/progression machinery or an equivalently representation-independent path, preserving fail-closed diagnostics for foreign-but-equivalent inventory serialization. Accepted as a non-landing G2 residual in [[wa.review.2026-08-23_0939-stagecraft-phase2-final-claude]].
Expand Down
311 changes: 79 additions & 232 deletions src/core/weave/mesh_inventory_renderers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { WeaveInputError } from "./errors.ts";
import {
planInventoryAppend,
prepareCurrentInventory,
type PreparedCurrentInventory,
renderInventoryAppendPlan,
} from "./inventory_append_planner.ts";
import type { MeshInventoryProgression } from "./progression_models.ts";
Expand All @@ -30,6 +31,12 @@ import {
} from "./turtle_blocks.ts";

const SFLO_HAS_KNOP_IRI = `${SFLO_NAMESPACE}hasKnop`;
const FIRST_KNOP_LEGACY_INVENTORY_PROGRESSION_PREDICATES = new Set([
`${SFLO_NAMESPACE}currentArtifactHistory`,
`${SFLO_NAMESPACE}nextHistoryOrdinal`,
`${SFLO_NAMESPACE}latestHistoricalState`,
`${SFLO_NAMESPACE}nextStateOrdinal`,
]);
const BATCHED_EXTRACTED_SINGLE_VALUED_PREDICATES = [
`${SFLO_NAMESPACE}currentArtifactHistory`,
`${SFLO_NAMESPACE}hasWorkingKnopInventoryFile`,
Expand All @@ -48,120 +55,68 @@ export function renderFirstKnopWovenMeshInventoryTurtle(
designatorPath: string,
meshInventoryProgression: MeshInventoryProgression,
): string {
const knopPath = toKnopPath(designatorPath);
const designatorPagePath = toDesignatorResourcePagePath(designatorPath);
const historyPath = meshInventoryProgression.historyPath;
const latestManifestationPath =
meshInventoryProgression.latestManifestationPath;
const nextStatePath = meshInventoryProgression.nextStatePath;
const nextStateOrdinal = meshInventoryProgression.nextStateOrdinal;
const nextManifestationPath = `${nextStatePath}/ttl`;
const initialBlocks = normalizeMeshInventoryHeader(
splitTurtleBlocks(currentMeshInventoryTurtle),
const preparedCurrentInventory = prepareCurrentInventory({
baseIri: meshBase,
currentInventoryTurtle: currentMeshInventoryTurtle,
currentInventoryLabel:
`current MeshInventory for first-Knop weave ${designatorPath}`,
});
assertNoLegacyFirstKnopInventoryProgression(
preparedCurrentInventory,
designatorPath,
);
if (
findSubjectBlockIndex(initialBlocks, "_mesh") === -1 ||
findSubjectBlockIndex(
initialBlocks,
latestManifestationPath,
) === -1 ||
findSubjectBlockIndex(initialBlocks, "_mesh/index.html") === -1
) {
return renderLegacyFirstKnopWovenMeshInventoryTurtle(
meshBase,
designatorPath,
const plan = planInventoryAppend({
preparedCurrentInventory,
requestedSettledFactsTurtle:
renderFirstKnopMeshInventoryRequestedFactsTurtle(
meshBase,
designatorPath,
meshInventoryProgression,
),
singleValuedSettledPredicates: BATCHED_EXTRACTED_SINGLE_VALUED_PREDICATES,
currentInventoryLabel:
`current MeshInventory for first-Knop weave ${designatorPath}`,
requestedFactsLabel:
`versioned first-Knop MeshInventory facts for ${designatorPath}`,
});
if (plan.kind === "conflict") {
throw new WeaveInputError(
`Could not append versioned first-Knop MeshInventory facts for ${designatorPath}: ${
plan.conflicts.map((conflict) => conflict.message).join(" ")
}`,
);
}
let blocks = initialBlocks;
const knopPaths = resolveMeshRootKnopPaths(
meshBase,
currentMeshInventoryTurtle,
);

if (!knopPaths.includes(knopPath)) {
knopPaths.push(knopPath);
}
return renderInventoryAppendPlan({
preparedCurrentInventory,
plan,
outputLabel:
`versioned first-Knop MeshInventory append for ${designatorPath}`,
});
}

blocks = replaceSubjectBlock(
blocks,
"_mesh",
renderMeshRootBlock(meshBase, knopPaths),
);
blocks = replaceSubjectBlock(
blocks,
"_mesh/_inventory",
renderMeshInventoryArtifactBlock(historyPath),
);
blocks = upsertSubjectBlockAfter(
blocks,
"_mesh",
designatorPath,
renderMeshIdentifierBlock(designatorPath),
);
blocks = replaceSubjectBlock(
blocks,
knopPath,
renderMeshKnopBlockWithResourcePage(knopPath),
);
blocks = replaceSubjectBlock(
blocks,
historyPath,
renderMeshInventoryHistoryBlock(
historyPath,
nextStateOrdinal,
nextStatePath,
),
);
blocks = upsertSubjectBlockAfter(
blocks,
latestManifestationPath,
nextStatePath,
renderMeshInventoryStateBlock(
nextStatePath,
nextStateOrdinal,
meshInventoryProgression.latestStatePath,
),
);
blocks = upsertSubjectBlockAfter(
blocks,
nextStatePath,
nextManifestationPath,
renderMeshInventoryStateManifestationBlock(nextStatePath),
);
blocks = upsertSubjectBlockAfter(
blocks,
`${latestManifestationPath}/inventory.ttl`,
`${nextManifestationPath}/inventory.ttl`,
renderLocatedFileBlock(`${nextManifestationPath}/inventory.ttl`),
);
blocks = upsertSubjectBlockAfter(
blocks,
"_mesh/index.html",
designatorPagePath,
renderResourcePageLocatedFileBlock(designatorPagePath),
);
blocks = upsertSubjectBlockAfter(
blocks,
designatorPagePath,
`${knopPath}/index.html`,
renderResourcePageLocatedFileBlock(`${knopPath}/index.html`),
);
blocks = upsertSubjectBlockAfter(
blocks,
`${latestManifestationPath}/index.html`,
`${nextStatePath}/index.html`,
renderResourcePageLocatedFileBlock(`${nextStatePath}/index.html`),
);
blocks = upsertSubjectBlockAfter(
blocks,
`${nextStatePath}/index.html`,
`${nextManifestationPath}/index.html`,
renderResourcePageLocatedFileBlock(
`${nextManifestationPath}/index.html`,
function assertNoLegacyFirstKnopInventoryProgression(
preparedCurrentInventory: PreparedCurrentInventory,
designatorPath: string,
): void {
const carriedPredicates = [
...new Set(
preparedCurrentInventory.quads
.map((quad) => quad.predicate.value)
.filter((predicate) =>
FIRST_KNOP_LEGACY_INVENTORY_PROGRESSION_PREDICATES.has(predicate)
),
),
);
].sort((left, right) => left.localeCompare(right));
if (carriedPredicates.length === 0) {
return;
}

return `${blocks.join("\n\n")}\n`;
throw new WeaveInputError(
`Could not append versioned first-Knop MeshInventory facts for ${designatorPath} because the current MeshInventory contains legacy inventory-owned mutable progression predicates: ${
carriedPredicates.map((predicate) => `<${predicate}>`).join(", ")
}. Regenerate the fixture or use an explicit repair path before retrying weave.`,
);
}

export function renderMeshMetadataWithMeshInventoryProgression(
Expand Down Expand Up @@ -483,6 +438,23 @@ ${blocks.join("\n\n")}
`;
}

function renderFirstKnopMeshInventoryRequestedFactsTurtle(
meshBase: string,
designatorPath: string,
meshInventoryProgression: MeshInventoryProgression,
): string {
return `${
renderExtractedKnopMeshInventoryRequestedFactsTurtle(
meshBase,
[designatorPath],
meshInventoryProgression,
).trimEnd()
}

<_mesh> sflo:hasKnop <${toKnopPath(designatorPath)}> .
`;
}

/*
* Batched extracted-term rendering intentionally has no block-replacement
* fallback. The append planner owns duplicate detection, conflict refusal,
Expand Down Expand Up @@ -608,131 +580,6 @@ function renderMeshInventoryHistoryMetaProgressionBlock(
}"^^xsd:nonNegativeInteger .`;
}

function renderLegacyFirstKnopWovenMeshInventoryTurtle(
meshBase: string,
designatorPath: string,
): string {
const knopPath = toKnopPath(designatorPath);
const designatorPagePath = toDesignatorResourcePagePath(designatorPath);

return `@base <${meshBase}> .
${SFLO_TURTLE_PREFIX_DECLARATION}
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<_mesh> a sflo:SemanticMesh ;
sflo:meshBase "${meshBase}"^^xsd:anyURI ;
sflo:hasMeshMetadata <_mesh/_meta> ;
sflo:hasMeshInventory <_mesh/_inventory> ;
sflo:hasKnop <${knopPath}> ;
sflo:hasResourcePage <_mesh/index.html> .

<${designatorPath}>
sflo:hasResourcePage <${designatorPagePath}> .

<${knopPath}> a sflo:Knop ;
sflo:hasWorkingKnopInventoryFile <${knopPath}/_inventory/inventory.ttl> ;
sflo:hasResourcePage <${knopPath}/index.html> .

<_mesh/_meta> a sflo:MeshMetadata, sflo:DigitalArtifact, sflo:RdfDocument ;
sflo:hasArtifactHistory <_mesh/_meta/_history001> ;
sflo:currentArtifactHistory <_mesh/_meta/_history001> ;
sflo:nextHistoryOrdinal "2"^^xsd:nonNegativeInteger ;
sflo:hasWorkingLocatedFile <_mesh/_meta/meta.ttl> ;
sflo:hasResourcePage <_mesh/_meta/index.html> .

<_mesh/_meta/_history001> a sflo:ArtifactHistory ;
sflo:historyOrdinal "1"^^xsd:nonNegativeInteger ;
sflo:hasHistoricalState <_mesh/_meta/_history001/_s0001> ;
sflo:latestHistoricalState <_mesh/_meta/_history001/_s0001> ;
sflo:nextStateOrdinal "2"^^xsd:nonNegativeInteger ;
sflo:hasResourcePage <_mesh/_meta/_history001/index.html> .

<_mesh/_meta/_history001/_s0001> a sflo:HistoricalState ;
sflo:stateOrdinal "1"^^xsd:nonNegativeInteger ;
sflo:hasManifestation <_mesh/_meta/_history001/_s0001/ttl> ;
sflo:locatedFileForState <_mesh/_meta/_history001/_s0001/ttl/meta.ttl> ;
sflo:hasResourcePage <_mesh/_meta/_history001/_s0001/index.html> .

<_mesh/_meta/_history001/_s0001/ttl> a sflo:ArtifactManifestation, sflo:RdfDocument ;
sflo:locatedFileForManifestation <_mesh/_meta/_history001/_s0001/ttl/meta.ttl> ;
sflo:hasResourcePage <_mesh/_meta/_history001/_s0001/ttl/index.html> .

<_mesh/_inventory> a sflo:MeshInventory, sflo:DigitalArtifact, sflo:RdfDocument ;
sflo:hasArtifactHistory <_mesh/_inventory/_history001> ;
sflo:currentArtifactHistory <_mesh/_inventory/_history001> ;
sflo:nextHistoryOrdinal "2"^^xsd:nonNegativeInteger ;
sflo:hasWorkingLocatedFile <_mesh/_inventory/inventory.ttl> ;
sflo:hasResourcePage <_mesh/_inventory/index.html> .

<_mesh/_inventory/_history001> a sflo:ArtifactHistory ;
sflo:historyOrdinal "1"^^xsd:nonNegativeInteger ;
sflo:hasHistoricalState <_mesh/_inventory/_history001/_s0001> ;
sflo:hasHistoricalState <_mesh/_inventory/_history001/_s0002> ;
sflo:latestHistoricalState <_mesh/_inventory/_history001/_s0002> ;
sflo:nextStateOrdinal "3"^^xsd:nonNegativeInteger ;
sflo:hasResourcePage <_mesh/_inventory/_history001/index.html> .

<_mesh/_inventory/_history001/_s0001> a sflo:HistoricalState ;
sflo:stateOrdinal "1"^^xsd:nonNegativeInteger ;
sflo:hasManifestation <_mesh/_inventory/_history001/_s0001/ttl> ;
sflo:locatedFileForState <_mesh/_inventory/_history001/_s0001/ttl/inventory.ttl> ;
sflo:hasResourcePage <_mesh/_inventory/_history001/_s0001/index.html> .

<_mesh/_inventory/_history001/_s0001/ttl> a sflo:ArtifactManifestation, sflo:RdfDocument ;
sflo:locatedFileForManifestation <_mesh/_inventory/_history001/_s0001/ttl/inventory.ttl> ;
sflo:hasResourcePage <_mesh/_inventory/_history001/_s0001/ttl/index.html> .

<_mesh/_inventory/_history001/_s0002> a sflo:HistoricalState ;
sflo:stateOrdinal "2"^^xsd:nonNegativeInteger ;
sflo:previousHistoricalState <_mesh/_inventory/_history001/_s0001> ;
sflo:hasManifestation <_mesh/_inventory/_history001/_s0002/ttl> ;
sflo:locatedFileForState <_mesh/_inventory/_history001/_s0002/ttl/inventory.ttl> ;
sflo:hasResourcePage <_mesh/_inventory/_history001/_s0002/index.html> .

<_mesh/_inventory/_history001/_s0002/ttl> a sflo:ArtifactManifestation, sflo:RdfDocument ;
sflo:locatedFileForManifestation <_mesh/_inventory/_history001/_s0002/ttl/inventory.ttl> ;
sflo:hasResourcePage <_mesh/_inventory/_history001/_s0002/ttl/index.html> .

<_mesh/_meta/meta.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<_mesh/_inventory/inventory.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<_mesh/_meta/_history001/_s0001/ttl/meta.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<_mesh/_inventory/_history001/_s0001/ttl/inventory.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<_mesh/_inventory/_history001/_s0002/ttl/inventory.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<${knopPath}/_inventory/inventory.ttl> a sflo:LocatedFile, sflo:RdfDocument .

<_mesh/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<${designatorPagePath}> a sflo:ResourcePage, sflo:LocatedFile .

<${knopPath}/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_meta/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_meta/_history001/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_meta/_history001/_s0001/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_meta/_history001/_s0001/ttl/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/_history001/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/_history001/_s0001/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/_history001/_s0001/ttl/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/_history001/_s0002/index.html> a sflo:ResourcePage, sflo:LocatedFile .

<_mesh/_inventory/_history001/_s0002/ttl/index.html> a sflo:ResourcePage, sflo:LocatedFile .
`;
}

function renderLegacyFirstPayloadWovenMeshInventoryTurtle(
meshBase: string,
designatorPath: string,
Expand Down
Loading