Контракт интеграционного слоя
2.23 связывает локальную line subsystem с внешним context/global pass. Он не является новым scorer и не решает композицию целиком. Его результат — проверяемая проекция внешнего решения в разрешённые line-side inputs.
Context-aware target projection, external selection trace и owner-routed correction для line candidates.
Никакого пересчёта global metrics, никакого прямого изменения line geometry, никакого generic rule-override budget.
Global pipeline → 48.xx; global scoring → 49.xx; universal override schema/budgets/conflicts → 65.xx.
CONSUMES / PROVIDES
LineStructureCandidate[] // 2.19 LineSystemScoreResult[] // 2.20 local ranking MaskCropSeamResult[]? // 2.22 descriptors LineSystemTarget // base target used by 2.20 ContextDirectiveRef[] // EXTERNAL owner ExternalSelectionDirective? // EXTERNAL global authority ExternalContextMetricRef[] // references only LineContextPolicy Compo0.seed / lineage
LineContextProjection {
status,
baseTargetRef,
effectiveTarget,
targetPatchTrace[],
localRankingRef,
externalSelectionRef?,
selectedCandidateRef?,
localVsContextDelta,
correctionRequests[],
ignoredDirectives[],
unresolvedConflicts[],
deferredGlobalRefs[],
recomputePlan,
audit
}LineStructureCandidate[]; 2.20 → LineSystemScoreResult[]; 2.22 → MaskCropSeamResult[]. 2.23 не вводит aliases для этих сущностей.Ownership: адаптер, а не глобальный owner
Самая важная граница 2.23 — отличить «линия реагирует на глобальный контекст» от «линия владеет глобальным контекстом».
Line-side projection
lineContext.effectiveTarget
lineContext.patchTrace
lineContext.overrideApplicationTrace
lineContext.recomputePlan
External authority
global/context diagnostics, hierarchy/balance/negative-space/eye-flow owners, external selection decision, future RuleOverride references. Только по ID + provenance + authority.
Global composition
global.balance, global.hierarchy, global.eyeFlow, global.negativeSpace, global rank/score, override budget, exception cost.
Reserved future owners
| Future area | Reserved owner | Что 2.23 делает сейчас |
|---|---|---|
| Multi-pass local → context → global orchestration | Compo 48.xx | Только отдаёт typed recompute plan; не управляет всей сценой и convergence. |
| Global MetricResult aggregation / ranking | Compo 49.xx | Хранит external refs; не вычисляет globalScore и не смешивает его с localScore 2.20. |
| Generic RuleOverride / budget / conflicts | Compo 65.xx | Принимает уже авторизованный directive ref. Общий override budget здесь не изобретается. |
Место 2.23 в multi-pass pipeline
Context pass может изменить требования к линии, но он не должен задним числом переписывать измерения. Изменяется target/policy или создаётся correction request, после чего владельцы пересчитывают свои результаты.
Target projection
Создаёт новый effective target с parent ref. Base target остаётся immutable.
Correction
Если нужен другой stroke/geometry/contact, 2.23 просит соответствующего owner, а не мутирует state.
Global selection
Решение выбрать локально второй candidate приходит извне и не маскируется под новый localScore.
ContextDirectiveRef: только внешний контракт
2.23 не владеет универсальной schema overrides. До появления 65.xx он принимает минимальный reference envelope, достаточный для line-side validation и audit.
Input reference
ContextDirectiveRef {
directiveId: string,
schemaOwner: string, // EXTERNAL
issuedBy: string, // metric/context/global owner
authority: "CONTEXT|GLOBAL|HARD_AUTHORITY",
scope: {
sceneId,
candidateIds?: string[],
lineIds?: string[],
lineRoles?: string[]
},
action:
"PATCH_LINE_TARGET" |
"REQUEST_LINE_CORRECTION" |
"SELECT_CANDIDATE" |
"EXCLUDE_CANDIDATE",
payloadRef | payload,
justificationRefs: string[],
confidence: 0..1,
provenance,
version
}Line-side validation
accept only if:
directiveId present
issuedBy present
authority explicit
scope intersects current scene / candidate / line
action in supported line adapter actions
justificationRefs non-empty
provenance present
otherwise:
ignoredDirectives.push({
directiveId,
reason
})Immutable target projection
Context может изменить способ интерпретации уже измеренных line metrics, но не сами owner values. Именно поэтому основной безопасный механизм — patch explicit target, а затем повторно вызвать 2.20.
Allowed target patches
LineTargetPatch {
requiredGroups?: + / - group,
optionalGroups?: + / - group,
disabledGroups?: + / - group,
semanticMultipliers?: {groupOrMetric: value},
styleMultipliers?: {groupOrMetric: value},
groupVoteCaps?: {group: value},
requiredEvidencePolicy?: enum
}Только поля, которые 2.20 уже понимает как target/policy. Новых metric values patch не создаёт.
Forbidden patch
FORBIDDEN: MetricResult.value = ... MetricResult.confidence = ... LinePathGeometry.* = ... stroke.width = ... stroke.color = ... global.balance = ... localScore = ... beautyScore = ...
Если context хочет изменить геометрию/rendering — только correction request владельцу.
Локальный победитель может не стать глобальным
2.20 ранжирует candidates внутри одного line target. Глобальный слой может предпочесть другой candidate из-за отношений, которыми line subsystem не владеет. 2.23 должен сохранить это различие явно.
2.20 stays true
Если A имел localScore .91, а B .87, эти значения сохраняются в audit.
B can still be selected
Например, внешний hierarchy-owner сообщает, что A конфликтует с доминантой всей сцены.
No hidden remix
Нельзя тайно сделать B.localScore=.93 добавив внутри 2.23 global hierarchy.
Context → owner-routed correction
Глобальный context часто не просто выбирает candidate, а требует изменить линию. 2.23 переводит это в typed request к существующему owner.
| Context asks for | Target owner | 2.23 output |
|---|---|---|
| Линия слишком тяжёлая относительно доминанты сцены | 2.06 / 2.16 | Correction request: уменьшить visual-weight target / contrast / opacity через owner. |
| Connector мешает объекту или пересекает protected region | 2.09 / 2.10 / 2.11 / 2.19 | Request reroute / contact correction; bounded regeneration by 2.19. |
| Divider должен поддержать новый grid/context | 2.13 / 2.14 | Request updated grid/boundary target; geometry mutation остаётся у owner/generator. |
| Seam/crop должен учитывать изображение | 2.22 + future image/global owners | Request new seam/crop intent or derived geometry; 2.23 не решает image composition. |
| Нужно другое глобальное eye-flow | future global flow owner | Global owner формулирует directive; 2.08 остаётся только local cue owner. |
CorrectionRequest envelope
LineContextCorrectionRequest {
requestId,
sourceDirectiveId,
targetOwner: "Compo2.xx",
targetCandidateId,
targetLineId?,
requestedEffect, // semantic request, NOT mutation command
targetPatch?, // owner-owned target only
constraints[],
justificationRefs[],
seedForkPolicy: "DETERMINISTIC",
provenance: "DERIVED"
}
set controlPoint=(x,y), strokeWidth=3 или move endpoint как приказ чужому state. Request описывает желаемый эффект/constraint; owner сам решает допустимое изменение по своему API.Conflicts: не изобретать универсальный resolver
До темы 65 конфликт двух внешних directives не должен разрешаться скрытой эвристикой внутри line subsystem.
Независимые patches
D1: disable GRID_RELATION D2: styleMultiplier.COLOR_TONE = .8 → deterministic order by directiveId/version → both applied → trace keeps both
Conflict
D1: require GRID_RELATION D2: disable GRID_RELATION → status = "context_conflict" → unresolvedConflicts += [D1,D2] → NO silent last-write-wins → request external resolver
Edge cases и invariants
Context integration — место, где проще всего нечаянно сломать ownership. Поэтому особые случаи фиксируются как контракт, а не как implementation trivia.
| Case | Policy |
|---|---|
| Нет external directives | effectiveTarget == baseTarget; локальный winner остаётся selectedCandidateRef. |
| Directive scope не пересекается | Ignored + audit reason; никакого влияния. |
| Directive без justification/provenance | Invalid for application; diagnostic-only. |
| Patch пытается изменить owner metric | Reject directive path; MetricResult immutable. |
| Patch делает N/A группу required, но evidence неприменим | 2.20 применяет свою requiredEvidencePolicy; 2.23 не инжектит value=0. |
| External selection указывает hard-rejected candidate | Reject selection directive; hard feasibility имеет приоритет. |
| External winner локально #2 | Разрешено; сохранить local rank/score и external justification отдельно. |
| Два конфликтующих directives | context_conflict; ждём external resolver. |
| Context требует geometry mutation | Только correction request owner; source candidate immutable. |
| Global metric отсутствует | Не угадывать; deferred/missing context ref, а не zero. |
| 2.22 seam descriptor доступен | Можно передать внешнему context owner как descriptor; он не становится global score. |
| Повтор pass с теми же refs/version | Projection и trace детерминированы. |
Визуальная лаборатория: local ≠ global
Один и тот же набор line candidates может иметь локального победителя A, но внешний контекст обоснованно выбрать B. Важно не переписать локальную историю задним числом.
Не переписываем прошлое
2.20 продолжает утверждать: в своём локальном target A лучше B. Это полезная информация даже после внешнего выбора B.
Выбор B хранится отдельно
2.23 записывает externalSelectionRef, justification refs и delta между local rank и context selection.
Можно вернуться в line subsystem
Если нужен новый A′, внешний context формулирует directive → 2.23 маршрутизирует correction → 2.19 regenerates → 2.20 rescoring.
Live projection demo
Детерминированные integration tests
2.21 владеет полным regression suite темы линии; эти tests проверяют только invariants самого context adapter 2.23.
DATA FOR LAYOUT ENGINE
Machine-readable integration contract. Он намеренно описывает только line-side adapter и явно резервирует глобальные функции будущим owners.
{
"module": "Compo 2.23",
"name": "line_global_context_adapter",
"version": "1.1-corrective",
"scope": "line-side context/global integration protocol: immutable target projection, external selection trace and owner-routed corrections",
"consumes": [
"Compo2.19.LineStructureCandidate[]",
"Compo2.20.LineSystemScoreResult[]",
"Compo2.22.MaskCropSeamResult[]?",
"Compo2.20.LineSystemTarget",
"ContextDirectiveRef[] from external owners",
"ExternalSelectionDirective?",
"ExternalContextMetricRef[]",
"LineContextPolicy",
"Compo0.seed/lineage"
],
"provides": [
"LineContextProjection",
"lineContext.effectiveTarget",
"lineContext.patchTrace",
"lineContext.overrideApplicationTrace",
"lineContext.recomputePlan",
"LineContextCorrectionRequest[]",
"localVsContextDelta",
"ignoredDirectives[]",
"unresolvedConflicts[]"
],
"owns_metrics": [],
"descriptors_only": [
"lineContext.patchTrace",
"lineContext.overrideApplicationTrace",
"lineContext.recomputePlan",
"localVsContextDelta",
"deferredGlobalRefs",
"audit"
],
"hard_constraints": [
"global metrics are never recomputed by 2.23",
"2.20 localScore is never overwritten by context selection",
"base target and owner MetricResults are immutable",
"foreign geometry/render mutation is forbidden",
"hard-rejected candidate cannot be externally selected",
"unsupported or unauthorised directive is ignored with audit",
"conflicting generic overrides are not silently resolved"
],
"soft_constraints": [
"non-conflicting target patches may be composed deterministically",
"target patch paths are allow-listed",
"context corrections are expressed as desired effects/constraints",
"same refs/version/seed produce same projection trace"
],
"preferences": [
"prefer target projection before geometry correction when sufficient",
"preserve local ranking facts even when external selection differs",
"retain full provenance and justification references",
"minimize dirty recompute to affected line owners"
],
"overrides_allowed_by": [
"external context/global authority",
"future Compo48 global pipeline",
"future Compo49 global scorer",
"future Compo65 rule override system"
],
"initial_heuristics": {},
"style_preset_values": {
"allowed": "only through fields already accepted by Compo2.20 target/policy",
"provenance": "STYLE_PRESET"
},
"allowed_target_patch_paths": [
"requiredGroups",
"optionalGroups",
"disabledGroups",
"semanticMultipliers.*",
"styleMultipliers.*",
"groupVoteCaps.*",
"requiredEvidencePolicy"
],
"directive_actions": [
"PATCH_LINE_TARGET",
"REQUEST_LINE_CORRECTION",
"SELECT_CANDIDATE",
"EXCLUDE_CANDIDATE"
],
"context_projection_policy": {
"base_target_immutable": true,
"metric_values_immutable": true,
"non_conflicting_patch_order": "directiveId|version lexical deterministic",
"conflicting_patch": "CONTEXT_CONFLICT_UNRESOLVED",
"generic_priority_resolution": "DEFERRED_TO_COMPO65"
},
"selection_policy": {
"local_winner_owner": "Compo2.20",
"global_selection_owner": "EXTERNAL/FUTURE_GLOBAL_SOLVER",
"external_selection_may_choose_local_rank_gt_1": true,
"external_selection_may_choose_hard_rejected": false,
"local_score_rewrite": "FORBIDDEN"
},
"correction_policy": {
"direct_foreign_mutation": "FORBIDDEN",
"request_target": "existing line owner 2.02-2.18 / 2.22 or orchestrator 2.19",
"orchestrator": "Compo2.19",
"recompute": "dirty owners then Compo2.20 rescore",
"seed_fork": "deterministic"
},
"deferred_inputs": [
"Compo48.xx global multi-pass pipeline/convergence",
"Compo49.xx global metric aggregation/ranking",
"Compo65.xx universal override schema/budget/conflict resolver",
"future global balance/hierarchy/eye-flow/negative-space owners"
],
"recompute_when": [
"applicable target directive set/version changes",
"external selection directive changes",
"owner correction changes candidate/metrics",
"base line target changes",
"external authority/provenance validation changes"
],
"tests": [
"C01_NO_CONTEXT_IDENTITY",
"C02_BASE_TARGET_IMMUTABLE",
"C03_METRIC_VALUE_IMMUTABLE",
"C04_SCOPE_MISMATCH_IGNORED",
"C05_MISSING_AUTHORITY_IGNORED",
"C06_MISSING_JUSTIFICATION_IGNORED",
"C07_ALLOWED_TARGET_PATCH",
"C08_FORBIDDEN_METRIC_PATCH",
"C09_NON_CONFLICTING_PATCH_DETERMINISM",
"C10_CONFLICT_NOT_LAST_WRITE_WINS",
"C11_NA_NOT_ZERO",
"C12_LOCAL_WINNER_DEFAULT_SELECTION",
"C13_EXTERNAL_CAN_SELECT_LOCAL_SECOND",
"C14_LOCAL_SCORE_NOT_REWRITTEN",
"C15_HARD_REJECT_SELECTION_FORBIDDEN",
"C16_CORRECTION_ROUTES_TO_OWNER",
"C17_FOREIGN_MUTATION_REJECTED",
"C18_DIRTY_RECOMPUTE_TARGETED",
"C19_GLOBAL_METRIC_REFERENCE_ONLY",
"C20_2_22_DESCRIPTOR_NOT_GLOBAL_SCORE",
"C21_NO_BEAUTYSCORE",
"C22_COMPO48_49_65_DEFERRED",
"C23_REPEATABLE_TRACE",
"C24_NO_DIRECTIVE_NO_RESCORE",
"C25_CANONICAL_HANDOFF_TYPES"
],
"finality": "LINE_CONTEXT_ADAPTER_ONLY",
"invariants": [
"ONE_METRIC_ONE_OWNER",
"N_A_NOT_ZERO",
"LOCAL_NOT_GLOBAL",
"GEOMETRY_NOT_INTERPRETATION",
"DESCRIPTOR_NOT_SCORE",
"NO_BEAUTYSCORE",
"NO_FOREIGN_MUTATION",
"GLOBAL_DECISION_DOES_NOT_REWRITE_LOCAL_FACTS"
]
}