COMPO · 22.02 · TORQUE-LIKE MOMENT DESCRIPTORS

Arm is signed.
Moment is descriptive.

22.02 берёт exact x/y и owner-qualified visual mass из 22.01, применяет их только к явно объявленным oriented reference axes и строит signed arm / torque-like moment descriptors. Нулевая сумма моментов относительно одной оси не объявляется качеством или глобальным балансом.

ModuleCompo 22.02
Axesexplicit only
Momentssigned descriptors
Counterweightsdeferred 22.03
Metricsnone
NextSTOP

Explicit axis → local moment descriptors

00 / contract
valid 22.00 root model + valid 22.01 VisualCentroid / contribution descriptors + explicit owner-declared oriented reference axis → signed perpendicular arm per subject → signed / absolute torque-like moment per subject → per-axis positive / negative / net / absolute aggregates NO counterweight inference NO regional balance NO score NO candidates

One owner for the moment layer

01 / ownership
OWNS

22.02

Explicit oriented axis declaration, signed arm, subject moment, per-axis aggregate and centroid-moment identity lineage.

FOREIGN / DOWNSTREAM

Preserved

22.00 root identities, 22.01 centroid, 22.03 counterweights/regions, 22.04 score/candidates, Topic21 mirror symmetry.

Reference axis is declared, never guessed

02 / axis
TorqueMomentReferenceAxis {
  axisSemanticRef,
  axisOwnerRef,
  axisContextRef,
  anchorX, anchorY,
  normalX, normalY,
  normalizedNormalX, normalizedNormalY,
  coordinateUnitRef,
  provenance,
  mutationAllowed: false
}

The normal orientation defines the sign convention. Reversing it flips signs but does not change absolute arms/moments.

Per-subject math stays observable

03 / moment math
armᵢ = (pᵢ − anchor) · n̂ Mᵢ = visualMassᵢ × armᵢ |armᵢ| and |Mᵢ| are descriptors. NEGATIVE / ON_AXIS / POSITIVE is exact sign only. 0 is valid. N_A is not 0.

No hidden cross-axis score

04 / system
TorqueMomentAxisDescriptor {
  subjectMomentDescriptors[],
  positiveMomentSum,
  negativeMomentMagnitude,
  signedNetMoment,
  absoluteMomentSum,
  centroidSignedArm,
  expectedNetMomentFromCentroid,
  identityResidual,
  score: null,
  metricResultRef: null
}

Каждая explicit axis остаётся отдельным observation context. 22.02 не усредняет оси и не выбирает «лучшую».

Centroid identity is math, not quality

05 / identity
signedNetMoment = totalVisualMass × signedDistance(VisualCentroid, axis) Therefore: axis through the same VisualCentroid → signedNetMoment = 0 This is a mathematical identity. It is NOT evidence that the composition is visually balanced.

N_A and INVALID remain distinct

06 / status
OK

Complete

Exact centroid lineage, valid explicit axis, matching unit, finite math.

N_A

Not computable

No axis, overflow, same semantic axis with conflicting declarations, incompatible unit, or upstream centroid N_A.

INVALID

Malformed

Zero/nonfinite normal, wrong frame/model lineage, invalid centroid record or policy.

Bounded explicit evaluation

07 / policy
AxesEXPLICIT_AXES_ONLY
SubjectsAll valid 22.01 contributions for each selected axis
ConflictN_A_NO_WINNER
OverflowN_A_NO_TRUNCATION
Auto centroid/frame/mirror axisfalse
Cross-axis aggregationfalse

Downstream stays downstream

08 / boundaries
22.03

Counterweights / regions

Regional mass partition and counterweight semantics may consume 22.02 moment descriptors but are not inferred here.

22.04

Scoring / candidates

Target profiles, MetricResult and bounded correction candidates remain one later owner.

Moment ≠ balance verdict

09 / firewalls
zero net moment about one axis != globally balanced nonzero net moment != automatically imbalanced absolute moment != penalty reference axis != mirror axis reference axis != target large moment != dominance small moment != redundancy no counterweight inference no regional partition no MetricResult no candidate generation

CANON → LAB → DATA → IDEAS

10 / mandatory hooks
IDEAS_REFS[]Moment perception and axis-choice studies.
DATA_CAPTURE[]Axis, arms, moments, aggregates and identity residual.
DEFERRED_SEMANTIC_INPUTS[]Regions, counterweights, scoring and candidates.
HUMAN_FEEDBACK_HOOKS[]Axis owner/context/orientation corrections.
CONFLICT_PRIORITY_ASSUMPTIONS[]No confidence winner; no canonical positive side.
LAB_HOOKS[]Moment-vs-human-balance controlled experiments.

22.02 regression suite

11 / deterministic tests

Suite covers explicit-axis lineage, normalization, signed arms/moments, centroid identity, zero semantics, conflicts/overflow, immutable attachments, no-score boundaries plus deterministic identity/sign/translation/mass-scaling sweeps.

Tests not run yet.

DATA FOR LAYOUT ENGINE

12 / machine contract
{
  "module": "Compo 22.02",
  "name": "torque_like_moment_descriptors",
  "version": "1.0-canonical",
  "canonical_main_title": "Torque-like moment descriptors",
  "topic": "22_АСИММЕТРИЧНЫЙ_БАЛАНС",
  "scope": "EXPLICIT_OWNER_DECLARED_ORIENTED_REFERENCE_AXES_OVER_ONE_VALID_COMPO22_01_VISUAL_CENTROID_AND_EXACT_PER_SUBJECT_SIGNED_ARM_AND_TORQUE_LIKE_MOMENT_DESCRIPTORS_ONLY_WITHOUT_COUNTERWEIGHTS_REGIONAL_DISTRIBUTION_SCORING_OR_CANDIDATES",
  "main_topic_contract": {
    "topic_title": "Асимметричный баланс",
    "topic_goal": "Описывает асимметричный баланс через visual center of mass, moments/плечи, regional distribution и counterweights, не требуя зеркального соответствия.",
    "expected_output": "VisualCentroid, mass moments, balance descriptors",
    "planned_files": [
      "22.00 Asymmetric balance model",
      "22.01 Visual center of mass",
      "22.02 Torque-like moment descriptors",
      "22.03 Counterweight and regional mass distribution",
      "22.04 Scoring, candidates and tests"
    ]
  },
  "ownership": {
    "owner": "Compo22.02",
    "owns": [
      "TorqueMomentReferenceAxis",
      "TorqueMomentSubjectDescriptor",
      "TorqueMomentAxisDescriptor",
      "TorqueMomentSelectionPolicy",
      "TorqueMomentSystem",
      "TorqueMomentAttachment",
      "explicit owner-declared oriented reference-axis normalization",
      "signed perpendicular arm computation in the exact Compo22.00 coordinate frame",
      "per-subject torque-like signed/absolute moment descriptors from Compo22.01 mass and position values",
      "per-axis positive/negative/net/absolute moment aggregates",
      "centroid-net-moment identity descriptor",
      "identity/status/provenance rules for Topic22 moment layer",
      "non-mutating correction request for axis or centroid-lineage errors"
    ],
    "does_not_own": [
      "AsymmetricBalanceModel / frame / subject / position / mass binding identities — Compo22.00",
      "VisualCentroid numeric evidence resolution and weighted centroid — Compo22.01",
      "visual-mass extraction or semantics — Compo4 / foreign owner",
      "counterweight inference / regional partition — Compo22.03",
      "balance scoring / candidate generation / MetricResult — Compo22.04",
      "mirror/reflection axis semantics — Topic21",
      "radial balance — Topic23",
      "dominance/hierarchy — Compo13/Topic19",
      "global beautyScore",
      "final-layout ranking",
      "foreign geometry/mass/style/semantic mutation"
    ]
  },
  "consumes": [
    "valid Compo22.00 model/frame/seed lineage",
    "valid Compo22.01 VisualCentroid and VisualCentroidAttachment",
    "exact Compo22.01 contributionDescriptors containing x/y/massValue for every model subject",
    "one or more explicit owner-declared oriented reference axes",
    "one explicit TorqueMomentSelectionPolicy"
  ],
  "provides": [
    "TorqueMomentReferenceAxis[]",
    "TorqueMomentSubjectDescriptor[]",
    "TorqueMomentAxisDescriptor[]",
    "TorqueMomentSystem",
    "TorqueMomentAttachment"
  ],
  "owns_metrics": [],
  "independent_numeric_votes": 0,
  "moment_math": {
    "axis": "anchor point a=(ax,ay) + owner-declared nonzero normal n, normalized to n_hat",
    "signed_arm_i": "dot(p_i - a, n_hat)",
    "absolute_arm_i": "abs(signed_arm_i)",
    "signed_moment_i": "visualMass_i * signed_arm_i",
    "absolute_moment_i": "abs(signed_moment_i)",
    "positive_moment_sum": "sum(max(signed_moment_i,0))",
    "negative_moment_magnitude": "sum(max(-signed_moment_i,0))",
    "signed_net_moment": "sum(signed_moment_i)",
    "absolute_moment_sum": "sum(abs(signed_moment_i))",
    "centroid_signed_arm": "dot(VisualCentroid - a, n_hat)",
    "centroid_identity": "signed_net_moment = totalVisualMass * centroid_signed_arm for the same mass/position data",
    "axis_normal_sign": "reversing n_hat reverses signed arms/moments but preserves absolute values",
    "zero_note": "signed arm 0, signed moment 0 and net moment 0 are valid exact numeric outcomes"
  },
  "axis_semantics": {
    "explicit_only": true,
    "axis_anchor_is_not_target": true,
    "axis_is_not_mirror_axis": true,
    "axis_is_not_fulcrum_by_default": true,
    "normal_orientation_is_owner_declared": true,
    "normal_is_normalized_deterministically": true,
    "zero_normal": "INVALID",
    "coordinate_unit": "must match the VisualCentroid coordinateUnitRef; no auto conversion"
  },
  "status_semantics": {
    "OK": "valid centroid lineage + complete explicit axes + finite moment math",
    "N_A": "no explicit axes, axis/evaluation overflow, conflicting declarations for one axisSemanticRef, unit incompatibility, or upstream centroid N_A; no guessing/truncation/conversion",
    "INVALID": "malformed axis/policy/bundle, zero/nonfinite normal, nonfinite anchor, wrong frame/model lineage, invalid centroid/contribution record",
    "zero_note": "zero is a valid descriptor value and is never replaced by N_A"
  },
  "selection_policy": {
    "axes": "EXPLICIT_AXES_ONLY",
    "subjects": "ALL_VALID_COMPO22_01_CONTRIBUTIONS_PER_AXIS",
    "duplicate_exact_axis_records": "DEDUPLICATE_BY_RECORD_IDENTITY",
    "conflicting_same_axis_semantic_ref": "N_A_NO_WINNER",
    "overflow": "N_A_NO_TRUNCATION",
    "auto_axis_generation": false,
    "auto_centroid_axis": false,
    "auto_frame_center_axis": false,
    "auto_mirror_axis_import": false,
    "auto_counterweight_inference": false,
    "cross_axis_aggregation": false,
    "full_cartesian_candidate_generation": false
  },
  "critical_firewalls": [
    "torque-like descriptor != physical force model",
    "reference axis != mirror axis",
    "reference axis != balance target",
    "reference axis != fulcrum by default",
    "axis through centroid gives zero net moment by centroid identity; this is not proof of visual balance",
    "zero net moment about one explicit axis != globally balanced",
    "nonzero net moment != automatically imbalanced",
    "signed moment sign depends on owner-declared normal orientation",
    "absolute moment != penalty",
    "large moment != dominance",
    "small moment != redundancy",
    "mass value remains owner-qualified visual mass, not geometric area",
    "22.02 does not infer counterweight pairs or regional groups",
    "22.02 does not average or score across axes",
    "no candidate generation in 22.02",
    "no MetricResult in 22.02",
    "N_A != 0",
    "INVALID != 0",
    "local != global",
    "geometry != interpretation",
    "descriptor != score",
    "heuristic != law",
    "correction request != foreign mutation",
    "module execution order != rule priority",
    "one metric = one owner",
    "no universal beautyScore",
    "IDEA != CANON",
    "EXPERIMENT != CANON"
  ],
  "IDEAS_REFS": [
    "IDEA-01 compare human balance judgements with signed-net versus absolute-moment profiles",
    "IDEA-02 test multiple explicit axes without assuming a canonical balance axis",
    "IDEA-03 study sensitivity of torque-like descriptors to visual-mass channel choice",
    "IDEA-04 compare centroid-offset and moment descriptors under controlled translation",
    "IDEA-05 study intentional high absolute moment with near-zero net moment"
  ],
  "DATA_CAPTURE": [
    "scopeRef",
    "snapshotRef",
    "asymmetricBalanceModelRef",
    "visualCentroidRef",
    "axisSemanticRef",
    "axisAnchor",
    "normalizedAxisNormal",
    "subjectRef",
    "signedArm",
    "absoluteArm",
    "massValue",
    "signedMoment",
    "absoluteMoment",
    "positiveMomentSum",
    "negativeMomentMagnitude",
    "signedNetMoment",
    "absoluteMomentSum",
    "centroidSignedArm",
    "expectedNetMomentFromCentroid",
    "identityResidual",
    "status",
    "reasonCode"
  ],
  "DEFERRED_SEMANTIC_INPUTS": [
    "22.03 regional partition semantics",
    "22.03 counterweight declarations/inference policy",
    "22.04 target profiles and balance scoring",
    "22.04 bounded candidate generation",
    "Topic21 mirror-axis/symmetry semantics"
  ],
  "HUMAN_FEEDBACK_HOOKS": [
    "correct axisSemanticRef/owner/context",
    "correct axis anchor or normal orientation",
    "flag incompatible coordinate unit",
    "inspect signed-side convention before interpretation"
  ],
  "CONFLICT_PRIORITY_ASSUMPTIONS": [
    "confidence never chooses between conflicting axis declarations",
    "axis normal direction has no universal positive-side preference",
    "centroid axis is not preferred over any other explicit axis",
    "no axis is globally primary unless downstream policy declares it"
  ],
  "LAB_HOOKS": [
    "LAB torque-descriptor perception study",
    "LAB axis-orientation sign invariance study",
    "LAB mass-channel sensitivity study",
    "LAB moment-profile versus balance-rating study"
  ],
  "topic22ProgressAfterThisModule": "3/5 local",
  "next_module": "Compo 22.03 — Counterweight and regional mass distribution",
  "hard_stop": "Do not implement 22.03 or 22.04 in this file"
}
VISITS / ...