Status: current inferred-facts implementation; final alpha.2 acceptance is pending
Schemas: cellscript-package-interface-v5 (current only), and
cellscript-interface-compatibility-v1
Every successful compile now constructs a canonical public package interface.
It is stored in compile metadata as public_interface; its CKB BLAKE2b-256
identity is stored as interface_hash.
The interface contains only exported items and records the contracts that a consumer or Registry upgrade must preserve:
- canonical module, type, constant, action, lock, and function identities;
- explicit
public,public(package), andprivatevisibility; - type parameters, phantom parameters, value abilities, and Cell lifecycle capabilities as separate fields;
- fields, enum variants, fixed layouts, and type identities;
- callable parameters, source qualifiers, outputs, return types, effects, and entry witness ABI;
- source generic templates and applied types in exported signatures, without implementation-only monomorphizations;
- target, VM, witness, lock-args, source-encoding, Spawn/IPC, and compatibility profile identities;
- the
cellscript-ckb-temporal-interface-v1fixed representation, RFC0017 constructor/decoder inventory, distinct domain names,since_abi, and mechanical migration identity; and - generated-builder and deployment-contract hashes.
Edition 2026 keeps the historical public-by-default behavior for an item with
no modifier. New reusable packages should spell visibility explicitly so a
future edition migration does not silently change the exported surface.
The 0.30 line selects restricted dependency-facing value generics and the
closed fixed_value profile; the normative syntax, derivation, compatibility,
and migration rules are in
CellScript Public Value Generics.
On the experimental 0.26b branch, the bounded native Edition 2027
type_script entry lowers to the existing action interface while its semantic
foundation separately records the exact type-group<T> trigger. The native
lock_script entry likewise lowers to the checked lock interface and records
its exact lock-group authorization boundary. The source edition, public
interface, core semantics, and entry contract remain distinct identities; see
the
Edition 2027 preview grammar.
The experimental cellc migrate --to 2027 command does not decide public API
compatibility or rewrite visibility. It replaces only the one final legacy
entry in a self-contained module, preserves all surrounding source bytes, and
requires the old and candidate core semantic identities and ELF bytes to
match. Full six-dimensional public-interface comparison remains a later
migration gate.
module example::math
public struct Pair<T: fixed_value> {
left: T
right: T
}
public(package) fn sum_pair(pair: Pair<u64>) -> u64 {
return pair.left + pair.right
}
private fn implementation_detail(value: u64) -> u64 {
return value
}
public(package) items are visible to modules in the same package but are not emitted
as dependency-facing exports. private items are local to their module.
Imported public generic templates may be specialized across package boundaries;
the specialization is generated in the template's owning module and linked by
a compiler-internal import. It is never a source-level export.
Edition 2026 compatibility remains public-by-default. When a module mixes an
explicit modifier with declarations that still rely on that default, compiler,
CLI metadata, and editor diagnostics emit W2500 and list the declarations to
classify.
For a source file or package:
cellc interface path/to/package
cellc interface path/to/package --json
cellc interface path/to/package --output target/package.interface.jsonWithout --json or --output, the command prints a compact exported-signature
view and abbreviates the exact six-ability profile as fixed_value. The JSON
envelope and output file contain both interface and interface_hash, with all
constraints expanded. The hash is computed over canonical JSON; reordering
source declarations or replacing the expanded profile with its compact source
spelling does not change the identity after normalization.
The declaration interface and its existing digest retain source type spellings. Renaming a private import alias used by a public field can change the declaration layout/interface digest and the conservative declaration-only comparison. A bare interface JSON document does not establish that two spellings name one owner. Do not infer nominal compatibility from equal offsets, sizes or ELF bytes.
Default native builds retain declaration/owner catalogs when multiple lowered
labels refer to one defining nominal declaration or interface handles require
an independently checked module projection. Those bindings are required
for independent admission even without --source-contracts; the checker
still rejects missing or rebound evidence. The flag requests optional complete
source-contract export, including constant values. It cannot suppress evidence
needed by an executable contract. Ordinary builds without these evidence needs
retain the existing compact output.
For alias-independent nominal compatibility, compile both candidates with
--source-contracts and retain their complete ELF, metadata, lowering record and
source map. Then use:
cellc interface-diff --checked --old old/main.elf --new new/main.elf --jsonThis mode independently verifies each four-file bundle under bounded reads, then
compares the existing qualified checked module projection directionally. The
report schema is cellscript-checked-interface-compatibility-v1; it names both
contract digests and artifact hashes. Same-owner aliases can agree, while a
same-width declaration from a different owner rejects. Missing, malformed,
modified or oversized sidecars reject before a compatibility result. Sidecars
use the same canonical neighboring paths as verify-artifact.
In JSON mode, a breaking comparison exits with E2501 and emits one diagnostic envelope containing the complete comparison fields. It does not print a report followed by a second JSON document. An explicitly requested output file retains the comparison report. This applies to both declared and checked comparisons.
The result covers the checked projected contracts. It does not establish source behavioral equivalence, deployment, peer execution or authorization. It does not replace package/Registry admission or change exact-hash receipt commitments.
cellc interface-diff \
--old target/old.interface.json \
--new path/to/candidate-package \
--jsonThe report classifies changes across six independent dimensions:
| Dimension | Examples of breaking changes |
|---|---|
source_api |
removing an export; changing a type parameter, parameter, return type, or output; tightening a generic constraint |
serialized_layout |
changing fields, variants, offsets, fixed sizes, or type identity |
runtime_abi |
changing an entry ABI, witness placement, target, or versioned VM contract |
effects_capabilities |
increasing inferred facts in any dimension, changing value abilities or Cell lifecycle capabilities |
builder |
changing the generated transaction-builder contract |
deployment |
changing the deployment/runtime identity contract |
A breaking report exits with stable compiler code E2501. Additive exports are
reported as compatible changes; they still change interface_hash, so a
consumer can choose whether it accepts a new exact identity.
Relaxing a generic constraint is source-compatible only when the serialized
layout, runtime ABI, effects/capabilities, builder, and deployment dimensions
remain independently compatible. Changing parameter count, name, order, or
phantom status and tightening any constraint are breaking.
Readers require the complete current v5 interface. Old or mixed generations
reject and must be rebuilt; there is no default temporal/effect contract or
older-interface comparison reader. Callable effects is mandatory: concrete
declarations carry canonical context_reads, lifecycle_ops and process_ops;
uninstantiated generic templates carry explicit null evidence. Missing evidence
is never converted into an empty fact set. Candidate facts must be a subset of
required facts independently in every dimension. See
the effect contract for evidence and lifecycle
boundaries. Changing an exported callable from raw u64 to a temporal domain
remains a source/call-ABI break. Registry publication validates current temporal
and fact fields instead of trusting an arbitrary interface hash.
It also requires the closed value-ability vocabulary in canonical order and the
fixed, serializable, non-linear public generic layout boundary.
CellScript source publication includes the canonical interface and hash in the
signed publish payload. The Registry API recomputes the hash, rejects a
mismatch, requires monotonically increasing SemVer, and compares a candidate
with the greatest predecessor on the same compatibility line. A new major
version (or new 0.minor line before 1.0) may intentionally break the old
interface; an incompatible change within a line is rejected. The standalone
Registry verifier also checks that the stored interface and interface_hash
agree. For ELF bundles, the parser-free artifact checker recomputes the public
interface hash and validates the expanded public generic record before
accepting its typed instantiations.
This is package compatibility evidence, not proof that an artifact is safe or deployed. Registry verification, the typed semantic checker, CKB-VM execution, deployment evidence, and chain commitment remain separate states.
The public interface answers “what can a dependency rely on?” The
cellscript-typed-semantics-v11 record answers “what typed operations and
control-flow facts were lowered?” Its embedded
cellscript-semantic-foundation-v3 additionally answers where values came
from, which transaction roles they bind, how Cells are disposed, where claims
are enforced, and how entry/artifact contracts are identified. These remain
distinct from the package interface hash. Its fixed-Cell binding table records
the resolved source, ordinal, local identity and Script-group membership;
syntactic parameter sources are not physical selectors or authentication.
An explicit policy's tagged export set and outer witness ABI are bound by its
entry contract. The package interface hash does not by itself select or prove a
particular deployed policy; deployment and builder consumers must retain the
selected artifact contract as well.
Generic instantiation v2 separately retains the declaration owner, ordered
parameter constraints and lowered names. Public declarations are cross-checked
against that contract; private and imported instances still undergo argument
and binding checks. Those checks do not provide universal template equivalence
or a compatible-open deployment receipt.
Typed semantics v8 can also name an exact, manifest-declared external verifier
under the trusted-external evidence tier. That record binds the selected
CellDep data hash and delegation operation; it is not part of the package
interface hash and is not a proof of the external program's implementation.
ELF builds additionally bind the typed record to the verified lowering and machine
records described in
CellScript Verified Artifact Boundary.