COMPO · 2.19 · AUTOMATIC LINE STRUCTURE GENERATOR

Автоматический
генератор
линейной структуры.

Первый orchestration-модуль линейной системы. Он не вводит новые художественные законы и не владеет чужими метриками. Его задача — из semantic intent, контекста сцены, StylePreset и возможностей модулей 2.01–2.18 породить ограниченный набор валидных line-structure candidates для последующего scoring в 2.20.

API-контракт

00 / orchestration ownership

CONSUMES

Scene Canvas SceneObject[] SemanticRelations[] ProtectedZones[] Grid? StylePreset Seed Line module APIs: 2.01 geometry 2.02 axis class 2.03 diagonal direction 2.04 curve candidates 2.05 polyline candidates 2.06 width targets 2.07 length targets 2.08 flow hypotheses 2.09 connector routes 2.10 crossing diagnostics 2.11 shape contacts 2.12 parallel groups 2.13 grid relation 2.14 divider/boundary 2.15 graphic motifs 2.16 color appearance 2.17 rhythm 2.18 tension

PROVIDES

LineGenerationRequest LineStructureCandidate[] CandidateLineage[] GenerationTrace GenerationStats RejectedCandidate[] candidate includes: Line[] moduleDescriptors hardViolations[] softSignals[] provenance seedState generationCost

DOES NOT OWN

line geometry metrics line visual weight line role length fit line flow cue connection semantics crossing/contact metrics parallel/grid scores boundary score graphic score color score rhythm score tension score final ranking // 2.20 global composition // later layer
Главный запрет: 2.19 не имеет права «улучшить» кандидата путём собственного пересчёта чужой метрики. Он только вызывает owner-модуль, применяет его candidates/repair requests и собирает результат.

Generation request

01 / what should be generated

Request

LineGenerationRequest { sceneId, intent: CONNECT | DIVIDE | GUIDE | FRAME | ANNOTATE | ACCENT | RHYTHMIZE | TEXTURE | MIXED, sourceIds[]?, targetIds[]?, targetRegionId?, desiredRole?, desiredSubrole?, constraints[], stylePresetId, seed, candidateBudget }

Intent → role mapping

CONNECT → connector DIVIDE → divider GUIDE → trajectory | axis FRAME → frame ANNOTATE → annotation ACCENT → accent RHYTHMIZE→ rhythm TEXTURE → texture MIXED: requires explicit role set / orchestration plan

Mapping задаёт семантический старт, но не top-level aesthetic verdict.

Semantic-first: если запрос говорит «соединить A и B», генератор не должен сначала перебирать случайные красивые линии, а затем угадывать их функцию. Сначала фиксируется роль, затем строятся допустимые geometry families.

Генерационный pipeline

02 / ordered passes
01
intent

Нормализация semantic request и role.

02
family

Выбор допустимых geometry/structure families.

03
instantiate

Создание базовых кандидатов через owner APIs.

04
hard filter

Удаление заведомо невалидных структур.

05
decorate

Width, grid, graphic, color, rhythm, tension variants.

06
diagnose

Запуск 2.10/2.11 и других relation owners.

07
repair

Bounded correction requests → новые lineage branches.

08
handoff

Передать surviving candidates в 2.20.

generate(request): normalizeIntent(request) families = allowedFamilies( intent, role, stylePreset, geometry context ) seeds = instantiateFamilies(families) for pass in generationPasses: candidates = expandBounded(candidates, pass) candidates = hardFilter(candidates) candidates = deduplicate(candidates) candidates = diversityPrune(candidates, budget) return candidates // NO final aesthetic rank here

Семейства кандидатов

03 / structural templates
FamilyОсновные owner-модулиКогда порождатьЧто не делать
DIRECT_SEGMENT2.01, 2.09прямое соединение, axis/dividerне строить connector без semantic endpoints
ORTHOGONAL_POLYLINE2.05, 2.09, 2.13grid/technical routingне считать grid fit самостоятельно
DIAGONAL_SEGMENT2.01, 2.03направленная структура / accentне награждать диагональ по умолчанию
CURVE2.04, 2.18flowing/organic/trajectoryне смешивать tension и eye-flow
SEGMENTED_ROUTE2.05, 2.09сложный connector/pathне плодить vertices без бюджета
PARALLEL_SET2.12, 2.17rhythm / texture / technical groupне пересобирать group ownership
BOUNDARY_FRAME2.14divider/frame/enclosureне судить balance разделённых областей
TECHNICAL_MOTIF2.15annotation/dimension/bracket/tickне создавать новые top-level roles
DASH_PATTERN_LINE2.17technical/rhythm/accent styleне считать регулярность универсально лучше

Hard / soft / deferred

05 / constraint semantics

HARD

examples: protected zone violation invalid endpoint semantics self-intersection forbidden required attachment missing invalid path geometry technical mark incomplete when marked hard

SOFT

examples: grid preference parallel preference target length range preferred curvature preferred contrast rhythm target

DEFERRED

global: balance hierarchy negative space composition eye-flow overall density poster archetype global beauty
CandidateValidity { hardStatus: VALID | INVALID, hardViolations[], softSignals[], deferredRequirements[], confidence } INVALID candidates: logged for audit not passed to 2.20 unless explicit debug mode.

Variant dimensions

06 / controlled expansion

GEOMETRY

segment / curve / polyline, anchor choice, route family.

STYLE

width, color, opacity, dash pattern, technical motif.

RELATION

grid snap, parallel set, boundary mode, attachment variant.

TENSION

curvature profile, inflection placement, local rhythmic variation.

DO NOT build full Cartesian product: geometryCandidates × widthCandidates × colorCandidates × rhythmCandidates × tensionCandidates × ... Instead: staged expansion + applicability gates + budget limits + deduplication + diversity pruning.

Seeded randomness

07 / bounded exploration

Determinism

same: Scene GenerationRequest StylePreset version seed engine version must produce: same candidate set and lineage ordering within deterministic runtime.

Late-stage randomness

allowed: choose within bounded range perturb control point select style variant phase jitter gap jitter forbidden: violating hard constraints inventing semantic endpoints changing protected content
Randomness is exploration, not quality: seed расширяет пространство кандидатов, но не заменяет scoring и не может самостоятельно оправдать нарушение правил.

Lineage и provenance

08 / reproducibility

Candidate lineage

CandidateLineage { candidateId, parentCandidateId?, rootFamily, operation: CREATE | ANCHOR | ROUTE | SNAP | WIDTH | COLOR | RHYTHM | TENSION | REPAIR, ownerModule, parameters, seedFragment?, timestampIndex }

Generation trace

GenerationTrace { requestId, engineVersion, stylePresetVersion, seed, passes[], candidateCounts[], rejectionReasons[], dedupeCount, budgetStops[], finalCandidateIds[] }
Никакой необъяснимой магии: любой surviving line candidate должен быть воспроизводим из root family + последовательности операций + seed state.

Deduplication

09 / structural equivalence

Geometry signature

signature may include: geometryType quantized anchors quantized bounds pathLength class tangent bins vertex count

Style signature

width class color role opacity class dash pattern family graphicKind rhythm model

Near duplicates

if candidateDistance < dedupeTau: keep representative with: lower generation cost or earlier deterministic id NOT final quality rank

Diversity pruning

10 / preserve alternatives

Candidate distance

distance = wG * geometryDistance + wR * roleDistance + wA * anchorDistance + wS * styleDistance + wT * tensionDistance weights: GENERATION_HEURISTIC not aesthetic score

Keep spread

goal: avoid 100 almost-identical straight connectors retain: several structurally distinct families when valid within budget.

Repair loop

11 / bounded corrective branching
for candidate in candidates: diagnostics = runOwnerModules(candidate) requests = collectCorrectionRequests( diagnostics ) for request in requests: if request.targetOwner available and repairDepth < maxRepairDepth and operation inside allowed bounds: child = applyByOwner(candidate, request) append lineage(child) hardValidate(child) else: record unresolved request IMPORTANT: repair creates NEW candidate branch. Do not silently mutate parent.
Parent candidate сохраняется для audit и сравнения, если он hard-valid. Это позволяет 2.20 решить, действительно ли repair улучшил итог, а не предполагать это заранее.

Generation cost

12 / search efficiency only

Cost sources

route complexity vertex count number of repairs expensive exact geometry number of variants sampling resolution

Use

generationCost: search bookkeeping tie-break for near-duplicate pruning NOT: aesthetic simplicity score

Important

Сложный candidate не должен проигрывать только потому, что вычислялся дольше. Runtime-cost и visual complexity — разные сущности.

Визуальная лаборатория

13 / candidate families
CONNECT → DIRECT_SEGMENT. Самый дешёвый базовый candidate, если hard constraints не запрещают.
CONNECT + technical/grid context → ORTHOGONAL_POLYLINE.
CONNECT / GUIDE + flowing target → curve family через 2.04 + tension variants через 2.18.
DIVIDE может породить несколько structural/style branches: solid grid-aligned divider и dashed technical variant. Их сравнивает уже 2.20.
RHYTHMIZE → 2.12 создаёт group structure, 2.17 задаёт interval model. 2.19 только комбинирует допустимые варианты в пределах budget.

Детерминированные тесты

14 / regression

TEST 01 · deterministic seed

same scene same request same style version same seed expected: same candidate IDs same lineage order

TEST 02 · connector semantics

intent=CONNECT source=A target=B expected: all surviving connectors preserve A/B semantic endpoints

TEST 03 · hard rejection

candidate crosses protected hard zone expected: rejected before 2.20 reason logged

TEST 04 · no metric theft

2.10 crossingPenalty=.8 expected: 2.19 stores result MUST NOT recompute crossingPenalty

TEST 05 · budget

maxTotal=24 expansion wants 100 expected: survivors <=24 after deterministic prune

TEST 06 · repair branch

parent valid repair requested expected: new child candidate parent unchanged

TEST 07 · dedupe

two candidates within dedupeTau expected: one representative plus dedupe trace

TEST 08 · no final rank

3 valid candidates expected: 2.19 outputs set without final winner

TEST 09 · global defer

balance unavailable expected: candidate generation continues deferredRequirements contains balance

LIVE REFERENCE TESTS

IDInputComputedStatus

DATA FOR LAYOUT ENGINE

15 / machine contract
{ "module": "Compo 2.19", "name": "automatic_line_structure_generator", "version": "1.0", "scope": "LINE_CANDIDATE_ORCHESTRATION", "consumes": [ "Scene", "Canvas", "SceneObject[]", "SemanticRelations[]", "ProtectedZones[]", "Grid?", "StylePreset", "Seed", "Compo2.01..Compo2.18 module APIs" ], "provides": [ "LineGenerationRequest", "LineStructureCandidate[]", "CandidateLineage[]", "GenerationTrace", "GenerationStats", "RejectedCandidate[]" ], "candidate_families": [ "DIRECT_SEGMENT", "ORTHOGONAL_POLYLINE", "DIAGONAL_SEGMENT", "CURVE", "SEGMENTED_ROUTE", "PARALLEL_SET", "BOUNDARY_FRAME", "TECHNICAL_MOTIF", "DASH_PATTERN_LINE" ], "owns_metrics": [], "owns_process_state": [ "generation.familySelection", "generation.candidateBudget", "generation.lineage", "generation.seedState", "generation.generationCost", "generation.rejectionLog", "generation.dedupeState", "generation.diversityState" ], "metric_policy": { "final_ranking": "FORBIDDEN_IN_2.19", "foreign_metrics": "CONSUME_ONLY", "hard_filter": "ALLOWED", "coarse_pruning": "ALLOWED_FOR_SEARCH_CONTROL_ONLY", "final_scoring_owner": "Compo2.20" }, "generation_passes": [ "NORMALIZE_INTENT", "SELECT_FAMILIES", "INSTANTIATE_BASE", "HARD_FILTER", "EXPAND_APPLICABLE_VARIANTS", "RUN_RELATION_DIAGNOSTICS", "BRANCH_BOUNDED_REPAIRS", "DEDUPLICATE", "DIVERSITY_PRUNE", "HANDOFF_TO_2.20" ], "initial_heuristics": { "max_families": { "value": 6, "source": "IMPLEMENTATION_HEURISTIC" }, "max_base_per_family": { "value": 8, "source": "IMPLEMENTATION_HEURISTIC" }, "max_variants_per_pass": { "value": 6, "source": "IMPLEMENTATION_HEURISTIC" }, "max_total_candidates": { "value": 48, "source": "IMPLEMENTATION_HEURISTIC" }, "max_repair_depth": { "value": 2, "source": "IMPLEMENTATION_HEURISTIC" }, "dedupe_geometry_tau_shortN": { "value": 0.006, "source": "IMPLEMENTATION_HEURISTIC" } }, "hard_rules": [ "2.19_must_not_own_or_recompute_metrics_from_2.01_to_2.18", "semantic_intent_must_be_resolved_before_geometry_family_selection_when_available", "hard_invalid_candidates_must_be_rejected_before_2.20", "repairs_must_create_lineage_branches_not_silent_parent_mutation", "same_scene_request_style_seed_and_engine_version_must_reproduce_candidate_set", "candidate_expansion_must_be_budgeted", "full_cartesian_product_of_all_variant_dimensions_is_forbidden", "dedupe_and_diversity_pruning_must_not_claim_final_aesthetic_rank", "foreign_owner_requests_must_be_applied_through_owner_API", "global_balance_hierarchy_negative_space_and_eye_flow_must_remain_deferred", "generation_cost_must_not_be_used_as_visual_quality_score" ], "deferred_inputs": [ "Compo2.20.lineSystemScore", "global.balanceScore", "global.hierarchyScore", "global.negativeSpaceScore", "global.compositionEyeFlow", "global.densityScore", "global.styleCoherence" ], "recompute_when": [ "Scene changes", "semantic intent changes", "ProtectedZones change", "Grid changes", "StylePreset or version changes", "seed changes", "candidate budget changes", "any consumed line-module API/version changes" ], "finality": "CANDIDATE_GENERATION_ONLY" }
ARCHITECTURE CHECKPOINT: 2.19 — не ещё один evaluator, а orchestrator. Он превращает уже созданные знания 2.01–2.18 в ограниченное, воспроизводимое пространство line candidates. Следующий Compo 2.20 должен заниматься их сравнением и scoring, строго уважая metric ownership и зависимости между composite metrics.
VISITS / ...