COMPO 1.00 / POINT ROLE ROUTER / CORE-COMPATIBLE

Точка
как система

Исправленный вводный модуль семейства Compo 1.xx. Он не смешивает структурную функцию точки с её визуальной иерархией: одна и та же точка может одновременно быть, например, узлом сети и главным визуальным акцентом. Compo 1.00 только классифицирует и маршрутизирует; размер, положение, цвет, collision и глобальную композицию решают другие владельцы метрик.

Контракт модуля

00 / Compo 0.00 compatibility

CONSUMES

Compo0.Scene Compo0.SceneObject Compo0.Constraint[] PointRequest? Point.relations? Point.locked?

PROVIDES

PointRoleDescriptor functionalRole visualRoleCandidate subroles[] roleRigidity routingTargets[]

OWNS METRICS

point.functional_role_confidence point.visual_role_confidence point.role_evidence_score

Никакие geometry / contrast / hierarchy метрики здесь не принадлежат модулю.

DEFERRED INPUTS

point.visual_weight point.placement_score point.grid_fit point.local_contrast global.hierarchy_score global.balance_score
Запрет на double counting: Compo 1.00 не вычисляет размер, визуальный вес, баланс, отрицательное пространство, контраст, collision или eye-flow. Он только назначает роли и передаёт объект владельцам соответствующих метрик.

Главная корректировка

01 / orthogonal roles

Старый подход — конфликтующий enum

role = focus | support | anchor | node | rhythm | marker | noise | corner

Такой enum смешивает структурную функцию и визуальную иерархию. Точка не может быть одновременно anchor и focus, хотя в реальной композиции это нормальный случай.

Новый подход — две независимые оси

functionalRole = free | anchor | node | rhythm_member | marker visualRole = focus | support | background subroles[] = optional specializations

Одна точка получает структурную функцию и визуальную роль независимо. Это устраняет конфликт taxonomy и делает правила совместимыми.

Пример: точка на конце важной линии может иметь functionalRole="anchor" и одновременно visualRole="focus". Малый узел сети может иметь functionalRole="node" + visualRole="background".

Формальная модель

02 / point role descriptor

Point — геометрическая сущность

Point { id: string, xN: float, yN: float, radiusN: float?, // owner: Compo 1.01 shape: enum?, // circle/square/diamond/... locked: bool, groupId?: string, relationIds?: string[] }

Compo 1.00 не обязан знать точный радиус. Если радиус ещё не рассчитан, роль можно назначить раньше.

PointRoleDescriptor — результат 1.00

PointRoleDescriptor { functionalRole: enum, visualRole: enum | UNRESOLVED, subroles: string[], roleRigidity: HARD | SOFT | FREE, functionalConfidence: 0..1, visualConfidence: 0..1, evidence: Evidence[], status: ASSIGNED | PROVISIONAL | AMBIGUOUS | UNRESOLVED, routingTargets: ModuleId[] }
F
FUNCTIONAL ROLE

Что точка делает в структуре сцены.

V
VISUAL ROLE

Насколько она важна для зрительного внимания.

S
SUBROLE

Специализация без разрастания базового enum.

Канонические роли

03 / role taxonomy

3.1 Functional role — структурная функция

FREE

Нет структурной привязки. Такая точка может быть визуальным акцентом или свободным декоративным элементом.

functionalRole = free

ANCHOR

Привязка линии, формы, выноски или другой геометрической сущности.

functionalRole = anchor

NODE

Узел сети или графа. Определяется topology, а не визуальной важностью.

functionalRole = node

RHYTHM MEMBER

Элемент последовательности. Его смысл определяется соседями и индексом в ритме.

functionalRole = rhythm_member

MARKER

Отметка координаты, измерения, границы, угла или служебной позиции.

functionalRole = marker subrole = coordinate | measurement | corner | boundary

SUBROLE НЕ РАВЕН НОВОЙ РОЛИ

corner больше не отдельный базовый role. Это специализация marker. Так taxonomy не разрастается бесконтрольно.

marker + subrole:"corner"

3.2 Visual role — зрительная иерархия

FOCUS

Визуальный акцент. Назначение предварительное до глобального hierarchy pass.

visualRole = focus

SUPPORT

Поддерживающий уровень. Не должен самовольно стать доминантой после расчёта веса.

visualRole = support

BACKGROUND

Фоновый/микродетальный уровень. noise становится subrole, а не отдельной осью иерархии.

visualRole = background subrole = decorative_noise | computational_noise

Детерминированная маршрутизация

04 / evidence → role

Functional role — сначала проверяются отношения

if connectionDegree >= nodeDegreeThreshold: functionalRole = NODE else if endpointRelations.count > 0: functionalRole = ANCHOR else if measurementRef != null or coordinateRef != null or cornerRef != null: functionalRole = MARKER else if sequenceId != null: functionalRole = RHYTHM_MEMBER else: functionalRole = FREE

INITIAL_HEURISTIC nodeDegreeThreshold = 3. Если topology-модуль использует другое определение node, он имеет право переопределить это значение.

Visual role — только как proposal

if upstreamRequestedVisualRole exists: visualRoleCandidate = requested value confidence = upstream confidence else if explicitBackgroundGeneration == true: visualRoleCandidate = BACKGROUND else: visualRoleCandidate = UNRESOLVED // IMPORTANT: // 1.00 does NOT infer FOCUS from size/contrast here. // those values are owned by 1.01 + 1.10 + global hierarchy.

Это убирает циклическую зависимость: visual role не притворяется известной до расчёта веса и общей иерархии.

Generated ≠ supplied: автоматически создаваемый point-candidate без функциональной причины и без requested visual role можно отклонить. Но входной/locked объект пользователя нельзя молча удалить только потому, что роль пока не определена: он получает status=UNRESOLVED и идёт в fallback/semantic pass.

Почему две оси ролей нужны

05 / visual proof
functional: ANCHORvisual: FOCUS
Один и тот же point — конец линии и главный акцент. Старый enum не мог выразить это без потери информации.
functional: NODEvisual: SUPPORT
Topology говорит NODE, но визуально узел может оставаться поддерживающим и не становиться фокусом.
functional: MARKERsubrole: CORNER
corner больше не базовая роль. Это marker-specialization, что предотвращает взрыв enum.

Последовательность работы

06 / local pipeline
1 INPUT
Point / PointRequest + relations.
2 RELATIONS
Собрать topology, sequence, measurement, anchors.
3 FUNCTION
Назначить functionalRole.
4 SUBROLE
Добавить специализации без нового enum.
5 VISUAL
Создать provisional visualRole candidate.
6 VALIDATE
Проверить evidence и locked policy.
7 ROUTE
Передать в 1.01–1.10 по необходимости.
8 REVISIT
После hierarchy/weight pass подтвердить visualRole.
Important loop: 1.00 assigns structural function → 1.01..1.10 compute geometry / weight / context → global hierarchy resolves visual importance → 1.00 descriptor.visualRole may change from PROVISIONAL to ASSIGNED Functional relation roles remain stable unless topology itself changes.

Metric ownership

07 / no overlap
Metric / fieldOwner1.00 actionStatus
point.functional_role_confidenceCompo 1.00computeLOCAL
point.visual_role_confidenceCompo 1.00compute proposal confidenceLOCAL
point.visual_weightCompo 1.01consume laterDEFERRED
point.placement_scoreCompo 1.02do not computeDEFERRED
point.grid_fitCompo 1.06do not computeDEFERRED
point.connection_geometryCompo 1.07relations only; geometry deferredDEFERRED
point.collision_stateCompo 1.09do not computeDEFERRED
point.local_contrastCompo 1.10do not computeDEFERRED
global.hierarchy_scorefuture hierarchy moduleconsume only during visual-role confirmationGLOBAL

Hard / soft правила

08 / semantics

HARD_CONSTRAINTS

  • Каждый generated point candidate перед финальным рендером должен иметь валидный PointRoleDescriptor.
  • functionalRole=node требует topology evidence.
  • functionalRole=anchor требует валидной relation к геометрической сущности.
  • functionalRole=rhythm_member требует sequenceId или эквивалентной последовательности.
  • Locked input object нельзя удалять только из-за UNRESOLVED role.

SOFT / PROVISIONAL

  • visualRole до глобального hierarchy pass считается provisional.
  • Visual role может быть переопределён после расчёта visual weight / local contrast / balance.
  • Generated free/background point без достаточной функции может быть удалён при economy/clutter pass.
  • Subrole можно менять без изменения основной функциональной роли.

Маршрутизация в Compo 1.xx

09 / family map
1.01
Размер точки и визуальный вес
Получает descriptor, но не определяет структурную роль.
1.02
Размещение одиночной точки
Работает с position candidates и placement score.
1.03
Две точки
Pair relation, distance, directional relation.
1.04
Кластеры
Cohesion, density, local grouping.
1.05
Ритм и последовательности
Обязателен для functionalRole=rhythm_member.
1.06
Точки и сетка
Grid fit / snap / occupancy — отдельный owner.
1.07
Точка как узел связей
Обязателен для anchor/node relation geometry.
1.08
Декоративный / вычислительный шум
visualRole=background + noise subroles.
1.09
Касания и конфликты
Collision / tangent / protected-zone checks.
1.10
Цвет и тон
Владеет local contrast, не 1.00.
1.11
Генератор
Оркестрирует point candidates по ролям.
1.12
Scoring
Собирает owned metrics без дублирования.
1.13
Regression tests
Проверяет контракты и cross-module consistency.

DATA FOR LAYOUT ENGINE

10 / canonical contract
{ "module": "Compo 1.00", "version": "2.0", "name": "point_role_router", "scope": "point role taxonomy and routing", "consumes": [ "Compo0.Scene", "Compo0.SceneObject", "Compo0.Constraint[]", "PointRequest?", "Point.relations?", "Point.locked?" ], "provides": [ "PointRoleDescriptor", "Point.functionalRole", "Point.visualRoleCandidate", "Point.subroles[]", "Point.roleRigidity", "Point.routingTargets[]" ], "owns_metrics": [ "point.functional_role_confidence", "point.visual_role_confidence", "point.role_evidence_score" ], "functional_role_enum": [ "free", "anchor", "node", "rhythm_member", "marker" ], "visual_role_enum": [ "focus", "support", "background", "UNRESOLVED" ], "canonical_subroles": { "marker": ["coordinate", "measurement", "corner", "boundary"], "anchor": ["line_endpoint", "shape_handle", "annotation_anchor", "grid_anchor"], "node": ["network_junction", "graph_node", "compute_node"], "rhythm_member": ["sequence", "progression", "orbit_member"], "background": ["decorative_noise", "computational_noise", "microdetail"] }, "defaults": { "node_degree_threshold": { "value": 3, "status": "INITIAL_HEURISTIC", "calibratable": true } }, "deferred_inputs": [ "point.visual_weight", "point.placement_score", "point.grid_fit", "point.connection_geometry", "point.collision_state", "point.local_contrast", "global.hierarchy_score", "global.balance_score", "global.negative_space_score" ], "hard_constraints": [ "generated_final_point_requires_role_descriptor", "node_requires_topology_evidence", "anchor_requires_relation_evidence", "rhythm_member_requires_sequence_evidence", "locked_input_must_not_be_deleted_only_for_unresolved_role" ], "routing": { "all": ["Compo 1.01", "Compo 1.02", "Compo 1.09", "Compo 1.10"], "anchor": ["Compo 1.07"], "node": ["Compo 1.07"], "rhythm_member": ["Compo 1.05"], "marker": ["Compo 1.06", "Compo 1.07"], "background.noise": ["Compo 1.08"], "multi_point": ["Compo 1.03", "Compo 1.04"], "generation": ["Compo 1.11"], "scoring": ["Compo 1.12"], "tests": ["Compo 1.13"] }, "finality": { "functional_role": "FINAL_IF_RELATION_TOPOLOGY_IS_STABLE", "visual_role": "PROVISIONAL_UNTIL_GLOBAL_HIERARCHY_PASS" } }

Минимальные regression tests

11 / deterministic cases

TEST 01 — anchor + focus

input: endpointRelations = ["L7.end"] requestedVisualRole = "focus" expected: functionalRole = "anchor" visualRole = "focus" status = ASSIGNED/PROVISIONAL

TEST 02 — corner marker

input: cornerRef = "shapeA.bottomRight" expected: functionalRole = "marker" subroles contains "corner" role != "corner"

TEST 03 — locked unresolved

input: locked = true no relations no visual role request expected: status = "UNRESOLVED" delete = false route_to_fallback = true

TEST 04 — graph node

input: connectionDegree = 4 expected: functionalRole = "node" functionalConfidence = 1.0 route includes Compo 1.07

TEST 05 — rhythm member

input: sequenceId = "seq_12" index = 3 expected: functionalRole = "rhythm_member" route includes Compo 1.05

TEST 06 — generated purposeless

input: generated = true no relation no requested visual role expected: functionalRole = "free" visualRole = "UNRESOLVED" candidate may be rejected before final render

Финальный чек

12 / validation
  • Структурная и визуальная роли не смешаны в один enum.
  • corner является subrole marker, а не отдельной базовой ролью.
  • Node/anchor/rhythm имеют relation evidence.
  • Visual role до hierarchy pass помечена provisional.
  • Compo 1.00 не пересчитывает чужие метрики.
  • Все чужие метрики объявлены DEFERRED_INPUT.
  • Generated point без функции может быть reject.
  • Locked input object не удаляется автоматически.
  • У каждого output есть routingTargets.
  • Результат совместим с контрактом Compo 0.00.