COMPO · 3.06 · SHAPE GENERATOR / SCORER / REGRESSION

Shape
generator,
scoring & tests.

Финальный модуль темы 3: bounded candidate orchestration поверх owner APIs 3.01–3.05, target-aware local aggregation canonical votes 3.03/3.04 и consolidated regression suite всей Shape-подсистемы. Geometry ownership не дублируется; visual mass, negative space и global composition остаются будущим owners.

ModuleCompo 3.06
Scopegenerator + local scorer
Regression3.00–3.06
Primary inputs3.03 + 3.04
Topic3 · SHAPE
NextTOPIC 3 AUDIT

Один финальный модуль — три обязанности

00 / module api

MAIN объединяет generator, scoring и tests в 3.06. Поэтому здесь они живут рядом, но с разными ownership-границами: search orchestration, aggregate local score и regression oracle.

GENERATOR

Bounded orchestration owner-provided proposals; immutable lineage, dedupe, diversity pruning.

SCORER

Aggregate only canonical primary votes 3.03/3.04 under explicit ShapeSystemTarget.

TESTS

Consolidated Topic 3 regression 3.00–3.06; suite itself owns no design metric.

3.06 ≠ UNIVERSAL SHAPE OWNER. Он не строит Bézier control points вместо 3.02, не считает convexity вместо 3.04 и не меняет transform matrix вместо Core/3.05.

Generation intent и scoring target — разные вещи

01 / explicit intent + target

Intent определяет search space. Target определяет, как интерпретировать уже измеренные owner metrics. Их нельзя смешивать.

ShapeGenerationIntent

{
  intentId,
  shapeRole,
  allowedGeometryKinds[],
  allowedPrimitiveFamilies?,
  sourceShapeRefs?,
  proposalProviderRefs[],
  silhouetteTarget?,
  regionTarget?,
  transformVariantPolicy?,
  hardConstraints[],
  stylePresetRef?,
  seed
}

ShapeSystemTarget

{
  targetId,
  requiredGroups[],
  optionalGroups[],
  disabledGroups[],
  silhouetteTarget?,
  regionTarget?,
  semanticMultipliers{},
  styleMultipliers{},
  groupVoteCaps{},
  requiredEvidencePolicy,
  hardConstraints[]
}
NO TARGET → NO RANK. Можно сгенерировать/валидировать candidates без scoring target, но localScore=null и rankEligible=false.

ShapeCandidate

02 / immutable lineage

Каждый repair/edit создаёт новый candidate branch. Parent остаётся неизменным для audit и воспроизводимости.

Candidate

ShapeCandidate {
  candidateId,
  parentCandidateId?,
  lineageRootId,
  shapeRef,
  proposalRefs[],
  metrics[],
  hardViolations[],
  generationDepth,
  repairDepth,
  generationCost,
  correctionCost,
  diversityKey?,
  canonicalSignature,
  stableTieBreak,
  provenance
}

Lineage rule

root A
 ├─ A:primitive
 │   ├─ A:r1 contour repair
 │   └─ A:r2 region repair
 └─ A:organic
     └─ A:r1 feature repair

parent immutable
child gets deterministic fork
no in-place geometry mutation

Proposal providers

03 / proposal ownership

3.06 расширяет search space только через typed proposals владельцев. Именно это не даёт generator превратиться во второй geometry engine.

Proposal kindOwner3.06 action
primitive family / params3.01accept proposalRef → validate → new candidate
organic contour edit3.02accept path proposal / correction result
hole/fill/outline/compound change3.04accept region proposal
position/rotation/scale/reflection/skewCore / 3.05 adapteronly when explicit transformVariantPolicy/provider exists
silhouette correction request3.03 → geometry ownerroute desired effect, never move points itself
NO DEFAULT TRANSFORM SWEEP. 3.06 не перебирает автоматически 0°, 15°, 30°, scale 0.8/1.0/1.2 и т.п. Это было бы скрытой эвристикой search space. Transform variants существуют только из explicit policy/provider.

GenerationBudget

04 / bounded search

Search должен заканчиваться по структуре, а не по удаче. Budget — implementation contract, не quality preference.

BASE

16

maxBaseCandidates — initial roots.

TOTAL

64

maxTotalCandidates after bounded expansion.

REPAIR

2

maxRepairDepth.

GenerationBudget { maxBaseCandidates: 16, maxProposalsPerBase: 12, maxTotalCandidates: 64, maxRepairDepth: 2, maxCorrectionBranchesPerCandidate: 4, maxDiversityPerBucket: 8, maxRuntimeMs? } These numbers: provenance = IMPLEMENTATION_HEURISTIC NOT aesthetic laws.

Bounded candidate orchestration

05 / generation pipeline

Полного Cartesian product нет. Каждый pass расширяет только уже существующие candidates конкретными provider proposals.

normalizeIntent() ↓ load immutable base seeds ↓ for each enabled provider: request bounded ShapeProposal[] ↓ boundedExpansion() ↓ ownerValidation() ↓ HARD_FILTER ↓ dedupe(canonicalSignature) ↓ diversityPrune(diversityKey, perBucketBudget) ↓ request 3.03 / 3.04 owner metrics ↓ LOCAL SCORE 3.06 ↓ owner correction requests? ├─ no → keep candidate └─ yes + budget → deterministic child branch → dirty owner recompute → score again ↓ rank + ShapeSearchReport
DEDUPE BEFORE SCORE. Два разных proposal paths, приведшие к одной canonical Shape+Transform+Paint signature, не получают два голоса в search population.

Hard filter до aesthetic score

06 / feasibility

Некорректная geometry не должна компенсироваться хорошим readability score.

Violation sourceExample3.06
3.01invalid primitive paramshard reject
3.02broken required closed contourhard reject / correction branch
3.04ambiguous required compound fill semanticshard reject if target requires resolved region
3.05singular transform when invertibility requiredhard reject
semantic constraintcandidate ShapeRole outside allowed rolehard reject
if candidate.hardViolations.length > 0: status = "rejected" rankEligible = false localScore = null NEVER: localScore - hardPenalty

Кто имеет право голосовать

07 / canonical votes

Тема 3 уже подготовлена composite-first: только primary composites 3.03 и 3.04 являются canonical scoring inputs.

3.03

SILHOUETTE_READABILITY

shape.silhouette.localReadabilityScore

owner: Compo3.03
composite: true
componentOf: null
3.04

SHAPE_REGION_TOPOLOGY

shape.region.localTopologyFit

owner: Compo3.04
composite: true
componentOf: null
НЕ ГОЛОСУЮТ. primitive family, segmentCount, featureCount, raw crossings, holeCount, convexityClass, indentationDepth, determinant, rotation, bounds, generationCost, silhouette area будущей темы 4.

Suppression contract

08 / double counting

Scorer не должен случайно дать отдельный голос компонентам composite или raw descriptors.

for MetricResult m: 1. applicability == 0 / status == N/A → suppress N_A 2. confidence <= 0 → suppress NO_CONFIDENCE 3. incomplete canonical metadata → diagnostic-only 4. componentOf points to active composite → suppress COMPONENT_OF_COMPOSITE 5. key is not allowlisted canonical primary vote → diagnostic-only 6. disabled scoringGroup → suppress TARGET_DISABLED 7. duplicate owner+key+version → keep deterministic canonical instance 8. same scoringGroup: → primary composite only 9. cross-group direct derivedFrom overlap: → suppress lower priority unless BOTH explicitly independent 10. dependsOn overlap alone: → NEVER suppress
SHARED GEOMETRY ≠ DOUBLE COUNT BY ITSELF. 3.03 и 3.04 могут вычислительно зависеть от одного contour, но подавление идёт по фактическому derivedFrom evidence lineage, а не по общему dependsOn.

Score, confidence, coverage

09 / local aggregation

Local score — агрегат owner interpretations для одного ShapeSystemTarget. Он ничего не говорит о global balance или visual mass.

rawGroupWeight_g = baseWeight_g × semanticMultiplier_g × styleMultiplier_g groupWeight_g = min(rawGroupWeight_g, groupVoteCap_g) effectiveScoreWeight_g = groupWeight_g × groupConfidence_g localScore = Σ(groupValue_g × effectiveScoreWeight_g) / Σ(effectiveScoreWeight_g) sceneConfidence = Σ(groupConfidence_g × groupWeight_g) / Σ(groupWeight_g) targetCoverage = coveredExpectedGroups / expectedGroups evidenceCoverage = coveredExpectedTargetWeight / totalExpectedTargetWeight localScoreConfidence = sceneConfidence × evidenceCoverage
N/A ≠ 0. Неприменимая group исключается. Если required evidence отсутствует — решение принимает requiredEvidencePolicy; scorer не подставляет ноль.

Missing-evidence policy

10 / required evidence

Explicit policy не даёт implementation самостоятельно решать, можно ли ранжировать candidate с неполными owner metrics.

PolicyMissing required group
REQUIRE_ALLstatus=insufficient_evidence, rankEligible=false
DIAGNOSTIC_IF_MISSINGdescriptors/breakdown available, localScore=null
RANK_WITH_LOW_COVERAGEscore available owner evidence; coverage/confidence explicitly fall
NO SILENT DEFAULT. Если policy отсутствует, scorer выбирает безопасный diagnostic-only режим.

Local rank

11 / deterministic ranking

Ranking — локальный факт Topic 3. Будущие mass/space/global owners могут предпочесть другого candidate и не имеют права переписывать этот local score.

compare(A,B): 1. hard-feasible before rejected 2. localScore if |A-B| > scoreEpsilon 3. targetCoverage 4. localScoreConfidence if |A-B| > confidenceEpsilon 5. lower correctionCost 6. lower generationCost 7. stableTieBreak lexical generationCost / correctionCost: bookkeeping tie-break only NEVER aesthetic quality

Correction creates a child

12 / correction loop

3.03/3.04/3.05 могут запросить изменение. 3.06 маршрутизирует запрос и создаёт новую ветку только после ответа owner/provider.

3.03

Silhouette

Desired feature-scale/topology effect → 3.02/provider proposal.

3.04

Region

Hole/fill/convexity target mismatch → region/contour owner proposal.

3.05

Transform

Singular/invalid transform → Core transform owner.

ShapeCorrectionBranch {
  parentCandidateId,
  sourceCorrectionRequestId,
  targetOwner,
  proposalRef,
  childCandidateId,
  seedFork,
  repairDepth,
  dirtyOwners[],
  provenance: "DERIVED"
}

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

13 / visual lab

Четыре candidates одной semantic задачи. Local scores показаны только как illustrative target-relative owner aggregates; mass/negative-space ещё не участвуют.

EXPLICIT TARGET · ORGANIC_CLEAR + CONCAVE ALLOWED A · organic clear local .91 · coverage 1.0 B · complex symbolic local .70 · target mismatch C · compound / hole local .76 · region evidence D · open invalid HARD REJECT · no score SEARCH LINEAGE A A:r1 A:r2 3.03 feature correction → owner proposal 3.04 region correction → owner proposal parent immutable · bounded depth · deterministic seed fork local score uses 3.03 + 3.04 only Topic4 mass / Topic5 free-space / global balance remain DEFERRED

Topic 3 regression coverage

14 / regression matrix

3.06 — test owner темы 3. Он проверяет публичные contracts, но не становится владельцем их geometry/metrics.

ModuleContractRegression barriers
3.00schema / rolesrole not inferred from geometry; no foreign mass/free-space score
3.01primitive geometrycanonical aliases, validity, deterministic primitive proposal ownership
3.02path contourclosure, reversal, self-intersection evidence, no score ownership
3.03silhouettetarget gate, composite primary vote, complex allowed counterexample
3.04region topologyfill/hole/convexity target fit, convex ≠ universally better
3.05transforminverse/parity, local immutability, transform descriptors not scores
3.06generator/scorerbudget, lineage, hard-filter, suppression, coverage, deterministic rank
BASELINE MIGRATION. Красный test нельзя «починить» переписыванием expected output. Baseline меняется только вместе с документированной contract migration/reason.

Детерминированные tests 3.00–3.06

15 / inline regression

Reference runner покрывает schema barriers, owner boundaries, generation determinism, hard filtering, target semantics и scoring aggregation.

Tests not run yet.

DATA FOR LAYOUT ENGINE

16 / machine contract

Machine-readable финальный contract темы 3.

{
  "module": "Compo 3.06",
  "name": "shape_generator_scoring_and_tests",
  "version": "1.0-canonical",
  "scope": "BOUNDED_SHAPE_CANDIDATE_ORCHESTRATION_LOCAL_SCORING_AND_TOPIC3_REGRESSION",
  "consumes": [
    "Compo3.00.Shape / ShapeRole / ShapeGeometry contracts",
    "Compo3.01.PrimitiveValidationResult / PrimitiveToPathResult / proposal adapters",
    "Compo3.02.PathShapeGeometry / ContourIntersectionEvent[] / correction requests",
    "Compo3.03.MetricResult[shape.silhouette.localReadabilityScore]",
    "Compo3.03.SilhouetteCorrectionRequest[]",
    "Compo3.04.MetricResult[shape.region.localTopologyFit]",
    "Compo3.04.ShapeRegionCorrectionRequest[]",
    "Compo3.05.ShapeTransformDescriptor / ShapeWorldGeometryView",
    "Compo3.05.TransformCorrectionRequest[]",
    "ShapeProposalProvider[]",
    "ShapeSystemTarget",
    "Compo0.seed / lineage"
  ],
  "provides": [
    "ShapeGenerationIntent",
    "ShapeGenerationBudget",
    "ShapeProposal",
    "ShapeCandidate",
    "ShapeCandidateLineage",
    "ShapeSystemTarget",
    "ShapeSystemScoreResult",
    "ShapeSearchReport",
    "ShapeCorrectionBranch",
    "ShapeRegressionCase[]",
    "ShapeRegressionSuite"
  ],
  "owns_metrics": [
    "shapeSystem.localScore",
    "shapeSystem.localScoreConfidence"
  ],
  "descriptors_only": [
    "shapeSystem.targetCoverage",
    "shapeSystem.evidenceCoverage",
    "shapeSystem.groupBreakdown",
    "shapeSystem.suppressionLog",
    "shapeSystem.generationCost",
    "shapeSystem.correctionCost",
    "shapeSystem.localRankKey",
    "shapeSystem.stableTieBreak",
    "shapeSystem.lineage",
    "shapeSystem.searchReport"
  ],
  "candidate_schema": {
    "candidateId": "string",
    "parentCandidateId": "string|null",
    "lineageRootId": "string",
    "shapeRef": "canonical owner-produced shape snapshot/ref",
    "proposalRefs": "string[]",
    "metrics": "MetricResult[]",
    "hardViolations": "HardConstraintViolation[]",
    "generationDepth": "integer>=0",
    "repairDepth": "integer>=0",
    "generationCost": "number>=0 bookkeeping only",
    "correctionCost": "number>=0 bookkeeping only",
    "diversityKey": "string|null supplied by provider/adapter",
    "canonicalSignature": "string",
    "stableTieBreak": "string",
    "provenance": "object"
  },
  "generation_intent": {
    "intentId": "string",
    "shapeRole": "ShapeRole",
    "allowedGeometryKinds": "PRIMITIVE|PATH|COMPOUND[]",
    "allowedPrimitiveFamilies": "optional explicit list",
    "sourceShapeRefs": "optional immutable bases",
    "proposalProviderRefs": "explicit provider refs",
    "silhouetteTarget": "optional Compo3.03 target",
    "regionTarget": "optional Compo3.04 target",
    "transformVariantPolicy": "optional explicit policy; no default rotation/scale sweep",
    "hardConstraints": "typed constraints",
    "stylePresetRef": "optional",
    "seed": "required deterministic seed"
  },
  "generation_budget": {
    "maxBaseCandidates": 16,
    "maxProposalsPerBase": 12,
    "maxTotalCandidates": 64,
    "maxRepairDepth": 2,
    "maxCorrectionBranchesPerCandidate": 4,
    "maxDiversityPerBucket": 8,
    "maxRuntimeMs": "optional host budget"
  },
  "generation_policy": [
    "normalize intent and explicit provider set",
    "load immutable source/base seeds",
    "request bounded proposals from owning adapters",
    "expand without Cartesian product",
    "validate via owner results",
    "hard-filter before scoring",
    "deduplicate by canonicalSignature",
    "diversity-prune using explicit provider diversityKey",
    "request 3.03/3.04 owner metrics",
    "score locally under explicit ShapeSystemTarget",
    "materialize bounded owner-routed correction branches",
    "repeat until budget/depth/convergence stop"
  ],
  "proposal_policy": {
    "geometry_proposal_owner": "3.01/3.02/3.04 or explicit external owner",
    "transform_proposal_owner": "Core/3.05 adapter",
    "3.06_role": "orchestrates proposal refs; never directly mutates control points/primitive params/transform matrix",
    "transform_variants": "generated only when explicit TransformVariantPolicy or provider proposals exist",
    "generation_cost": "bookkeeping/tie-break only, never aesthetic score"
  },
  "target_schema": {
    "targetId": "string",
    "requiredGroups": "string[]",
    "optionalGroups": "string[]",
    "disabledGroups": "string[]",
    "silhouetteTarget": "optional Compo3.03 target",
    "regionTarget": "optional Compo3.04 target",
    "semanticMultipliers": "map group->positive finite number",
    "styleMultipliers": "map group->positive finite number",
    "groupVoteCaps": "map group->positive finite number",
    "requiredEvidencePolicy": "REQUIRE_ALL|DIAGNOSTIC_IF_MISSING|RANK_WITH_LOW_COVERAGE",
    "hardConstraints": "typed constraints",
    "stylePresetRef": "optional"
  },
  "allowed_primary_votes": {
    "shape.silhouette.localReadabilityScore": {
      "owner": "Compo3.03",
      "scoringGroup": "SILHOUETTE_READABILITY"
    },
    "shape.region.localTopologyFit": {
      "owner": "Compo3.04",
      "scoringGroup": "SHAPE_REGION_TOPOLOGY"
    }
  },
  "scoring_policy": {
    "explicit_target_required": true,
    "no_target": "DIAGNOSTIC_ONLY_LOCAL_SCORE_NULL",
    "hard_filter_before_score": true,
    "N_A": "EXCLUDE_NOT_ZERO",
    "components_of_active_composite": "SUPPRESS",
    "unknown_or_non_primary_metric": "DIAGNOSTIC_ONLY",
    "dependsOn_alone": "NEVER_SUPPRESS",
    "cross_group_direct_derivedFrom_overlap": "SUPPRESS_LOWER_PRIORITY_UNLESS_BOTH_EXPLICITLY_INDEPENDENT",
    "group_value": "weighted mean of selected canonical primary votes inside group; currently one canonical primary per group",
    "raw_group_weight": "baseWeight * semanticMultiplier * styleMultiplier",
    "group_weight": "min(raw_group_weight, groupVoteCap)",
    "effective_score_weight": "group_weight * MetricResult.confidence",
    "localScore": "weighted mean groupValue by effective_score_weight",
    "sceneConfidence": "weighted mean groupConfidence by group_weight",
    "targetCoverage": "covered expected groups / expected groups",
    "evidenceCoverage": "covered expected target weight / total expected target weight",
    "localScoreConfidence": "sceneConfidence * evidenceCoverage",
    "no_soft_aesthetic_penalty_layer": "owner fits already encode target interpretation; generation/correction cost remains non-aesthetic"
  },
  "ranking_policy": [
    "hard-feasible candidates only",
    "higher localScore outside scoreEpsilon",
    "higher targetCoverage",
    "higher localScoreConfidence outside confidenceEpsilon",
    "lower correctionCost",
    "lower generationCost",
    "stableTieBreak lexical"
  ],
  "initial_heuristics": {
    "score_epsilon": {
      "value": 0.015,
      "provenance": "INITIAL_HEURISTIC"
    },
    "confidence_epsilon": {
      "value": 0.03,
      "provenance": "INITIAL_HEURISTIC"
    },
    "default_group_vote_cap": {
      "value": 1.0,
      "provenance": "INITIAL_HEURISTIC"
    },
    "default_base_group_weight": {
      "value": 1.0,
      "provenance": "INITIAL_HEURISTIC"
    },
    "max_base_candidates": {
      "value": 16,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "max_proposals_per_base": {
      "value": 12,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "max_total_candidates": {
      "value": 64,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "max_repair_depth": {
      "value": 2,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "max_correction_branches_per_candidate": {
      "value": 4,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "max_diversity_per_bucket": {
      "value": 8,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    }
  },
  "hard_constraints": [
    "candidate hard violations are evaluated before local scoring",
    "candidate source snapshots are immutable; repair creates a child branch",
    "no full Cartesian product of proposal dimensions",
    "same intent+provider outputs+seed+versions produce same candidate ordering and lineage",
    "3.06 must not recalculate raw primitive/path/region/transform geometry under new metric names",
    "only canonical primary owner composites from 3.03 and 3.04 may vote in current Topic3 local score",
    "MetricResult componentOf active composite is diagnostic-only",
    "descriptor/raw complexity/area/bounds/transform magnitude cannot vote directly",
    "missing required evidence follows explicit requiredEvidencePolicy; never inject zero",
    "generationCost and correctionCost are not aesthetic scores",
    "visual mass/occupancy metrics from Topic4 are not owned or synthesized here",
    "positive/negative-space metrics from Topic5 are not owned or synthesized here",
    "global balance/hierarchy/eye-flow are not owned here",
    "no beautyScore"
  ],
  "correction_policy": {
    "foreign_mutation": "FORBIDDEN",
    "silhouette_mismatch": "consume 3.03 SilhouetteCorrectionRequest and route to 3.02/3.06 provider",
    "region_mismatch": "consume 3.04 ShapeRegionCorrectionRequest and route to 3.02/3.04 provider",
    "transform_invalid": "consume 3.05 TransformCorrectionRequest and route to Core transform owner",
    "new_branch": "immutable child candidate with parentCandidateId and deterministic seed fork",
    "max_depth": "bounded by ShapeGenerationBudget.maxRepairDepth"
  },
  "regression_scope": {
    "covers": [
      "Compo3.00",
      "Compo3.01",
      "Compo3.02",
      "Compo3.03",
      "Compo3.04",
      "Compo3.05",
      "Compo3.06"
    ],
    "owns_design_metrics": false,
    "baseline_policy": "expected outputs change only with explicit contract migration reason",
    "determinism": "same fixture/seed/version => same structural output"
  },
  "deferred_inputs": [
    "Topic4 visual mass / silhouette area / occupancy / density factor",
    "Topic5 positive and negative space",
    "Core ObjectTransform final migration",
    "global balance / hierarchy / eye-flow",
    "future global pipeline / final scene scorer",
    "style calibration datasets"
  ],
  "recompute_when": [
    "ShapeGenerationIntent or generation budget changes",
    "proposal provider version/output changes",
    "3.03/3.04 primary metric contract changes",
    "ShapeSystemTarget changes",
    "candidate hard-violation state changes",
    "owner correction creates new candidate branch",
    "Core transform version changes when candidate world evidence depends on it"
  ],
  "finality": "TOPIC3_LOCAL_SEARCH_SCORING_AND_REGRESSION_ONLY"
}
ARCHITECTURE CHECKPOINT · 3.06 CLOSES THE PLANNED SHAPE SUBSYSTEM BUT DOES NOT AUTO-MARK TOPIC 3 DONE BEFORE AUDIT. GENERATION IS BOUNDED / SEEDED / LINEAGE-BASED AND USES OWNER PROPOSALS. LOCAL SCORE AGGREGATES ONLY CANONICAL PRIMARY COMPOSITES FROM 3.03 AND 3.04 UNDER EXPLICIT TARGET. 3.01/3.02/3.05 DESCRIPTORS DO NOT VOTE. TOPIC4 MASS/OCCUPANCY, TOPIC5 FREE-SPACE AND GLOBAL BALANCE/HIERARCHY/EYE-FLOW REMAIN DEFERRED. NO BEAUTYSCORE.
VISITS / ...