Geometry boundary → topology identity
8.02 превращает track boundaries 8.01 в canonical vertical lines и 1D inline nodes, затем — при наличии explicit registry — описывает occupancy этих nodes.
Vertical geometric realization.
1D topology identity on X.
Explicit registry state only.
Сначала собираем все причины существования границы
Одна X-позиция может одновременно быть правой границей колонки, левой границей gutter и т. д.
GridBoundaryEvent {
eventRef,
x,
role:
DOMAIN_LEFT |
DOMAIN_RIGHT |
COLUMN_LEFT |
COLUMN_RIGHT |
GUTTER_LEFT |
GUTTER_RIGHT,
sourceTrackRef,
sourceIndex?,
provenance: DERIVED
}
Coincident boundaries → one canonical position
De-duplication нужна прежде всего для zero-width gutters и floating-point closure.
Геометрическая вертикаль
Line охватывает Y-extent grid domain и не имеет собственной occupancy semantics.
GridLine {
gridLineRef,
topologyRef,
ordinal,
orientation:
VERTICAL,
xRaw,
y0Raw,
y1Raw,
sourceUnit,
coordinateFrame,
boundaryRoles[],
sourceTrackRefs[],
eventRefs[],
confidence,
provenance: DERIVED
}
1D topology-node, не 2D intersection
Node — стабильная топологическая идентичность X-boundary. Его geometric realization — соответствующий GridLine.
GridNode {
gridNodeRef,
topologyRef,
gridLineRef,
ordinal,
nodeKind:
INLINE_BOUNDARY_NODE,
axis: X,
xRaw,
boundaryRoles[],
incidentTrackRefs[],
confidence,
provenance: DERIVED
}
Каждый track связывает nodes
Column/Gutter identity сохраняется как topology-edge поверх canonical nodes.
GridTrackTopologyEdge {
edgeRef,
trackRef,
trackKind:
COLUMN |
GUTTER,
trackIndex,
leftNodeRef,
rightNodeRef,
lengthRaw,
zeroLength,
confidence,
provenance
}
Zero gutter не порождает duplicate nodes
При `gutter.widthRaw=0` обе стороны gutter указывают на один и тот же node.
Occupancy приходит как explicit assertion
Registry хранит факт привязки из placement/layout/integration owner, но не выводит его из координат.
NodeOccupancyBinding {
bindingRef,
gridRef,
topologyRef,
nodeRef,
contentRef,
bindingKind:
PLACEMENT_ANCHOR |
CONTENT_EDGE |
CONTENT_CENTER |
CUSTOM,
sourceOwnerRef,
sourceEvidenceRef,
bindingStatus:
ACTIVE |
INACTIVE,
confidence,
provenance
}
COMPLETE vs PARTIAL
Это ключ к корректному различению `FREE` и `UNKNOWN`.
COMPLETE
Registry заявляет полное покрытие snapshot. Нет active bindings → FREE.
PARTIAL
Registry знает только часть bindings. Нет active bindings → UNKNOWN.
FREE / UNKNOWN / OCCUPIED / MULTI_OCCUPIED
Количество occupants — descriptor, а не встроенная capacity violation.
One state per canonical node
Output registry идёт в node ordinal order и хранит active/inactive binding lineage.
ColumnGridNodeOccupancyRegistry {
registryRef,
gridRef,
topologyRef,
coverageMode,
sourceSnapshotRef,
nodeStates[],
activeBindings[],
inactiveBindings[],
status,
confidence,
provenance: DERIVED
}
Occupancy ≠ alignment ≠ cell occupancy
Три похожих понятия разведены по owners.
| Question | Owner |
|---|---|
| Какие X-boundaries/lines/nodes существуют? | 8.02 |
| Какой content explicit registered on node? | 8.02 |
| Как генерировать placement candidate? | 8.03 |
| Является ли multi occupancy нарушением target? | 8.04 / explicit constraint owner |
| Какая 2D grid cell occupied? | Topic 9 |
| Насколько object edge близок/выровнен к line? | Topic 10 |
Topology/registry change only invalidates downstream
8.02 не передвигает объекты и не пересобирает кандидатов самостоятельно.
Topology не является quality vote
Количество линий, узлов, свободных или занятых nodes само по себе ничего не говорит о качестве композиции.
Visual Lab
Главный counterexample — zero gutter и PARTIAL registry.
8.02 topology/occupancy regression
Проверяем line/node canonicalization, zero-gutter self-edge, registry coverage, multi occupancy, invalid bindings и ownership barriers.
DATA FOR LAYOUT ENGINE
Machine-readable 8.02 contract.
{
"module": "Compo 8.02",
"name": "grid_lines_nodes_and_occupancy_registry",
"version": "1.0-canonical",
"canonical_main_title": "Grid lines, nodes и occupancy registry",
"topic": "08_КОЛОННАЯ_СЕТКА",
"scope": "CANONICAL_COLUMNGRID_BOUNDARY_LINES_1D_TOPOLOGY_NODES_TRACK_EDGES_AND_EXPLICIT_NODE_OCCUPANCY_REGISTRY",
"consumes": [
"Compo8.00.ColumnGrid",
"Compo8.01.ResolvedColumnGeometry",
"optional explicit NodeOccupancyRegistrySpec",
"owner-qualified NodeOccupancyBinding[]"
],
"provides": [
"GridBoundaryEvent",
"GridLine[]",
"GridNode[]",
"ColumnGridTopology",
"GridTrackTopologyEdge[]",
"NodeOccupancyBinding",
"NodeOccupancyRegistrySpec",
"NodeOccupancyState[]",
"ColumnGridNodeOccupancyRegistry",
"TopologyInvalidationRequest"
],
"owns_metrics": [],
"descriptors_only": [
"grid.line.xRaw",
"grid.line.boundaryRoles",
"grid.line.sourceTrackRefs",
"grid.node.ordinal",
"grid.node.xRaw",
"grid.node.boundaryRoles",
"grid.node.incidentTrackRefs",
"grid.node.occupancyState",
"grid.node.activeBindingCount",
"grid.node.occupantRefs",
"grid.topology.nodeCount",
"grid.topology.lineCount"
],
"boundary_event_schema": {
"eventRef": "derived stable ref",
"x": "finite source-unit X coordinate",
"role": "DOMAIN_LEFT|DOMAIN_RIGHT|COLUMN_LEFT|COLUMN_RIGHT|GUTTER_LEFT|GUTTER_RIGHT",
"sourceTrackRef": "ColumnTrack/GutterTrack ref or domain ref",
"sourceIndex": "optional track index",
"provenance": "DERIVED"
},
"grid_line_schema": {
"gridLineRef": "stable derived ref within one columnGeometryRef",
"topologyRef": "parent topology ref",
"ordinal": "zero-based left-to-right unique position index",
"orientation": "VERTICAL",
"xRaw": "canonical X coordinate",
"y0Raw": "grid-domain top",
"y1Raw": "grid-domain bottom",
"sourceUnit": "inherits Compo8.01 geometry",
"coordinateFrame": "CANVAS_TOP_LEFT_Y_DOWN",
"boundaryRoles": "sorted unique roles from clustered boundary events",
"sourceTrackRefs": "sorted unique source refs",
"eventRefs": "sorted source event refs",
"confidence": "minimum source confidence",
"provenance": "DERIVED"
},
"grid_node_schema": {
"gridNodeRef": "stable derived ref",
"topologyRef": "same topology",
"gridLineRef": "one-to-one canonical geometric realization",
"ordinal": "same canonical ordinal as line",
"nodeKind": "INLINE_BOUNDARY_NODE",
"axis": "X",
"xRaw": "same canonical X as line",
"boundaryRoles": "sorted unique roles",
"incidentTrackRefs": "sorted unique track refs touching this boundary",
"confidence": "0..1",
"provenance": "DERIVED",
"important": "not a generic 2D point/intersection owner"
},
"track_topology_edge_schema": {
"edgeRef": "derived ref",
"trackRef": "Compo8.01 ColumnTrack/GutterTrack ref",
"trackKind": "COLUMN|GUTTER",
"trackIndex": "integer",
"leftNodeRef": "canonical node at track x0",
"rightNodeRef": "canonical node at track x1",
"lengthRaw": "track width",
"zeroLength": "true only for zero-width gutter baseline",
"confidence": "0..1",
"provenance": "DERIVED"
},
"canonicalization": {
"input": "all domain/column/gutter X boundary events",
"sort": "ascending X, then canonical role order, then eventRef",
"cluster": "adjacent positions whose difference <= topologyEpsilon",
"representative": "minimum finite X in cluster; only an implementation canonicalization choice",
"roles": "union all roles",
"source_refs": "union all source track refs",
"output_order": "strictly left-to-right unique line/node ordinals",
"zero_gutter": "its left/right events cluster to one canonical node",
"column_positive_width": "column left/right must resolve to different nodes"
},
"occupancy_binding_schema": {
"bindingRef": "stable unique ref",
"gridRef": "same ColumnGrid",
"topologyRef": "same ColumnGridTopology",
"nodeRef": "existing canonical GridNode ref",
"contentRef": "owner-qualified content/object ref",
"bindingKind": "PLACEMENT_ANCHOR|CONTENT_EDGE|CONTENT_CENTER|CUSTOM",
"sourceOwnerRef": "owner that asserts this occupancy binding",
"sourceEvidenceRef": "evidence/candidate/layout snapshot ref",
"bindingStatus": "ACTIVE|INACTIVE",
"confidence": "0..1",
"provenance": "object",
"important": "binding asserts registry occupancy; it is not inferred from proximity"
},
"occupancy_registry_spec_schema": {
"registryRef": "stable versioned ref",
"gridRef": "same ColumnGrid",
"topologyRef": "same topology",
"coverageMode": "COMPLETE|PARTIAL",
"sourceSnapshotRef": "layout/candidate/integration snapshot identity",
"bindings": "NodeOccupancyBinding[]",
"confidence": "0..1",
"provenance": "object",
"duplicate_binding_ref": "INVALID"
},
"node_occupancy_state_semantics": {
"COMPLETE + 0 active bindings": "FREE",
"PARTIAL + 0 active bindings": "UNKNOWN",
"1 active binding": "OCCUPIED",
"2+ active bindings": "MULTI_OCCUPIED",
"inactive_bindings": "do not count toward current activeBindingCount",
"multi_occupied": "descriptor only; no universal violation",
"absence_without_registry": "N_A for occupancy subsystem"
},
"column_grid_node_occupancy_registry_schema": {
"registryRef": "source registry ref",
"gridRef": "grid identity",
"topologyRef": "topology identity",
"coverageMode": "COMPLETE|PARTIAL",
"sourceSnapshotRef": "source state snapshot",
"nodeStates": "one NodeOccupancyState per canonical GridNode, in ordinal order",
"activeBindings": "sorted active bindings",
"inactiveBindings": "sorted inactive bindings",
"status": "OK|N_A|INVALID",
"confidence": "minimum relevant evidence confidence",
"provenance": "DERIVED"
},
"ownership_map": {
"8.00": "ColumnGrid root/domain/coordinate ownership",
"8.01": "columns/gutters/spans and resolved 1D geometry",
"8.02": "canonical GridLine/GridNode topology and ColumnGrid node occupancy registry",
"8.03": "placement candidate generation using topology/occupancy evidence",
"8.04": "variants, target interpretation/scoring and Topic8 regression",
"9.x": "ModularGrid rows/cells/regions and 2D cell/region occupancy",
"10.x": "alignment/proximity relations to existing Topic8 grid evidence"
},
"semantic_firewalls": {
"line_vs_node": "GridLine is geometric vertical line; GridNode is one-dimensional topology identity",
"node_vs_intersection": "Topic8 GridNode is not a generic 2D intersection-point contract",
"occupancy_vs_alignment": "occupancy binding is explicit state; visual closeness/alignment is Topic10",
"occupancy_vs_placement": "registry may describe an accepted/current placement snapshot but does not generate the placement",
"multi_occupancy_vs_violation": "MULTI_OCCUPIED is descriptive until explicit capacity/target policy exists downstream",
"free_vs_unknown": "absence of binding is FREE only under COMPLETE registry coverage",
"node_vs_cell_occupancy": "Topic8 node occupancy and Topic9 cell/region occupancy are distinct owners"
},
"metric_policy": {
"direct_scoring": "FORBIDDEN in 8.02",
"node_count_score": "FORBIDDEN",
"occupancy_count_score": "FORBIDDEN",
"free_nodes_are_better": "FORBIDDEN",
"single_occupancy_is_better": "FORBIDDEN without explicit downstream capacity policy",
"beautyScore": "FORBIDDEN"
},
"hard_constraints": [
"8.02 owns canonical ColumnGrid GridLine[], one-dimensional GridNode[] topology and the ColumnGrid node occupancy registry.",
"GridLine is geometric evidence; GridNode is the canonical topology identity associated with one unique inline X boundary position.",
"GridNode in Topic8 is one-dimensional INLINE_BOUNDARY_NODE, not a generic 2D intersection node.",
"Canonical GridLine/GridNode positions are derived only from an already resolved Compo8.01 column geometry.",
"Coincident boundary events within implementation equality tolerance are de-duplicated into one canonical GridLine/GridNode while preserving every boundaryRole and sourceTrackRef.",
"Zero-width gutters must not create duplicate coincident lines/nodes.",
"A zero-width gutter remains a real GutterTrack identity and maps to a zero-length topology edge whose leftNodeRef equals rightNodeRef.",
"Positive-width columns must always map between two distinct canonical nodes.",
"Grid lines are vertical and span the resolved grid domain Y extent.",
"Boundary roles are descriptive provenance: DOMAIN_LEFT, DOMAIN_RIGHT, COLUMN_LEFT, COLUMN_RIGHT, GUTTER_LEFT, GUTTER_RIGHT.",
"Boundary role multiplicity at one node is valid and expected at shared track boundaries.",
"8.02 does not change 8.01 track geometry while canonicalizing topology.",
"Node occupancy is explicit registry state; 8.02 must not infer occupancy from visual proximity, alignment tolerance, overlap or content bounding boxes.",
"Node occupancy bindings must be owner-qualified and reference an existing canonical node in the same grid/topology.",
"Registry coverageMode COMPLETE means absence of an active binding may be resolved as FREE.",
"Registry coverageMode PARTIAL means absence of an active binding resolves as UNKNOWN, never FREE.",
"One active binding yields OCCUPIED; more than one yields MULTI_OCCUPIED. MULTI_OCCUPIED is descriptive and not automatically a violation.",
"No universal node capacity is defined in 8.02.",
"Inactive bindings do not count as current occupancy but remain available as registry provenance if supplied.",
"Duplicate bindingRef values are INVALID.",
"Unknown nodeRef in a binding is INVALID.",
"A contentRef may explicitly occupy more than one node; 8.02 does not prohibit this.",
"A node may explicitly carry more than one occupant; 8.02 records it without scoring.",
"Topic10 owns geometric alignment/proximity relations to grid lines/nodes and must not re-own occupancy identity.",
"Topic9 owns ModularGrid cell/region occupancy and must not re-own ColumnGrid node occupancy.",
"8.03 may consume topology/occupancy to generate placement candidates but does not own the registry.",
"8.04 may interpret explicit occupancy constraints/targets but raw occupancy counts/states do not vote independently.",
"Topology or occupancy change only invalidates downstream evidence; it does not mutate content.",
"N/A != 0.",
"No beautyScore."
],
"hard_rules": [
"8.02 owns canonical ColumnGrid GridLine[], one-dimensional GridNode[] topology and the ColumnGrid node occupancy registry.",
"GridLine is geometric evidence; GridNode is the canonical topology identity associated with one unique inline X boundary position.",
"GridNode in Topic8 is one-dimensional INLINE_BOUNDARY_NODE, not a generic 2D intersection node.",
"Canonical GridLine/GridNode positions are derived only from an already resolved Compo8.01 column geometry.",
"Coincident boundary events within implementation equality tolerance are de-duplicated into one canonical GridLine/GridNode while preserving every boundaryRole and sourceTrackRef.",
"Zero-width gutters must not create duplicate coincident lines/nodes.",
"A zero-width gutter remains a real GutterTrack identity and maps to a zero-length topology edge whose leftNodeRef equals rightNodeRef.",
"Positive-width columns must always map between two distinct canonical nodes.",
"Grid lines are vertical and span the resolved grid domain Y extent.",
"Boundary roles are descriptive provenance: DOMAIN_LEFT, DOMAIN_RIGHT, COLUMN_LEFT, COLUMN_RIGHT, GUTTER_LEFT, GUTTER_RIGHT.",
"Boundary role multiplicity at one node is valid and expected at shared track boundaries.",
"8.02 does not change 8.01 track geometry while canonicalizing topology.",
"Node occupancy is explicit registry state; 8.02 must not infer occupancy from visual proximity, alignment tolerance, overlap or content bounding boxes.",
"Node occupancy bindings must be owner-qualified and reference an existing canonical node in the same grid/topology.",
"Registry coverageMode COMPLETE means absence of an active binding may be resolved as FREE.",
"Registry coverageMode PARTIAL means absence of an active binding resolves as UNKNOWN, never FREE.",
"One active binding yields OCCUPIED; more than one yields MULTI_OCCUPIED. MULTI_OCCUPIED is descriptive and not automatically a violation.",
"No universal node capacity is defined in 8.02.",
"Inactive bindings do not count as current occupancy but remain available as registry provenance if supplied.",
"Duplicate bindingRef values are INVALID.",
"Unknown nodeRef in a binding is INVALID.",
"A contentRef may explicitly occupy more than one node; 8.02 does not prohibit this.",
"A node may explicitly carry more than one occupant; 8.02 records it without scoring.",
"Topic10 owns geometric alignment/proximity relations to grid lines/nodes and must not re-own occupancy identity.",
"Topic9 owns ModularGrid cell/region occupancy and must not re-own ColumnGrid node occupancy.",
"8.03 may consume topology/occupancy to generate placement candidates but does not own the registry.",
"8.04 may interpret explicit occupancy constraints/targets but raw occupancy counts/states do not vote independently.",
"Topology or occupancy change only invalidates downstream evidence; it does not mutate content.",
"N/A != 0.",
"No beautyScore."
],
"soft_constraints": [],
"preferences": [],
"overrides_allowed_by": [
"a newer Compo8.01 columnGeometryRef produces a new topology version",
"a newer explicit occupancy registry snapshot produces a new registry version",
"historical topology/registry outputs remain immutable and tied to original refs"
],
"initial_heuristics": {
"topology_epsilon": {
"formula": "max(1e-12, abs(domainWidth)*1e-12)",
"provenance": "IMPLEMENTATION_HEURISTIC",
"note": "used only to de-duplicate numerically coincident boundary events"
},
"role_sort_order": {
"value": [
"DOMAIN_LEFT",
"COLUMN_LEFT",
"GUTTER_LEFT",
"GUTTER_RIGHT",
"COLUMN_RIGHT",
"DOMAIN_RIGHT"
],
"provenance": "IMPLEMENTATION_HEURISTIC",
"note": "deterministic serialization order only; no semantic priority"
}
},
"style_preset_values": [],
"candidate_generation": {
"placement_candidates": "NONE",
"reason": "8.02 resolves topology/registry state; 8.03 owns candidate generation"
},
"correction_policy": {
"foreign_content_mutation": "FORBIDDEN",
"invalid_column_geometry": "route to 8.01",
"unknown_node_binding": "return INVALID and request binding/source correction",
"missing_registry": "occupancy = N_A, not FREE",
"alignment_question": "route to Topic10",
"cell_occupancy_question": "route to Topic9",
"placement_question": "route to 8.03",
"capacity_or_scoring_question": "route to 8.04 or explicit downstream constraint owner"
},
"deferred_inputs": [
"Compo8.03 placement candidate contracts",
"Compo8.04 occupancy/capacity target interpretation if needed",
"Topic9 2D ModularGrid cell/region occupancy",
"Topic10 alignment relations"
],
"recompute_when": [
"Compo8.01 columnGeometryRef changes",
"track x0/x1 changes",
"domain Y extent changes",
"occupancy registry spec changes",
"binding status/node/content/source snapshot changes"
],
"tests": [
"positive-gutter topology",
"zero-gutter dedup",
"boundary-role union",
"track-to-node mapping",
"zero-length gutter edge",
"column distinct-node invariant",
"topology determinism",
"complete registry free state",
"partial registry unknown state",
"single/multi occupancy",
"inactive binding",
"duplicate binding",
"unknown node",
"same content multiple nodes",
"missing registry N_A",
"no alignment inference",
"no cell occupancy",
"no scoring/global leakage"
],
"finality": "COLUMNGRID_CANONICAL_BOUNDARY_TOPOLOGY_AND_EXPLICIT_NODE_OCCUPANCY_OWNER"
}