기능별 사용 위치
현재 Component surface 경계
현재 @px.component는 companion metadata와 annotation-derived input/result를 등록합니다. Flow reader의 기본 projection은 exact target/settings를 read-only 지원 불가 상태로 보존합니다. production host의 명시적 component presentation resolver가 exact installed declaration을 찾으면 host-owned component.declarative@2 projection으로 승격하고, 찾지 못하거나 declaration이 잘못됐으면 지원 불가 상태를 유지합니다. package UI는 Canvas에 마운트하지 않으며 settings는 component-declared-settings@1이, rich surface는 RFC-016의 component-rich-surface-declaration@1이 소유합니다. signed/verified라는 표현은 RFC-005 검증 기록이 있는 marketplace release에만 씁니다.
Normative surface registries
아래 두 목록은 생성 계약과 양방향으로 검사하는 public surface registry입니다. 항목은 이 문서의 다른 예제를 대체하지 않으며, 계약에만 있거나 이 목록에만 있는 이름을 허용하지 않습니다.
MCP Tool registry: project_search, report_search, report_describe, pxflow_search, pxflow_describe, function_search, function_describe, component_search, component_describe, report_plan_change, report_apply_change, function_validate_change, function_plan_change, function_apply_change, pxflow_validate, pxflow_plan_change, pxflow_apply_change, pxflow_run, run_get, run_cancel, result_read.
Python grammar registry: px.Flow, flow.input, flow.node, flow.connect, flow.result, flow.group, flow.subflow, flow.preview_html, px.function, px.component, px.loads, px.dumps, px.Report, px.Report.open, report.section, section.text, section.value, section.table, table.select, section.result_slot, section.result_table, section.artifact_slot, section.attachment, report.connect_flow, report.connection, connection.bind, connection.show, connection.remove_mapping, report.move, report.remove, report.remove_connection, report.save, report.plan_pages, report.export_pdf, report.preview_html, px.Client, client.create_project, client.search_catalog, client.save, client.open_report, client.run, client.run_many, client.run_batch, report.block, report.result_slot, report.document, block.to_dict, block.replace, block.set_value, block.select, block.insert_result, selection.format, selection.as_value, client.export_documents, px.ReportDocument, px.ReportDocument.from_wire, document.to_dict, report.settings, report.set_settings, client.import_documents, px.DocumentAnalysis, px.DocumentAnalysis.from_wire, analysis.to_dict, analysis.citation, px.DocumentCitation, px.DocumentCitation.from_wire, citation.to_dict, citation.resolve, px.DocumentTranslation, px.DocumentTranslation.from_wire, translation.to_dict, translation.resolve, client.retain_document, client.document_job, client.cancel_document_job, client.review_document_job, client.apply_document_result, client.document_application, client.resume_document_application, client.submit_document_job, client.document_submission, client.document_job_result, px.DocumentTranslatedPdf, px.DocumentTranslatedPdf.from_wire, translated_pdf.to_dict, translated_pdf.resolve, client.retain_translated_pdf, px.ProjectPdfFiles, pdf_files.read, pdf_files.list, pdf_files.remember, pdf_files.import_pdf, pdf_files.open_pdf, report.table, table.cell, table.set_cell, selection.read, selection.replace, client.read_report, client.read_attachment, report.capture_context, report.apply_edits, attachment.capture, run.read_result, px.Artifact.from_bytes, flow.viewer, client.plan_flow_change, client.apply_flow_change, client.search_functions, client.describe_function, client.plan_function_source_change, client.apply_function_change, client.read_flow_input_draft, client.save_flow_input_draft, client.get_run, run.read_inputs.
Project Function, Report와 Flow는 같은 Project에서 함께 사용하며 각각의 authoring owner와 revision 경계를 가집니다.
Project
├─ Function source · Python SDK 또는 Definitions에서 작성
├─ Report (.pxreport) · Report Workbench 또는 Python SDK에서 작성·연결
└─ Flow (.pxflow) · PXFLOW Studio 또는 Python SDK에서 작성Flow 작성: 같은 의미, 다른 조작 방식
Flow는 PXFLOW Studio에서 직접 만들거나 Python SDK에서 작성합니다. 선택한 authoring owner가 Flow의 public boundary, Node와 내부 연결을 저장합니다.
일반 Python 예제의 public client는 client = px.Client(workspace="structural_team", project="bridge_design")로 만듭니다. hosted surface를 포함한 current public client도 Workspace와 Project를 명시합니다. lowercase px.client()는 host scope 주입을 검토할 후속 계약에 예약돼 있으며 현재 facade에는 없습니다.
현재 Function·Component input은 일반 Python parameter annotation, 이름 있는 result는 px.Results subclass의 annotated field로 선언하고 px.input·px.result marker가 그 선언부에 description·unit을 더합니다. 계획된 record decorator, px.Table, px.Artifact는 current executable grammar가 아니라 별도 계약으로 보존한 계획 이름입니다.
| 의도 | Python SDK | PXFLOW Studio | MCP/LLM |
|---|---|---|---|
| Project Function 만들기 | @px.function(key=..., version=...) | Definitions → Functions → New Function | function_validate_change → plan/apply |
| Project Function 새 버전 만들기 | 같은 key와 새 version으로 source 변경 | Function → Edit | CreateFunctionVersion plan/apply |
| 특정 Node만 다른 Function으로 분기 | 새 key의 @px.function을 만들고 해당 flow.node(...) target 변경 | Function → Branch for this Node | BranchProjectFunction + ReplaceNodeTarget |
| 설치된 Component 찾기 | public module import | Components dock 검색 · 계획 | dependency evidence + component describe · 계획 |
| Component 정의 | @px.component(key=...) companion metadata | exact resolver 성공 시 host declarative Node, 아니면 read-only 지원 불가 | resolved Component contract 설명 |
| Function 찾기·계약 확인 | exact FunctionRef 사용 | Definitions → Functions | function_search → function_describe |
| public input 추가 | flow.input(...) | Flow interface input 추가 | plan/apply public input command |
| Node 배치 | flow.node("node_key", target) | Place Node / Add | plan/apply AddNode |
| Node 연결 | flow.connect(...) | result port → input port | plan/apply ConnectInput |
| public result 추가 | flow.result(...) | Flow interface result 추가 | plan/apply public result command |
| Group 만들기 | flow.group(...) | drag-select → Group selection | plan/apply AddGroup |
| 외부 Flow 배치 | flow.subflow(...) | Canvas Add → External Flow | plan/apply AddExternalSubflow |
| Component setting 저장 | flow.node(..., settings={...}) raw object | 현재 schema 없는 opaque settings 보존; Settings UI는 계획 | plan/apply SetNodeSetting · 계획 |
| 검증 | SDK validator | Validate | pxflow_validate |
| 저장 | materialize/build | Save | approved apply |
| Flow 직접 실행 | client.run(flow, **inputs) | Run | pxflow_run |
| 결과 읽기 | named result | Result panel | result_read |
SDK-linked Flow의 Studio 변경은 source-safe diff를 거쳐 Python source로 반영합니다. PXFLOW-native Flow의 Studio 변경은 .pxflow revision으로 저장합니다.
Report와 Flow 연결
Report 작성값과 결과 위치는 Report Workbench 또는 Python SDK에서 편집합니다. 두 경로는 같은 typed Report command를 적용하고 .pxreport revision을 저장합니다. Flow는 연결 가능한 public input/result를 공개합니다.
Python 열은 report = px.Report(...)로 만든 Report 객체, summary = report.section(...)으로 받은 Section handle, connection = report.connect_flow(...)으로 받은 Connected Flow handle, client = px.Client(workspace=..., project=...)로 만든 Client 객체를 기준으로 읽습니다.
| 의도 | Python SDK | Report Workbench | 저장 객체 | MCP/LLM |
|---|---|---|---|---|
| Report 시작 | report = px.Report(...) | New Report | ReportDocument draft | CreateReport |
| 저장된 Report 열기 | px.Report.open(...) | Project에서 Report 열기 | exact base revision을 고정한 draft | report_describe 후 exact target으로 plan |
| section·text 작성 | summary = report.section(...) → summary.text(...) | 본문 작성 | blocks[] | InsertReportBlock |
| 작성값·표 만들기 | Section handle의 .value(), .table() | 값·표 삽입 | typed block/table | UpsertReportValue / UpsertReportTable |
| result 위치 만들기 | Section handle의 .result_slot() | @ Insert → Result position | named result slot | InsertReportResultSlot |
| Connected Flow 추가 | connection = report.connect_flow(...) | Connected Flows → Add Flow | flowConnections[] | AddReportFlowConnection |
| Report 작성값 → Flow input | Connected Flow handle의 .bind(..., to=...) | 값 선택 → Use report input | inputMappings[] | SetReportFlowInputSource |
| Flow result → Report 위치 | Connected Flow handle의 .show(..., at=...) | 표시 위치 → Show result | resultMappings[] | SetReportFlowResultTarget |
| Report 항목 이동 | report.move(...) | block drag/reorder | 같은 stable key의 parent/order 변경 | MoveReportBlock |
| Report 항목 제거 | report.remove(...) | block Delete | 영향 검토 후 block 제거 | RemoveReportBlock |
| input/result mapping 제거 | connection.remove_mapping(...) | connection Remove | exact mapping 제거 | RemoveReportFlowMapping |
| Connected Flow 제거 | report.remove_connection(...) | Connected Flow Remove | connection과 mapping 영향 검토 | RemoveReportFlowConnection |
| Report 저장 | Report 객체의 .save() | Save | 새 .pxreport revision | approved Report apply |
| 연결 실행 | Client 객체의 .run(connection) | Run this Flow | ordinary Flow Run | RunReportFlowConnection |
| 여러 연결 실행 | client.run_many([...]) | Run selected | 독립 ordinary Run 목록 | connection별 run command |
| scalar case 묶음 실행 | client.run_batch(...) | Batch Run | ordinary child Run 묶음 | RunReportFlowBatch |
| 결과 확인 | returned Run·Result handle | Report result position / Activity | immutable Result projection | run_get / result_read |
flow.connect(...)는 현재 Flow 안의 port-to-port 연결을 나타냅니다. Report의 inputMappings와 resultMappings는 Flow 바깥의 public boundary를 사용하며 .pxreport에 저장됩니다.
client.run(flow, **inputs)는 Report 연결 없이 Flow를 바로 실행하며 호출자가 public input을 전달합니다. client.run(connection)은 저장한 Report connection의 input mapping을 사용하고 Result를 연결된 Report 위치에 표시합니다. 두 호출 모두 같은 ordinary Flow Run을 만들며, 입력과 결과 위치를 어디서 가져오는지만 다릅니다.
표와 여러 case
| Report source | Flow input | 실행 의미 |
|---|---|---|
| scalar 하나 | scalar | ordinary Flow Run 1회 |
| 여러 행의 field | List<T> | list 하나로 ordinary Flow Run 1회 |
| 여러 행과 field | Table<Record> | table 하나로 ordinary Flow Run 1회 |
| 여러 scalar case | explicit Batch Run | 검토한 case 수만큼 실행 |
Report selection 자체는 실행 수를 결정하지 않습니다. Collection은 typed value 하나로 전달하고, scalar 반복은 Batch Run plan에서 실행 수와 result merge를 확인합니다.
계획된 V2 host Component surface도 Core Flow 규칙 사용
Python package/distribution은 Component symbol을 하나 이상 export할 수 있습니다. 별도의 portable V1 Component container는 declaration 하나만 받습니다. 아래 dock 동선은 V2 host-declarative discovery가 구현된 뒤 사용할 목표 계약입니다.
| 의도 | Component package SDK | PXFLOW Studio | MCP/LLM |
|---|---|---|---|
| Component package 추가 | pxlab dependency add <distribution>@<range> · 계획 | Project dependencies → Add · 계획 | dependency plan/apply · 계획 |
| Component 찾기 | public @px.component import | Components → Installed · 계획 | component search/describe · 계획 |
| Component 배치 | flow.node(..., component) | 명시적 installed resolver가 exact target을 찾으면 host declarative Node, 아니면 read-only 지원 불가 | 일반 AddNode |
| 값 연결 | flow.connect(...) | 일반 result → input 연결 | 일반 ConnectInput |
| Node 상세 확인 | host-owned component.declarative@2 | exact identity·Port 확인 | 일반 component describe |
| settings | @px.component(..., settings=...) 선언 · 선언당 최대 8개 | host control registry가 그리는 control | 미제공 |
| rich surface | component-rich-surface-declaration@1 선언 | RFC-016이 소유하는 격리 editor | 미제공 |
| artifact 만들기 | Component result contract | 같은 Flow Run | 일반 pxflow_run |
Component rich editor 내부 command나 block schema는 이 V2에서 package가 소유하지 않습니다. field·entry·message는 RFC-016의 component-rich-surface-declaration@1이 정의하고, command shape는 열지 않으며 Core Flow command에 package 이름과 전용 block 종류를 추가하지 않습니다.
Project Function command
이 절이 Project Function write command 이름의 정식 정의입니다. Project가 소유한 @px.function(key=..., version=...) source만 이 command로 작성합니다. 설치한 dependency package의 Function과 Component source는 consumer Project에서 읽기 전용이며, 변경하려면 해당 package의 owning source와 release 절차로 이동합니다.
| kind | 필수 payload | 정확한 의미 |
|---|---|---|
CreateProjectFunction | Project scope, complete typed Function draft | 새 functionKey와 첫 immutable version 생성 |
CreateFunctionVersion | exact base FunctionRef, 같은 functionKey의 새 version draft, referencePolicy: "all_current_usages" | 기존 version을 보존하고 새 immutable version 후보와 모든 현재 사용처 갱신을 함께 계획 |
BranchProjectFunction | exact base FunctionRef, 새 functionKey와 첫 version draft | 기존 Function을 보존한 채 독립적으로 편집할 Project Function 생성 |
Function draft는 explicit functionKey, 새 version, description, typed input/result contract와 decorator에 결합된 완전한 구현 후보를 담습니다. line-based patch는 payload가 아닙니다. CreateFunctionVersion은 같은 Project의 현재 editable head에서 해당 Function을 쓰는 모든 Node를 새 FunctionRef로 옮기는 정책만 지원합니다. 일부 Node만 다르게 만들 때는 BranchProjectFunction과 Core Flow의 ReplaceNodeTarget을 한 plan에 넣습니다.
Plan은 command 외에 derived reference update를 정확히 나열합니다.
- old/new FunctionRef와 source-safe Python diff
- 영향받는
flowKey·nodeKey, 각 새 Flow revision과 rematerialized semantic diff - 그 Flow revision을 pin한 Report connection과 승인 시 갱신될 Report revision
- immutable history, published revision 또는 권한 때문에 갱신하지 않는 reference와 그 이유
Apply는 Function source, 새 Function version, 승인된 Node target, Flow revision과 Report connection reference를 하나의 multi-target transaction으로 확정합니다. 하나라도 stale이거나 권한·contract·source parity 검사를 통과하지 못하면 아무 target도 저장하지 않습니다. 기존 Function version과 기존 Flow·Report revision은 덮어쓰지 않습니다.
Source edit 위치는 explicit decorator key와 base source digest로 찾습니다. Python symbol 이름, 파일 순서 또는 label을 identity로 추측하지 않습니다. Apply는 syntax-aware diff를 적용한 뒤 Function과 영향받는 Flow를 다시 materialize하고 planned semantic contract와 같을 때만 새 revision을 확정합니다.
Core Flow command
Flow 변경 command의 discriminant는 다음 범위를 사용합니다.
CreateFlow
AddNode
RemoveNode
AddGroup
RemoveGroup
SetGroupMembers
SetGroupLabel
AddExternalSubflow
RemoveExternalSubflow
ReplaceNodeTarget
SetNodeSetting
ClearNodeSetting
AddFlowInput
UpdateFlowInput
RemoveFlowInput
AddFlowResult
UpdateFlowResult
RemoveFlowResult
ConnectInput
DisconnectInput
RenameSemanticKey
SetFlowMetadata
SetPresentation
SetResultViewer
RemoveResultViewer| kind | 필수 payload | 정확한 의미 |
|---|---|---|
CreateFlow | document | 검증된 canonical direct document를 세대 0의 첫 revision과 head로 저장 |
AddNode | node | 완전한 direct Node 추가 |
RemoveNode | nodeKey | 영향받는 binding·Group membership 검토 후 제거 |
AddGroup | group | 기존 Node의 editable Group membership 추가 |
SetGroupMembers | groupKey, members | exact member nodeKey 집합 교체 |
AddExternalSubflow | subflow | imported Flow의 exact external reference 추가 |
ReplaceNodeTarget | nodeKey, target, precondition | exact target과 target-kind state 교체 |
SetNodeSetting | nodeKey, settingKey, value | descriptor schema에 맞는 setting 지정 |
ConnectInput | nodeKey, portKey, binding | destination input에 typed internal binding 설정 |
RenameSemanticKey | target kind, current/new key | key와 모든 in-scope reference를 함께 변경 |
SetPresentation | target key, position | 계산 Node의 Canvas 위치 변경; 실행 의미 유지 |
SetResultViewer | viewerKey, viewer | V2 public result viewer 전체 정의 추가/교체. renderer/results/position은 Flow V2 계약, V1의 첫 추가는 새 V2 revision |
RemoveResultViewer | viewerKey | 존재하는 viewer 하나 제거. 빈 V2 유지; Run·원본 파일은 삭제하지 않음 |
첫 저장은 새 Tool이나 Tool 밖 쓰기가 아니라 pxflow_plan_change → pxflow_apply_change의 CreateFlow 한 command입니다. 계획 대상은 project scope, CreateFlow document 안의 flowKey와 같은 flowKey, 그리고 검증된 canonical direct document의 byteDigest와 같은 revisionRef를 가져야 하며 expectedGeneration은 0입니다. Apply 성공은 같은 digest를 newRevisionRef로, 0을 newGeneration으로 반환합니다. 같은 flowKey의 head가 이미 있으면 FlowHeadAlreadyExists로 거부합니다. 이 규칙은 Flow·Report·Function 쓰기를 모두 plan→apply와 generation 검사 한 경로에 두어 생성 감사 기록이 별도 표면으로 갈라지지 않게 합니다.
Node target은 Project 또는 installed package가 소유한 FunctionRef나 ComponentRef의 exact reference를 사용합니다. Decorator 없는 Python helper는 target이 아니며 Canvas에 표시되지 않습니다. Function이 부르는 helper는 decorator의 helpers 선언으로 그 Function revision에 저장됩니다. Imported Flow는 external Subflow reference로 배치하고 Group은 같은 Flow의 기존 Node membership을 저장합니다.
Core Report command
Report Workbench, Python SDK와 AI/MCP는 같은 command family를 사용합니다.
| kind | 의미 |
|---|---|
CreateReport | 이름·제목을 가진 ReportDocument draft 생성 |
SetReportMetadata | title·description 같은 Report metadata 변경 |
InsertReportBlock | 이름 있는 section·text·result slot 삽입 |
UpdateReportBlock | existing block content·presentation 변경 |
MoveReportBlock | stable block key를 유지하며 parent 또는 순서 변경 |
RemoveReportBlock | 영향 검토 후 block 제거 |
UpsertReportValue | typed authored value 추가·변경 |
UpsertReportTable | stable row key와 field schema를 가진 table 추가·변경 |
SetReportTableCells | exact table·row·field 값 변경 |
UpsertReportAttachment | stable attachment key에 content digest·media type·size를 가진 파일 reference 추가·변경 |
InsertReportResultSlot | scalar·Record·List result의 읽기 전용 표시 위치 추가 |
InsertReportResultTable | stable row/field schema를 가진 읽기 전용 Table result 위치 추가 |
InsertReportArtifactSlot | 허용 media type을 가진 Artifact result 위치 추가 |
AddReportFlowConnection | exact Flow revision을 가리키는 Connected Flow 추가 |
SetReportFlowInputSource | Report source를 exact Flow public input에 지정 |
SetReportFlowResultTarget | Flow public result를 Report destination에 지정 |
RemoveReportFlowMapping | exact input/result mapping 제거 |
RemoveReportFlowConnection | connection과 소유 mapping의 영향을 검토한 뒤 제거 |
SaveReportRevision | expected revision을 검사하고 새 canonical .pxreport revision 저장 |
RunReportFlowConnection | 저장한 connection을 ordinary Flow Run으로 실행 |
RunReportFlowBatch | stable caseKey별 ordinary child Run과 explicit result merge 실행 |
Report command는 Report block·field·slot과 Flow revisionRef·portKey를 사용합니다. Canvas Node key와 내부 edge를 Report mapping에 복제하지 않습니다. UpsertReportAttachment의 src는 Run input payload와 같은 filesystem CAS가 발행한 RFC-002 PublicDigestRef이며, size는 그 CAS에 commit하기 위해 supervisor가 읽은 exact byte 수입니다. 로컬 source 경로는 Report command나 저장 revision에 들어가지 않습니다.
변경 내용 미리 보기와 적용
모든 의미 변경은 같은 순서를 사용합니다.
- Plan은 변경되는 Report mapping 또는 Flow Node·binding과 진단을 보여 줍니다.
- Apply는 expected revision과 generation을 다시 검사합니다.
- 동시에 다른 변경이 저장되었으면 새 plan으로 현재 상태를 검토합니다.
- Canvas 위치 같은 presentation edit와 실행 의미를 바꾸는 edit를 구분합니다.
SDK-linked Flow 편집
SDK가 authoring owner인 Flow는 semantic Flow command를 Python source-safe diff로 변환합니다.
Report command는 이 Flow source edit 경로를 사용하지 않습니다. Report Workbench, Python SDK와 AI/MCP가 같은 typed command를 canonical .pxreport revision에 적용합니다. Python에서 px.Report를 사용해도 Python source와 .pxreport가 동시에 수정 가능한 두 원본이 되지 않습니다.
모든 화면에서 지키는 원칙
- 사용자에게 보이는 이름은 같은 semantic key를 가리킵니다.
- Type, unit, shape와 nullability는 모든 surface에서 같은 계약을 사용합니다.
- Function/Component definition과 Canvas Node instance를 구분합니다.
- Report mapping과 Flow 내부 binding의 저장 owner를 구분합니다.
- Component는 Core Flow 계약을 사용하고 전용 실행 계층을 추가하지 않습니다.
- 결과는 immutable Result snapshot에서 읽습니다.
- 권한, capability와 approval은 server에서 다시 검사합니다.
이어서 보기
V2 viewer 편집의 참조 일관성
RenameSemanticKey에서 target kind를 flowResult로 지정하면 모든 viewer의 result key도 함께 바꿉니다. 참조된 public result를 제거하려면 같은 atomic command 묶음에서 해당 viewer binding을 수정하거나 제거해야 합니다. 최종 candidate가 유효하지 않으면 전체 Plan을 거절합니다. 기존 V1 revision/hash는 유지하며 SetPresentation의 대상 의미는 확대하지 않습니다.