Skip to content

symfonic.memory.layers.procedural.sharing

sharing

Platform-shared skills: the reserved tenant and its node shapes.

Cross-org learning rides the tenant model instead of bypassing it: published skills live under a reserved tenant id, so prefix isolation, scoping, and the PG backend apply unchanged. Nothing here is ambient -- reads union the platform scope explicitly (see ProceduralSkillsSource.include_platform), and writes arrive only through the publish pipeline (review + scrub), never through the turn path. A deployment that never opts in sees byte-identical behavior.

platform_copy_node

platform_copy_node(snapshot: dict[str, Any], provenance: dict[str, Any], importance: float) -> MemoryNode

The reviewed platform copy: scrubbed content, approved, attributed.

Source code in src/symfonic/memory/layers/procedural/sharing.py
def platform_copy_node(
    snapshot: dict[str, Any], provenance: dict[str, Any], importance: float,
) -> MemoryNode:
    """The reviewed platform copy: scrubbed content, approved, attributed."""
    return MemoryNode(
        layer=MemoryLayer.PROCEDURAL,
        tenant_id=PLATFORM_TENANT,
        label=str(snapshot.get("label", ""))[:100],
        properties={
            "content": snapshot.get("content", ""),
            "steps": snapshot.get("steps", []),
            "context": snapshot.get("context", ""),
            "status": "approved",
            "active": True,
            "publication": provenance,
        },
        importance=importance,
    )

platform_scope

platform_scope() -> TenantScope

The scope platform-published skills are read from and written to.

A plain tenant root on purpose: every prefix check, distance rule, and backend treats it like any tenant, so sharing reuses isolation instead of punching through it. Only the id is reserved.

Source code in src/symfonic/memory/layers/procedural/sharing.py
def platform_scope() -> TenantScope:
    """The scope platform-published skills are read from and written to.

    A plain tenant root on purpose: every prefix check, distance rule, and
    backend treats it like any tenant, so sharing reuses isolation instead
    of punching through it. Only the id is reserved.
    """
    return TenantScope.root("tenant", PLATFORM_TENANT)

proposal_node

proposal_node(scope: TenantScope, source: MemoryNode, snapshot: dict[str, Any], scrub_report: dict[str, Any], proposer: str) -> MemoryNode

A pending publication proposal in the source tenant (never recalled: its status is outside the skill lifecycle vocabulary).

Source code in src/symfonic/memory/layers/procedural/sharing.py
def proposal_node(
    scope: TenantScope, source: MemoryNode, snapshot: dict[str, Any],
    scrub_report: dict[str, Any], proposer: str,
) -> MemoryNode:
    """A pending publication proposal in the source tenant (never recalled:
    its status is outside the skill lifecycle vocabulary)."""
    return MemoryNode(
        layer=MemoryLayer.PROCEDURAL,
        tenant_id=scope.tenant_id,
        label=f"Platform publication: {source.label}"[:100],
        properties={
            "status": "pending-platform-review",
            "active": False,
            "publication": {
                "source_node_id": str(source.id),
                "source_tenant": scope.tenant_id,
                "proposer": proposer,
                "proposed_at": datetime.now(UTC).isoformat(),
                "snapshot": snapshot,
                "scrub_report": scrub_report,
            },
        },
        importance=source.importance,
    )