feat(lab): complete E30 evidence review gate

This commit is contained in:
DCCONSTRUCTIONS
2026-07-27 11:00:32 +03:00
parent a44d7627fd
commit 001d597a89
55 changed files with 15897 additions and 1548 deletions
+18 -1
View File
@@ -634,7 +634,7 @@ with a complete `missioncore.laboratory-method/v1` manifest.
| LAB | Question and admitted input | Required evidence and measures | Exit decision |
| --- | --- | --- | --- |
| **E30 — disagreement audit** | Why did E29 produce 38 conflicts, 13,246 camera-only observations and 21,321 unassociated occupied components? Input is the immutable E29 result plus its exact RAVNOVES00 camera/LiDAR/pose evidence. | Review all conflict episodes and a stratified sample of agree, camera-only, unknown and geometry-only cases. Each reviewed item keeps synchronized camera, point cloud, source time and classification into evidenced causes such as FOV, occlusion, time binding, projection/calibration, sparse return, local-surface error, association error or self/rig geometry. | Freeze a cause distribution and the minimum correction set. Do not tune thresholds before this audit. |
| **E30 — disagreement audit** | Why did E29 produce 38 conflicts, 13,246 camera-only observations and 21,321 unassociated occupied components? Input is the immutable E29 result plus its exact RAVNOVES00 camera/LiDAR/pose evidence. | Run an AI-assisted engineering audit over the stratified immutable set using exact camera + projected LiDAR as the primary evidence and synchronized map-frame 3D as the secondary check. Each item records detector validity, projection alignment, point ownership, confidence and evidenced cause. Route only ambiguous or high-impact cases to human exception review; never label the AI generation as human ground truth. | Freeze a cause distribution and the minimum correction set after exceptions are resolved. Do not tune thresholds before this audit. |
| **E31 — time, transform and self-mask qualification** | Are camera↔LiDAR binding, factory calibration identity, pose age and rig footprint sufficient for E29? | Pin the read-only calibration/profile identities; measure timestamp/pose-age distributions, projection residuals where corresponding evidence exists, offset sensitivity and the effect of a source-defined vehicle/self mask. No hard-coded handheld sensor height and no inferred raw firing time. | Accept one evidenced binding/profile or fail closed and retain diagnostic-only E29. |
| **E32 — camera-first geometry v2** | Does the accepted E31 profile improve consistency without erasing occupied evidence? | Re-run the full 4,489-frame source with the exact E31 profile. Compare E29 and E32 by class, distance, scene interval and cause bucket: agree, camera-only, conflict, unknown, geometry-only, occupied support and excluded samples. Show before/after evidence for every changed conflict episode. | Accept the profile only if conflict/staleness improves without converting unknown or unsupported space to free and without hidden source loss. |
| **E33 — recorded-source-paced fusion shadow** | Can the complete camera-first + geometry pipeline keep up with the recorded source stream on the worker? | Replay E32 at original host pace through bounded latest-wins queues. Record sensor-to-result p50/p95/max, deadline misses, queue depth, replacements, drops, stale results, recovery, CPU, RSS, GPU/VRAM, runtime/container and exact model-weight identities. Commands remain impossible. | Admit a replay-shadow candidate only when accounting is closed, resource bounds are declared and every late/missing result becomes explicit health state. |
@@ -642,6 +642,23 @@ with a complete `missioncore.laboratory-method/v1` manifest.
| **E35 — deterministic degradation and recovery** | Does the accepted pipeline fail safely when one source degrades? | Derive immutable replay variants for camera loss, LiDAR loss, pose staleness, delayed frames, bounded drops and timing offset. Preserve the original source and record every injected transformation. Measure status transitions, recovery time, queue accounting and false confidence. | Pass only if missing evidence becomes camera-only, geometry-only, stale or unknown; never guessed class, false free space or hidden success. |
| **E36 — second-source transfer gate** | Does the result survive another real capture rather than only RAVNOVES00? | First audit the source catalog for a second recording with the required camera, LiDAR, pose, time and calibration identities. Run the accepted E32E35 profile unchanged when such evidence exists. Public GOOSE/RELLIS data may qualify an algorithm but cannot substitute for this K1 transfer gate. | Compare the frozen profile without retuning. If no eligible source exists, keep the gate blocked only in the roadmap/Ops plan: do not publish an empty LAB page, fabricate a result or collect new data by default. |
The current E30 AI-assisted engineering generation is
`e30-engineering-generation-62a4fea10dea9b77f69ceac1af5bf0e4928d9c7716083c22258a03670fe5bd4f`.
It covers all `486` selected items: `403` confirmed, `81` corrected and `2`
retained as `insufficient-evidence` human exceptions. The earlier five-case
generation and its human draft remain immutable history. Frames 1213, 162 and
1823 are now automatic engineering outcomes; only geometry frames 2622 and
4147 require a human decision. It found no systematic camera↔LiDAR
registration failure in the review set. The dominant actionable signals are
detector errors (`110`, including barrier false positives and 21 missed
class-bearing objects), sparse occupied support (`98`), held-track time
freshness (`92`) and self points (`10`). This is diagnostic engineering
evidence, not human ground truth, detection accuracy or safety acceptance. The
exception budget is 1% only for diagnostic residual work and never overrides a
repeated-cause or high-impact blocker. The current queue is `2 / 486` (`0.41%`);
E31 remains blocked until those two decisions freeze the E30 minimum correction
set.
Execution is strictly sequential through E33: E30 determines what E31 is
allowed to change; E31 determines the E32 profile; E32 determines the E33
runtime input. E34 and E35 may proceed only after E33 closes exact accounting.
+5 -1
View File
@@ -125,7 +125,11 @@ The result must explicitly state:
There are not two unrelated laboratory-page templates. Mission Core has one
`LaboratoryWorkTemplate` with fixed slots:
`task → method → evidence → result → details`.
`compact summary → evidence → result → optional reusable details`.
Catalog profile/work selectors precede the template. The compact summary
projects the task, method, principal result, limitation, and retained authority
from typed LAB data; it does not reproduce the complete engineering report.
The evidence slot has two admitted renderers:
@@ -0,0 +1,157 @@
# Architecture audit execution roadmap
Date: 2026-07-26
Status: active
This roadmap turns the architecture audit into bounded implementation and LAB
gates. It does not supersede immutable source/LAB policy, the accepted E29
generation, the Polygon SRS or any authority boundary.
## Non-negotiable invariants
- K1 `lio_pcl` is a registered post-LIO map increment, not a native scan.
- Missing K1 endpoints are not free-space evidence.
- Source, LAB derivative, result and acceptance decision remain separate.
- Camera owns semantic class and track identity; geometry may confirm or
disagree but does not invent semantics.
- Current, held and persistent geometry are separate products.
- Worker and simulation compatibility never grant command or safety authority.
- ROS 2 remains an execution/provider bus; Mission Core owns identity, policy,
evidence and operator history.
## Workstream A — camera-first geometry qualification
| Phase | Deliverable | Depends on | Exit |
| --- | --- | --- | --- |
| A0 — freeze baseline | Preserve E29 and its exact source/method/result identity | Accepted E29 | No mutation, threshold tuning or replacement of the accepted generation |
| A1 — representation admission | ADR 0023, `SensorRepresentationCapabilities v1`, strict algorithm requirements and binary admission | ADRs 0018/0020/0021 | K1 admits endpoint marking and rejects projective free-space mapping in tests |
| A2 — E30 review substrate | Review-pack schema, stratified selector and fixed reason taxonomy covering conflict, agree, camera-only, unknown and geometry-only strata | A0A1 | Every selected item binds native camera, projected/current/rejected points, times, pose and profile identities |
| A3 — E30 engineering audit | Immutable AI-assisted engineering generation, cause distribution and bounded human-exception queue | A2 | Every item has an evidenced verdict or `insufficient-evidence`; ambiguous/high-impact exceptions are resolved; no algorithm tuning before the decision |
| A4 — E31 source qualification | Source-time audit, offset sweep, calibration residual and versioned mount/self-mask profile | A3 | One evidenced binding/profile is accepted or the gate fails closed |
| A5 — TrackGeometry contract | `TrackGeometry v1`, PointSlab, source-index ownership, current/held separation and explicit camera-only/conflict/unknown states | A1 and the E31 profile shape | Contract round-trip, no double ownership, no fake range/class, all rejection reasons retained |
| A6 — E32 full replay | Camera-first geometry v2 over all 4,489 source frames | A4A5 | E29/E32 comparison by cause, class, range and scene; no hidden source loss or false free space |
| A7 — E33 worker shadow | Persistent recorded-source-paced execution with channel-specific deadlines and resource telemetry | A6 | Closed queue/drop/recovery accounting; diagnostic/shadow only |
| A8 — E34/E35 local model | Short-TTL occupied/unknown layers and deterministic degradation suite | A7 | Explicit current/held/unknown aging and safe degradation; planner authority remains false |
| A9 — E36 transfer | Frozen-profile replay on a mounted second real source | A8 and eligible source | Generalization decision without retuning; blocked if no eligible source exists |
The strict critical path is:
```text
A0 → A1 → A2 → A3 → A4 → A5 → A6 → A7 → A8 → A9
```
A5 contract design may start before E31 closes, but the accepted E31
time/calibration/mount identities must be bindable before E32 publication.
## Workstream B — Simulation Polygon
This workstream may proceed in parallel but cannot bypass Workstream A or grant
real authority.
| Phase | Deliverable | Exit |
| --- | --- | --- |
| B1 — finish S1 | Full run lifecycle, canonical `VehicleState`, frame golden tests, Ackermann/Differential mapping, sequence/TTL/heartbeat, watchdog/failsafe, provider loss, restart reconciliation and repeatability report | Deterministic virtual-only provider run with clean stop and zero orphan processes |
| B2 — S2 trusted navigation | Synthetic trusted map → Nav2 → canonical command → PX4 rover adapter → Gazebo | No unknown traversal, footprint collision checking, command expiry/provider-loss stop and repeatable route completion |
| B3 — Virtual K1 | Isaac Sim native scan plus separately degraded K1-like mapped derivative with point/object ground truth | Quantified representation-loss and TrackGeometry quality |
| B4 — unified replay UX | RAVNOVES replay represented inside Polygon | Evidence/replay only; never labelled closed loop |
| B5 — controller/HIL | Controller-in-loop, HIL or physical shadow | Only after S1, S2, E33, E35, Edge Agent and independent safety review |
## Workstream C — field transfer
1. Define a local Edge Agent boundary with local perception minimum, command
TTL, watchdog, failsafe and local evidence.
2. Bind capability profiles to physical unit, firmware family and mount profile.
3. Add authenticated digest-bound source fetch, resumable transfer, job leases,
atomic result publication and restart reconciliation.
4. Add MCAP only as a normalized P1/P2 sidecar; retain MQTT/fMP4 P0 evidence.
5. Require an independent safety gate before any real actuator authority.
## Current implementation slice
- [x] Preserve E29 as the accepted immutable diagnostic baseline.
- [x] Add ADR 0023.
- [x] Add `missioncore.sensor-representation-capabilities/v1`.
- [x] Add strict `missioncore.sensor-algorithm-requirements/v1`.
- [x] Encode the K1 `lio_pcl` registered-map-increment capability profile.
- [x] Prove that endpoint marking is compatible while projective free-space
mapping rejects.
- [x] Implement the first A2 slice: E30 review-pack schema, deterministic
stratified selector, immutable E29 evidence bindings and reason taxonomy.
- [x] Materialize source-bound projected/current/rejected point views for all
486 selected E30 items, retaining lossless frame-local source indices for
selected and candidate points.
- [x] Add a fail-closed read-only E30 API that verifies the materialization,
linked review pack, index and per-item NPZ hashes before publication.
- [x] Add the evidence surface over the immutable selection pack with five
strata, exact camera frame, KB4 LiDAR projection, point ownership and
synchronized map-frame 3D.
- [x] Harden the Control Station application boundary before A3: consume the
Design Guideline packages as the only visual platform, isolate the LAB
feature and CSS, add typed workspace contracts and enforce one-way imports
plus composition-size ratchets.
- [x] Validate the real A2 generation:
`e30-review-pack-faec915a771022cceaf4ee62bece698afc8018d09b6b0ac7602157216fbb3686`
`e30-materialization-841af926d8d28ab93538c46d8f31278a2234c4d1c12c7dc4dc296b249d59735a`.
Counts are 38 conflict, 96 agree, 128 camera-only, 96 unknown and 128
geometry-only. It contains 486 item bindings and 465 deduplicated exact
camera-frame artifacts; `human_review_complete=false` and
`lab_published=false`.
- [x] Implement the A3 collection and finalization boundary: a resumable
append-only reviewer draft with revision/idempotency checks, explicit
reviewer identity and server timestamps, one frozen-taxonomy reason for
every changed stratum, full-coverage finalization and a content-addressed
immutable reviewer generation with cause distribution.
- [x] Replace the owner-facing manual-review form with an isolated A3
engineering-audit surface using only admitted Design Guideline controls.
Camera + projected LiDAR is primary, map-frame 3D is secondary, and the
deterministic readiness triage explicitly carries no semantic verdict.
- [x] Issue the first AI-assisted engineering generation over all 486 immutable
items with explicit producer/method/confidence, three component questions
(detector validity, projection alignment, point ownership) and verdict
`confirmed`, `corrected` or `insufficient-evidence`. The immutable generation
is
`e30-engineering-generation-24f7d73393e1b018596a97813cecac07334d0ce678e9ba73bc5b85e49b2096a3`.
It records 401 confirmed, 80 corrected and five `insufficient-evidence`
decisions with mean confidence `0.8705`. The evidenced cause distribution is
109 detector errors, ten self-point cases, 97 sparse-support cases, 91
time-freshness mismatches and five unresolved ambiguities.
- [x] Issue the corrected A3 generation
`e30-engineering-generation-62a4fea10dea9b77f69ceac1af5bf0e4928d9c7716083c22258a03670fe5bd4f`
without rewriting the first generation or its human draft. It records 403
confirmed, 81 corrected and two `insufficient-evidence` decisions with mean
confidence `0.8730`. Frames 1213, 162 and 1823 are now explicit automatic
engineering outcomes; only geometry frames 2622 and 4147 remain in the
human queue.
- [ ] Resolve only the resulting ambiguous/high-impact human-exception queue
and freeze the minimum correction set and cause distribution.
The current A3 AI-assisted engineering generation covers all 486 items and
retains the exact A2 materialization/review-pack and 42-sheet evidence
identities. It explicitly claims neither human ground truth nor navigation or
safety acceptance and retains `lab_published=false`. The dominant conflict
cause is detector placement on striped road/construction barriers rather than
camera↔LiDAR registration; the `unknown` stratum is dominated by held
world-track time freshness; geometry-only contains both expected static scene
geometry and 21 visible missed class-bearing objects.
A3 is not complete until the two routed human exceptions are resolved and the
minimum correction set is frozen. Earlier generations and drafts remain
historical and are not rewritten or presented as the current product workflow.
A4 remains blocked. No perception threshold changes are allowed before the
exception decision is frozen.
### A3 residual and human-exception policy
- Every selected item is accounted for by an automatic evidenced decision or
an explicit human exception; silent drops are forbidden.
- Human review is limited to genuine ambiguity or a high-impact decision. An
obvious detector, freshness or support outcome remains an engineering
decision even when the result is negative.
- For a diagnostic LAB, unresolved `insufficient-evidence` may occupy at most
1% of the immutable stratified set. This is a residual-work budget, not an
accuracy, navigation or safety acceptance threshold.
- A repeated cause cluster or a high-impact case blocks the gate regardless of
percentage. The 1% budget cannot hide a systematic defect.
- The current queue is 2 / 486 (`0.41%`) and therefore bounded, but A3 still
requires those two recorded decisions before its correction set is frozen.
@@ -0,0 +1,206 @@
# Mission Core product UI and laboratory presentation canon
Status: accepted by product owner, 2026-07-26
## Purpose
Mission Core is an engineering product, not a visual notebook. Experimental
work may change algorithms, evidence, and conclusions without creating a new
GUI for every LAB run. The product surface remains compact, readable,
predictable, and based on the approved NODE.DC Design Guideline.
This document governs Control Station product UI, laboratory summaries,
evidence viewers, and the boundary with complete engineering reports in Ops.
It complements `docs/15_LABORATORY_RUN_CANON.md`, which governs publication and
provenance. New non-LAB surfaces and their placement are governed by
`docs/19_PRODUCT_SURFACE_EXTENSION_PROTOCOL.md`.
Consistency means one visual and interaction grammar, not one universal page
layout. Different operator jobs may use different task-specific compositions
while retaining the canonical shell, controls, states, icons, and code
boundaries.
## Design source of truth
The sibling `NODEDC_DESIGN_GUIDELINE` repository is the only source of visual
components, states, geometry, icons, themes, and page patterns.
Before UI implementation:
1. read `registry/registry.json`;
2. resolve the required component in `registry/components.json`;
3. resolve every icon in `registry/icons.json`;
4. read the relevant component and governance documentation;
5. consume the package export rather than reproducing it locally.
Application CSS may arrange domain content and size a visualization viewport.
It may not redefine canonical button, segmented, select, glass, focus, hover,
active, disabled, window, dropdown, or icon behavior.
If no canonical visual entity satisfies the requirement, implementation stops
for product-owner approval. An approved generic entity is added to the Design
Guideline with registry entry, API, interaction states, documentation, catalog
example, and validation before Mission Core consumes it.
## Allowed Mission Core UI code
Mission Core may own domain renderers and domain composition:
- point-cloud, projection, timeline, camera, map, and diagnostic renderers;
- adapters from immutable evidence contracts to renderer inputs;
- application state and orchestration;
- LAB configuration and concise domain copy;
- layout of domain facts inside a canonical surface.
Mission Core may also own a task-specific workspace composition when a new
operator job cannot be expressed honestly by an existing page pattern. It must
first pass the product-surface protocol; it does not inherit the LAB template
merely because LAB was implemented first.
Mission Core must not own substitutes for general UI controls or surfaces.
Renderer actions use canonical `Button`, `IconButton`, `SegmentedControl`,
`Select`, `StatusBadge`, `GlassSurface`, `WorkspaceWindow`, and canonical
`Icon` exports.
## One laboratory product template
Every LAB uses the same product hierarchy:
1. **Catalog selectors** — profile and immutable LAB run.
2. **Canonical summary** — one compact block, not a full report.
3. **Evidence** — one or more admitted reusable evidence viewers.
4. **Result** — decision-relevant metrics and conclusion.
5. **Technical details** — optional reusable diagnostic component, never a
one-off page.
A LAB provides typed data to these slots. It does not create its own page
grammar, toolbar language, status geometry, or decorative card stack.
### Canonical summary content
The summary must let an operator understand the evidence before opening the
viewer:
- decision question and reason for the experiment;
- immutable physical source and tested bounds;
- pipeline and execution class;
- models, algorithms, tools, and worker/runtime that materially affected the
result;
- experimental feature or configuration under test;
- principal result and known limitation;
- retained command, navigation, safety, and publication authority.
Show short product names and exact identities only where they aid comparison.
Long manifests, hashes, implementation file lists, validation logs, and the
history of rejected approaches belong in Ops.
## Evidence viewer contract
Primary visual evidence is hosted in one reusable viewer frame.
The viewer frame must:
- provide the canonical expand/restore `IconButton`;
- preserve the selected evidence case and view mode while resizing;
- expose mode switching through canonical `SegmentedControl`;
- expose a canonical in-frame layer toggle when an overlay can obscure the
immutable source image; hiding a client-rendered overlay must not trigger a
second backend materialization;
- keep renderer-specific actions inside the frame;
- use the same loading, unavailable, and error grammar across LAB runs;
- remain keyboard-addressable and restore the previous surface on Escape;
- avoid hard-coded product colors and application-local focus/hover states.
### 3D and 2D policy
Choose the default representation from the operator question:
- use **3D** for spatial shape, range, height, topology, surface support,
occupied volume, and relationships between sensor-local objects;
- use **2D** for camera-plane reprojection, bbox/mask agreement, calibration
residuals, field-of-view boundaries, image occlusion, and pixel-space
correspondence.
When both questions matter, expose 2D and 3D as modes of the same viewer. They
must use the same selected case and immutable source indices. Do not create a
second LAB page or duplicate the evidence state.
For E30, **camera + projected LiDAR is the default** because the first review
question is whether a camera claim, its bbox and the projected points refer to
the same visible object. A black pixel-plane scatter without the exact camera
frame is not admissible review evidence. Synchronized 3D remains the secondary
mode for point ownership, shape, range, surface leakage and occlusion checks.
The exact camera frame remains independently inspectable: the projected LiDAR
layer may be hidden without hiding the observation bbox or changing the
selected evidence item.
The 3D scene uses the gravity-aligned map frame; a sensor-local horizontal grid
must not be presented as a measured road or ground plane.
### Automated audit and human exceptions
Evidence readiness, engineering decisions and human review are separate
provenance layers:
1. deterministic triage may verify hashes, bindings, availability and route an
item, but it does not issue a semantic verdict;
2. an AI-assisted engineering generation may issue `confirmed`, `corrected` or
`insufficient-evidence` only against the immutable camera/2D/3D substrate
and must identify its producer, method and confidence;
3. only ambiguous or high-impact items are routed into a human exception
queue;
4. an AI generation is never labelled `human review`, ground truth or
navigation/safety acceptance.
The default product view states the result in one short sentence and keeps
expert evidence and provenance available in the same reusable composition.
The owner is not asked to approve an uninterpretable point cloud or to repeat
the complete engineering audit manually.
## Forbidden product UI
Do not render:
- roadmap steps, phase numbers, next-gate checklists, or internal acceptance
queues;
- raw internal reason taxonomies as chips or footer content;
- debug-only controls, fake progress, mock viewers, or placeholder metrics;
- implementation notes, file paths, stack traces, worker logs, or test output;
- new local button, tab, dropdown, card, status, icon, or focus styles;
- a separate layout because one LAB has a different algorithm.
If information is necessary only for development or governance, place it in
Ops, a report, an ADR, a runbook, or developer tooling.
## Ops engineering report
The complete report for a LAB or architecture milestone lives in the Mission
Core Ops project. Keep the issue description concise and place the report in
titled structured blocks. Use this canonical order:
1. Objective and architecture stage.
2. Decision question and hypothesis.
3. Immutable source evidence and tested bounds.
4. Method, preprocessing, models, algorithms, tools, and identities.
5. Worker/runtime topology and resource policy.
6. Experimental changes and implementation.
7. Validation and reproduced evidence.
8. Quantitative and qualitative results.
9. Regressions, rejected approaches, and honest limitations.
10. Decision: continue, revise, reject, or promote.
11. Next stage and authority that remains forbidden.
12. Acceptance checker with short verifiable items.
The product summary is a projection of this report, never a second independent
narrative.
## Review gate before A3
Before A3 or any subsequent LAB UI change:
1. verify the UI uses the fixed template;
2. verify controls and icons exist in the Design Guideline registry;
3. verify no temporary experiment or roadmap UI is present;
4. verify primary visual evidence can expand and restore;
5. verify every admitted representation answers a named operator question;
6. run typecheck, unit tests, production build, and browser interaction QA;
7. visually inspect normal and expanded modes at representative viewport sizes.
@@ -0,0 +1,228 @@
# Mission Core application component architecture
Status: accepted, 2026-07-26
## Decision
Mission Core adopts the same dependency discipline as the NODE.DC Design
Guideline without copying its application code.
The Design Guideline remains the visual platform:
```text
@nodedc/tokens
@nodedc/ui-core
@nodedc/ui-react
→ Mission Core application
```
Inside Mission Core, dependencies flow in one direction:
```text
typed contracts and data adapters
→ reusable domain components and renderers
→ feature workspaces
→ product registry and reviewed composition roots
→ App shell
```
A lower layer does not import a higher layer. The application owns domain
meaning and data flow; the Design Guideline owns general visual controls,
surfaces, interaction states, icons, and shell geometry.
This dependency direction constrains ownership, not product composition. New
workspaces may have different information architectures when their operator
jobs differ. Their placement and form follow
`docs/19_PRODUCT_SURFACE_EXTENSION_PROTOCOL.md`.
## Why Design Guideline code is not copied
The reusable architecture in `NODEDC_DESIGN_GUIDELINE` is its published package
boundary, registries, validation, and one-way imports. Its living catalog is an
application and is not a source template to paste into Mission Core.
Mission Core consumes `@nodedc/tokens`, `@nodedc/ui-core`, and
`@nodedc/ui-react`. A visual primitive missing from those packages is proposed
and approved in the Design Guideline first. Mission Core does not fork it.
The current `file:` package dependencies are suitable for the local standalone
development contour, but they are not an immutable distribution contract.
Before portable CI or deployment, the packages must be published, vendored with
content verification, or pinned to a verified donor revision.
## Internal layers
### `src/core`
Owns typed domain contracts, parsers, API adapters, state machines, and
domain-specific hooks. It may depend on React for a hook or context boundary,
but it does not import visual adapters, workspaces, or the App shell.
### `src/components`
Owns reusable Mission Core domain components such as observation sources,
timelines, media adapters, and laboratory presentation/evidence frames.
Components may consume core contracts and canonical Design Guideline exports.
They do not select routes, own product navigation, or import workspaces.
### `src/workspaces`
Owns domain composition. A workspace connects core data to reusable components
and renderers. A new domain gets its own module or feature directory; it is not
appended to the central workspace hub.
`workspaces/contracts.ts` is the host contract shared by workspace
implementations. The central `Workspaces.tsx` is a composition hub for existing
generic workspaces, not a home for LAB-specific adapters or evidence logic.
### `src/workspaces/laboratory`
Owns the laboratory catalog feature. It may compose:
- the reusable laboratory presentation components;
- immutable LAB adapters from `core/laboratory`;
- domain evidence renderers;
- the generic spatial workspace through the explicit `SpatialView` contract.
Every new LAB adds a bounded result component and typed data adapter here. It
does not add LAB imports, selectors, styles, or conditional evidence code to
`Workspaces.tsx` or `App.tsx`.
### `src/composition`
Owns reviewed integration imports and registries. Vendor/plugin contributions
enter Core only through this layer and the public plugin SDK. Composition does
not become a second business-logic layer.
### `src/productModel.ts`
Is the typed application registry for roots, workspaces, labels, icons, and
declared capabilities. Navigation and routing project from it rather than
duplicating lists across the App shell.
It is a product registry, not a runtime ontology and not a substitute for
evidence or domain contracts.
New workspaces and roots enter this registry only after their user job and
placement are resolved. The registry must not accumulate placeholder pages for
unapproved future ideas.
### `src/App.tsx`
Owns shell-level orchestration: selected root/workspace, global panels, runtime
providers, and passing typed controllers to a workspace. It must not absorb
domain API calls, per-LAB renderers, or new visual primitives.
## CSS ownership
CSS follows the same feature boundary:
- general workspace composition lives in `styles/workspaces.css`;
- laboratory presentation and E30 evidence layout live in
`styles/laboratory.css`;
- spatial, observation, device, and shell rules remain in their named files;
- plugin CSS is plugin-local and scoped below its contribution root.
Application CSS may arrange domain content. Canonical control geometry and
states remain in the Design Guideline packages. A feature must not add selectors
to a generic CSS bucket merely because that file is already imported.
## Component admission
A Mission Core component is admitted only when all of the following are true:
1. Its responsibility can be stated in one sentence.
2. Its inputs are typed domain data or callbacks, not hidden global state.
3. It does not duplicate a Design Guideline entity.
4. It has explicit loading, empty, unavailable, and error behavior where
relevant.
5. It has no knowledge of unrelated workspaces or vendor implementations.
6. Its styles are feature-scoped.
7. Its contract or behavior is covered by a unit or architecture test.
If the entity is visually generic rather than domain-specific, it belongs in
the Design Guideline and requires product-owner approval before implementation.
## Laboratory feature template
The code shape of a new laboratory increment is:
```text
core/laboratory/eNNContract.ts
immutable API/schema adapter
workspaces/laboratory/ENNResult.tsx
concise summary + admitted evidence + result projection
domain renderer module
only when an existing renderer cannot express the evidence
LaboratoryArchiveWorkspace.tsx
registry/selection composition only
styles/laboratory.css
shared LAB layout; no per-run visual language
```
The complete engineering narrative remains in Ops. The product component
receives a concise typed projection.
## Local ontology decision
Mission Core already has three semantic mechanisms:
1. `productModel.ts` for application navigation and capability declarations;
2. versioned TypeScript/Pydantic/JSON contracts for executable data;
3. `docs/domain-model/mission-core-experimental-vocabulary-v0alpha2.md` for
meanings that are not yet stable enough for Platform Ontology.
These mechanisms are sufficient before A3. A new RDF/graph store, ontology
service, or parallel entity catalog would introduce duplicated identity and
migration work without a current query or integration consumer.
A formal local runtime ontology is introduced only when:
- at least two independent runtime consumers require the same relationships;
- typed contract traversal is demonstrably insufficient;
- ownership, identity, lifecycle, versioning, and migration are agreed;
- the graph answers named queries used by the product or automation;
- promotion or synchronization with NODE.DC Platform Ontology is defined.
Until those conditions hold, new stable meanings extend the versioned local
vocabulary and executable contracts. They do not create a second runtime model.
## Automated boundary gate
`test/applicationArchitecture.test.mjs` enforces:
- no upward imports from core/components into workspaces or App;
- no visual adapter imports from core;
- no local vendor icon library or direct Design Guideline source imports;
- LAB code and CSS remain outside the central workspace buckets;
- central composition files cannot silently return to their previous size.
The line limits are ratchets, not quality targets. When a file reaches a limit,
split a feature; do not raise the limit to accommodate unrelated behavior.
From `apps/control-station` run:
```bash
npm run test:unit
npm run typecheck
npm run build
```
## Known bounded debt
- `App.tsx` remains a large shell orchestrator. Its current size is frozen by a
ratchet; future shell behavior must extract a controller/hook or panel module.
- `Workspaces.tsx` still contains several established generic workspaces. New
domains must be separate modules, and existing ones may be extracted when
their behavior changes.
- `LaboratoryArchiveWorkspace.tsx` is now physically isolated but at its
ratchet. A3 receives its own component/module instead of growing that file.
- Design Guideline dependencies are mutable local `file:` links until a
portable package/distribution decision is implemented.
None of these debts require a new ontology or a copy of the Design Guideline
application.
@@ -0,0 +1,196 @@
# Mission Core product surface extension protocol
Status: accepted by product owner, 2026-07-26
## Purpose
Mission Core must remain coherent without forcing every future capability into
the same page layout. Consistency applies to product grammar; composition
follows the operator task.
The stable grammar is:
- the NODE.DC application shell and navigation mechanics;
- canonical controls, surfaces, icons, states, focus, motion, and responsive
behavior from the Design Guideline;
- one-way code dependencies and feature ownership;
- explicit loading, empty, unavailable, error, disabled, and authority states;
- typed product registry and domain contracts;
- compact product copy instead of implementation scaffolding.
The variable composition is:
- information hierarchy and density;
- map-, scene-, timeline-, list-, table-, graph-, form-, or editor-first layout;
- permanent workspace, transient window, inspector, or view mode;
- renderer arrangement and synchronization;
- task-specific actions and domain facts;
- placement in an existing product root or an approved new root.
Reusing product grammar does not mean reusing one layout. A different operator
job may require a different application composition.
## Surface taxonomy
Choose the smallest surface that owns the complete user job.
| Surface | Use when | Do not use when |
| --- | --- | --- |
| View mode | The entity, task, state, and actions stay the same; only representation changes | The user enters a different workflow or lifecycle |
| Inspector or panel | The user examines or adjusts the selected entity without leaving the primary task | The panel would contain its own navigation or long-running workflow |
| Floating window | A synchronized auxiliary source must remain visible over a primary workspace | The content is the primary task or must own product navigation |
| Existing workspace section | The feature is one bounded part of the workspace's existing user job | It introduces a separate object, lifecycle, permission model, or success criterion |
| Dedicated workspace | The feature has a distinct recurring job, state, actions, and completion condition inside an existing product domain | It is only a different visualization of the same task |
| New product root | A durable product domain owns several related workspaces and cannot be named honestly inside an existing root | There is only one screen, experiment, or implementation module |
| Plugin contribution | Vendor- or equipment-specific workflow belongs to a reviewed host slot | The behavior is product-wide or controls global navigation |
| LAB result | Immutable experimental evidence is projected through the canonical LAB contract | The user is operating, planning, configuring, or monitoring the production product |
Do not use a modal for a workspace, a new root for a single screen, or a new
workspace for a view-mode switch.
## Product-surface brief
Before implementing a new surface or materially relocating an existing one,
write a concise brief in the task/Ops card or architecture document:
1. **Operator and job** — who opens it and what must be completed or decided.
2. **Trigger and frequency** — where the workflow begins and how often it is
used.
3. **Primary entity and lifecycle** — what owns state, identity, history, and
completion.
4. **Evidence and authority** — what data is shown and which actions remain
forbidden.
5. **Information hierarchy** — the primary content, secondary context, and
details.
6. **Actions and states** — primary action, secondary actions, loading, empty,
unavailable, error, disabled, and recovery behavior.
7. **Placement candidates** — at least two credible placements or
compositions, with the rejected alternative and reason.
8. **Selected surface** — view mode, panel, window, existing section,
workspace, root, plugin slot, or LAB result.
9. **Design Guideline reuse** — resolved components, icons, shell/page pattern,
and any proven gap.
10. **Acceptance evidence** — what browser interaction and real data prove that
the surface solves the job.
The brief is a design decision, not product UI. Do not render this planning
material inside Mission Core.
## Novelty classes and approval
### A — new domain content in an admitted composition
Examples: another layer in the spatial workspace, a new evidence renderer
inside an existing reusable viewer, or an additional field in a canonical
inspector.
Mission Core may implement this after resolving existing Design Guideline
components and confirming that the user job and placement do not change.
### B — new Mission Core composition
Examples: a mission editor, operational review queue, fleet topology workspace,
or long-running worker monitor.
The composition may be unique to Mission Core. Prepare the product-surface
brief, compare placement alternatives, and obtain product-owner agreement when
the change creates or relocates a workspace, changes primary navigation, or
changes the main user workflow. Use canonical primitives but do not force the
new task into the LAB or catalog template.
### C — new shared visual entity or page pattern
Examples: a general split-pane state machine, a reusable graph editor, or a new
global navigation form factor.
Stop for explicit product-owner approval. Implement the generic contract in the
Design Guideline first with registry entry, states, documentation, catalog
example, validation, and versioned package export. Mission Core then consumes
it.
### D — new product root or platform meaning
A new top-level root changes the information architecture. It requires:
- more than one durable related workspace, or a documented reason one root must
initially contain one workspace;
- a stable domain name, owner, entity/lifecycle boundary, and relationship to
existing roots;
- product-owner approval;
- `productModel.ts` update and navigation/browser acceptance;
- an ontology decision only if the separate multi-consumer admission gate is
also met.
A new root does not automatically require a runtime ontology.
## Composition rule
Use the same composition when the user job, entity, lifecycle, and action model
are the same. Create or approve a different composition when at least one of
those changes materially.
Valid Mission Core compositions may therefore include:
- scene-first spatial operation;
- map-first planning;
- timeline-first replay;
- list/detail operational triage;
- table-first catalog or audit;
- form/editor mission construction;
- graph/topology monitoring;
- compact dashboard;
- immutable LAB evidence review.
The Design Guideline supplies the visual language. Mission Core supplies the
task-specific composition.
## Code placement after the product decision
After the surface is admitted:
```text
core/<feature>/
contracts, API adapters, state machines, domain hooks
components/<feature>/
reusable domain components and renderers
workspaces/<feature>/
task composition and workspace controller
composition/
reviewed registry or plugin wiring only when needed
productModel.ts
root/workspace registration when navigation changes
styles/<feature>.css
feature layout only
test/
contract, interaction, boundary, and registry coverage
```
Do not create an empty production route, placeholder workspace, temporary
navigation item, or mock status page while the composition is undecided. Use
the brief, Ops, an ADR, or an isolated visual prototype outside product
navigation.
## Review questions
Before implementation, answer:
1. Is this a new user job or only a new representation?
2. What entity owns the state and lifecycle?
3. Can the user complete the job without opening another workspace?
4. Does the surface need permanent navigation?
5. Which existing root describes it honestly?
6. Which Design Guideline primitives and page patterns already solve the
generic interaction?
7. Is the missing element domain-specific, Mission Core-specific, or truly
shared?
8. What layout alternative was rejected, and why?
9. What real data and interaction will prove the decision?
If these answers are not available, continue investigation and surface design;
do not start production implementation.
@@ -0,0 +1,79 @@
# ADR 0023: require sensor capabilities before algorithm admission
Date: 2026-07-26
Status: accepted
## Context
ADR 0018 introduced the immutable K1-specific
`missioncore.lidar-evidence-profile/v1`, and ADRs 00200021 established that the
external K1 `lio_pcl` product is a post-LIO, map-registered increment rather
than a native sensor scan. Those decisions correctly block known incompatible
LiDAR stages, but the compatibility rules are still encoded per stage.
Mission Core must also admit future native scanners, depth sources and
simulation providers without allowing an algorithm to infer missing physical
properties from a successful API call. In particular, the absence of endpoints
in the current K1 representation is not evidence that a ray traversed free
space.
## Decision
1. Mission Core owns
`missioncore.sensor-representation-capabilities/v1` as a provider-neutral
description of the physical properties admitted for one versioned source
representation.
2. The existing LiDAR evidence profile remains immutable. The capability
profile references it by `source_profile_id`; it does not replace or rewrite
source evidence.
3. K1 `lio_pcl` is represented as `registered-map-increment` with
`frame-increment` currentness. It admits metric XYZ, metric intensity,
map registration and a separate sensor pose.
4. K1 `lio_pcl` does not admit per-point time, ring/channel, a separate IMU,
a shared hardware clock, a native ray model, per-point ray origin, motion
compensation, ray clearing, free-space evidence or persistent
reconstruction.
5. Algorithms own a versioned requirements document with accepted
representation kinds and required capabilities.
6. Admission is binary and fail-closed. A missing capability or incompatible
representation rejects the algorithm/input pairing; Mission Core never
synthesizes a capability to make an integration run.
7. Successful compatibility admission does not grant command, navigation or
safety authority.
8. `absence_of_endpoints_means_free` is fixed to `false`, and unknown remains
unknown. Planner adapters must separately require accepted free-space
evidence.
## Consequences
- Endpoint-only occupied marking can consume the K1 registered increment.
- Projective free-space mappers, ray clearing, TSDF/ESDF integrations and
native-scan algorithms reject the K1 profile until a different admitted
source supplies their requirements.
- A future native MID-360 export or synthetic scan receives a separate source
and capability profile; it does not upgrade historical K1 recordings.
- Capability compatibility can be used by workers, provider adapters and LAB
manifests without moving product ownership into ROS 2.
- Track geometry and local occupied/unknown contracts can bind the exact
representation profile and preserve the same fail-closed semantics.
## Implementation
- `src/k1link/compute/sensor_representation.py`
- `src/k1link/compute/e30_review_pack.py`
- `src/k1link/compute/e30_materialization.py`
- `src/k1link/web/e30_review_api.py`
- `apps/control-station/src/core/laboratory/e30Review.ts`
- `apps/control-station/src/workspaces/E30ReviewWorkspace.tsx`
- `tests/test_sensor_representation.py`
- `tests/test_e30_review_pack.py`
- `tests/test_e30_materialization.py`
- `apps/control-station/test/e30Review.test.mjs`
- `docs/16_ARCHITECTURE_AUDIT_EXECUTION_ROADMAP.md`
## References
- ADR 0018: LiDAR evidence before models
- ADR 0020: Patchwork++ vendor-map boundary
- ADR 0021: native scan, normalized scan and rolling-map separation
- `docs/13_LIDAR_WORKER_PRODUCT_AND_ROADMAP.md`