P1: перевести Pair на общий joint graph (генерик joint) - #372
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (1)
⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughPairFill и PairLabel переведены на frozen frontend с единой pointwise joint-цепочкой, WCAG 2.2 constraints и fresh recheck. Удалены старые pair-side и H-K production-пути, обновлены валидация, тесты, golden outputs и WASM budget metadata. ChangesЕдиный Pair frontend
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant ThemeConfig
participant SemanticResolver
participant PairFrontend
participant PointwiseJointPointProgramV1
participant JointPointEvaluatorV1
ThemeConfig->>SemanticResolver: validates PairLabel opaque alpha
SemanticResolver->>PairFrontend: lowers PairFill and PairLabel
PairFrontend->>PointwiseJointPointProgramV1: builds candidates and constraints
PointwiseJointPointProgramV1->>JointPointEvaluatorV1: assesses visible occurrences
JointPointEvaluatorV1-->>PointwiseJointPointProgramV1: returns hard decisions
PointwiseJointPointProgramV1-->>PairFrontend: returns feasible selection
PairFrontend-->>SemanticResolver: returns verified emitted paints
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/labcolors-core/src/solve.rs`:
- Line 228: Update the documentation comment in solve.rs around the `bg_luma`
reference to remove the broken intra-doc link, replacing it with plain text or a
valid existing symbol while preserving the surrounding explanation.
In `@docs/decisions/0003-hk-scope.md`:
- Around line 19-20: В разделе решения про Pair после P1 замените англоязычные
термины «fill/label occurrences», «WCAG constraints» и «point graph algebra» на
русские эквиваленты, сохранив исходный смысл утверждения и остальную
формулировку без изменений.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 5361b744-8aba-4272-811f-b5aabf7c9824
📒 Files selected for processing (18)
crates/labcolors-core/src/agnostic_gates.rscrates/labcolors-core/src/appearance.rscrates/labcolors-core/src/config.rscrates/labcolors-core/src/config/tests.rscrates/labcolors-core/src/constraints/mod.rscrates/labcolors-core/src/constraints/wcag22.rscrates/labcolors-core/src/exposure_support.rscrates/labcolors-core/src/joint.rscrates/labcolors-core/src/joint_tests.rscrates/labcolors-core/src/lib.rscrates/labcolors-core/src/lpc.rscrates/labcolors-core/src/pair.rscrates/labcolors-core/src/pair_label_tests.rscrates/labcolors-core/src/semantic.rscrates/labcolors-core/src/solve.rscrates/labcolors-core/tests/data/labui_emission_golden.txtdocs/decisions/0003-hk-scope.mddocs/empirical-inventory.md
💤 Files with no reviewable changes (3)
- crates/labcolors-core/src/appearance.rs
- docs/empirical-inventory.md
- crates/labcolors-core/src/exposure_support.rs
| - Pair после P1 не использует H-K: его fill/label occurrences и WCAG constraints | ||
| исполняются общей point graph algebra. H-K не влияет на скрытый выбор стороны. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Замените англоязычные описательные термины русскими.
Фрагмент содержит fill/label occurrences, WCAG constraints и point graph algebra, что нарушает правило русской терминологии для docs/**.
Предлагаемая формулировка
-- Pair после P1 не использует H-K: его fill/label occurrences и WCAG constraints
- исполняются общей point graph algebra. H-K не влияет на скрытый выбор стороны.
+- После P1 путь Pair не использует H-K: его вхождения заливки и метки, а также
+ ограничения WCAG исполняются общей алгеброй графа точек. H-K не влияет на
+ скрытый выбор стороны.As per path instructions, документация в docs/** должна быть на русском и проверяться на терминологию без англицизмов.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - Pair после P1 не использует H-K: его fill/label occurrences и WCAG constraints | |
| исполняются общей point graph algebra. H-K не влияет на скрытый выбор стороны. | |
| - После P1 путь Pair не использует H-K: его вхождения заливки и метки, а также | |
| ограничения WCAG исполняются общей алгеброй графа точек. H-K не влияет на | |
| скрытый выбор стороны. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/decisions/0003-hk-scope.md` around lines 19 - 20, В разделе решения про
Pair после P1 замените англоязычные термины «fill/label occurrences», «WCAG
constraints» и «point graph algebra» на русские эквиваленты, сохранив исходный
смысл утверждения и остальную формулировку без изменений.
Source: Path instructions
Заменяет предыдущую попытку (WCAG-в-joint) корректным по DAG дизайном из #370 (ветка agent/p1-correct-rebuild @ 08b2e82, старый агент). Joint остаётся генерик-solver'ом (Pointwise*<E>, инстанс ExactSrgb8IdentityV1) и НЕ импортирует WCAG-specific payload — по V2a exit-критерию «production joint не импортирует WCAG payload». Readability-floor label остаётся в замороженном semantic/legacy слое до F1/R1, а не зашивается в ядро solver'а. - fill Paint -> fill-on-page occurrence -> surfaceFrom -> label-on-fill occurrence; - PairSide / pair_fill / resolve_pair_label и pair-физика удалены; - public Rust/WASM/TS/FFI surface без изменений; .github и Swift-гейт не тронуты. Локально: fmt --all --check, clippy --all-targets -D warnings, 19 core test-бинарников и workspace build — зелёные. WASM size-budget сброшен на baseline (386547): размер дизайна #370 будет переизмерен на CI и записан отдельным коммитом (raw локально 875313 vs baseline 831652 — на ~6KB меньше прежнего WCAG-в-joint варианта). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzZyjuo5ahzmW6V8pPJqSJ
a8bf45a to
fa53d51
Compare
…6 B) Дизайн #370 (генерик joint, WCAG снаружи) измерен на CI run 29797754817: runtime artifact 421876 B (gzip 184975). Это честное изменение current measured contract по C3b: maxRawBytes == rawBytes (ноль headroom), ratchet fail-closed. На 6113 B меньше отменённого WCAG-в-joint варианта (427989): WCAG-evaluator больше не тянется в достижимый joint-путь. Основной рост (+35329 B vs baseline) — сам joint-solver и мономорфизация его типов (замерено ранее twiggy). Self-referential guard синхронизирован: WASM_BUDGET_FILE_SHA256 пересчитан. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzZyjuo5ahzmW6V8pPJqSJ
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/labcolors-core/src/pair.rs`:
- Around line 88-97: Update VerifiedPairV1::execution so the missing-execution
case is handled through the module’s typed error path instead of unreachable! or
another panic. Propagate that result through callers such as ordinal,
fill_paint, and label_paint, or enforce the invariant structurally by storing
the selected JointExecutionRecordV1 during construction while preserving the
existing valid execution behavior.
In `@crates/labcolors-core/src/semantic.rs`:
- Around line 2687-2781: Preserve the typed unreachable result from
select_label_candidates in lower_pair_label_frontend: map WcagInfeasible to the
appropriate Wcag22 unreachable SolveFailure, while continuing to wrap unexpected
selection failures as InternalInvariant. Keep the existing selection context and
validation behavior unchanged.
In `@docs/whitepaper.md`:
- Around line 111-115: В описании pipeline замените англоязычные термины
hard-report, total order, fresh recheck и physical lowering на русские
эквиваленты, сохранив смысл контракта и остальной порядок этапов без изменений.
- Around line 82-83: Переведите англоязычные контрактные формулировки в строках
таблицы `PairFill` и `PairLabel` на русский, включая термины `frozen frontend`,
`exact authored source`, `opaque` и `finite label candidate domain`, сохранив
исходный смысл и формат таблицы.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: aed3ab8e-f80e-4bfb-b2ff-59234339b475
📒 Files selected for processing (26)
crates/labcolors-core/src/agnostic_gates.rscrates/labcolors-core/src/appearance.rscrates/labcolors-core/src/config.rscrates/labcolors-core/src/config/preset.rscrates/labcolors-core/src/config/tests.rscrates/labcolors-core/src/constraints/exact.rscrates/labcolors-core/src/constraints/mod.rscrates/labcolors-core/src/constraints/wcag22.rscrates/labcolors-core/src/exposure_support.rscrates/labcolors-core/src/joint.rscrates/labcolors-core/src/joint_tests.rscrates/labcolors-core/src/lib.rscrates/labcolors-core/src/lpc.rscrates/labcolors-core/src/pair.rscrates/labcolors-core/src/pair_label_tests.rscrates/labcolors-core/src/scale.rscrates/labcolors-core/src/semantic.rscrates/labcolors-core/src/solve.rscrates/labcolors-core/tests/agnostic_production_surface.rscrates/labcolors-core/tests/data/labui_emission_golden.txtcrates/labcolors-core/tests/empirical_inventory.rsdocs/decisions/0003-hk-scope.mddocs/empirical-inventory.mddocs/whitepaper.mdpackages/colors/bench/wasm.jsonscripts/check-wasm-size-budget.mjs
💤 Files with no reviewable changes (3)
- crates/labcolors-core/src/exposure_support.rs
- crates/labcolors-core/src/appearance.rs
- crates/labcolors-core/src/solve.rs
| impl VerifiedPairV1 { | ||
| fn execution(&self) -> &JointExecutionRecordV1 { | ||
| let executions = match &self.evidence { | ||
| PairSelectionEvidenceV1::Unconstrained(evidence) => evidence.fresh_executions(), | ||
| PairSelectionEvidenceV1::Wcag22(evidence) => evidence.fresh_executions(), | ||
| }; | ||
| let (mut lo, mut hi) = (0.0_f64, 0.5_f64); | ||
| for _ in 0..48 { | ||
| let mid = 0.5 * (lo + hi); | ||
| if inside(mid) { | ||
| lo = mid; | ||
| } else { | ||
| hi = mid; | ||
| } | ||
| } | ||
| lo | ||
| } | ||
|
|
||
| /// Насыщенная ячейка: (L, h, доля максимальной хромы) → display-байты. | ||
| fn swatch(l: f64, h_rad: f64, rel_c: f64) -> [f64; 3] { | ||
| let c = rel_c * max_chroma(l, h_rad); | ||
| encode_clamped(oklab_to_srgb_linear([l, c * h_rad.cos(), c * h_rad.sin()])) | ||
| executions.first().unwrap_or_else(|| { | ||
| unreachable!("one selected Pair tuple over one case has one execution") | ||
| }) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
execution() паникует на "unreachable" состоянии вместо типизированного возврата.
executions.first().unwrap_or_else(|| unreachable!(...)) — хотя инвариант действительно держится (recheck всегда над 1 candidate / 1 case → execution_count == 1), само правило репозитория требует, чтобы unreachable-состояния возвращались типизированно, а не паниковали. Это приватный helper, но заводить панику на «invariant drift» новым кодом — прямое нарушение декларированной политики.
As per coding guidelines, "Новый или изменяемый public path не должен вызывать panic и не должен получать plausible fallback; invalid, unreachable, unsupported и incomplete context должны возвращаться типизированно."
🛡️ Пример типизированного варианта
-impl VerifiedPairV1 {
- fn execution(&self) -> &JointExecutionRecordV1 {
- let executions = match &self.evidence {
- PairSelectionEvidenceV1::Unconstrained(evidence) => evidence.fresh_executions(),
- PairSelectionEvidenceV1::Wcag22(evidence) => evidence.fresh_executions(),
- };
- executions.first().unwrap_or_else(|| {
- unreachable!("one selected Pair tuple over one case has one execution")
- })
- }
+impl VerifiedPairV1 {
+ fn execution(&self) -> Result<&JointExecutionRecordV1, PairInvariantDriftV1> {
+ let executions = match &self.evidence {
+ PairSelectionEvidenceV1::Unconstrained(evidence) => evidence.fresh_executions(),
+ PairSelectionEvidenceV1::Wcag22(evidence) => evidence.fresh_executions(),
+ };
+ executions.first().ok_or(PairInvariantDriftV1)
+ }Далее вызывающие методы (ordinal/fill_paint/label_paint/...) пробрасывают эту ошибку типизированно, либо execution() можно оставить &self без Result, если весь модуль согласится нести инвариант через конструктор (например, хранить JointExecutionRecordV1 напрямую в VerifiedPairV1 при создании, а не искать .first() каждый раз).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/labcolors-core/src/pair.rs` around lines 88 - 97, Update
VerifiedPairV1::execution so the missing-execution case is handled through the
module’s typed error path instead of unreachable! or another panic. Propagate
that result through callers such as ordinal, fill_paint, and label_paint, or
enforce the invariant structurally by storing the selected
JointExecutionRecordV1 during construction while preserving the existing valid
execution behavior.
Source: Coding guidelines
| fn lower_pair_label_frontend( | ||
| bg: &BgInput, | ||
| tint: crate::ladder::LadderTint, | ||
| tint: LadderTint, | ||
| fraction: f64, | ||
| floor: Floor, | ||
| surface_alpha_light: f64, | ||
| surface_alpha_dark: f64, | ||
| vc: &ViewingConditions, | ||
| ) -> PendingResolution { | ||
| let alpha = if vc.is_dark_theme() { | ||
| surface_alpha_dark | ||
| } else { | ||
| surface_alpha_light | ||
| }; | ||
| let tint_q = quantise_encoded(tint.for_vc(vc)); | ||
| let surface_hex = | ||
| match crate::alpha::composite_hex_from_encoded(tint_q, alpha, bg.encoded_display()) { | ||
| Ok(hex) => hex, | ||
| Err(error) => { | ||
| return Err(SolveFailure::InvalidInput(format!( | ||
| "тинт-поверхность бейджа вне encoded-sRGB8 reference-домена: {error}" | ||
| ))); | ||
| } | ||
| }; | ||
| let Ok(surface_bg) = BgInput::solid(&surface_hex) else { | ||
| return Err(SolveFailure::InternalInvariant( | ||
| "тинт-поверхность бейджа вне кодированного домена sRGB".into(), | ||
| if surface_alpha_light.to_bits() != 1.0_f64.to_bits() | ||
| || surface_alpha_dark.to_bits() != 1.0_f64.to_bits() | ||
| { | ||
| return Err(SolveFailure::InvalidInput( | ||
| "PairLabel surface representation must be opaque after P1".into(), | ||
| )); | ||
| }; | ||
| } | ||
|
|
||
| let source = tint.srgb8_for_vc(vc); | ||
| let backdrop = pair_root_surface(bg)?; | ||
| let fill = lower_pair_fill_occurrence(bg, tint, vc)?; | ||
| let surface = fill.visible(); | ||
| let surface_bg = BgInput::solid(&surface.to_hex()).map_err(|error| { | ||
| SolveFailure::InternalInvariant(format!("generated PairFill Surface was rejected: {error}")) | ||
| })?; | ||
| let surface_ctx = ResolveContext::new(&surface_bg, vc); | ||
| let anchor = TextAnchor::new(fraction, floor)?; | ||
| resolve_hued_anchor(&surface_bg, anchor, tint, vc, &surface_ctx) | ||
|
|
||
| let mut resolved_candidates = Vec::new(); | ||
| let mut physical_candidates = Vec::new(); | ||
| let mut order = Vec::new(); | ||
|
|
||
| match pair_candidate(&surface_bg, fraction, Floor::None, source, vc, &surface_ctx) { | ||
| Ok((resolved, bytes)) => { | ||
| let ordinal = crate::joint::CandidateOrdinalV1::new(1); | ||
| resolved_candidates.push((ordinal, resolved)); | ||
| physical_candidates.push(crate::pair::PairLabelCandidateV1::new(ordinal, bytes)); | ||
| order.push(ordinal); | ||
| } | ||
| Err(error) if matches!(floor, Floor::None) => return Err(error), | ||
| Err(error) if error.boundary().is_none() => return Err(error), | ||
| Err(_) => {} | ||
| } | ||
|
|
||
| if !matches!(floor, Floor::None) { | ||
| let (resolved, bytes) = | ||
| pair_candidate(&surface_bg, fraction, floor, source, vc, &surface_ctx)?; | ||
| if physical_candidates | ||
| .iter() | ||
| .all(|candidate| candidate.source() != bytes) | ||
| { | ||
| let ordinal = crate::joint::CandidateOrdinalV1::new(2); | ||
| resolved_candidates.push((ordinal, resolved)); | ||
| physical_candidates.push(crate::pair::PairLabelCandidateV1::new(ordinal, bytes)); | ||
| order.push(ordinal); | ||
| } | ||
| } | ||
|
|
||
| if physical_candidates.is_empty() { | ||
| return Err(SolveFailure::InternalInvariant( | ||
| "Pair frontend produced an empty candidate domain".into(), | ||
| )); | ||
| } | ||
|
|
||
| let verified = crate::pair::select_label_candidates( | ||
| source, | ||
| crate::composition::AdmittedOpacityV1::OPAQUE, | ||
| physical_candidates, | ||
| order, | ||
| backdrop, | ||
| pair_requirement(floor), | ||
| ) | ||
| .map_err(|error| { | ||
| SolveFailure::InternalInvariant(format!( | ||
| "Pair joint selection failed after typed proposal admission: {error:?}" | ||
| )) | ||
| })?; | ||
|
|
||
| if verified.fill_occurrence() != fill.occurrence() | ||
| || verified.fill_paint() != fill.paint() | ||
| || verified.label_occurrence().visible() != verified.label_paint().source().bytes() | ||
| { | ||
| return Err(SolveFailure::InternalInvariant( | ||
| "Pair joint evidence drifted from the selected physical chain".into(), | ||
| )); | ||
| } | ||
|
|
||
| resolved_candidates | ||
| .into_iter() | ||
| .find(|(ordinal, _)| *ordinal == verified.ordinal()) | ||
| .map(|(_, resolved)| resolved) | ||
| .ok_or_else(|| { | ||
| SolveFailure::InternalInvariant( | ||
| "Pair selection returned an ordinal outside the proposal domain".into(), | ||
| ) | ||
| }) | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Сравнить формулу контраста в WCAG22-эвалюаторе joint-модуля с legacy wcag.rs
fd -a 'wcag22.rs' crates/labcolors-core/src
fd -a 'joint.rs' crates/labcolors-core/src
rg -n -A15 'struct Wcag22Srgb8V1' crates/labcolors-core/src/wcag22.rs crates/labcolors-core/src/joint.rs 2>/dev/null
rg -n -A10 'impl.*Wcag22Srgb8V1' crates/labcolors-core/src/wcag22.rs crates/labcolors-core/src/joint.rs 2>/dev/null
rg -n -B2 -A10 'fn contrast_ratio' crates/labcolors-core/src/wcag.rsRepository: Labpics-Team/lab-colors
Length of output: 1458
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map relevant symbols and inspect the exact error path.
ast-grep outline crates/labcolors-core/src/semantic.rs --view expanded >/tmp/sg_semantic.txt || true
ast-grep outline crates/labcolors-core/src/joint.rs --view expanded >/tmp/sg_joint.txt || true
ast-grep outline crates/labcolors-core/src/constraints/wcag22.rs --view expanded >/tmp/sg_wcag22.txt || true
ast-grep outline crates/labcolors-core/src/wcag22.rs --view expanded >/tmp/sg_wcag22_top.txt || true
printf '\n== semantic excerpt ==\n'
sed -n '2700,2775p' crates/labcolors-core/src/semantic.rs
printf '\n== joint.rs relevant symbols ==\n'
rg -n -A6 -B4 'select_label_candidates|PairLabelCandidateV1|CandidateOrdinalV1|boundary\(' crates/labcolors-core/src/joint.rs
printf '\n== constraints/wcag22.rs relevant symbols ==\n'
rg -n -A8 -B4 'Wcag22Srgb8V1|Wcag22CriterionV1|contrast_ratio|infeasible|criterion' crates/labcolors-core/src/constraints/wcag22.rs
printf '\n== wcag22.rs top-level ==\n'
rg -n -A8 -B4 'Wcag22Srgb8V1|Wcag22CriterionV1|contrast_ratio|infeasible|criterion' crates/labcolors-core/src/wcag22.rsRepository: Labpics-Team/lab-colors
Length of output: 21451
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,260p' crates/labcolors-core/src/joint.rsRepository: Labpics-Team/lab-colors
Length of output: 8755
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect pair-specific requirements and the selection error surface.
rg -n -A8 -B8 'fn pair_requirement|enum Floor|fn pair_candidate|select_label_candidates\(' crates/labcolors-core/src/semantic.rs crates/labcolors-core/src/pair.rs crates/labcolors-core/src/joint.rsRepository: Labpics-Team/lab-colors
Length of output: 5246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,260p' crates/labcolors-core/src/pair.rsRepository: Labpics-Team/lab-colors
Length of output: 9209
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the candidate construction and the exact Wcag22 infeasible/error paths.
sed -n '2664,2795p' crates/labcolors-core/src/semantic.rs
printf '\n== pair errors in pair.rs ==\n'
rg -n -A6 -B4 'ExactInfeasible|WcagInfeasible|ExactRecheck|WcagRecheck|Infeasible\(report\)' crates/labcolors-core/src/pair.rsRepository: Labpics-Team/lab-colors
Length of output: 7460
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find whether SolveFailure has a typed pair infeasible variant or similar paths.
rg -n -A4 -B4 'enum SolveFailure|WcagInfeasible|ExactInfeasible|PairLoweringErrorV1|InternalInvariant' crates/labcolors-core/srcRepository: Labpics-Team/lab-colors
Length of output: 43970
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the surrounding public API and whether pair-label failures are mapped
# to a typed SolveFailure elsewhere.
rg -n -A5 -B5 'lower_pair_label_frontend|PairLoweringErrorV1|FloorUnreachable|WcagInfeasible|select_label_candidates\(' crates/labcolors-core/srcRepository: Labpics-Team/lab-colors
Length of output: 28189
Не сворачивайте Wcag22-недостижимость в InternalInvariant crates/labcolors-core/src/semantic.rs:2757-2761 — если select_label_candidates возвращает WcagInfeasible для обычного no-solution case, это должно выходить как типизированная unreachable-ошибка, а не как внутренний баг.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/labcolors-core/src/semantic.rs` around lines 2687 - 2781, Preserve the
typed unreachable result from select_label_candidates in
lower_pair_label_frontend: map WcagInfeasible to the appropriate Wcag22
unreachable SolveFailure, while continuing to wrap unexpected selection failures
as InternalInvariant. Keep the existing selection context and validation
behavior unchanged.
| | `PairFill` | frozen frontend: exact authored source как opaque Paint/Occurrence | | ||
| | `PairLabel` | finite label candidate domain против фактически emitted PairFill Surface | |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Переведите контрактные формулировки на русский.
Новые строки содержат frozen frontend, exact authored source, opaque и finite label candidate domain, что нарушает требования к русскоязычной документации и терминологии без англицизмов.
Предлагаемая формулировка
-| `PairFill` | frozen frontend: exact authored source как opaque Paint/Occurrence |
-| `PairLabel` | finite label candidate domain против фактически emitted PairFill Surface |
+| `PairFill` | замороженный фронтенд: точный авторский источник как непрозрачные Paint/Occurrence |
+| `PairLabel` | конечная область кандидатов метки относительно фактически выданной поверхности PairFill |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `PairFill` | frozen frontend: exact authored source как opaque Paint/Occurrence | | |
| | `PairLabel` | finite label candidate domain против фактически emitted PairFill Surface | | |
| | `PairFill` | замороженный фронтенд: точный авторский источник как непрозрачные Paint/Occurrence | | |
| | `PairLabel` | конечная область кандидатов метки относительно фактически выданной поверхности PairFill | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/whitepaper.md` around lines 82 - 83, Переведите англоязычные контрактные
формулировки в строках таблицы `PairFill` и `PairLabel` на русский, включая
термины `frozen frontend`, `exact authored source`, `opaque` и `finite label
candidate domain`, сохранив исходный смысл и формат таблицы.
Sources: Coding guidelines, Path instructions
| `PairLabel` использует фактически emitted `PairFill` occurrence как derived | ||
| Surface. Frontend формирует конечный label candidate domain; общий joint engine | ||
| исполняет `fill → surfaceFrom → label`, строит полный hard-report, выбирает по | ||
| явному total order и повторяет fresh recheck. Имена клиентских токенов и | ||
| `FillPrimary` в physical lowering не участвуют. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Уберите англоязычные термины из описания pipeline.
hard-report, total order, fresh recheck и physical lowering оставляют ключевую часть контракта на английском. Используйте русские эквиваленты; например, «явно заданный общий порядок» и «повторная проверка свежими данными».
🧰 Tools
🪛 LanguageTool
[uncategorized] ~113-~113: Слово пишется через дефис: «по-явному».
Context: ...l`, строит полный hard-report, выбирает по явному total order и повторяет fresh recheck. ...
(Pravopisanie_po-prezhnemu)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/whitepaper.md` around lines 111 - 115, В описании pipeline замените
англоязычные термины hard-report, total order, fresh recheck и physical lowering
на русские эквиваленты, сохранив смысл контракта и остальной порядок этапов без
изменений.
Sources: Coding guidelines, Path instructions
…(30 leaves) P1 убирает старый pair_fill притемняющий nudge: brand/danger/info accent-fill эмитируются как сырые identity-якоря. 30 листьев resolveVars (5 fill-ключей x 6 фонов, light-тема) обновлены на фактический выход движка. recheck-секция байт-идентична (0/2752 drift, замерено локально). Значения сверены собранным pkg через engine.resolveTheme; полный npm-suite зелёный (dev-deps установлены). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzZyjuo5ahzmW6V8pPJqSJ
Прежняя фраза утверждала «ни один fill не изменён» (верно для glow-регена ADR-0004, но ложно после P1). Дополнена правдой: 30 fill-leaves перешли на identity-якорь, pair_fill nudge удалён, recheck 0/2752 drift. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzZyjuo5ahzmW6V8pPJqSJ
Canonical execution trackerThe post-P1 hardening program, file-ownership rules and recovery procedure are now centralized in #399. P1 remains intentionally isolated: do not fold #386/#393/#382/#378, #395/#392/#394/#397 or other optimization slices into this PR. After merge, record the merge SHA and newly released file ownership in #399. |
Что это
Чистый P1 поверх C8c: лоуверит Pair в общий генерик joint graph.
Ключевое исправление относительно #365/#366
jointостаётся генерик-solver'ом (Pointwise*<E>, инстансExactSrgb8IdentityV1) и НЕ импортирует WCAG-specific payload — по V2a exit-критерию «production joint не импортирует WCAG payload». Прежняя попытка зашивалаJointHardConstraintV1::Wcag22прямо в ядро solver'а — это дрейф семантики в core; здесь он убран. Readability-floor label остаётся в замороженномsemantic/legacy слое до F1/R1, а не в generic-ядре.Дизайн взят из #370 (
agent/p1-correct-rebuild@08b2e828, старый агент); здесь доведён до зелёного на моей ветке.Инварианты
PairSide/pair_fill/resolve_pair_labelи pair-физика удалены;lower → surfaceFrom → upper;.githubи Swiftnative-conformancegate целы;Согласовано с DAG
V2a + C8b → P1; предпосылки G1a/V1a/V2a/C8b вmain. WCAG-в-joint убран строго по V2a exit-критерию.Статус
Локально зелёное:
fmt --all --check,clippy --workspace --all-targets -D warnings, 19 core test-бинарников, workspace build (core/wasm/ffi/conformance). WASM size-budget переизмеряется на CI и будет записан отдельным коммитом.🤖 Generated with Claude Code
https://claude.ai/code/session_01LzZyjuo5ahzmW6V8pPJqSJ
Summary by CodeRabbit
Новые возможности
Исправления