COMPO · 24.00 · DIAGONAL AXIS CANDIDATES

Candidate first.
Main diagonal later.

24.00 задаёт root-слой Topic 24: явные owner-qualified диагональные оси в одной 2D frame, exact geometric equivalence и bounded candidate set. Здесь ещё нет main/counter selection, object alignment, mass projection, tension profile или scoring.

ModuleCompo 24.00
Axis inputexplicit only
Equivalenceexact · no tolerance
Main axisdeferred
Metricsnone
NextSTOP

Geometry before interpretation

Only explicit diagonal candidate geometry is canonical here.

00 / contract
explicit scope + snapshot + one owner-qualified 2D coordinate frame + explicit requested axisRef[] + owner-qualified anchor + direction evidence → DiagonalAxisEvidenceResolution[] → DiagonalAxisCandidate[] → DiagonalAxisCandidateSet → DiagonalCompositionSeed NO object orientation NO mass projection NO main/counter role NO tension profile NO score / generator

How a diagonal candidate is represented

Пояснительная графика показывает именно геометрический слой, без скрытой оценки композиции.

01 / visual explainer

Rising diagonal

Canonical direction points to +x. Positive dy gives the RISING geometry class. This is a descriptor only.

anchor direction (dx>0, dy>0) exact non-zero angle RISING ≠ “better”
candidate axisdescriptor only

Falling diagonal

Canonical direction still points to +x. Negative dy gives FALLING. No reading-order or tension assumption is attached.

anchor direction (dx>0, dy<0) FALLING ≠ “worse”
candidate axisdescriptor only
1 · explicit refs

Caller requests exact axisRef values. No all-lines scan and no geometry-driven discovery.

→
2 · evidence resolution

Owner-qualified anchor + direction evidence is validated. Missing/conflicting evidence stays N_A.

→
3 · bounded set

1..256 candidates. Exact duplicate geometry across refs produces N_A instead of multiple pseudo-votes.

hard stop
24.00 stops at candidate geometry. It does not decide which diagonal is “main”, whether objects follow it, how mass projects onto it, or whether the scene has desirable tension.

One owner for candidate identity

24.00 владеет геометрией candidate identity, но не её композиционной интерпретацией.

02 / ownership
OWNS

Frame + evidence + candidate set

2D frame binding, explicit axis evidence, resolution, exact line equivalence, rising/falling orientation descriptor, bounded candidate set and immutable root seed.

DOES NOT OWN

Alignment + mass + tension + score

Object orientation is 24.01, mass distribution is 24.02, counter-diagonal/tension is 24.03, scoring/candidate generation is 24.04.

Coordinate frame is explicit

The same axis numbers are meaningless without exact frame lineage.

03 / frame
DiagonalCoordinateFrameBinding { scopeRef, snapshotRef, coordinateFrameRef, coordinateFrameOwnerRef, unitRef, dimensionality: 2, provenance, status, mutationAllowed: false } frame x-axis != main diagonal frame y-axis != counter-diagonal frame center != diagonal anchor

Evidence is owner-qualified

Each requested axisRef resolves from exact anchor + direction declarations.

04 / evidence
ANCHOR

One point on the line

{x,y} in the exact coordinate frame. No viewport-center or object-centroid inference is allowed.

DIRECTION

Non-zero vector

{dx,dy} must be finite and both components non-zero for a diagonal candidate.

CONFLICT

No confidence winner

Multiple declarations for one axisRef must be exactly line-equivalent. Contradiction → N_A; confidence is diagnostic only.

Exact line equivalence, no epsilon

Scaled/reversed directions can still denote the same infinite line.

05 / exact math

Same infinite line

Direction reversal or scale does not create a new geometric axis. Exact line equivalence is tested algebraically, without tolerance.

A: (1, -0.5 screen) B: reversed exact same line → duplicate geometry

Near-parallel is still different

No hidden angle epsilon. If cross products are not exactly equal, the declarations are different candidates until a downstream policy says otherwise.

AB near ≠ equal · no implicit tolerance
parallel(A,B) := A.dx * B.dy === A.dy * B.dx sameLine(A,B) := parallel(A,B) AND (B.x-A.x) * A.dy === (B.y-A.y) * A.dx NO angular epsilon NO pixel tolerance NO near-parallel merge

Diagonal means mathematically non-axis-aligned

No hidden “looks diagonal enough” threshold is introduced at 24.00.

06 / validity

Valid candidate

Both direction components are non-zero. Even a very shallow slope remains diagonal unless an explicit downstream threshold is provided.

dx ≠ 0 AND dy ≠ 0 → geometric diagonal

Axis-aligned firewall

Exact horizontal and vertical directions are not diagonal candidates. The module rejects them rather than inventing a near-diagonal tolerance.

horizontalverticalINVALID as diagonal evidence

Bounded explicit candidate set

No full line search and no duplicate-equivalent geometry inflation.

07 / candidate set
SelectionEXPLICIT_CANDIDATES_ONLY
Bounds1..256 requested axis refs
OverflowN_A without truncation
Duplicate geometryN_A, no winner
DiagonalAxisCandidate {
  axisRef,
  scopeRef, snapshotRef,
  coordinateFrameRef,
  anchor: {x,y},
  direction: {dx,dy},
  orientationClass: RISING | FALLING,
  evidenceRefs[],

  objectOrientationAttachmentRef: null,
  massDistributionAttachmentRef: null,
  tensionProfileAttachmentRef: null,
  scoreRef: null,

  status,
  mutationAllowed: false
}

Immutable root seed

Downstream modules attach results without mutating 24.00 records.

08 / seed
DiagonalCompositionSeed { axisCandidateSetRef, objectOrientationAttachmentRef: null, massDistributionAttachmentRef: null, tensionProfileAttachmentRef: null, scoringAttachmentRef: null, metricResultRefs: [], mutationAllowed: false }

Downstream ownership stays explicit

Execution order does not collapse ownership boundaries.

09 / next owners
ModuleOwns next24.00 explicitly does not do it
24.01Object orientation vs diagonalNo angle/alignment between object orientation and candidate axis.
24.02Mass distribution along diagonalNo projection coordinate, density, centroid-along-axis or side mass.
24.03Counter-diagonal and tension profilesNo main/counter role assignment, angular tension or controlled tension profile.
24.04Scoring, candidates and testsNo MetricResult, target fit, independent vote or repair generator.

Descriptor ≠ score

These separations are normative and testable.

10 / firewalls
Candidate ≠ main

Being declared does not make an axis the primary compositional diagonal.

Rising ≠ preferred

RISING/FALLING are exact orientation descriptors only.

Near ≠ equal

Near-parallel or near-collinear axes remain distinct without explicit tolerance.

No beautyScore

24.00 owns zero MetricResult records and zero independent numeric votes.

CANON → LAB → DATA → IDEAS

Canonical geometry can later feed perceptual studies without turning hypotheses into laws.

11 / mandatory hooks
IDEAS_REFS[]Perceived diagonal strength, multiple-axis competition.
DATA_CAPTURE[]Frame, anchor, direction, conflicts, equivalent duplicates.
DEFERRED_SEMANTIC_INPUTS[]Main/counter role, tension target, desirability.
HUMAN_FEEDBACK_HOOKS[]Correct or merge declared axes.
CONFLICT_PRIORITY_ASSUMPTIONS[]Confidence and lexical order are not winners.
LAB_HOOKS[]Perceived-vs-geometric diagonality and tension studies.

24.00 regression suite

Tests cover exact frame lineage, axis evidence validity, conflict preservation, exact line equivalence, axis-aligned rejection, bounded explicit candidate selection, duplicate-equivalent handling, immutable seed, zero metrics and strict 24.01–24.04 / Topic21–23/25 firewalls.

12 / deterministic tests
Tests not run yet.

DATA FOR LAYOUT ENGINE

Machine-readable contract for integration and cross-module audit.

13 / machine contract
{
  "module": "Compo 24.00",
  "name": "diagonal_axis_candidates",
  "version": "1.0-canonical",
  "canonical_main_title": "Diagonal axis candidates",
  "topic": "24_ДИАГОНАЛЬНАЯ_КОМПОЗИЦИЯ",
  "scope": "EXPLICIT_OWNER_QUALIFIED_2D_DIAGONAL_AXIS_EVIDENCE_EXACT_GEOMETRIC_CANDIDATE_RESOLUTION_BOUNDED_CANDIDATE_SET_AND_IMMUTABLE_ROOT_SEED_ONLY_WITHOUT_OBJECT_ORIENTATION_MASS_PROJECTION_COUNTER_DIAGONAL_TENSION_OR_SCORING",
  "main_topic_contract": {
    "topic_title": "Диагональная композиция",
    "topic_goal": "Описывает диагональную структуру всей сцены: main diagonal, counter-diagonal, проекции масс на ось и controlled diagonal tension.",
    "expected_output": "DiagonalCompositionDescriptor, main/counter axes, projection distribution",
    "planned_files": [
      "24.00 Diagonal axis candidates",
      "24.01 Object orientation vs diagonal",
      "24.02 Mass distribution along diagonal",
      "24.03 Counter-diagonal and tension profiles",
      "24.04 Scoring, candidates and tests"
    ]
  },
  "ownership": {
    "owner": "Compo24.00",
    "owns": [
      "DiagonalCoordinateFrameBinding",
      "DiagonalAxisEvidence",
      "DiagonalAxisEvidenceResolution",
      "DiagonalAxisCandidate",
      "DiagonalAxisOrientationClass taxonomy",
      "DiagonalAxisCandidateSetPolicy",
      "DiagonalAxisCandidateSet",
      "DiagonalCompositionSeed root identity",
      "exact geometric line-equivalence test without tolerance",
      "explicit-only bounded diagonal candidate selection",
      "identity/status/provenance rules for Topic24 root axis-candidate layer",
      "non-mutating correction request for frame/axis-evidence/candidate-set errors"
    ],
    "does_not_own": [
      "raw object geometry or raw line extraction — upstream geometry owners",
      "automatic diagonal discovery from scene pixels/objects — deferred / foreign owner",
      "object orientation relative to a diagonal — Compo24.01",
      "mass projection or distribution along diagonal — Compo24.02",
      "main-vs-counter diagonal relationship and controlled tension — Compo24.03",
      "target profile, MetricResult, candidate generator or final scoring — Compo24.04",
      "flow-template diagonal path matching — Topic25",
      "radial axes / rings / sectors — Topic23",
      "symmetric mirror axis semantics — Topic21",
      "asymmetric centroid/moment semantics — Topic22",
      "dominance / hierarchy / beautyScore / final-layout ranking",
      "foreign geometry/style/semantic mutation"
    ]
  },
  "consumes": [
    "explicit scope and snapshot identity",
    "one explicit owner-qualified 2D coordinate frame",
    "explicit requested diagonal axis refs",
    "owner-qualified axis evidence with anchor point and non-axis-aligned direction vector",
    "optional source/provenance/confidence metadata"
  ],
  "provides": [
    "DiagonalCoordinateFrameBinding",
    "DiagonalAxisEvidenceResolution[]",
    "DiagonalAxisCandidate[]",
    "DiagonalAxisCandidateSet",
    "DiagonalCompositionSeed"
  ],
  "owns_metrics": [],
  "independent_numeric_votes": 0,
  "status_semantics": {
    "OK": "valid exact explicit geometry lineage",
    "N_A": "missing/conflicting/duplicate-equivalent/overflow evidence; never numeric zero",
    "INVALID": "malformed or impossible record; never numeric zero"
  },
  "orientation_semantics": {
    "RISING": "canonical direction has dx > 0 and dy > 0",
    "FALLING": "canonical direction has dx > 0 and dy < 0",
    "HORIZONTAL": "not a valid diagonal candidate",
    "VERTICAL": "not a valid diagonal candidate",
    "note": "RISING/FALLING are geometric orientation descriptors, not quality, reading direction or tension."
  },
  "exact_equivalence": {
    "parallel": "dx1 * dy2 === dy1 * dx2",
    "same_infinite_line": "parallel AND (x2-x1)*dy1 === (y2-y1)*dx1",
    "tolerance": null,
    "near_parallel_is_equal": false
  },
  "policy": {
    "selectionMode": "EXPLICIT_CANDIDATES_ONLY",
    "maxCandidates": [
      1,
      256
    ],
    "overflow": "N_A_WITHOUT_TRUNCATION",
    "duplicateEquivalentGeometry": "N_A_NO_WINNER",
    "autoAxisDiscovery": false,
    "autoMainAxisSelection": false,
    "autoCounterAxisSelection": false,
    "autoScoring": false
  },
  "root_seed_contract": {
    "axisCandidateSetRef": "exact",
    "objectOrientationAttachmentRef": null,
    "massDistributionAttachmentRef": null,
    "tensionProfileAttachmentRef": null,
    "scoringAttachmentRef": null,
    "metricResultRefs": [],
    "mutationAllowed": false
  },
  "firewalls": [
    "axis candidate != selected main diagonal",
    "axis candidate != counter-diagonal",
    "diagonal orientation != movement direction",
    "rising/falling != good/bad",
    "near-horizontal nonzero direction != horizontal by hidden threshold",
    "near-parallel != exact parallel",
    "duplicate equivalent axis declarations != extra evidence votes",
    "candidate count != compositional strength",
    "axis geometry != object orientation",
    "axis geometry != mass distribution",
    "axis geometry != tension",
    "N_A != 0",
    "INVALID != 0",
    "descriptor != score",
    "local != global"
  ],
  "visual_explanation": {
    "diagrams": [
      "anatomy of rising/falling diagonals",
      "same infinite line under reversed/scaled direction",
      "valid diagonal vs horizontal/vertical firewall",
      "explicit bounded candidate-set pipeline"
    ]
  },
  "ideas_data_hooks": {
    "IDEAS_REFS": [
      "perceived diagonal strength vs exact geometric slope",
      "scene-dependent main diagonal selection",
      "counter-diagonal tension perception",
      "mass projection profile experiments",
      "diagonal direction and reading-order interactions",
      "near-axis-aligned perceptual thresholds",
      "multiple-diagonal competition"
    ],
    "DATA_CAPTURE": [
      "scope/snapshot/frame lineage",
      "axis refs",
      "anchor and direction evidence",
      "evidence conflicts",
      "exact-equivalence collisions",
      "rising/falling orientation class",
      "candidate-set status"
    ],
    "DEFERRED_SEMANTIC_INPUTS": [
      "main diagonal choice",
      "counter-diagonal role",
      "controlled tension target",
      "desirability of rising/falling direction"
    ],
    "HUMAN_FEEDBACK_HOOKS": [
      "correct axis anchor/direction",
      "merge duplicate equivalent axes",
      "withdraw a candidate",
      "declare missing candidate evidence"
    ],
    "CONFLICT_PRIORITY_ASSUMPTIONS": [
      "confidence cannot resolve contradictory geometry",
      "lexical axisRef order is not priority",
      "candidate request order is not strength ranking"
    ],
    "LAB_HOOKS": [
      "exact vs perceived diagonal threshold",
      "main/counter diagonal perceptual studies",
      "tension response to angular separation",
      "projection-density perception"
    ]
  },
  "topic24ProgressAfterThisModule": "1/5 local",
  "next_module": "Compo 24.01 — Object orientation vs diagonal",
  "hard_stop": "No 24.01–24.04 implementation in this file"
}
VISITS / ...