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
@@ -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.