Oberon RTK

ECS for Control — Round 1 Retrospective

The round-1 outlook tracked against what round 2 delivered: item by item, including the one sketched mechanism the round refuted.

Overview

The round-1 outlook named four things the first evaluation left open, sketched the work to close them, and reserved one mechanism for the future. Round 2 – the EcsControlStore program and its documents – closed all four, mostly more strongly than sketched, and refuted the reserved mechanism. This document goes through the outlook in its own order; what it hands forward is collected at the end, for the round-2 outlook to take over.

The four open items, at a glance:

Left open by round 1 Verdict
the roles are annotations, not declarations delivered beyond – declarations, with five classes
the schedule is hand-written delivered – derived at start-up
access rests on discipline delivered differently – a three-level regime
the storage model is the simplest thing that worked delivered – the value store, arrays split per writer

Deriving the Schedule

Delivered beyond. The roles became declarations – each System's manifest, a value record of token sets, authored in the System's own module and exported read-only. The outlook foresaw produce and consume; the manifests landed with five classes (C, O, P, Cx, Px), separating private state from products and adding the deposit classes for shared facilities – a taxonomy the sketch did not anticipate. The run order is derived from the declarations at start-up, and the registration order is explicitly meaningless.

The outlook promised three construction checks: a second producer rejected, a cycle caught, a dead Component flagged. Round 2 built eight, and around them a check regime: Plan collects every violation before Commit gates, so a broken program reports all its findings in one run; a development build prints the whole derivation; the three coverage checks – the promised dead-Component flag among them – can be waived during development, the structural checks cannot.

The implementation document covers the mechanism; the example program runs it with no check relaxed and no exemption.

One design point the outlook fixed in advance held without amendment: no precedence primitive. Nothing beside data edges orders the Systems – the round's one addition to the dataflow vocabulary, the deposit classes, is itself declared data, and the collector's place after its depositors follows from those declarations like any other edge.

An Enforceable, Checkpointable Store

Enforceable access: delivered differently. The outlook asked for roles "checked by the compiler, not upheld by discipline", the alias workaround gone. The language draws the line here: an exported variable is read-only to every importer – Oberon offers no finer grant, no per-System write right – so the variable half of the store cannot be compiler-policed at all; were it possible, it would be.

Round 2 settled where each rule is held instead: the compiler's share went where it reaches and is final – the locked half read-only by the export rule, a System's read parameters read-only by mode – and the single-writer discipline over the variable half is carried by the manifests, the checks, and the Run/runSystem seam, with the local store pointer, round 1's workaround, now the necessary write path. The aspiration resolved into a position: the compiler where it reaches, checks where it cannot, review at the seams – stated as such in the implementation document.

A checkpointable store: delivered; the payoff carried forward. The store's variable half is one value record – no internal pointers, copyable, comparable, snapshottable in one assignment. The snapshot itself – capture, compare, restore, the recovery motivation's first working demonstration – has not been exercised yet: carried forward, below.

The storage model: delivered. The pointer-per-Component store gave way to the value store, and the open grouping question answered itself on the way: arrays split where the writers differ, so the single-writer invariant holds by construction, and storage layout and token granularity turned out to be independent decisions. The outlook's claim that attributions, schedule, and storage were "one problem seen from four sides" held exactly – round 2 solved them as one coupled step.

Cross-Cutting Systems and the Capability Query

Refuted – the one mechanism the outlook sketched that round 2 disproved rather than built, and the round's most instructive outcome.

The outlook reserved the capability query for the first System that cuts across entity kinds, and its own gating clause – "the query earns its place with the first that does" – resolved negatively: the first cross-cutting concerns arrived, reporting and then tick monitoring, and needed no query.

In a bounded, closed world, membership is authored, not discovered – what a query would find at run-time is written down at design time, and what is written down can be checked. The slot the query was reserved for is filled by service spaces under the deposit classes: participants own slots under per-participation identities, collectors iterate a population, and adding a participant edits declarations, not the collector. Cross-cutting concerns cost the architecture zero new run-time machinery.

The refutation is a result, not a retreat: the query would have discovered at run-time what a control program settles at design time, and the control domain supplied the invariant that made the machinery redundant. The positive form of the claim now opens the concepts document; the mechanism that took the query's place is in the implementation document, running in the example program.

One assignment passes forward with this: the outlook cast recovery's surveys – "every faulted entity", "every entity gone stale" – as queries. They will have to take the authored form instead; whether that holds under recovery's demands is carried forward with the recovery work.

Toward a Framework

Carried forward, advanced. The kernel and its development-build modules now live in the example's own lib directory as framework candidates, alongside the service modules; the extend-not-replace intent stands. The questions the outlook said this step is gated on remain open as predicted – where program-specific sizes live, first among them.

The Next Artefacts

Delivered differently, on both counts. The promised "sibling set of evaluation programs" became one program: round 2's intermediate versions were stages of one exploration, not controlled experiments like round 1's variants, and publishing stages would document the path rather than the result. The promised "follow-up to the concepts document" became two documents: a second edition of the concepts, and a new implementation document – the division into what must hold and what holds it earning its own layer.

The demonstration promised alongside them – the checks proven "by perturbing a working program" – is delivered: the example program demonstrates it – two violations induced by editing two manifest lines, both reported by name in one run, Commit faulting with the construction error. Two of the promised perturbations are shown live, a second writer and a self-consumption; the remaining checks differ only in which set expression trips.

Carried into the Round-2 Outlook

  • the snapshot demonstration – capture, compare, restore; the recovery motivation's first exercised payoff;

  • the framework step – the sizes question and the graduation of the candidates in lib;

  • the horizon, unchanged from round 1: partitioning and second schedules, and recovery built on the store – now joined by what round 2 added to build on: disturbance recording and monitoring over service spaces.

See Also

Last updated: 30 July 2026