Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/reviews/v0.18.0-phase-1.md

v0.18.0 Phase 1 Final Review

Status: complete on 2026-08-26. This review covers source-declared named builtin types and the primitive func syntax migration. It applies the repository boundary rule that each responsibility may depend on another responsibility's published contract but not on its implementation details.

Reviewed Boundaries

OwnerPublished contractForbidden knowledge checked
syntaxPrimitiveTypeDeclaration and an ordinary FunctionDeclaration with a primitive modifiersemantic builtin IDs, standard paths, runtime roles
discoveryexact BuiltinTypeInput and PrimitiveRoleInput declaration tokenssemantic arena IDs, namespace construction, source presentation
declaration loweringExportedEntity::BuiltinType, standard ownership, frozen source namespaces, frontend projectionsfilesystem paths, later checking state, editor queries
declarationscanonical builtin module ownership and structural slice attachment authoritysource tokens, locator spellings, discovery traversal
checkingexported name targets and canonical TypeStore identitiesstandard paths, builtin spelling tables, discovery locators
analysissemantic entities, source projections, and declaration documentationparsing builtin names, reconstructing module authority

Findings And Remediation

1. Builtin names had two semantic resolution paths

Body name resolution still contained a spelling switch that manufactured NameTarget::Builtin after ordinary namespace lookup. Header binding had a similar historical direct builtin path. This would have allowed the new declarations and the old implicit mapping to disagree.

Resolution: removed NameTarget::Builtin and every semantic spelling decoder. Header and body uses now resolve ExportedEntity::BuiltinType from the frozen source namespace. Construction calls such as error.new(...) consume that same exported entity.

2. Named builtin ownership had two authorities

The toolchain selected both named type declarations and Scalar, Str, and Error attachment modules. Instance authorization therefore required two independently maintained descriptions of the same ownership boundary.

Resolution: removed the three named attachment variants and renamed the remaining contract to StructuralAttachment. A named builtin's declaration module is its inherent-surface authority. Only StructuralAttachment::Slice remains because [T] has no named source declaration.

3. Invalid primitive types crossed an internal-error boundary

An unselected primitive type could reach reservation without a semantic entity and become InconsistentSurface, even though user source can author that syntax.

Resolution: surface validation now emits source diagnostic E0235 before reservation. The reservation error remains only as an invariant guard after this authored rule.

4. The fallback contract was mislabeled and repeated work

PreparedNamespaces::prelude contained both universal builtins and the package-external prelude. It also searched the toolchain builtin list again for every projected origin.

Resolution: renamed the stored layer to fallback and carry each already validated declaration token through fallback construction. The former monolithic application step is split into resolution, installation, and fallback composition; each substep consumes the preceding value rather than inspecting or reconstructing its work. Namespace freezing performs no second role lookup.

5. Editor capability selection omitted the new entity

Source projection and presentation supported SemanticEntity::BuiltinType, but the central interactive-entity capability filter did not. Header references therefore had semantic bindings that hover could not select.

Resolution: added the entity to the shared interactive capability and added an analysis test covering presentation plus navigation from an application i32 use to std/num/index.nct.

6. Presentation retained a second builtin spelling table

Type rendering used a local exhaustive switch while declaration rendering used the model's canonical spelling.

Resolution: all semantic presentation now calls BuiltinType::spelling(). The syntax crate's contextual spelling classifier remains separate: it is a grammar vocabulary contract, not a semantic identity or standard-library authority.

7. Obsolete syntax and fixtures remained

The unused NodeKind::BuiltinType, legacy primitive name(...) fixture strings, and a test that mixed old and new primitive forms survived the initial migration.

Resolution: removed the node kind and migrated active fixtures and tests. Historical release records and archived design documents remain unchanged as versioned records.

8. Universal and prelude fallback composition could repeat one entity

The complete workspace test exposed a single-file toolchain shape whose prelude module also owned the primitive type declarations. The same builtin then entered the recipient fallback once as a universal builtin and once through the prelude. The collision appeared only when the semantic module namespace was frozen.

Resolution: fallback composition now gives universal builtin names precedence before adding visible prelude entries. The normalization remains in declaration lowering, which owns fallback composition; neither the immutable namespace representation nor later checking and analysis layers contain a duplicate-tolerating exception. Discovery fixtures now carry exact declaration locators through this path, and the language-server token fixture recognizes the resulting exact void binding.

Authority And Flow Audit

The completed flow is:

standard source declaration
  -> discovery-selected SyntaxToken
  -> BuiltinTypeInput
  -> ReservedEntity / ExportedEntity::BuiltinType
  -> frozen module and source fallback namespaces
  -> FrontendDeclaration + SemanticEntity projection
  -> checking and analysis consumers

No later layer searches a package path or declaration spelling to recover builtin authority. SourceIndex receives declaration and reference projections for diagnostics and editor features; it is not an input to type binding, name resolution, instance authorization, or checking. The semantic path uses FrontendBindings, DeclarationGraph, StandardLibrary, and TypeStore.

Final Result

The review found no remaining compatibility parser, named attachment duplication, semantic spelling decoder, repeated declaration-role search, duplicate fallback entry, checking-to-analysis reverse dependency, or contract that requires a consumer to inspect another responsibility's internal state. Named builtin representation remains compiler-owned by design, while its source name, documentation, navigation identity, and inherent extension boundary now have one selected declaration authority.