Object/protocol contract audit
May 20, 2026 · View on GitHub
Updated: 2026-05-20
Purpose
This is a prerequisite audit for moving collections, reader, runtime, and evaluator code out of the root core package. The goal is to identify the contracts that must become explicit before concrete types can move into core/types/collections, core/reader, or core/runtime.
Breaking internal package paths are acceptable. Compatibility wrappers are not a goal. The risk to avoid is import cycles and vague cross-package reach-through.
Current object-model anchors
The canonical object/protocol surface has moved substantially out of root core and into core/types. Root core no longer owns or aliases Object; callers now use coretypes.Object directly. core/types currently owns:
- the canonical
Objectprotocol, includingGetType() *Type; - source metadata (
Position,ObjectInfo,InfoHolder); - type descriptors/registry/builders and type metadata labels;
- scalar and reader values:
Int,Double,Boolean,Char,String,Time,Regex,Comment; - big numeric values and numeric mechanics:
BigInt,BigFloat,Ratio,Number,Precision,Ops, promotion helpers, numeric compare/min/max/category helpers, rune/native-int bounds, andMakeMathBigInt*helpers; - simple runtime values such as
RecurBindings,Delay, and transient collection implementations (TransientVector,TransientMap); - protocol contracts that are now package-independent:
Equality,Counted,Named,Printer,Pprinter,Formatter,Native,Pending,Comparable,Comparator,Sequential,StringReader,Callable,Conjable,Deref,CountedIndexed,Indexed,Stack,Gettable,Seq,Seqable,Associative,Reversible,Collection,KVReduce,Reduce,Error,Map,Set,Vec,Meta, andRef; - shared collection helpers/contracts such as
MapIterator,Pair,EmptyMapIterator,SafeMerge,EmptyMapIteratorInstance, and iterator error construction; - assertion helpers for
coretypes.*and stdlib I/O return types, using root-installed error callbacks so rootEvalErrorbehavior is preserved; - small generic helpers such as
NamedSlice,ComparatorSlice,NewHash32,WithInfo, andRootObject.
Root core still owns higher-level runtime/object systems that carry root-only concrete types or mutable namespace/evaluator state:
Nil,Var,Proc,Fn, andExInfo;- sorted collections, transients, records, protocol dispatch, unchecked arithmetic procs, hierarchy/protocol/public-form installers, and collection-adjacent runtime/proc helpers that still depend on root construction, metadata propagation, proc/sorted helpers, or evaluator/runtime behavior; their recent arity/error cleanup routes through
core/typesruntime hooks where practical; - namespace/bootstrap/proc systems and generated runtime mutation payloads;
- evaluator/parser/runtime/executor files that still require root
Fn,Var,Expr,LocalEnv, namespace, and frame state.
This means future extraction work should treat core/types as the durable object/protocol package and core/runtime as the owner of runtime leaf primitives/object wrappers where cycles permit, rather than adding new root protocol aliases.
Collections move status and remaining prerequisites
Concrete collection implementations have moved to core/types/collections: vectors, persistent vectors, maps, sets, lists, seqs, and chunks are no longer root core files. Root code constructs them through corecollections.*, and tests/layout_guard.sh rejects reintroducing the old root collection files.
The contract tests still exercise ArrayVector, Vector, PersistentVector, ArrayMap, HashMap, MapSet, list/array/vector/cons sequences, transient round-trips, and sorted collection behavior. Sorted collections and transients remain root-owned or root-adjacent because they are tied to proc registration, comparator callables, and evaluator/runtime behavior.
For any further collection-adjacent movement, preserve or document:
- Equality/hash contract for keys and values.
- Seq contract (
Seqable, empty seq representation,First/Restbehavior). - Persistent update contract (
Assoc,Conj,Without, structural sharing expectations). - Transient mutation contract and ownership/lifetime rules.
- Metadata propagation rules.
- Printing/
ToStringcontract. - Construction API the reader/evaluator/std/generated packages should use. Current state: stale
CollectionConstructionAdapterand its guard have been removed; call sites usecorecollections.*direct constructors. - Protocol dispatch surface required by moved concrete types.
- Runtime hook initialization for errors, arity, formatting, reduced values, nil, and type descriptors.
The collection package owns concrete data structures, not the whole object universe. Runtime/proc/env behavior should move only as coherent runtime batches.
Reader move prerequisites
Before moving reader/parser code, define or document:
- Object construction interface for scalars and collections.
- Tagged literal registration and lookup contract.
- Source metadata/object info attachment contract.
- Namespace/data-reader interaction boundaries.
- Error reporting shape and line/column handling.
- Conditional read feature flags.
Candidate reader package should not know evaluator internals:
core/reader/
├── lexer.go
├── reader.go
├── tagged.go
├── source_info.go
└── conditionals.go
Runtime/evaluator move prerequisites
Before moving runtime/evaluator pieces, define or document:
- Call dispatch contract for
Fn,Proc,Callable, and IR-compiled functions. - Error/panic/ex-info contract.
- Eval frame/source stack contract.
- Dynamic var/thread binding contract.
- Namespace/var deref and symbol resolution hooks.
- Tracing/profiling hook points.
- Concurrency/goroutine runtime ownership.
Candidate packages should avoid mutual imports with collections/reader:
core/runtime/
├── calls.go
├── frames.go
├── errors.go
├── goroutines.go
└── tracing_hooks.go
core/eval/ (future target; not reserved yet)
├── runtime_kernel.go
├── forms.go
├── runtime_kernel.go (including tail-call rewrite/trampoline)
└── compiler_bridge.go
Recommended next code moves
Safe moves before broad object extraction:
- Continue moving pure helpers with no root
Fn/Var/Expr/namespace dependency intocore/ir,core/wasm, andcore/types. - Add tests for extracted helpers before moving callers.
- Keep root-core adapter functions temporary only while their surrounding subsystem is still coupled.
- Keep reader construction behind
readerConstructionwhile reader ownership is still root-coupled; collection construction adapters have been removed in favor of direct constructors until concrete types move fully intocore/types/collections.
Do not yet move wholesale:
- sorted collections/transients whose methods still depend on root proc/comparator/evaluator coupling;
- reader/parser orchestration with namespace/tagged-literal/evaluator side effects;
- evaluator/forms/runtime frames;
- namespace/proc/bootstrap systems.
The next safe moves should continue coherent runtime/env/proc boundary work, generated/bootstrap placement cleanup, or IR/WASM executor work only when their root dependencies are explicit and acyclic.
Checklist status
- Identify object/protocol contracts that block collection moves.
- Identify reader construction/tagged literal contracts.
- Identify runtime/evaluator call/error/frame contracts.
- Confirm broad R5 moves should continue waiting on explicit contracts.