Engineering Paper SDK
Contract-only Extension surface
The editor, template contribution, settings schema, and presentation resources in this page are target contracts, not a live production Flow surface. Today @px.component registers companion metadata and annotation-derived ports, and the Canvas renders a read-only unsupported Node. Portable V1 accepts one content/component.json declaration per container. Multi-declaration containers and host presentation belong to the contract_only V2 in Node presentation and third-party UI. That V2 Canvas uses only host-owned component.declarative@2. Rich Engineering Paper editors, renderers, and non-empty settings cannot be declared or activated until RFC-014 and a separate versioned settings contract are both approved.
The canonical current V1 legacy EngineeringPaperNodeSetting is a separate compatibility branch: its schema and Rust codec require contractSnapshot and document, validate the snapshot on read, and require its ComponentRef to equal the Node target. That V1 snapshot is not generic Component recovery authority and does not authorize successor V2 settings.
No successor V2 release artifact bytes exist. The seven-field ComponentRef is therefore approved only as a contract-only non-resolvable member shape: no concrete packageDigest or releaseByteDigest value, exact-ref creation, installation, or admission is valid yet.
Engineering Paper is a target for the optional Components layer. Its planned surface has one Canvas Component, template syntax, a Node-owned editor, and Document/PDF artifacts. Formula blocks, evidence tables, and sections are editor elements rather than separate Nodes.
Install and import
# Planned dependency command; it is not a current public CLI.
pxlab dependency add engineering_paper@^1.0from pipelinexlab import px
from engineering_paper import components as paper_componentspaper_components.engineering_paper is the Component package's @px.component companion symbol; it is not itself a portable declaration or package compiler output. Installing the package also enables the optional typed px.paper, px.Paper, and FormulaExpression SDK symbols. Those symbols belong to the Component package release; the core SDK currently provides explicit-key @px.function targets, @px.component targets, px.Results, px.Record, list[T], and px.Flow. The @px.record decorator is planned and absent from the current facade. Undecorated Python functions remain helpers inside a Function or Component body.
Complete minimal example
The entire Python fence below is contract_only and is not executable with the current SDK. Its core Function portion uses the current facade's plain parameter annotations, px.Results annotated fields, and list[T] collection values. @px.paper, document.input(...), non-empty settings={"template": ...}, and the derived input connections remain post-contract candidates, so the fence must not be copied as a current example. Successor V2 allows only ports fixed in component declaration.inputs, and settings declared through component-declared-settings@1 at most eight per declaration.
This example is contract_only and is not executable with the current SDK.
from pipelinexlab import px
from engineering_paper import components as paper_components
class CheckResults(px.Results):
utilizations: list[float]
passed: list[bool]
@px.function(
key="check_load",
version="1.0.0",
description="Checks one load against the design limit.",
)
def check_load(loads: list[float]) -> CheckResults:
utilizations = [load / 500.0 for load in loads]
return CheckResults(
utilizations=utilizations,
passed=[utilization <= 1.0 for utilization in utilizations],
)
@px.paper(
version="1.0.0",
title="Load check document",
description="Presents the structured load-check result.",
)
def load_check_document(document: px.Paper):
utilizations = document.input("utilizations", list[float])
passed = document.input("passed", list[bool])
summary = document.section("summary", title="Check summary")
summary.result("utilizations", utilizations)
summary.result("passed", passed)
flow = px.Flow(
"load_review",
label="Load review",
description="Checks a design load and prepares an optional document artifact.",
)
loads = flow.input("loads", list[float], unit="kN", description="Design loads.")
check = flow.node("load_check", check_load)
paper = flow.node(
"design_document",
paper_components.engineering_paper,
settings={"template": load_check_document},
)
flow.connect(loads, check.inputs.loads)
flow.connect(check.results.utilizations, paper.inputs.utilizations)
flow.connect(check.results.passed, paper.inputs.passed)
flow.result(
"utilizations",
check.results.utilizations,
description="Load-check utilization values.",
)
flow.result(
"paper_document",
paper.results.document,
description="Generated engineering document.",
)SDK-to-UI mapping
| SDK | PXFLOW |
|---|---|
installed engineering-paper package | Engineering Paper in Project dependencies |
paper_components.engineering_paper | Engineering Paper card in Components · planned |
flow.node("design_document", ...) | Engineering Paper Node on the canvas |
document.input("utilizations", list[float]) · candidate | a fixed declaration input after separately approved publish/materialization lowering; never a Node-instance port |
flow.connect(..., paper.inputs.utilizations) | upstream result-to-input connection |
flow.result("paper_document", paper.results.document) | typed Document artifact Result from the Flow Run |
summary.result(...) | mapped value position in the Node editor |
Use an explicit flow.node(...) placement to create each Node instance in the current Flow. The planned template build and package-to-catalog bridge prepare selectable definitions; flow.connect(...) owns every value relationship.
Initial successor V2 takes ports only from install-time component declaration.inputs. A future deterministic Paper compiler may lower document.input(...) at publish/materialization time into fixed declaration inputs after separate approval; it must not create Node-instance ports. The Engineering Paper public inventory remains exactly one engineering_paper Component, so a template with a different input contract is unsupported until versioned settings and port-projection contracts exist. Generic package one-to-many support does not widen this inventory. Add input and instance-port materialization stay blocked on the same contracts.
Template operations
The template function called by @px.paper receives the document builder. For example, summary = document.section(...) returns a Section handle, and the template then calls summary.text(...).
| Owner | Call | Purpose |
|---|---|---|
PipelineXLab SDK px | @px.paper(...) | Declare Component template identity and metadata |
Document builder document | .input(key, type) | Candidate compiler input for a fixed declaration port after separate approval; not an instance port |
Document builder document | summary = document.section(...) | Declare document structure and return a Section handle |
Section handle summary | .text(key, ...) | Add narrative content |
Section handle summary | .result(key, source) | Project a mapped input field |
Section handle summary | .table(key, source) | Project a mapped Table input |
Section handle summary | .calculation(key, ...) | Add a short package-provided formula |
Section handle summary | .evidence(key, source) | Present mapped evidence rows |
All execution enters the Component through its current Flow input bindings. The planned editor chooses where those mapped inputs appear in the document.
Formula expressions
Formula helpers create a typed expression tree rather than evaluating a Python string.
formula = px.formula.maximum(
px.formula.div(demand, capacity),
px.formula.div(service_demand, service_capacity),
)Use Formula blocks for short document-local presentation and checks. Put internal calculation helpers in an undecorated Python def, executable calculations in explicit-key @px.function definitions, and package-provided custom surfaces in explicit-key @px.component definitions.
Drafts and artifacts
| Object | Created when | Owner |
|---|---|---|
| Current V1 legacy setting | V1 Engineering Paper Node is saved | Flow revision stores required contractSnapshot · document; V1-only compatibility authority |
| Document draft · planned | Save in the Node editor | Component Node setting in the Flow revision |
| Document artifact | Engineering Paper Component runs with its connected inputs | immutable typed Result/artifact store |
| PDF artifact | Export PDF from a Document artifact | immutable artifact store |
The Document and PDF artifacts belong to the optional Engineering Paper Component. A Project Report is a separate .pxreport document authored with px.Report or Report Workbench.
Missing Component package behavior
For generic Component recovery and successor V2, the current reader preserves the exact ComponentRef, raw settings, and usage-derived partial ports. Original package bytes are evidence only when their package artifact owner retained them; they are not inferred from Flow state. This generic branch has no full last-verified snapshot owner. Separately, the current V1 legacy Engineering Paper setting continues to read and validate its required persisted contractSnapshot · document; that snapshot is not generic recovery or successor V2 authority.