Programming Language

Nocter

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

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

v0.30.0 Phase 1 Process-context and Raw-target Review

Status: completed on 2026-09-03; later qualification finding closed by Phase 2. Phase 1 carries the two target facts that ordinary Nocter source cannot derive—the inherited environment-vector address and both successful result registers of a zero-argument Darwin syscall—then closes their interpretation inside typed standard-library transitions. It does not publish Command, create a child, or execute another image.

Phase 2 found that the authored pair-syscall native case had not been selected into an executable. Once public Command made the operation reachable, ARM64 correctly classified the three-word result as an indirect aggregate and rejected Phase 1's direct-result selector. Phase 2 replaced that selector with validated 24-byte caller storage and added native selection of both process and pair tests. The raw contracts described here remain unchanged; the original executable- qualification claim is superseded by the Phase 2 review.

Reviewed Boundary

The review traced both primitive roles from the closed runtime inventory through their exact bundled-source locators, target-program contract validation, Machine context requirements, ARM64 selection, instruction materialization, authored standard declarations, and native execution. It separately traced the raw Darwin result from std/internal/os/darwin into target-gated std/process state transitions.

The adversarial search covered loss of the second result register, swapped pipe descriptors, carry-set values escaping as successful data, an environment address reconstructed from public UTF-8 views, target constants duplicated in process policy, wait bits decoded by a future caller, partial or interrupted exec-report reads, a missing close-on-exec flag, leaked descriptors on flag failure, speculative wrappers without consumers, and accidental public exposure.

Compiler and ABI Authority

PrimitiveRole remains the single exhaustive semantic inventory. The standard profile binds each new role to one exact source declaration. Target validation fixes visibility, target gate, parameter count, result shape, provenance, and no-allocation eligibility before Machine lowering. Machine context planning treats the environment-vector read exactly like the existing argument and environment queries, so every transitive caller receives the immutable process-context pointer.

ARM64 selection records two new closed instructions. Environment access loads the existing ENVIRONMENT_VECTOR_OFFSET; it neither scans nor decodes the vector. Pair syscall materialization moves the syscall number to Darwin's syscall register, preserves x0 and x1 on carry-clear success, writes errno zero in x2, and on carry-set failure moves the kernel error to x2 while zeroing both value words. No later layer reads condition flags or reconstructs this choice.

The ordinary syscall instruction and two-field SyscallResult are unchanged. The exceptional three-field result is available only to the implicit standard package and only for the exact zero-argument role. This avoids imposing a meaningless second word on every file, time, memory, and process syscall.

Standard-library Authority

std/internal/os/darwin owns syscall numbers, descriptor flags, raw result records, and the only pair primitive declaration. Its native test writes one byte to the pair's second descriptor and reads it from the first, proving register preservation and descriptor order. Both descriptors are closed on every test path.

Target-gated std/process owns typed ForkAttempt, LaunchPipeAttempt, WaitAttempt, and ExecReportAttempt transitions. It alone interprets the fork child marker and wait-status bits. Launch-pipe construction sets close-on-exec on the child report end, retries an interrupted flag operation, and closes both descriptors if setup fails. Exec-report reading owns retry, exact four-byte accumulation, clean pre-payload EOF, malformed partial EOF, excessive read counts, raw channel failure, and rejection payload classification.

An initial review build exposed five raw operation functions that had no consumer before Phase 2. The authored-standard architecture gate rejected them. They were removed instead of hidden behind test-only references. Phase 1 retains only operations it can execute and qualify now; fork, exec, child failure reporting, and wait invocation will enter with the owning orchestration that uses them.

Qualification

The Phase 1 focused gates passed source discovery, checking, and the tests selected at that time. The pair-descriptor case itself was authored but, contrary to the original review conclusion, was not reachable in an executable until Phase 2. Current qualification after Phase 2 passes:

  • complete native standard-library execution, now explicitly selecting real pair-descriptor ordering, a close-on-exec launch channel, clean EOF as exec success, exact errno payload recovery, typed wait classification, and a nonzero inherited environment-vector address;
  • authored-standard discovery and dependency validation, including the no-unused-private-function architecture gate;
  • Machine process-context propagation for independent argument-count and environment-vector readers;
  • the affected runtime-contract, standard-profile, target-program, Machine, ARM64, and native- session library suites.

Complete locked workspace, Clippy, no-default-features, documentation, and repository checks are run before the Phase 1 commit. No open remediation remains. Phase 2 is the next implementation boundary.