Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .spec/knowledge/standards/repository-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ metadata:
- 逐 Entity/逐 Voxel/逐包 FFI 必须先证明批处理不足;不得把跨边界调用开销扩散到上层。
- 结果必须可诊断、可取消、可重复;不能以“调用方自行保证”替代契约,panic 必须在 ABI 边界转换为稳定错误。
- ABI/Capability/Error Schema、ID 与 Fixture 只在架构源维护;本仓消费已发布 Baseline,不复制生成器或第二套 Schema。
- Root ABI 消费机制(ADR-040 §7):上游发布物字节级镜像在 [`docs/architecture/abi/`](../../../docs/architecture/abi/README.md)(钉 revision + `.baseline.sha256` 钉 Hash),Rust 侧数值经 `cargo xtask gen-contracts` 从镜像生成,测试与镜像互证;ErrorCode 数值权威只有 `ids/index.json`,Capability bit(D-015)与非 `linux-x86_64-glibc` 布局(D-016)保持不绑定。
- 性能改动记录吞吐、p95/p99、分配、峰值内存、硬件/构建配置和结果确定性范围。
205 changes: 183 additions & 22 deletions crates/lumio-contract-types/src/generated.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,202 @@
//! Architecture-source generated-contract adapter.
//!
//! The architecture source has published baseline id `LGE-V1.4-2026-08-27` and,
//! under ADR-040, the Root ABI bundle at `origin/main:packages/abi/` — this
//! repository is a registered consumer of that bundle (`rootAbi.consumers`) and
//! binds its C Header directly. It is deliberately NOT a consumer of the Rust /
//! C# generated packages.
//! Binds the published Root ABI bundle (`origin/main:packages/abi/`, recorded
//! by ADR-040 — Draft, but the artifacts themselves are published) for which
//! this repository holds `rootAbi.consumers` standing. The values below are
//! transcriptions of the byte-pinned mirror under `docs/architecture/abi/`
//! (pinned revision in its README, hashes in `.baseline.sha256`); the crate's
//! integration tests re-read the mirror and reject any drift, so nothing here
//! is invented. Per ADR-040 §7 this repository consumes the C Header plus the
//! four indices, never the Rust/C# generated packages.
//!
//! Binding is not done yet, so this module is still the internal seam only:
//! opaque newtypes, no public numeric registries, no copied schemas. What the
//! bundle publishes (handle / buffer / status layout, ABI version) is bindable;
//! ErrorCode, Capability bits and Operation ids are still unpublished for this
//! repository's needs. See `layout.rs` for the layout-profile caveat.
//! Still deliberately unbound (treated as absent, not inferred):
//! - `capability_bits` semantics and any bit position (D-015 pending);
//! - any layout profile other than `linux-x86_64-glibc` (D-016 pending);
//! - an `OperationId` namespace (does not exist; identity is the published
//! (`apiTable[].name`, `slots[].slotIndex`) pair).

/// Published architecture baseline this crate binds to.
pub(crate) const ARCHITECTURE_BASELINE_ID: &str = "LGE-V1.4-2026-08-27";

/// Revision recorded by this adapter.
///
/// Until a generated package exists, the seam records the published baseline id
/// rather than inventing a second schema.
/// The bundle carries the baseline id as its revision anchor; the digest
/// chain (`RootAbiBinding`) carries the byte-level identity.
pub(crate) const GENERATED_CONTRACT_REVISION: &str = ARCHITECTURE_BASELINE_ID;

/// ABI package version scalar. Width and layout remain blocked.
const ROOT_ABI_BUNDLE_ID: &str = "root-abi-v1";
const ROOT_ABI_BUNDLE_DIGEST: &str =
"03ca75361fed3ca95f8efd55af2e311ea8300b2635b590ae6d46394d58bc6a39";
const ROOT_ABI_HEADER_DIGEST: &str =
"040451bbde5a4dec3726be5f5a7be4bb934c3f68a1ca87f9c55559cae738efc7";
const ROOT_ABI_COMPILER_NAME: &str = "lumio-abi-compiler";
const ROOT_ABI_COMPILER_VERSION: &str = "1.0.0";
const ROOT_ABI_COMPILER_DIGEST: &str =
"217437fd4755e1a339e2029838cc4a2d2fb305fa05520c8cfd10ea98cc2ff290";
const ROOT_ABI_INPUT_HASH: &str =
"696a58d0525b897b549dd1e432166ae1020835902a5984221a8e60d5d8285bb3";
const ROOT_ABI_LAYOUT_PROFILE_ID: &str = "linux-x86_64-glibc";
const ROOT_ABI_SYMBOL_PREFIX: &str = "lumio_";
const ROOT_ABI_ABI_VERSION: u32 = 1;

/// Identity record of the bound Root ABI bundle (ADR-040 §7 verification
/// obligations: bundle digest, compiler identity, input hash, layout profile).
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RootAbiBinding {
pub baseline_id: &'static str,
pub bundle_id: &'static str,
pub bundle_digest: &'static str,
pub header_digest: &'static str,
pub compiler_name: &'static str,
pub compiler_version: &'static str,
pub compiler_digest: &'static str,
pub input_hash: &'static str,
pub layout_profile_id: &'static str,
pub symbol_prefix: &'static str,
}

pub fn root_abi_binding() -> RootAbiBinding {
RootAbiBinding {
baseline_id: ARCHITECTURE_BASELINE_ID,
bundle_id: ROOT_ABI_BUNDLE_ID,
bundle_digest: ROOT_ABI_BUNDLE_DIGEST,
header_digest: ROOT_ABI_HEADER_DIGEST,
compiler_name: ROOT_ABI_COMPILER_NAME,
compiler_version: ROOT_ABI_COMPILER_VERSION,
compiler_digest: ROOT_ABI_COMPILER_DIGEST,
input_hash: ROOT_ABI_INPUT_HASH,
layout_profile_id: ROOT_ABI_LAYOUT_PROFILE_ID,
symbol_prefix: ROOT_ABI_SYMBOL_PREFIX,
}
}

/// ABI package version scalar (`abi.abiVersion` of the bundle).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct AbiVersion {
_private: (),
pub struct AbiVersion(u32);

impl AbiVersion {
pub const fn raw(self) -> u32 {
self.0
}
}

/// Architecture error-code newtype. No public numeric constants.
/// The published ABI version of the bound bundle.
pub fn abi_version() -> AbiVersion {
AbiVersion(ROOT_ABI_ABI_VERSION)
}

/// One registered `ErrorCode` value. `ids/index.json` is the sole numeric
/// authority (ADR-040 §7); instances exist only in the generated registry
/// tables, so no caller can mint an unregistered numeric.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ArchitectureErrorCode {
_private: (),
id: &'static str,
numeric: i32,
}

/// Architecture operation-id newtype. No public numeric constants.
impl ArchitectureErrorCode {
/// Only the generated registry tables construct instances.
pub(crate) const fn new(id: &'static str, numeric: i32) -> Self {
Self { id, numeric }
}

/// Registered id string, e.g. `"InvalidHandle"`.
pub const fn id(self) -> &'static str {
self.id
}

/// Registered numeric; the value carried by `lumio_status_t` (ADR-040 §3).
pub const fn numeric(self) -> i32 {
self.numeric
}
}

/// Architecture operation-id newtype. Permanently uninhabited: no
/// `OperationId` namespace exists or is reserved — the public identity of a
/// callable operation is (`apiTable[].name`, `slots[].slotIndex`) (ADR-040
/// §7, B-ABI-004 adjudicated not-applicable). Kept only because `lumio-job`'s
/// negative gate consumes the empty iterator.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ArchitectureOperationId {
_private: (),
}

/// Capability-bit newtype. No public numeric constants.
/// Capability-bit newtype. Uninhabited until D-015 lands: V1 freezes neither
/// mask-vs-count semantics nor any bit position, and the ID Registry
/// `Capability` numerics are CoreEngine package-capability enumeration
/// ordinals, not bit positions — deriving a key from either is forbidden
/// (ADR-040 §7).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct CapabilityBits {
_private: (),
}

/// Generated struct size token. No public ABI sizes while the Header is blocked.
/// Byte size of a generated type or struct, as published by the bundle
/// Golden. Constructed only from generated data or measured Rust layouts.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct StructSize {
_private: (),
pub struct StructSize(u32);

impl StructSize {
pub(crate) const fn new(bytes: u32) -> Self {
Self(bytes)
}

pub const fn bytes(self) -> u32 {
self.0
}
}

/// `lumio_status_t`: `int32_t` carrying a registered `ErrorCode` numeric;
/// `0` is success and no other value is reused (ADR-040 §3, ADR-046).
/// Constructible only as success or from a registered code, so an
/// unregistered non-zero status cannot originate in this workspace.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct LumioStatus(i32);

impl LumioStatus {
pub const SUCCESS: LumioStatus = LumioStatus(0);

pub const fn from_error_code(code: ArchitectureErrorCode) -> Self {
Self(code.numeric())
}

pub const fn raw(self) -> i32 {
self.0
}

pub const fn is_success(self) -> bool {
self.0 == 0
}
}

/// `lumio_handle_t`: the Index+Generation+Context encoding of ADR-006
/// (16 bytes, align 8 on the published profile).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(C)]
pub struct LumioHandle {
pub index: u32,
pub generation: u32,
pub context: u64,
}

/// `lumio_buffer_t`: the Ptr+Len+Capacity layout of ADR-017 (24 bytes,
/// align 8). `len`/`capacity` are fixed-width `u64`, never `usize`.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct LumioBuffer {
pub ptr: *mut core::ffi::c_void,
pub len: u64,
pub capacity: u64,
}

/// `struct lumio_core_config_v1`: caller-owned opaque payload. The body is
/// not part of the Root ABI at this granularity and stays guarded by its own
/// leading `struct_size` (ADR-040 §3); it crosses the boundary by pointer
/// only, so this type is deliberately not constructible.
#[repr(C)]
pub struct LumioCoreConfigV1 {
_private: [u8; 0],
}

/// Generated revision does not match the expected architecture baseline.
Expand Down Expand Up @@ -77,3 +225,16 @@ pub fn verify_generated_contract_revision_against(
Err(ContractMismatch { expected, found })
}
}

/// Drift gate for the bundle bytes: an observed bundle digest that differs
/// from the bound `rootAbi.bundleDigest` is a contract drift, not a warning.
/// (CI's `sha256sum -c` proves the mirror file still hashes to the pin; the
/// crate tests prove pin == published digest == this constant.)
pub fn verify_root_abi_bundle_digest_against(found: &'static str) -> Result<(), ContractMismatch> {
let expected = ROOT_ABI_BUNDLE_DIGEST;
if found == expected {
Ok(())
} else {
Err(ContractMismatch { expected, found })
}
}
107 changes: 107 additions & 0 deletions crates/lumio-contract-types/src/generated_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//! @generated by `cargo xtask gen-contracts` — DO NOT EDIT BY HAND.
//!
//! Source of truth: the byte-pinned mirrors under `docs/architecture/abi/`
//! (upstream revision in that directory's README). Regenerate with
//! `cargo xtask gen-contracts` after a mirror update; commit together.

use crate::generated::ArchitectureErrorCode;
use crate::layout::{AbiStructGolden, AbiTypeGolden};

pub(crate) const ABI_POINTER_BYTES: u32 = 8;
pub(crate) const ABI_MAX_ALIGNMENT: u32 = 8;

#[rustfmt::skip]
pub(crate) const ABI_TYPE_GOLDEN: &[AbiTypeGolden] = &[
AbiTypeGolden { name: "lumio_status_t", size: 4, align: 4 },
AbiTypeGolden { name: "lumio_handle_t", size: 16, align: 8 },
AbiTypeGolden { name: "lumio_buffer_t", size: 24, align: 8 },
];

#[rustfmt::skip]
pub(crate) const ABI_STRUCT_GOLDEN: &[AbiStructGolden] = &[
AbiStructGolden { name: "lumio_root_api", declared_size: 64, minimum_size: 32, members: &[
("abi_version", 0),
("struct_size", 4),
("capability_bits", 8),
("lumio_core_api", 16),
("lumio_voxel_api", 24),
] },
AbiStructGolden { name: "lumio_core_api", declared_size: 48, minimum_size: 48, members: &[
("version", 0),
("struct_size", 4),
("reserved0", 8),
("lumio_core_init", 16),
("lumio_core_shutdown", 24),
("lumio_core_last_error_detail", 32),
] },
AbiStructGolden { name: "lumio_voxel_api", declared_size: 32, minimum_size: 32, members: &[
("version", 0),
("struct_size", 4),
("reserved0", 8),
("lumio_voxel_world_create", 16),
("lumio_voxel_world_destroy", 24),
] },
];

#[rustfmt::skip]
pub(crate) const ABI_TABLE_VERSIONS: &[(&str, u32)] = &[
("lumio_core_api", 1),
("lumio_voxel_api", 1),
];

#[rustfmt::skip]
pub(crate) const ERROR_CODES: &[ArchitectureErrorCode] = &[
ArchitectureErrorCode::new("RevisionConflict", 1001),
ArchitectureErrorCode::new("MaintenanceKick", 1002),
ArchitectureErrorCode::new("ReleaseMismatch", 1003),
ArchitectureErrorCode::new("NativeAbiMismatch", 1004),
ArchitectureErrorCode::new("StaleEpoch", 1005),
ArchitectureErrorCode::new("FencingTokenStale", 1006),
ArchitectureErrorCode::new("ManifestMalformed", 1007),
ArchitectureErrorCode::new("ManifestUnsupportedVersion", 1008),
ArchitectureErrorCode::new("ManifestDigestMismatch", 1009),
ArchitectureErrorCode::new("ArtifactMissing", 1010),
ArchitectureErrorCode::new("ArtifactDigestMismatch", 1011),
ArchitectureErrorCode::new("SignatureMissing", 1012),
ArchitectureErrorCode::new("SignatureInvalid", 1013),
ArchitectureErrorCode::new("TrustRootUnknown", 1014),
ArchitectureErrorCode::new("TrustPolicyRejected", 1015),
ArchitectureErrorCode::new("KeyRevoked", 1016),
ArchitectureErrorCode::new("EvidenceMissing", 1017),
ArchitectureErrorCode::new("EvidenceDigestMismatch", 1018),
ArchitectureErrorCode::new("TargetProfileMismatch", 1019),
ArchitectureErrorCode::new("CapabilityMissing", 1020),
ArchitectureErrorCode::new("SymbolMissing", 1021),
ArchitectureErrorCode::new("SymbolCollision", 1022),
ArchitectureErrorCode::new("PackageIdentityConflict", 1023),
ArchitectureErrorCode::new("WorkerPoolDuplicate", 1024),
ArchitectureErrorCode::new("LoaderTimeout", 1025),
ArchitectureErrorCode::new("LoaderCancelled", 1026),
ArchitectureErrorCode::new("LoaderOutOfMemory", 1027),
ArchitectureErrorCode::new("PartialLoadRolledBack", 1028),
ArchitectureErrorCode::new("InvalidHandle", 1029),
ArchitectureErrorCode::new("HandleDoubleRelease", 1030),
ArchitectureErrorCode::new("MessagePermissionDenied", 1031),
ArchitectureErrorCode::new("StaleConnectionGeneration", 1032),
ArchitectureErrorCode::new("ChunkUnavailable", 1033),
ArchitectureErrorCode::new("TargetRevisionUnavailable", 1034),
ArchitectureErrorCode::new("BudgetExceeded", 1035),
ArchitectureErrorCode::new("QueueFull", 1036),
ArchitectureErrorCode::new("CoordinateOutOfBounds", 1037),
ArchitectureErrorCode::new("DirtyChunkNotDurable", 1038),
ArchitectureErrorCode::new("SnapshotBaseMismatch", 1039),
ArchitectureErrorCode::new("SessionMismatch", 1040),
ArchitectureErrorCode::new("RoleMismatch", 1041),
ArchitectureErrorCode::new("ClaimNotGranted", 1042),
ArchitectureErrorCode::new("SessionAntiReplay", 1043),
ArchitectureErrorCode::new("InvalidArgument", 1044),
ArchitectureErrorCode::new("WrongContext", 1045),
ArchitectureErrorCode::new("BufferTooSmall", 1046),
ArchitectureErrorCode::new("CapacityExceeded", 1047),
ArchitectureErrorCode::new("Cancelled", 1048),
ArchitectureErrorCode::new("TimedOut", 1049),
ArchitectureErrorCode::new("ContextClosing", 1050),
ArchitectureErrorCode::new("ContextDestroyed", 1051),
ArchitectureErrorCode::new("PanicBoundary", 1052),
ArchitectureErrorCode::new("InternalInvariant", 1053),
];
Loading
Loading