{
  "$schema": "./sdk-distribution-profile.v1.schema.json",
  "contractVersion": "1.0.0",
  "topic": "sdk-distribution-deliverables-and-read-only-preview-scope",
  "availability": "contract_only",
  "authority": {
    "decisionRecord": "RFC-007",
    "decidedBy": "product owner, in session, 2026-08-26",
    "decision": "The SDK is distributed separately from the product, per language. Its locally generated front is a read-only preview of Flows and Reports — no editing surface ships in any SDK deliverable. Flow and Report functionality operates at the code level through the SDK facades. This contract fixes the deliverable set, the preview scope, the single-version rule and the publish seal; the packaging slices that make each deliverable installable follow under it. Revised 2026-08-26, same session, packaging slice: the python facade gained its installable pyproject; the javascript deliverable gained the sdk/js wrapper so a manifest exists without a hand file entering the generator-owned pkg; the preview bundle gained sdk/preview, which re-exports the two readers and nothing that edits. The seal did not move. D4 standalone packaging: private npm tarballs carry package-local JavaScript, declaration and asset exports. The JavaScript wrapper stages generated JS/types/WASM byte-for-byte; the preview bundles its reader API, declaration closure and self-contained HTML with fonts and lazy chunks. All six preview workspace dependencies are build-only and installed runtime dependency sets are empty. Consumers access package names only. test:sdk-js-installed proves isolated offline pack/install, Node file-URL init, codec, type resolution and Flow/Report generation/render; it does not unseal publication or replace generated-binding remeasurement.",
    "machineProfilePath": "Report_Doc/docs/public/contracts/sdk-distribution-profile.v1.json",
    "machineProfileSchemaPath": "Report_Doc/docs/public/contracts/sdk-distribution-profile.v1.schema.json",
    "relatedContracts": [
      "Report_Doc/docs/public/contracts/toolchain-release-profile.v1.json",
      "Report_Doc/docs/public/contracts/authoring-profile.v1.json"
    ]
  },
  "deliverables": {
    "python": {
      "distributionName": "pipelinexlab",
      "facadeUnit": "pipelineXlab_pxflow/sdk/python/src/pipelinexlab",
      "nativeUnit": "pipelineXlab_pxflow/crates/pxflow-python",
      "nativeDistributionName": "pxflow_python",
      "carries": [
        "pxflow-codec",
        "digest-and-identity",
        "type-and-unit-vocabulary",
        "structural-validation",
        "flow-code-authoring",
        "report-code-authoring",
        "supervisor-client",
        "read-only-preview-emission"
      ],
      "packagingStatus": "installable"
    },
    "rust": {
      "distributionName": "pxflow-core",
      "units": [
        "pipelineXlab_pxflow/crates/pxflow-core"
      ],
      "carries": [
        "pxflow-codec",
        "digest-and-identity",
        "type-and-unit-vocabulary",
        "structural-validation"
      ],
      "packagingStatus": "sealed-workspace"
    },
    "javascript": {
      "distributionName": "@pipelinexlab/pxflow-wasm",
      "units": [
        "pipelineXlab_pxflow/crates/pxflow-wasm/pkg",
        "pipelineXlab_pxflow/sdk/js"
      ],
      "carries": [
        "pxflow-codec",
        "digest-and-identity",
        "structural-validation",
        "typescript-declarations"
      ],
      "packagingStatus": "private-workspace-packages"
    },
    "previewBundle": {
      "distributionName": "@pipelinexlab/preview",
      "units": [
        "pipelineXlab_pxflow/packages/flow-reader-application",
        "pipelineXlab_pxflow/packages/report-reader-application",
        "pipelineXlab_pxflow/packages/pxflow-surface",
        "pipelineXlab_pxflow/sdk/preview"
      ],
      "carries": [
        "flow-read-only-preview",
        "report-read-only-preview",
        "embedded-wasm-codec"
      ],
      "packagingStatus": "private-workspace-packages"
    }
  },
  "previewScope": {
    "readOnly": true,
    "readerUnits": [
      "pipelineXlab_pxflow/packages/flow-reader-application",
      "pipelineXlab_pxflow/packages/report-reader-application"
    ],
    "editingSurfacesExcluded": [
      "FlowSourceEditor",
      "NodePlacementDialog",
      "NodeInlineInput"
    ],
    "meaning": "The SDK's locally generated front presents Flows and Reports and never edits them. The excluded names are real editing exports of the shared surface package; excluding a name that does not exist would exclude nothing, so the checker requires each to exist there and to appear nowhere in the reader sources."
  },
  "versioning": {
    "singleVersionAcrossDeliverables": true,
    "sealedVersion": "0.0.0",
    "meaning": "Every SDK deliverable of one release carries one version, bound to that release. 0.0.0 is the unreleased value; while the publish seal holds, every measured surface must still say it.",
    "graduationPreconditions": [
      "cross-binding parity gates green for the release",
      "byte-reproducible committed artifacts under the generated-binding-pins discipline",
      "SBOM present for every native artifact",
      "supply-chain gates of the toolchain release profile",
      "product owner ratification recorded in this contract"
    ]
  },
  "publishSeal": {
    "sealed": true,
    "measuredSeals": [
      "workspace Cargo.toml publish = false",
      "workspace Cargo.toml version = 0.0.0",
      "reader and surface npm packages private = true"
    ],
    "unsealAuthority": "product owner",
    "unsealedOn": null,
    "meaning": "Nothing distributes while sealed. Unsealing is a deliberate contract change by the unseal authority, not a side effect of a packaging slice; the checker holds the contract and the workspace to the same answer in both directions."
  },
  "localPreviewEmission": {
    "status": "emission-functions-landed",
    "templateUnit": "pipelineXlab_pxflow/sdk/preview/dist/preview-template.html",
    "templateSource": "branch toto9999/preview-template, commit 447d9aae2, byte-deterministic across consecutive builds",
    "injectionPlaceholder": "__PXFLOW_PREVIEW_PAYLOAD__",
    "payloadKinds": [
      "flow",
      "report"
    ],
    "payloadShapes": {
      "flow": "{\"kind\":\"flow\",\"document\":<direct flow document JSON, exactly what the codec produced>}",
      "report": "{\"kind\":\"report\",\"revision\":<the REPORT_REVISION_READ response shape>}"
    },
    "emissionApi": {
      "python": "Flow.preview_html(path) and Report.preview_html(path) on the pipelinexlab facade",
      "javascript": "emitPreviewHtml(payload, template) from @pipelinexlab/preview -- pure, the caller supplies the template text so no filesystem capability enters the package"
    },
    "renderingAuthority": "The reader applications compute the deterministic partial layout from the document; no server round trip and no binding change is required for emission.",
    "mergePreconditions": [
      "the product frontend completes and its session lands its own tree, per the owner hold of 2026-08-26",
      "the template artifact joins ops/generated-binding-pins.v1.json as a pinned generation (command build:template, measured on the merge tree)",
      "the emission functions land with the sealed version rule unchanged"
    ],
    "meaning": "The owner held integration on 2026-08-26 until the product frontend is finished; the template merged and was pinned as the preview-template generated binding on 2026-08-28, and the emission functions landed on 2026-09-02 with the sealed version rule unchanged -- Flow.preview_html/Report.preview_html verified end to end against the real supervisor, the template travelling in the platform wheel beside the runtime binary. What still holds is the seal itself: nothing distributes while publishSeal.sealed is true.",
    "emissionFunctionsLandedOn": "2026-09-02"
  },
  "refusals": [
    "A deliverable that ships an editing surface is refused; the preview is read-only.",
    "A deliverable published while the seal holds is refused.",
    "Two SDK deliverables of one release carrying different versions are refused.",
    "An excluded editing surface name that does not exist in the surface package is refused, because it would exclude nothing.",
    "A reader unit whose source names an excluded editing surface is refused."
  ],
  "commercializationSeats": {
    "whyThisMemberExists": "Each seat is a rule that would cost a migration if decided after customers exist; deciding it while the seal holds makes every later step additive.",
    "versionSkew": {
      "status": "implemented",
      "rule": "From the first unsealed release, every SDK release names the product wire-release range it supports, and a connection outside that range is a named refusal on both sides.",
      "todayReality": "The SDK first sends handshakeVersion 1 with an explicit product wire-release range and diagnosticRegistryVersion; Runtime selects the highest common version and the SDK verifies the response before use. Core/native ABI initialization remains separate. Linux sockets and Windows named pipes share the same negotiation implementation; Windows execution evidence remains pending.",
      "landing": "Owner decision 2026-09-08 (foundation A1): implement negotiation before unsealing. The initial wire release is 0.1.0, independent of the sealed distribution version 0.0.0 and core ABI 1.1.0. The first unsealed release must retain this negotiation; this decision does not unseal or renumber any deliverable.",
      "sdkVersionSource": "px.__version__ reads the installed distribution metadata and answers the sealed version while the seal holds.",
      "negotiation": {
        "handshakeVersion": 1,
        "wireReleaseRange": {
          "min": "0.1.0",
          "max": "0.3.0"
        },
        "diagnosticRegistryVersion": "1.1.0",
        "registrySource": "type-diagnostic-profile.v1.json#/contractVersion",
        "requestRequired": [
          "name",
          "handshakeVersion",
          "wireReleaseRange",
          "diagnosticRegistryVersion"
        ],
        "requestOptional": [
          "sdkVersion",
          "pythonEnvironmentLock"
        ],
        "responseRequired": [
          "contractVersion",
          "supervisorVersion",
          "operationSchemaDigest",
          "payloadTransfer",
          "handshakeVersion",
          "wireReleaseRange",
          "selectedWireVersion",
          "diagnosticRegistryVersion"
        ],
        "rangeRule": "Closed inclusive min/max canonical numeric major.minor.patch tuples, each component 0..4294967295, no leading zeros, prerelease, build suffix, wildcard or comparator syntax. min <= max. Every version in the advertised interval is explicitly supported; select min(client.max, runtime.max) only when >= max(client.min, runtime.min). Equal major alone never implies support. Initial support is exactly 0.1.0; 0.2.0 adds the product descriptor; 0.3.0 adds host Python environment acknowledgment and an optional lock expectation.",
        "shapeRule": "Arguments contain only client. Dispatch by handshakeVersion: integer 1 uses the required/optional member allowlist, never a member-count limit; unknown members are refused. Optional sdkVersion is a nonempty informational string. Unsupported handshakeVersion is PX_RUNTIME_INCOMPATIBLE; malformed shape is PX_REQUEST_SHAPE_INVALID. Responses have the responseRequired closed member set, plus exactly the featureAdditions members the selected wire version admits; payloadTransfer retains its own versioned contract. Optional pythonEnvironmentLock requires selection >= 0.3.0; Core decodes and normalizes it and Runtime compares its digest to the host-selected environment before any success. It never installs packages or selects client paths.",
        "refusalRule": "No overlap, malformed range, selected version outside either interval, or diagnostic registry mismatch refuses with PX_RUNTIME_INCOMPATIBLE, actualVersion and supportedVersion strings, and the failing member path. Ranges render as min..max; malformed values render as compact JSON. Registry versions compare exactly against registrySource, independently of wire range and core ABI. SDK closes the connection on an invalid success response; it never silently retries the sealed protocol.",
        "legacyRule": "Only a request with no handshakeVersion and exactly name + contractVersion dispatches to sealed exact ABI compatibility. Accept only core ABI 1.1.0 (the current diagnostic registry); return the original four response members. Legacy requests never claim negotiated wire support. New SDKs do not fall back to legacy responses. Remove this dispatch only by a new explicit contract decision.",
        "fixtures": "fixtures/sdk-wire-negotiation.v1.cases.json",
        "featureAdditions": {
          "0.2.0": {
            "responseMembers": [
              "productOperationSchemaDigest"
            ],
            "rule": "present exactly when the selected wire version is 0.2.0 or later; it is the sha256 digest of the committed generated product-operation descriptor, and a client refuses a digest that is not the one its approved product list was written against",
            "descriptorSource": "pipelineXlab_pxflow/ops/generated/product-operation-schema.v1.json"
          },
          "0.3.0": {
            "responseMembers": [
              "pythonEnvironment"
            ],
            "requestMembers": [
              "pythonEnvironmentLock"
            ],
            "rule": "Present exactly when selected wire version is 0.3.0 or later. pythonEnvironment is null for an unconfigured host, otherwise the canonical sha256 environment digest. An optional client.pythonEnvironmentLock is a Core PythonEnvironmentLock expectation, not execution authority. Malformed lock is PX_REQUEST_SHAPE_INVALID; absent or different host environment is PX_RUNTIME_INCOMPATIBLE at /client/pythonEnvironmentLock, with actualVersion = host digest or unconfigured and supportedVersion = expected canonical digest. This acknowledgment proves host selection, not immutable custody or external dependency support. SDK clients with PXL_DESKTOP_PYTHON_ENVIRONMENT_FILE require min 0.3.0 and send only its environmentLock; an older or unconfigured response cannot silently satisfy that expectation."
          }
        }
      }
    },
    "remoteTransport": {
      "status": "implemented",
      "seat": "pipelinexlab._transport.SupervisorConnection remains the single transport owner. Client service_url, access_token and organization select authenticated HTTP with default TLS trust and hostname verification; plaintext is limited to numeric loopback. HTTP carries operation and arguments while the server owns release. No redirects, automatic retries or local bootstrap fallback. Entitlement lease remains future work.",
      "invariant": "The operation catalog, wire negotiation, frame bounds and refusal rules stay in SupervisorConnection. Server-advertised logical sessions enable bounded large Report transfer and import_documents attachment staging, bound to principal, Organization, credential and Project. A separate attachment-ingest advertisement enables ordinary Report save to read the caller local file at save time and send verified bytes; the server reauthorizes the ingestion operation and Project before committing the existing attachment custody transaction. Each tunneled command and response read is reauthorized; staging requires Project read and write access. Old servers and tokens without the transfer operation retain empty payloadTransfer capability. Sessions expire after 60 idle seconds or server restart; import retries restage bytes with the same command receipt identity. Local-file operations remain refused by the server."
    },
    "refusalStability": {
      "status": "normative",
      "stable": "px.Error is the one refusal root, and a closed RFC-003 code in Diagnostic.code is the stable branch point, from the first unsealed release. RFC-003 rule 5 closes the Diagnostic shape and RFC-010 rule 6 requires a schema-valid Diagnostic for a business failure, so a business refusal branches on a closed PX_ code and its params; a refusal the registry does not name is not a coded diagnostic and nothing about its text is API. The second branch is px.Error.refusal_reason for closed out-of-envelope reasons, including invariantViolation for stored bytes that contradict their revision, whether detected by Runtime or locally by the SDK. A missing or incompatible native pxflow-python binding is the SDK's own local refusal with the closed reason nativeBindingUnavailable, raised as a px.Error that keeps RuntimeError as a base for existing handlers. SDK descriptor failures use the code/params mapping in authoring-profile descriptorContracts. SDK Report document/revision lookup misses use PX_TARGET_NOT_FOUND with the missing reportKey or revisionRef in params.targetKey; a missing connected Flow revision uses PX_REPORT_FLOW_REVISION_NOT_FOUND with params.revisionRef.",
      "free": "px.Error.detail and the exception message are display-only prose and may improve without notice; the exception subclasses live in private modules and are not the documented branch. Diagnostic accepts only the closed RFC-003 object shape and never promotes legacy detail prose into Diagnostic.code. Receive-only compatibility parsing for the pre-RFC-003 {detail: prose} response is removed: a diagnostics member that is not a schema-valid Diagnostic is refused, not classified.",
      "authorityModel": "The SDK spelling of the RFC-003 stable-diagnostic-code principle."
    },
    "platformMatrix": {
      "built": [
        "pxflow_python native wheel: manylinux_2_34 x86_64 (abi3, cp312+)"
      ],
      "pendingVerification": [
        "pipelinexlab bundled-runtime facade wheel (clean provenance and a released platform tag; a local linux_x86_64 wheel is not release evidence)",
        "windows (four verifications held in server-backend-improvement-round.v1.md)"
      ],
      "ownerDecisionPending": [
        "macos-x86_64",
        "macos-arm64"
      ],
      "note": "abi3 keeps native-wheel additions a CI-matrix cost, not a code change. The bundled-runtime facade is a separate platform wheel and must pass its release-only clean installed-wheel gate before it joins this built list."
    },
    "executionModel": {
      "api": "sync-only in V1; an async surface lands additively later",
      "concurrency": "one in-flight request per connection, enforced by a named refusal; concurrent threads use one Client each",
      "frameLimitBytes": 1048576,
      "largePayloadPath": "bytes above the frame limit travel as CAS references or local-file sources, never inline",
      "supportDiagnostic": "px.diagnose() answers SDK version, Python, platform, endpoint and product reachability in one read-only call"
    },
    "performanceAndScaling": {
      "benchFloor": {
        "status": "implemented",
        "gate": "check:sdk-bench runs sdk/python/benchmarks/sdk_floor_bench.py in the verify chain against ceilings an order of magnitude above the 2026-08-29 measurements",
        "measured2026_08_29": {
          "flowAuthoring201Inputs200Nodes": "33ms",
          "dumps117KB": "19ms",
          "table2000RowsBy8Fields": "54ms after the staged-command copy removal; 259ms before it"
        }
      },
      "resultReuse": {
        "status": "seat-declared",
        "rule": "A Run of a deterministic function version with byte-identical canonical inputs may answer from the recorded result keyed by (functionVersionRef, inputsDigest) instead of re-executing; a function not declared deterministic is never reused.",
        "whyTheSeatIsCheap": "Function versions, canonical input bytes and results are already content-addressed in the ledger and CAS; activation is an index over existing records, not a new store.",
        "landing": "Activated as a product decision after unseal; the determinism declaration joins the function descriptor additively."
      },
      "tablePayloadPath": {
        "status": "reference-path-implemented",
        "implemented2026_08_29": "product.report.run_batch accepts its cases member as either inline rows or a { kind: localFile, path } source; the supervisor stats the file against a named 64 MiB cap before reading, commits the bytes to the CAS for custody, and decodes the same rows the inline spelling carries. The SDK switches forms automatically above 524,288 canonical bytes (PXL_SDK_INLINE_CASES_LIMIT overrides), removing the 1,048,576-byte frame ceiling for case tables; the live batch suite runs the whole route and the pinned run keys are identical to the inline spelling's.",
        "remainingCandidate": "A columnar (Arrow-class) byte form for the referenced payload stays recorded; adopting it changes the file bytes, not the path."
      },
      "freeThreadedWheel": {
        "status": "watch",
        "today": "The abi3 wheel does not cover the free-threaded CPython build and installation there is refused with a clear message per RFC-007.",
        "direction": "A free-threaded wheel tag is added on demand; PyO3 already supports the build, and batch worker parallelism is where the gain lands.",
        "activationPreconditions": "A cp314t wheel tag beside the abi3 wheel is an RFC-007 toolchain-matrix decision; PyO3 support is present and the build is a CI-matrix addition once decided."
      },
      "serializationEngine": {
        "status": "refused-by-measurement",
        "measured2026_08_29": "msgspec 0.21.1 with deterministic ordering spells float exponents 1e16/1e-7 where the facade's pinned canonical spelling is 1e+16/1e-07; 1,112 of 5,000 seeded fuzz structures diverged, every one a float spelling.",
        "consequence": "Adopting it would move every facade-computed digest, so the swap is refused; the canonical spelling is held by golden vectors in pipelinexlab._canonical and a sentinel test reports if a future msgspec release converges."
      },
      "workerIsolationAlternative": {
        "status": "long-term-note",
        "note": "A wasm component sandbox offers millisecond cold starts, determinism and platform uniformity; recorded, not planned, while Python-in-wasm maturity remains the constraint."
      }
    }
  }
}
