Programming Language

Nocter

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

/development/milestones/v0.20.0.md

v0.20.0: Interface Prerequisites and Associative Collections

Status: Phase 0 through Phase 3 complete and reviewed (2026-08-30). v0.19.0 is the latest published release. The Phase 0 review, Phase 1 review, Phase 2 review, and Phase 3 review record the completed implementation boundaries and qualification evidence.

v0.20.0 begins the associative-collection foundation required by practical applications. Phase 0 first makes interface prerequisites a checked language capability so later APIs can state one meaningful bound such as K impl Hash without repeating consequences owned by that interface. Phase 1 now closes the compiler computation-model debt before hashing and HashMap; those APIs remain later phases and do not enter Phase 0 or Phase 1 implicitly.

Phase 0: Interface Prerequisite Closure

The canonical source form uses the existing interface-header where clause:

pub interface ExactSizeIterator where Self impl Iterator {
    pub method &self.remaining_len(): usize
}

Phase 0 gives T impl ExactSizeIterator the statically checked capabilities of Iterator while retaining separate explicit implementation facts on concrete types. The compiler does not create an implementation, infer an associated binding, or search source declarations at a later stage.

Semantic Authority

The declaration capability graph owns:

  • the acyclic dependency graph across every interface predicate;
  • each interface's authored direct prerequisite declarations;
  • the narrower Self-inheritance graph;
  • every uniquely inherited method and associated-type declaration identity;

Checking expands a predicate-keyed worklist from those direct edges after substituting Self, interface arguments, and associated bindings. Each normalized predicate is expanded at most once; diamond inheritance therefore scales with distinct semantic facts rather than declaration paths. Checking separately owns proof-only declaration requirements, evidence-bearing body requirements, proof that each explicit implementation satisfies every prerequisite, and the exact evidence consumed by generic lookup, associated projection, provenance, loans, concrete dispatch, and editor queries.

Each body evidence record retains its authored root, exact prerequisite origin, and specialized predicate. Declaration lowering may retain authored predicate origins for diagnostics, but source positions, rendered names, and declaration order do not participate in the closure. Checking freezes the specialized capability evidence before body analysis. Later stages cannot reconstruct it by walking interface declarations or implementation members.

Completion Gate

Phase 0 is complete only when:

  • the specification defines nominal-interface, equality, ordering, indexing, borrow-coercion, and expansion prerequisites on interface Self through the common where grammar;
  • callable, copy, and binder-refinement predicates remain invalid on interface Self;
  • prerequisite cycles and effective method or associated-type name collisions are rejected without source-order selection;
  • Derived { .Item = T } binds one uniquely inherited associated declaration without creating an alias or duplicate identity;
  • a generic T impl Derived body can use prerequisite methods, associated types, default methods, operators, coercions, indexes, and expansions through frozen evidence;
  • every impl Derived is rejected unless separate explicit implementations and structural operations prove all prerequisites for every admitted specialization;
  • concrete implementation remains explicit and no prerequisite creates another impl fact;
  • ExactSizeIterator requires Iterator, standard-library predicates remove redundant Iterator bounds, and iterator behavior and ABI remain unchanged;
  • hover renders the authored derived header while completion, navigation, references, and rename preserve inherited declaration identities from ordinary semantic queries;
  • focused conformance, formatter, declaration, checking, native, and language-server tests cover direct, transitive, generic, associated-binding, structural, cycle, collision, and unsatisfied cases;
  • complete workspace tests, warnings-denied all-target Clippy, formatting, generated documentation, and repository integrity checks pass;
  • the final review finds no compatibility syntax, implicit conformance, repeated prerequisite traversal, source-text inference, duplicate associated identity, order-dependent selection, or downstream semantic reconstruction.

Non-goals

Phase 0 does not add Hash, Hasher, HashMap, dynamic interface values, interface-specific adapters, automatic implementation inheritance, or a second prerequisite spelling inside an interface body. Later v0.20.0 phases require their own accepted API and completion gates.

Phase 1: Incremental Semantic Computation

Status: complete and reviewed (2026-08-29).

The revision owner and semantic session result are now separated, the domain-independent computation kernel is established, and package topology, package graph loading, and workspace discovery reuse unchanged source parsing through one validated syntax-product binding. Stable canonical-path queries now form source_text -> parse; overlay membership, per-source editor bytes, and filesystem changes are disjoint inputs. The package root probe and graph no longer parse the same retained bytes twice. Speculative semantic mutations use an isolated candidate database. Source-neutral declaration syntax and module-surface queries are now connected: a body-only edit preserves the source surface fingerprint and reuses the containing module query without execution. Declaration syntax now owns stable surface locators that rebind non-body nodes and tokens into the current syntax tree while making body descendants unaddressable through a declaration product. Declaration lowering emits one source-neutral projection recipe and materializes semantic frontend bindings plus the editor index from that single recipe; documentation is refreshed from current syntax, and body-local imports remain outside it. Accepted declaration programs can create owned checking branches without rebuilding their decisions. Those source-neutral values are now owned by ReusableDeclarations, separately from current frontend bindings and source indexes. Declaration and analysis now share the exact immutable discovery snapshot rather than cloning a generation-local graph. Discovery now publishes a canonical source-neutral semantic topology surface for the declaration query; source contents and body-local imports are excluded, resolution kinds are validated, and owning contracts supply stable encoded vocabulary. Reusable declarations now materialize directly against a verified current source domain: module/path/kind keys must match, stable locators refresh every source identity and documentation attachment, and body-local imports join through the frozen physical-to-semantic module mapping without rerunning topology. The private semantic subsystem in nocter-compiler-computation now composes topology and module surfaces into declaration-scope input. Accepted declarations are reused across body-only edits and session checking continues from an owned semantic branch plus freshly materialized current projection. Declaration symbols are now a stable reusable prefix; exact current-body spellings are appended only to the checking branch, so new local and member names cannot invalidate or corrupt declaration identity. Rejected declarations carry their diagnostic and recovery authority in an exact path/bytes/source-identity domain; session continues from an owned branch without a second declaration traversal. Body query migration now has its exact input substrate: syntax publishes each executable block under a stable declaration locator, and workspace orchestration atomically stages path-plus-locator body inputs. Name-resolution and checker queries still need to consume them. Instrumented tests prove exact source-text, parse, source-surface, and module-surface execution/reuse counts and compare warm multi-revision analysis with a fresh analysis of the same final source. Program-wide checking preparation is now query-owned as well: the source-neutral ProgramEnvironment, type/copyability authority, interface implementations, construction surfaces, instance operations, drops, body assumptions, and capability evidence are reused across body-only edits. Current body symbols and SourceAccessTable no longer live in that reusable owner; session attaches them through an explicit current-generation branch. Lexical resolution is now a real per-body query. Its reusable recipe stores body-local syntax locators and spellings instead of current NodeId, SourceId, span, or Symbol identities, and session materializes every recipe into one current name arena and source projection without resolving names again. A shared exact-current context prevents each initial body query from rebuilding the full projection; its unchanged semantic fingerprint stops sibling invalidation. Instrumentation proves that an edit which changes one body and shifts a sibling's syntax-arena IDs executes exactly one body-name query and still equals fresh analysis. Typed-body success migration is now query-owned. A body type-extension recipe separates types from the immutable prepared-program prefix and body-local structural additions, and binds closure types through body-local closure identities. Replaying after an unrelated body adds types or closures preserves structural meaning without retaining its allocation order. The body checker now opens every body from the same prepared semantic prefix and an empty closure domain. Successful type and closure contributions replay in canonical order, and a closed rebinder updates all checked operations, places, selections, generic substitutions, iterations, and opaque witnesses. The successful checked graph carries no current source, syntax, span, or symbol identity. References, node origins, and associated-type completion sites use one body-local source recipe; local and capture declarations are restored from the lexical recipe rather than duplicated. Lexical and typed queries share one private current semantic context, so declaration projection is not rebuilt for the two responsibilities. Session replays the complete query-owned body set in canonical BodyId order and does not check those bodies again. Instrumentation proves that a single-body edit executes exactly one lexical and one typed query, reuses the shifted unchanged sibling, and equals a fresh analysis. Authored typed rejection is now an exact-current query outcome: successful siblings replay into editor evidence and session assembles interruption-aware BodyAnalysisRecovery without rechecking. Authored lexical rejection follows the same boundary. Its current diagnostic and optional source-neutral lexical prefix form a complete canonical body-name set; session materializes NameAnalysisRecovery without rerunning resolution. Instrumentation proves that an edited rejecting body executes once, reuses an unchanged shifted sibling, and equals fresh analysis. Program-wide authored preparation rejection is now an exact-current query outcome as well. It retains the exact rule category, declaration recovery, and interface-repair capability; session opens an owned branch instead of repeating preparation. An exact-current edit test matches fresh analysis. Canonical body replay plus ownership, provenance, loan, opaque-witness, and semantic completion now form one exact-current whole-program query. It shares the body context's sole current declaration projection, publishes either a branchable CheckedProgramOutput or the exact BodyCheckFailure, and executes once after an edited body while unchanged lexical and typed siblings remain reused. The session-side typed-body finalization path has been removed; unavailable finalization after a complete typed set is an integrity error rather than a recomputation fallback. Authored lexical and preparation failures, declaration recovery, and incomplete syntax now remain in the same query-owned model. A top-level exact-current analysis query is the sole source-complete workspace/session handoff; unavailable intermediate authority is an integrity failure rather than an eager fallback.

Phase 1 replaces eager affected-scope recompilation with a revision-pinned, demand-driven query model. The adopted cross-crate contract is Incremental Computation Boundary. The existing immutable-generation, typed-recovery, semantic-presentation, and protocol boundaries remain authoritative.

Completion Gate

Phase 1 is complete only when:

  • accepted document revisions are owned outside semantic analysis and physical paths end at the workspace-planning boundary;
  • analysis consumes a session-owned semantic result and cannot invoke compiler stages;
  • query dependencies are recorded by evaluation rather than duplicated in feature-specific or workspace invalidation lists;
  • unchanged parse, package, module-surface, declaration, and body products are reused by exact opaque keys and deterministic fingerprints;
  • a body-only edit does not parse or check unrelated sources and bodies;
  • an unchanged public module surface stops invalidation before dependent modules;
  • semantic products and their source-projection contributions are published inseparably;
  • complete and recovered evidence use the same computation graph and retain explicit coverage;
  • generation-local IDs cannot be used as cross-revision query keys;
  • instrumented tests prove which queries were recomputed, and warm incremental results equal fresh results for the same final revision;
  • CLI, LSP, diagnostics, rename, and code actions preserve their current public behavior;
  • architecture tests, complete workspace tests, warnings-denied all-target Clippy, formatting, generated documentation, and repository checks pass;
  • final review finds no eager compatibility pipeline, manual downstream invalidation authority, stale semantic/source join, or compiler invocation hidden inside analysis.

Non-goals

Phase 1 does not add background execution, request cancellation, persistent disk caches, remote indexes, parallel backend work, hashing APIs, or associative collections.

Completion Record

Phase 1 completed on 2026-08-29. The final review records the corrected fallback, recovery, finalization, source-authority, and top-level handoff design plus its qualification evidence. No required Phase 1 work remains.

Phase 2: Unified CLI and LSP Query Entry

Status: complete and reviewed on 2026-08-30.

Phase 2 removes the remaining execution-model split between direct commands and persistent workspace analysis. A command creates an ephemeral compiler-computation owner, while the language server retains that owner across accepted workspace revisions. Both publish source inputs, discover through the same computed syntax provider, demand the same closed unit analysis query, and enter target construction through the same session consumer. Lifetime and reuse policy may differ; semantic stage order and recovery meaning may not.

The target flow is:

CLI command --------------------> ephemeral compiler computation
                                                        |
workspace accepted revision ---> persistent compiler computation
                                                        |
              source input -> parse -> discovery -> semantic publication
                                                        |
                                          closed unit analysis query
                                           /                    \
                                 complete semantics       incomplete syntax
                                           \                    /
                                              session consumer
                                                    |
                                           target construction

The shared compiler-computation boundary owns source-text and parse queries, declaration and body surface composition, atomic semantic input publication, and the sole complete-versus- incomplete analysis demand. Command and workspace layers continue to own their physical input, package acquisition, revision lifetime, and presentation policies; they cannot invoke or order semantic stages.

The completion review reopened Phase 2 to close enforcement gaps. Source syntax now requires an owner-bound current revision token, every discovery-owned package-root probe receives that same provider, and command graph inspection uses the shared computation entry. Semantic result types are exported through nocter-semantic-product, so session cannot depend on query execution. Root executable closure retains its declaring target program internally, and package resolution advances its filesystem revision only after publishing packages or committing generated lock source.

One exact-current unit-analysis product owns the discovery snapshot once and retains either the closed source-complete program outcome or the closed incomplete-syntax outcome. Session exposes one consumer for that product and remains the sole owner of target/runtime validation. The direct declaration-lowering/checking pipeline and its public analyze_target, analyze_unit, and compile_target entry points are removed rather than retained as compatibility paths. Native, check, build, run, and test commands will consume the query-backed target result.

Completion Gate

Phase 2 is complete only when:

  • CLI and LSP source parsing use the same query provider and syntax-product binding contract;
  • command compilation uses an ephemeral instance of the same compiler-computation owner retained by workspace analysis;
  • one exact-current query product selects complete versus incomplete syntax and owns the sole discovery snapshot crossing into session;
  • session exposes one query-result consumer and cannot invoke declaration lowering, checking preparation, name resolution, typed-body checking, or semantic finalization;
  • command, native, test, and workspace callers cannot select semantic phase order or reconstruct a missing query product;
  • the old eager semantic pipeline and direct semantic entry points are deleted without aliases, wrappers, feature flags, or compatibility fallback;
  • successful targets, authored diagnostics, incomplete-source recovery, editor capabilities, and native output are equivalent between the ephemeral and persistent owners;
  • instrumentation proves that a one-shot command executes the same semantic query families as a fresh workspace analysis and that persistent workspace reuse remains unchanged;
  • architecture tests freeze the shared owner below command/workspace policy and keep session free of semantic compiler-stage calls;
  • complete workspace tests, warnings-denied all-target Clippy, formatting, generated documentation, and repository integrity checks pass;
  • final review finds no duplicate source parser, semantic scheduler, recovery traversal, target transition, source authority, or caller-selected fallback.

Non-goals

Phase 2 does not introduce stable declaration keys, module-local declaration checking, feature-demand editor analysis, cancellation, parallel evaluation, persistent caches, incremental parsing within a changed file, hashing APIs, or associative collections. Hashing and associative collections remain a later phase and require a separately accepted public API design.

Completion Record

Phase 2 introduced nocter-compiler-computation as the only compiler query owner used by command and workspace analysis. Commands retain it for one invocation; workspace analysis retains it across accepted revisions. Both package/discovery paths request syntax from its computed provider, publish one exact discovered unit, demand the same complete-or-incomplete unit query, and pass that closed product to nocter-session::analyze_unit_from_query.

The old eager session pipeline and its analyze_target, analyze_unit, and compile_target entries were deleted. Native compilation now accepts only a CompiledTarget, so it cannot reopen discovery or semantic work. Architecture tests reject command/workspace dependencies on semantic stage crates and reject semantic-stage calls from session.

Migration testing exposed two pre-existing source-authority defects and closed them at their owners. Discovery had reused a package-declaration syntax tree as a module source tree solely because both represented the same physical path; it now requests the exact source-file parse goal. Package-state transactions had returned a package graph captured before their own generated-lock source commit; they now revalidate through the injected resolver and return the post-commit snapshot. The Phase 2 review records the final boundary audit and qualification evidence.

Phase 3: Dependency-Local Exact Selections

Status: complete, reopened, corrected, and reviewed on 2026-08-30.

Phase 3 removes the parallel top-level #lock directive. Each entry in #dependencies becomes the sole syntax authority for both its authored source intent and its optional exact selection:

#dependencies: {
    json: {
        git: "https://github.com/example/json.git",
        revision: "main",
        commit: "7db21c1000000000000000000000000000000000",
    },
    http: {
        archive: "https://nocter.dev/lib/http.tar.gz",
        sha256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    },
}

The declaration decoder produces one dependency value containing a DependencySource and an optional syntax-bearing exact selection. Resolution still keeps source intent and exact selection as different domain values; syntax integration does not collapse their meaning. nocter fetch inserts only a missing source-specific exact field after validating the complete graph. It does not reserialize #dependencies, change an existing selection, or retain compatibility parsing for #lock.

Completion Gate

Phase 3 is complete only when:

  • Git dependencies accept only optional 40-hex commit, archive dependencies accept only optional 64-hex sha256, and path dependencies accept neither;
  • top-level #lock, its format number, prefixed lock literals, and the independent authored lock map are deleted without aliases or compatibility parsing;
  • each dependency declaration is the sole syntax authority for source intent and exact selection, while semantic source and selection values remain separate types;
  • source generation inserts only missing exact fields, preserves surrounding bytes, comments, newline style, declaration order, and concurrent-edit compare-before-write protection;
  • a complete exact package may remain cached after a rejected source update but cannot enter the graph without its dependency record's exact field;
  • --locked, --offline, graph inspection, fetch, build, test, run, and LSP retain their resolution policies under the new syntax;
  • all active sources, fixtures, specifications, crate contracts, and generated documentation use the new syntax, while historical release records remain unchanged;
  • focused tests cover Git, archive, path, malformed and mismatched fields, missing separators, comments, CRLF, idempotence, concurrent edits, and post-commit graph revalidation;
  • complete workspace tests, warnings-denied all-target Clippy, rustdoc, formatting, generated documentation, and repository integrity checks pass;
  • final review finds no second source-of-truth map, whole-directive reserialization, legacy parser, duplicated source-kind judgment, or caller-dependent update contract.

Non-goals

Phase 3 does not change the --locked CLI policy name or the format-1 package-graph JSON schema. It does not introduce dependency updates, version solving, public Nocter hashing APIs, or associative collections.

Completion Record

The independent authored lock map and complete-block renderer were deleted. One dependency value now carries source intent, optional syntax-bearing exact selection, and its record identity. A dedicated source projection validates the closed effective selection map before inserting only missing source-specific fields. DependencySource owns the shared source-to-selection-kind contract used by graph validation, package state, and source generation.

The repository-wide follow-up added a separate exact-package cache representation owner. Package acquisition seals a deterministic streaming tree manifest; staging overlays, publication races, persistent stores, locked resolution, and offline resolution accept only its verified-root capability. Resolution rejects provisional source-kind mismatches before lookup or transport, and package state rejects an exact repeated driver request instead of depending on caller progress.

The Phase 3 review records the source-of-truth audit, mutation boundary, closed review findings, and qualification evidence.