본문으로 건너뛰기

입력·결과 타입, 단위와 오류

Type과 unit은 연결 가능한 값을 판단하고 잘못된 계산을 실행 전에 막기 위해 사용합니다. 예를 들어 길이 24 m는 길이 input에 연결할 수 있지만 힘 24 kN으로 자동 해석하지 않습니다. 같은 열 이름을 가진 표라도 field type이나 단위가 다르면 호환되는 표가 아닙니다.

Component API와 resolver의 현재 경계

px.setting(...)은 현재 public API이며 선언 schema는 component-declared-settings@1이 소유합니다. 현재 V1 @px.component는 companion descriptor metadata만 등록하며 installed declaration, executor나 renderer를 생성하지 않습니다. settings=로 붙인 px.Settings subclass의 field는 그 descriptor의 settings가 됩니다. production Flow reader는 installed Component target을 read-only unsupported로 열고 exact target·raw settings와 연결 사용처에서 유도한 일부 port만 보존합니다.

아래 Component editor·MCP·resolver diagnostic은 admitted target에 적용할 contract 의미입니다. 현재 production의 서드파티 Component install admission과 activation은 exact ProjectScope isolation과 execution-trust closure가 모두 닫힐 때까지 차단하며, diagnostic action이 그 차단을 우회하지 않습니다. 정확한 경계는 Component container V2와 서드파티 Node UI를 따릅니다.

V1 승인 bounds

다음 값은 RFC-003 승인과 함께 고정한 V1 상한입니다. 상한을 넘는 값이나 descriptor는 일부만 materialize하지 않고 진단과 함께 전체를 거부합니다.

bound측정 기준
decimal.precisionMax38부호와 decimal point를 제외한 전체 digit 수
decimal.scaleMin0decimal point 오른쪽 digit 수의 최솟값
decimal.scaleMax18decimal point 오른쪽 digit 수의 최댓값
semanticKey.maxLength128Unicode character 수
string.maxByteLength1048576UTF-8 byte 수(1 MiB)
list.maxItems100000list item 수
table.maxRows100000table row 수
record.maxFields512record field descriptor 수
compositeDepth.max32root composite를 1로 세는 record·list·table nesting depth

Decimal precision 38은 IEEE decimal128과 일반적인 DECIMAL(38,s) column에 맞습니다. 100,000 row는 structural hazard table과 load-case table에 필요한 여유를 남깁니다. Composite depth 32는 공격 방어와 실제 authoring을 모두 만족합니다.

V1 승인 unit registry

V1은 **UCUM 2.2 (2024-06-17)**을 pin합니다. 이 release는 UCUM 공식 specification이 날짜와 version을 함께 식별하고, 구현자가 사용할 ucum-essence.xml release artifact를 제공하는 최신 고정 specification이므로 선택했습니다. 전체 UCUM vocabulary를 노출하지 않고 다음 32개 case-sensitive canonical code만 허용합니다.

engineering categorycanonical code subset
dimensionless1, %, [ppm]
lengthmm, cm, m, km, [in_i], [ft_i]
massmg, g, kg, t
timems, s, min, h
anglerad, deg
forceN, kN, MN
stress/pressurePa, kPa, MPa, GPa, N/mm2
momentN.m, kN.m
densitykg/m3
accelerationm/s2
temperatureK

Derived force와 pressure 정의에 필요한 kg, m, s, N, Pa는 이 subset 안에 포함되어 있습니다. Moment는 owner가 승인한 kN.m sibling을 열며 canonical unit은 N.m로 유지합니다. MN.m는 승인되지 않았습니다. Density, acceleration, temperature는 owner가 지정한 canonical code 하나만 열며, 승인되지 않은 sibling code를 암묵적으로 추가하지 않습니다.

각 code의 canonical unit에 대한 conversion factor는 exponent 표기 없는 canonical decimal string으로 저장합니다. Multiplicative conversion은 {scale}을, affine conversion은 {scale, offset}을 사용하며 affine의 scaleoffset은 둘 다 canonical decimal string입니다. Conversion 중에는 rounding하지 않습니다. 결과가 선언된 decimal precision 38을 넘으면 값을 자르거나 반올림하지 않고 diagnostic을 반환합니다. V1 subset에는 non-zero offset이 필요한 unit pair가 없지만 affine wire form은 닫혀 있으며, fixture는 offset: "0"인 worked example로 두 member가 항상 존재함을 검증합니다.

승인 subset과 reader evolution 경계

실행 가능한 unit은 machine profile의 unit.canonicalCodeSubset 32개와 정확히 일치합니다. Direct schema, Component V2 input/result/setting admission과 Run input은 같은 case-sensitive 코드를 검사하며 M, pa 같은 미승인 값은 거부합니다. 화면용 임의 문구는 executable unit이 아니며, 필요하면 별도로 승인한 presentation role로 정의해야 합니다.

새 unit 또는 closed type kind는 versioned profile과 RFC-003 후속 결정이 필요합니다. 기존 reader가 모르는 값을 받기 전에 다음 소유 경계를 올려야 합니다.

  • Package: 해당 package kind의 required_contract_version을 올립니다. Safe container 검사 다음, content/declaration 해석 전에 지원 범위를 확인합니다. 초과 시 typed ContractTooNew { required, supported }를 반환하며 공개 응답은 기존 PX_SCHEMA_UNSUPPORTED_VERSIONactualVersion/supportedVersion으로 분기합니다. 낮은 requirement를 거짓 선언한 unknown unit/type은 content admission에서 거부됩니다.
  • Runtime/binding wire: A1의 core contract 지원 range/handshake가 transport peer를 먼저 검사합니다. 새 vocabulary를 기존 지원 range에 슬쩍 추가해서는 안 됩니다.
  • Standalone document: 문서 schemaVersion과 schema identity를 새 reader 세대로 올립니다. package나 handshake 없이 여는 reader는 document version 경계에서 거부합니다.

componentContractVersion은 특정 Component의 계약 revision이며 전역 UCUM subset을 확장하는 권한이 아닙니다. 현재 subset 교정은 새 code/kind를 도입하지 않아 버전을 올리지 않으며 별도의 custom unit registry도 만들지 않습니다.

V1 승인 diagnostic params contract

params는 아래에 적힌 key만 허용하는 closed object입니다. string은 locale-independent token, semantic key, ref, digest 또는 canonical decimal string이고 integer는 JSON integer입니다. 표의 key는 ascending order이며, 없는 key를 추가하거나 적힌 key를 생략하면 해당 code의 Diagnostic이 유효하지 않습니다.

code허용 params (key:type)
PX_SCHEMA_UNSUPPORTED_VERSIONactualVersion:string, supportedVersion:string
PX_SCHEMA_UNKNOWN_FIELDfield:string
PX_KEY_INVALIDkey:string
PX_KEY_DUPLICATEkey:string
PX_REPORT_CONNECTION_NOT_FOUNDconnectionKey:string
PX_REPORT_FLOW_REVISION_NOT_FOUNDrevisionRef:string
PX_REPORT_MAPPING_SOURCE_NOT_FOUNDsourceKey:string
PX_REPORT_MAPPING_TARGET_NOT_FOUNDtargetKey:string
PX_REPORT_MAPPING_CONFLICTmappingTarget:string
PX_REPORT_MAPPING_INCOMPATIBLEsourceKind:string, targetKind:string
PX_REPORT_TABLE_ROW_KEY_INVALIDreason:string, rowKey:string
PX_REPORT_BATCH_REQUIREDcaseCount:integer
PX_OUTPUT_EXISTSoutputName:string
PX_AMBIGUOUS_TARGETcandidateCount:integer
PX_TARGET_NOT_FOUNDtargetKey:string
PX_PACKAGE_NOT_INSTALLEDpackageKey:string
PX_PACKAGE_VERSION_MISMATCHexpectedVersion:string, installedVersion:string
PX_PACKAGE_CATALOG_UNAVAILABLEpackageKey:string
PX_PACKAGE_ACCESS_DENIEDpackageKey:string
PX_FUNCTION_NOT_FOUNDfunctionKey:string
PX_FUNCTION_VERSION_MISMATCHactualVersion:string, expectedVersion:string
PX_COMPONENT_NOT_FOUNDcomponentKey:string
PX_COMPONENT_CONTRACT_MISMATCHactualDigest:string, expectedDigest:string
PX_COMPONENT_UNRESOLVEDcomponentKey:string
PX_PUBLIC_MODULE_INVALIDmoduleName:string, reason:string, symbolName:string
PX_DEPENDENCY_RESOLUTION_FAILEDpackageKey:string, requestedRange:string
PX_REQUIRED_INPUT_UNBOUNDportKey:string
PX_PORT_NOT_FOUNDportKey:string
PX_PORT_DIRECTION_MISMATCHactualDirection:string, expectedDirection:string
PX_TYPE_INCOMPATIBLEsourceKind:string, targetKind:string
PX_UNIT_INCOMPATIBLEsourceUnit:string, targetUnit:string
PX_CARDINALITY_AMBIGUOUSobservedCardinality:string
PX_FORMULA_REFERENCE_NOT_FOUNDreferenceKey:string
PX_FORMULA_OPERATOR_UNSUPPORTEDoperator:string
PX_FORMULA_SHAPE_INCOMPATIBLEactualShape:string, expectedShape:string
PX_FORMULA_DOMAIN_ERRORoperator:string
PX_FORMULA_COMPLEXITY_LIMITactual:integer, limit:integer
PX_SOLVER_CONFIGURATION_INVALIDreason:string, settingKey:string
PX_SOLVER_DID_NOT_CONVERGEiterationLimit:integer
PX_FLOW_CYCLEnodeCount:integer
PX_GROUP_INVALIDgroupKey:string, reason:string
PX_PLAN_EXPIREDplanRef:string
PX_PLAN_MISMATCHactualPlanDigest:string, expectedPlanDigest:string
PX_GENERATION_STALEactualGeneration:integer, expectedGeneration:integer
PX_MERGE_CONFLICTconflictCount:integer
PX_SOURCE_EDIT_NOT_SAFEreason:string
PX_TARGET_NOT_PORTABLEtargetKind:string
PX_PERMISSION_DENIEDrequiredPermission:string
PX_CAPABILITY_DENIEDcapability:string
PX_RESOURCE_LIMITactual:string, limit:string, resource:string
PX_FUNCTION_FAILEDfunctionKey:string
PX_COMPONENT_FAILEDcomponentKey:string
PX_RESULT_NOT_FOUNDresultKey:string
PX_RESULT_STALEresultRevisionRef:string, sourceRevisionRef:string
PX_EFFECT_INDETERMINATEeffectRef:string
PX_DOCUMENT_LEGACY_FORMATdetectedFormat:string
PX_DOCUMENT_MALFORMED없음
PX_RUNTIME_UNREACHABLE없음
PX_RUNTIME_INCOMPATIBLEactualVersion:string, supportedVersion:string
PX_RUNTIME_DISCONNECTED없음
PX_BASE_REF_MISMATCHactualHeadRef:string, expectedBaseRef:string
PX_HEAD_ALREADY_EXISTSactualGeneration:integer
PX_PLAN_NOT_FOUNDplanRef:string
PX_FUNCTION_USAGE_STALE없음
PX_FUNCTION_BASE_TARGET_MISMATCHbaseTargetDigest:string, changeTargetDigest:string
PX_FUNCTION_DRAFT_INVALIDreason:string
PX_REQUEST_SHAPE_INVALIDmember:string, reason:string
PX_SOURCE_UNREADABLEreason:string
PX_RUN_STATE_CONFLICTreason:string
PX_SUBFLOW_DEPENDENCY_NOT_INSTALLEDflowKey:string
PX_EXECUTION_INFRASTRUCTURE_FAILEDreason:string, stage:string

PX_EXECUTION_INFRASTRUCTURE_FAILED는 사용자 함수 예외나 supervisor 연결 끊김이 아닌 실행 기반 실패입니다. 현재 Runtime이 생성하는 stage / reason 조합은 다음과 같습니다.

  • material / readFailed, invalidMaterial
  • workerStart / sandboxRejected, startFailed
  • workerResponse / invalidResponse, missingDiagnostic, noResponse
  • resultCommit / writeFailed

codeparams로 분기하며 원시 OS 경로·저장소 메시지·worker 출력은 params에 넣지 않습니다. path는 실패 위치를 설명하고 retryable은 해당 실행 시도의 재시도 가능성입니다. 없는 Function·Component·외부 Subflow는 기존 진단 코드를 사용합니다. 새 코드를 받는 SDK는 같은 공개 registry를 포함해야 하므로 SDK와 bundled Runtime을 함께 갱신합니다. 71개 registry의 Core/SDK 호환성 버전은 1.1.0입니다. 이전 1.0.0 Client는 최초 handshake에서 기존 PX_RUNTIME_INCOMPATIBLE로 거부되며 UPDATE_APPLICATION을 안내합니다. 이 버전은 native binding과 Runtime 호출의 호환성 버전이며 저장 파일의 schemaVersion이나 기존 revision bytes를 변경하지 않습니다. 기존 저장 Run에 진단이 없는 경우는 그대로 읽으며 사후에 원인을 만들어 넣지 않습니다.

PX_FUNCTION_DRAFT_INVALID.params.reasonpolicyNotExecutable, capabilityNotExecutable, dependencyNotExecutable, emptySource, entrySymbolInvalid, declaredVersionInvalid, timeoutInvalid, outputNotRequired, capabilityNetworkInvalid, dependencyPinInvalid 중 하나입니다. 중복 port·secret·dependency key는 각 key를 보존하는 PX_KEY_DUPLICATE를 사용하고, draft schema version 불일치는 PX_SCHEMA_UNSUPPORTED_VERSION을 사용합니다.

PX_REQUEST_SHAPE_INVALID.params.member는 요청 member 이름이고, params.reason은 runtime 요청에서는 memberSetUnexpected, memberTypeInvalid, memberValueInvalid 중 하나입니다. SDK descriptor 등록에서는 authoring-profile의 공개 분기에 따라 member="annotation"missingAnnotation 또는 unsupportedAnnotation, member="metadata"invalidMetadata를 사용합니다. SDK descriptor 진단의 path는 빈 문자열이며, runtime 요청의 path는 그 member의 JSON Pointer입니다. Key 자체가 문법 밖이면 PX_KEY_INVALID를, 중복이면 PX_KEY_DUPLICATE를 사용합니다.

PX_SOURCE_UNREADABLE.params.reasonnotFound, notPermitted, notReadable, notWritable 중 하나입니다. 호출자가 지정한 local 파일 경로에만 사용하며, 경로 문자열은 params에 넣지 않고 path가 그 요청 member를 가리킵니다.

PX_RUN_STATE_CONFLICT.params.reasontransitionNotPermitted, runStateMoved, commandBodyConflict, batchAlreadySubmitted, projectionConflict, completionStale 중 하나입니다. 여섯 경우 모두 durable Run·Batch 상태가 요청이 가정한 상태와 다르다는 하나의 사실이며, 조치도 하나입니다 -- 다시 읽고 다시 요청합니다.

외부 Subflow가 이 Project의 설치 closure에서 resolve되지 않을 때는 두 code를 구분해서 씁니다. 그 Flow key를 publish하는 release가 하나도 설치되어 있지 않으면 PX_SUBFLOW_DEPENDENCY_NOT_INSTALLED를 쓰고 params.flowKey에 그 Flow key를 담습니다 -- 조치는 그 Flow를 publish하는 package를 설치하는 것입니다. Flow key는 설치되어 있고 요청이 지정한 exact target·revision만 없으면 PX_TARGET_NOT_FOUND를 씁니다 -- 조치는 설치된 target을 지정하는 것입니다. path는 어느 member가 문제인지만 가리키며 branch 기준이 아닙니다: client가 분기하는 것은 codeparams뿐입니다.

이 세 code는 2026-09-03 supervisor refusal 경계 결정과 함께 열렸습니다. 그 결정 이후 supervisor가 도달할 수 있는 모든 business 실패는 RFC-003 schema-valid Diagnostic을 가진 ResponseEnvelope 안에 남습니다. free-form prose나 {"detail": ...} 객체는 diagnostics 원소가 될 수 없습니다. 저장 레코드·내부 불변식 위반만 봉투 밖에서 {"outcome":"refusedWithoutFixedDiagnostic","reason":"invariantViolation","detail":<display-only>} 로 답하며, 그 detail은 비규범 표시 전용 문자열이라 어떤 client도 parsing하거나 분기하지 않습니다.

Canonical params-digest preimage은 key를 ascending order로 정렬한 뒤 RFC 8785 JCS를 적용한 bytes입니다. 이 preimage 정의는 RFC-002와 공동 소유하며 RFC-002의 정의와 항상 byte-for-byte 동일해야 합니다. Key 정렬 또는 JCS 규칙을 독립적으로 바꾸지 않습니다.

현재 SDK 개발자는 target input의 일반 Python parameter annotation과 px.Results annotated field에 type을 한 번 선언합니다. px.input(...), px.result(...)px.setting(...)은 그 선언부에 description·unit·required를 더하는 current facade의 metadata marker이고, px.field(...)contract_only인 계획 문법으로 남아 현재 public facade에 없습니다. Flow public port의 unit·description·constraint는 flow.input(...)flow.result(...)가 소유합니다. V1 Component companion descriptor의 port shape는 Python annotation에서 유도합니다. PXFLOW Studio는 materialize된 Flow와 Node port 계약을 읽고, Report Workbench는 같은 계약으로 authored value와 public input/result의 호환성을 확인합니다. 후속 admitted Component의 host projection과 MCP resolver도 같은 TypeDescriptor를 사용해야 하지만, 현재 installed Component editor나 MCP activation 경로가 있다는 뜻은 아닙니다.

지원하는 입력·결과 타입

값의 크기와 생김새에 맞는 type을 선택합니다. 숫자 하나는 scalar, 이름 있는 여러 값은 record, 같은 record의 여러 행은 table, PDF와 큰 결과 파일은 artifact를 사용합니다. Public port는 다음 kind만 사용합니다.

text
boolean · int64 · float64 · decimal · string · enum
date · timestamp · duration · record · list · table
binary · artifact · evidence · calculation_trace
  • record는 ordered field descriptor와 조건부 rowKeyField를 가집니다.
  • list는 item type을 가집니다.
  • table은 row record와 ordered field key를 가진 하나의 typed value입니다. table input 하나는 target을 한 번 실행합니다.
  • enum은 stable key 목록과 label projection을 분리합니다.
  • file, image와 PDF는 path string이 아니라 artifact/binary reference입니다.
  • calculation_trace는 Function, Component 또는 Flow가 반환하는 수식·대입·solver·검토 근거의 immutable structured result입니다. arbitrary log, HTML이나 Python source가 아닙니다.
  • unrestricted any와 unknown component fallback은 금지합니다.

Report의 여러 행을 List<T> 또는 Table<Record> public input에 연결하면 collection 하나로 ordinary Flow Run 한 번을 실행합니다. Scalar public input에 여러 행을 각각 전달하려면 explicit Batch Run을 선택하고 case 수와 result merge를 먼저 검토합니다.

Exact TypeDescriptor shape

json
{ "kind": "float64" }
json
{ "kind": "record", "recordKey": "load_case" }
json
{ "kind": "enum", "values": ["s355", "s460"] }
json
{ "kind": "list", "items": { "kind": "float64" } }
json
{
  "kind": "table",
  "row": { "kind": "record", "recordKey": "load_case" }
}
json
{ "kind": "calculation_trace" }

recordKey는 자신을 소유한 FunctionDescriptor, ComponentDescriptor 또는 Flow interface의 typeDefinitions closure에서 exact definition을 resolve합니다. Record definition의 조건부 rowKeyField는 해당 Record를 Table row로 쓸 때 사용할 exact field를 가리키며 그 field는 required·non-null string 또는 int64여야 합니다. enum values는 중복 없는 semantic key 오름차순이며 화면 label은 type 의미에 포함하지 않습니다. list.itemstable.row는 다시 TypeDescriptor입니다.

Direct Flow의 소유 closure는 같은 immutable Flow revision의 optional top-level typeDefinitions.records[]입니다. 각 record definition은 recordKey, ordered fields[]와 optional rowKeyField를 갖고, 각 field는 fieldKey, type, required, nullable을 모두 저장합니다. Closure가 있으면 Flow interface에서 도달하는 record descriptor가 모두 resolve되어야 합니다. 기존 V1 document가 closure를 생략한 경우에는 그 revision을 계속 읽되 record Run value를 object 경계까지만 검증합니다. 현재 Run value나 다른 revision의 moving definition에서 field를 역추론하지 않습니다.

calculation_trace 값은 수식, 대입, solve·iteration·check 구조와 실행 provenance를 담습니다. Report에 표시할 때는 authored value로 복사하지 않고 result mapping이 immutable Result snapshot을 읽습니다.

숫자와 시간

  • int64는 type context 안에서 leading zero 없는 base-10 string으로 직렬화합니다.
  • float64는 finite JSON number만 허용하고 -00으로 정규화합니다.
  • decimal은 canonical decimal string입니다. 문법은 선택적 leading -, 0이거나 leading zero 없는 digit string인 integer part, 그리고 선택적 . 뒤에 trailing zero 없는 digit string인 fraction part입니다. fraction이 없는 -0은 거부합니다. 따라서 01, 1.0, .5, 1., +1, -0은 모두 canonical이 아니며 PX_TYPE_INCOMPATIBLE로 거부합니다. 한 값에 표기가 하나뿐이므로 canonical bytes와 digest를 바인딩 간에 그대로 비교할 수 있습니다.
  • 값의 표기는 값 자체만 나타냅니다. 유효자릿수나 재료 산포처럼 "이 값이 얼마나 잘 알려져 있는가"를 담는 별도 field는 V1 계약에 없습니다. 그런 값은 측정이나 확률 해석에서 나오며 결정론적 계산의 결과가 아니므로, 계산 프로그램 사이의 중립 교환 형식인 V1의 질문이 아닙니다. 약속하는 문장과 담는 field는 함께 존재하거나 함께 존재하지 않습니다. 한쪽만 남기는 것이 계약을 깨뜨립니다.
  • NaN, Infinity, locale 숫자와 표시용 comma는 numeric typed value에 저장하지 않습니다.
  • timestamp는 UTC RFC 3339, date는 ISO 8601 date, duration은 canonical ISO 8601 duration입니다.

unit

Unit은 화면에 붙이는 문자열이 아니라 값의 차원과 변환 규칙입니다. 숫자형 공학 값에는 canonical unit을 선언하고, 단위가 없는 비율에는 1을 사용합니다.

  • UCUM 2.2 (2024-06-17)의 위 32개 case-sensitive canonical code만 사용합니다.
  • dimensionless는 1입니다.
  • generic conversion은 multiplicative 또는 affine {scale, offset}만 지원합니다.
  • nonlinear/logarithmic conversion은 명시적 Function이어야 합니다.
  • type이 맞아도 dimension이 다르면 연결할 수 없습니다.
  • compatible unit conversion은 validator가 plan에 표시하고 Runtime provenance에 남깁니다.

canonical unit discipline

저장·계산·digest되는 값은 항상 해당 물리량의 canonical unit입니다. 변환은 ingress normalisation과 presentation/export egress에서만 일어나고 그 밖의 어디에서도 일어나지 않습니다. 표시 단위를 바꾸는 일이 저장된 값을 다시 쓰는 일이 되어서는 안 됩니다.

canonical system은 coherent SI입니다.

categorycanonical unit
dimensionless1
lengthm
masskg
times
anglerad
forceN
stress/pressurePa
momentN.m
densitykg/m3
accelerationm/s2
temperatureK
  • ingress: 사용자가 제출한 값은 MeasuredDecimal이며 아직 canonical이 아닙니다. normalise()가 이를 canonical unit으로 변환해 CanonicalQuantity를 만듭니다. 이미 canonical인 값도 같은 문을 지나고, 그때 변환은 exact identity입니다.
  • storage/calculation: CanonicalQuantity만 저장·계산·digest에 들어갑니다. private field와 canonical unit을 검사하는 단 하나의 constructor를 가지므로, 이 type을 들고 있다는 사실 자체가 ingress normalisation을 통과했다는 증거입니다. 새 call site가 잊을 수 있는 검사가 아닙니다.
  • egress: CanonicalQuantity::present_in(target)CanonicalQuantity가 아니라 PresentationQuantity를 반환합니다. 이 type은 public constructor가 없고 Deserialize도 없으며 저장 가능한 값으로 가는 경로가 없습니다. 따라서 표시 변환 결과는 저장될 수 없습니다.
  • 사용자 재제출: 사용자가 3.28 [ft_i]처럼 보고 있는 값을 다시 입력하는 것은 별개의 일이며 계속 동작합니다. into_resubmitted_input()이 그 값을 새 ingress input으로 돌려주고, 다른 모든 입력과 똑같이 normalise()를 지나 canonical value가 됩니다. 금지되는 것은 표시 변환의 조용한 write-back뿐입니다.
  • moment는 N.mkN.m를 허용하고 canonical unit은 N.m입니다. 두 방향 변환은 exact이며 1 kN.m = 1000 N.m입니다. MN.m는 승인되지 않았습니다. Density, acceleration, temperature에는 owner가 지정한 canonical code만 있습니다. 특히 Cel[degF]는 affine unit이므로, temperature에 추가하려면 각 code의 승인을 받은 뒤 genericConversionFormsaffineMembers가 이미 선언한 {scale, offset} 경로를 registry conversion planner에 연결해야 합니다. 현재는 그 경로를 사용하는 registry code가 없습니다.

Diagnostic envelope

입력이나 연결을 사용할 수 없을 때는 화면마다 다른 문자열을 반환하지 않습니다. 모든 제품이 같은 diagnostic code와 오류 위치를 받고, 각 화면이 이를 사용자 언어로 설명합니다. 사용자는 무엇이 잘못됐는지와 다음에 할 일을 보고, 개발자는 같은 diagnosticId로 실행 기록을 찾을 수 있습니다.

json
{
  "code": "PX_UNIT_INCOMPATIBLE",
  "path": "/flow/nodes/resistance_check/inputBindings/span",
  "severity": "error",
  "retryable": false,
  "params": {
    "sourceUnit": "kN",
    "targetUnit": "m"
  },
  "suggestedAction": "SELECT_COMPATIBLE_PORT",
  "diagnosticId": "opaque-correlation"
}
  • path는 RFC 6901 JSON Pointer이며 root는 빈 문자열 ""입니다.
  • code, path, severity, retryable, params, suggestedAction은 항상 포함합니다. 추가 parameter가 없으면 params는 빈 object이고, severityerror, warning, info 중 하나입니다.
  • params는 locale-independent structured values입니다.
  • 사용자 문구는 UI가 code + params로 지역화합니다.
  • diagnosticId는 server correlation이며 Local/offline 진단에서는 생략할 수 있습니다.
  • 여러 진단은 severity(error, warning, info)의 선언 순서 뒤에 path, code, canonical params digest를 각각 ascending으로 적용해 정렬합니다.
  • 이 object가 HTTP, MCP, SDK와 UI가 공유하는 canonical Diagnostic wire shape입니다. Localized message, recoveryActions[] 또는 surface별 자유 형식 field를 같은 object에 추가하지 않습니다. 복구 동작 하나는 suggestedAction, 추가 선택지는 별도 typed candidates 또는 nextActions response field로 제공합니다.

v1 core stable code registry

다음 표는 type·unit·numeric·Flow·Report mapping·Runtime core가 소유한 v1 stable code 집합입니다. PX_ prefix는 core가 예약하지만, core 밖의 업무 영역은 자신의 계약 문서에서 같은 envelope와 명명 규칙으로 code를 소유합니다.

영역 code 소유 문서decision record
organization-access-and-policy.mdRFC-006
report-output-and-external-delivery.mdRFC-008
../integrations/mcp-and-llm.mdRFC-010
publication-and-embed-delivery.mdRFC-011

이 네 문서 밖의 사용자·API 문서는 새 PX_ code를 만들지 않고 아래 core 표의 code를 그대로 인용합니다.

Component diagnostic은 설치 명령이 아닙니다

아래 package·Component row는 resolver가 반환할 stable code와 target semantics를 고정합니다. INSTALL_PACKAGE, INSTALL_PACKAGE_VERSION, SELECT_COMPONENT, REVIEW_COMPONENT_UPDATERESOLVE_COMPONENT는 typed suggestedAction 식별자이며, 현재 production 서드파티 Component 설치·활성화 UI/CLI/MCP를 승인하지 않습니다. 현재 reader는 exact target·raw settings와 usage-derived partial ports를 read-only로 보존합니다.

code의미기본 suggestedAction
PX_SCHEMA_UNSUPPORTED_VERSION지원하지 않는 production schemaOPEN_READ_ONLY
PX_SCHEMA_UNKNOWN_FIELDunknown core fieldREMOVE_UNKNOWN_FIELD
PX_KEY_INVALIDsemantic key grammar 위반RENAME_KEY
PX_KEY_DUPLICATEscope 안 key 중복RENAME_KEY
PX_REPORT_CONNECTION_NOT_FOUNDexact connectionKey를 current Report revision에서 찾을 수 없음SELECT_REPORT_CONNECTION
PX_REPORT_FLOW_REVISION_NOT_FOUNDReport connection이 고정한 exact Flow revisionRef를 resolve할 수 없음CHOOSE_FLOW_REVISION
PX_REPORT_MAPPING_SOURCE_NOT_FOUNDinput mapping의 Report block·field·table source를 찾을 수 없음SELECT_REPORT_SOURCE
PX_REPORT_MAPPING_TARGET_NOT_FOUNDresult mapping의 Report block·slot·table destination을 찾을 수 없음SELECT_REPORT_DESTINATION
PX_REPORT_MAPPING_CONFLICT같은 Flow input 또는 Report result 위치를 둘 이상의 active mapping이 소유함REVIEW_REPORT_MAPPING
PX_REPORT_MAPPING_INCOMPATIBLEReport source/destination과 Flow public port의 type·unit·shape가 맞지 않음SELECT_COMPATIBLE_PORT
PX_REPORT_TABLE_ROW_KEY_INVALIDselected Table의 row key가 없거나 nullable·중복 상태임SELECT_ROW_KEY
PX_REPORT_BATCH_REQUIRED여러 scalar case를 scalar input에 각각 실행하도록 사용자가 선택함CREATE_BATCH_RUN
PX_OUTPUT_EXISTS생성할 파일과 다른 기존 파일이 있음CHOOSE_OUTPUT
PX_AMBIGUOUS_TARGET검색 후보가 둘 이상SELECT_TARGET
PX_TARGET_NOT_FOUNDfull scope와 semantic key로 지정한 exact target을 찾을 수 없음SELECT_EXACT_TARGET
PX_PACKAGE_NOT_INSTALLEDexact SDK package가 target Project의 admitted installed closure에 없음INSTALL_PACKAGE
PX_PACKAGE_VERSION_MISMATCHProject closure의 package version이 exact ref와 다름INSTALL_PACKAGE_VERSION
PX_PACKAGE_CATALOG_UNAVAILABLESDK package catalog를 조회할 수 없어 exact release를 resolve하지 못함RETRY_PACKAGE_CATALOG
PX_PACKAGE_ACCESS_DENIEDSDK package 또는 release를 읽거나 설치할 권한이 없음REQUEST_PACKAGE_ACCESS
PX_FUNCTION_NOT_FOUNDpinned Function을 resolve할 수 없음INSTALL_FUNCTION
PX_FUNCTION_VERSION_MISMATCHNode contract가 바뀜REVIEW_FUNCTION_UPDATE
PX_COMPONENT_NOT_FOUNDexact package/project owner에 componentKey가 없음SELECT_COMPONENT
PX_COMPONENT_CONTRACT_MISMATCHgeneric/successor V2에서 resolved installed declaration이 saved exact ComponentRef와 충돌하거나 raw settings·usage-derived partial ports를 현재 declaration에 안전하게 admit할 수 없음; generic persisted full/last-verified snapshot 비교를 뜻하지 않음. current V1 Engineering Paper legacy setting 검증은 기존 domain codec 경계임REVIEW_COMPONENT_UPDATE
PX_COMPONENT_UNRESOLVEDinstalled Component의 exact release, descriptor 또는 executable source를 완전히 resolve하지 못함RESOLVE_COMPONENT
PX_PUBLIC_MODULE_INVALIDpublic Python import·symbol·.pyi가 descriptor와 불일치FIX_PUBLIC_API
PX_DEPENDENCY_RESOLUTION_FAILED요청 range와 channel trust policy를 만족하는 compatible package release를 고정할 수 없음SELECT_COMPATIBLE_VERSION
PX_REQUIRED_INPUT_UNBOUNDrequired input 연결 없음CONNECT_INPUT
PX_PORT_NOT_FOUNDexact port key 없음SELECT_COMPATIBLE_PORT
PX_PORT_DIRECTION_MISMATCHinput/result 방향 오류SELECT_COMPATIBLE_PORT
PX_TYPE_INCOMPATIBLEclosed type/shape 불일치SELECT_COMPATIBLE_PORT
PX_UNIT_INCOMPATIBLEunit dimension 불일치SELECT_COMPATIBLE_PORT
PX_CARDINALITY_AMBIGUOUSdirect typed Run request의 scalar·list·table shape를 하나로 확정할 수 없음FIX_RUN_REQUEST_SHAPE
PX_FORMULA_REFERENCE_NOT_FOUNDFormulaExpression의 exact value reference를 찾을 수 없음SELECT_FORMULA_REFERENCE
PX_FORMULA_OPERATOR_UNSUPPORTED지원하지 않는 formula operator 또는 operand shapeREWRITE_FORMULA
PX_FORMULA_SHAPE_INCOMPATIBLEscalar·vector·matrix shape가 연산과 맞지 않음FIX_FORMULA_SHAPE
PX_FORMULA_DOMAIN_ERRORcore math operator 또는 다른 formula operation의 수학적 정의역을 벗어남FIX_FORMULA_DOMAIN
PX_FORMULA_COMPLEXITY_LIMITFormulaExpression의 node 수 또는 depth가 배포 한도를 초과함SIMPLIFY_FORMULA
PX_SOLVER_CONFIGURATION_INVALIDmethod, unknown, initial value, tolerance 또는 branch 설정이 유효하지 않음REVIEW_SOLVER_SETTINGS
PX_SOLVER_DID_NOT_CONVERGE허용한 iteration 안에서 수렴하지 않음REVIEW_CONVERGENCE
PX_FLOW_CYCLEFlow connection cycleREMOVE_CYCLE
PX_GROUP_INVALIDGroup member가 둘 미만이거나, member 중복·다중 Group membership 또는 nested Group을 요청함FIX_GROUP
PX_PLAN_EXPIRED검토한 Plan의 유효 시간이 끝났거나 pinned precondition이 더 이상 유효하지 않음REFRESH_AND_REPLAN
PX_PLAN_MISMATCHApply의 plan digest, target, expected generation 또는 command body가 검토한 Plan과 다름REFRESH_AND_REPLAN
PX_GENERATION_STALEexpected generation 불일치REFRESH_AND_REPLAN
PX_MERGE_CONFLICTcurrent revision과 proposed command가 같은 semantic path를 서로 다르게 변경함REVIEW_CONFLICTS
PX_SOURCE_EDIT_NOT_SAFESDK-linked 변경을 기존 source에 손실 없이 표현하거나 rematerialize parity를 증명할 수 없음OPEN_SOURCE_OR_CREATE_NATIVE_COPY
PX_TARGET_NOT_PORTABLEsession-only target이 저장·내보내기에 남음ATTACH_DEPENDENCY
PX_PERMISSION_DENIEDcapability 없음REQUEST_ACCESS
PX_CAPABILITY_DENIEDexecution target의 runtime capability 거부REVIEW_CAPABILITY
PX_RESOURCE_LIMITCPU/memory/time/result-size budget 초과REDUCE_WORKLOAD
PX_FUNCTION_FAILEDsanitized Function target execution failureOPEN_DIAGNOSTIC
PX_COMPONENT_FAILEDsanitized Component execution failureOPEN_DIAGNOSTIC
PX_RESULT_NOT_FOUNDrequested result 없음SELECT_RESULT
PX_RESULT_STALEsource/revision과 result가 다름RUN_AGAIN
PX_EFFECT_INDETERMINATE외부 effect 결과 확정 불가RECONCILE_EFFECT
PX_DOCUMENT_LEGACY_FORMAT이전 PXFLOW 포맷으로 작성된 documentOPEN_READ_ONLY
PX_DOCUMENT_MALFORMEDdecode 불가능한 documentCHOOSE_ANOTHER_FILE
PX_RUNTIME_UNREACHABLE실행 중인 runtime 프로세스가 없음START_RUNTIME
PX_RUNTIME_INCOMPATIBLEruntime이 호환되지 않는 releaseUPDATE_APPLICATION
PX_RUNTIME_DISCONNECTED요청 중 runtime 연결이 끊김RUN_AGAIN
PX_BASE_REF_MISMATCH변경이 base로 지정한 ref(Flow·Report는 revisionRef, Function은 versionRef)가 더 이상 head가 아님REFRESH_AND_REPLAN
PX_HEAD_ALREADY_EXISTS첫 저장인데 해당 key의 head가 이미 존재함REFRESH_AND_REPLAN
PX_PLAN_NOT_FOUNDApply가 지정한 단기 Plan이 없거나 이미 정리됨REFRESH_AND_REPLAN
PX_FUNCTION_USAGE_STALEFunction 변경 Plan 이후 연결된 Flow/Report usage가 달라짐REFRESH_AND_REPLAN
PX_FUNCTION_BASE_TARGET_MISMATCHFunction 변경 command의 base target과 변경 target이 서로 다른 Function을 가리킴REFRESH_AND_REPLAN
PX_FUNCTION_DRAFT_INVALIDFunction draft shape가 저장 가능한 규칙을 충족하지 않음REVIEW_FUNCTION_UPDATE
PX_REQUEST_SHAPE_INVALID요청의 member 집합·JSON kind·값이 해당 operation이 받는 것이 아님FIX_RUN_REQUEST_SHAPE
PX_SOURCE_UNREADABLE호출자가 지정한 local 파일을 읽거나 쓸 수 없음CHOOSE_ANOTHER_FILE
PX_RUN_STATE_CONFLICTdurable Run·Batch 상태가 요청이 가정한 상태와 다름REFRESH_AND_REPLAN
PX_SUBFLOW_DEPENDENCY_NOT_INSTALLED외부 Subflow가 가리키는 Flow를 publish하는 release가 이 Project에 설치되어 있지 않음INSTALL_PACKAGE
PX_EXECUTION_INFRASTRUCTURE_FAILED실행 자료 저장소·worker 시작/응답·결과 저장 실패OPEN_DIAGNOSTIC

SDK package별 Function/Component error는 package namespace를 붙인 uppercase code를 사용할 수 있습니다. core PX_ prefix는 예약되어 있습니다.

surface mapping

surface업무 오류 표현
Rust/NativeDiagnostic[]
Python SDKPxValidationError(diagnostics); expected target 오류는 typed result diagnostic
HTTPoperation에 도달한 요청은 application/json ResponseEnvelope + schema-valid diagnostics; protocol 실패는 RFC 9457 application/problem+json이며 diagnostics 없음
MCP업무 결과는 isError: false + schema-valid structuredContent; router failure만 JSON-RPC error
Studio/Report같은 code를 지역화하고 suggested action 버튼 제공

Stack trace, host path, secret, internal UUID mapping과 다른 tenant candidate는 public diagnostic에 넣지 않습니다.

호환성 기준은 Diagnostic.codeparams입니다. 각 surface가 제공하는 예외·오류 클래스는 같은 사실을 그 언어의 관용구로 전달하는 편의 계층이며, 호환성 단위가 아닙니다. 하나의 code가 여러 클래스로 갈 수 있고 한 클래스가 여러 code를 받을 수 있으므로, 분기해야 하는 호출자는 클래스가 아니라 code를 읽습니다. 클래스는 잡는 데 쓰고, code로 무엇을 할지 정합니다.

Diagnostic vocabulary와 binding failure

V1 suggestedAction은 현재 profile의 50 distinct member로 닫히며 추가는 versioned follow-up contract가 필요합니다. REPORT_UNREADABLE_FILERESTORE_FROM_BACKUP은 명시적으로 거절한 non-member literal이고 dedicated declined-candidate field 밖에서는 vocabulary citation이 아닙니다.

Decode failure는 WASM에서 sentence message를 가진 Error, Python에서 ValueError이며 둘 다 full Diagnostic JCS bytes를 diagnostic member에 보존합니다. Generated TypeScript surface는 PxflowDecodeFailure extends Error { readonly diagnostic: Uint8Array }를 공개하고 caller는 caught unknown을 narrow합니다. RFC-003 correctness gate는 stdlib-Python contract reimplementation으로 accepted diagnostic ordering fixture를 Rust core와 독립 비교합니다.

Python SDK 도메인 실패 분기

공개 SDK에서는 from pipelinexlab import px로 가져온 px.Error를 잡습니다. diagnostics의 code/params와 refusal_reason이 공개 분기이며 메시지와 detail은 표시 전용입니다.

실패 소유 경계공개 분기
Function/Component descriptor 등록authoring-profile의 PX_REQUEST_SHAPE_INVALID member/reason 또는 PX_KEY_DUPLICATE key
Report 열기: 문서 없음PX_TARGET_NOT_FOUND, params.targetKey=<reportKey>
Report 열기: revision 없음PX_TARGET_NOT_FOUND, params.targetKey=<revisionRef>
저장된 Report connection의 Flow revision 없음PX_REPORT_FLOW_REVISION_NOT_FOUND, params.revisionRef=<revisionRef>
Report 또는 연결된 Flow의 반환 bytes가 요청한 revision digest와 불일치빈 diagnostics와 refusal_reason="invariantViolation"
Runtime이 거부한 Flow/Report/Run/Batch/package operationRuntime의 registry Diagnostic을 보존; out-of-envelope 거부는 닫힌 refusal_reason을 보존
worker 평가 실패기존 registry Diagnostic 유지; generic fallback은 PX_DOCUMENT_MALFORMED
사용자 Function/Component 본문 exceptionPX_FUNCTION_FAILED / PX_COMPONENT_FAILED; exception detail과 stack은 표시 전용

Report key와 revision ref는 요청한 식별자 그대로 params에 보존됩니다. 누락을 invariant로 분류하거나 메시지에서 code를 추출하지 않습니다. 아직 개별 분류가 없는 SDK-local Flow/Report authoring, Client/session precondition, packaging/preview와 protocol-shape 예외는 px.Error로 잡을 수 있지만 코드별 복구 분기를 보장하지 않습니다. 이 표는 모든 private exception의 코드 배정을 주장하지 않으며 built-in TypeError는 일반 Python 호출 오류로 유지합니다.