Skip to content

core: define the public Program API - #461

Closed
lemone112 wants to merge 3 commits into
agent/session-schema-ssotfrom
agent/public-program-api
Closed

core: define the public Program API#461
lemone112 wants to merge 3 commits into
agent/session-schema-ssotfrom
agent/public-program-api

Conversation

@lemone112

@lemone112 lemone112 commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Stack

Stacked draft over #460 (agent/session-schema-ssot).
NOT independently mergeable or publishable.

This head intentionally exposes labcolors_core::program for isolated review while the recipe façade still exists below it. #419 permits this only on unmerged stacked drafts; no merged or published head may contain both authoring roots.

No compatibility alias is introduced. Consumer README/package docs remain on the currently published contract and are replaced atomically by the terminal descendant.

Only the terminal descendant may land after packed Program→WASM, the atomic controller, complete legacy deletion and the zero-legacy gates.

What

  • hard-cuts hidden package_bridge to the documented module-qualified program API;
  • keeps opaque client IDs and one canonical compiled graph;
  • exposes the full compile → instantiate → update → Set | Hold | Remove path;
  • preserves full typed certificates, content identity and exact owner authority;
  • makes update failures lossless: subject IDs, contexts, evaluator source and invariant witnesses remain typed;
  • keeps UpdateErrorKindV1 and invariant contract identity as derived projections;
  • introduces no root re-exports, transport prefixes, aliases or compatibility layer.

Correctness

RED tests first demonstrated loss of internal invariant payload. The final algebra now preserves every observation, evaluator, physical/modeled, occurrence-formation, output-invariance and final-recheck fact. Two facts previously lost inside Core (occurrence and context) are captured at their exact failure site.

The proof-bound observation source changed only by a consuming field projection. The point-support artifact was canonically rebound; its claim, algebra, domains and exclusions are unchanged.

Gates

  • Rust 1.96 workspace tests and doctests;
  • workspace clippy with -D warnings;
  • rustdoc with -D warnings;
  • Rust 1.85 MSRV all-targets check;
  • release wasm32-unknown-unknown check;
  • offline Core package inventory;
  • WCAG source binding;
  • point-support source-binding mutation suite;
  • independent point-support verifier and byte-exact replay;
  • architecture/API, documentation, numerical/proof and performance-path reviews: PASS.

Part of #419.

Summary by CodeRabbit

  • Новые возможности
    • Добавлен/расширен публичный API модуля program: создание draft, компиляция в owner, инстанцирование сессии и получение проекции с операциями Set/Hold/Remove.
    • Сформированы типизированные представления наблюдений, evidence/certificates и color-point связей (физические/моделируемые).
  • Документация
    • Существенно обновлён Rustdoc с подробным описанием границы program и примерами.
  • Исправления
    • Уточнён формат ошибок оценивания с дополнительным контекстом (occurrence/context).
    • Обновлены контрольные суммы в верификации proof-содержимого.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b9e61a09-2830-43de-8f28-7b44a2d91998

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Добавлен публичный program API для построения, компиляции и исполнения цветовых программ с типизированными evidence, operations и ошибками. Boundary-тесты переведены на новый API, обновлены внутренние мапперы и контрольные SHA-256 значения.

Changes

Публичный Program API

Layer / File(s) Summary
Контракты и жизненный цикл Program
crates/labcolors-core/src/program.rs
Добавлены DraftV1, OwnerV1, SessionV1, evidence, certificates, operations, lifecycle-состояния и типизированные ошибки.
Маппинг ошибок и диагностические факты
crates/labcolors-core/src/program.rs, crates/labcolors-core/src/observation.rs, crates/labcolors-core/src/program_session.rs, crates/labcolors-core/src/constraints/mod.rs
Внутренние ошибки преобразуются в публичные payload-ориентированные типы; добавлены occurrence/context и разбор schema mismatch.
Видимость публичного модуля и boundary-контракта
crates/labcolors-core/src/lib.rs, crates/labcolors-core/src/generic_boundary_tests.rs, crates/labcolors-core/tests/program_public_api.rs
program раскрывается как публичный модуль без package-транспортных алиасов; Rustdoc и API-тесты фиксируют доступные точки входа.
Проверка evidence, lifecycle и operations
crates/labcolors-core/src/program_mixed_evaluator_tests.rs
Тесты сравнивают public projection с core и проверяют evidence, ownership, lifecycle, provenance и канонический порядок операций.
Интеграционные проверки authoring и compile errors
crates/labcolors-core/tests/program_boundary.rs
Boundary-тесты проверяют typed handles, input-port invariants, joint diagnostics, cycles, контексты и update errors.
Синхронизация proof-проверок
crates/labcolors-core/contracts/*.json, scripts/verify_point_support_surplus.py
Обновлены контрольные SHA-256 значения proof-контракта и source capsule.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant DraftV1
  participant OwnerV1
  participant SessionV1
  Client->>DraftV1: construct graph and constraints
  DraftV1->>OwnerV1: compile()
  Client->>OwnerV1: instantiate(stream_id)
  OwnerV1->>SessionV1: create session
  Client->>OwnerV1: update(UpdateV1)
  OwnerV1->>SessionV1: admit observation and evaluate
  SessionV1-->>OwnerV1: evidence state
  OwnerV1-->>Client: ProjectionV1 and OperationV1
Loading

Possibly related PRs

  • Labpics-Team/lab-colors#447 — связан с proof/source-binding SHA-256 для того же retained-surplus контракта.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Заголовок точно отражает основное изменение: введение публичного Program API в core.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/public-program-api

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 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/generic_boundary_tests.rs`:
- Around line 181-190: Update the assertions in the generic boundary test around
LIB_SOURCE to avoid requiring exactly two occurrences of “PackageProgram” and
“package_bridge”. Verify that every occurrence is confined to compile_fail
blocks, or at minimum assert the count is at least two, so adding valid negative
sentinels does not break the test.
- Around line 164-169: Update the vocabulary assertion in the generic boundary
tests to remove the broad PROGRAM_SOURCE.contains("package ") check and replace
it with an identifier-aware check, while retaining the existing precise
PackageProgram and package_bridge validations.

In `@crates/labcolors-core/src/program_mixed_evaluator_tests.rs`:
- Around line 411-414: Импортируйте ConstraintModeV1 вместе с остальными
публичными типами в существующем use crate::program блоке и замените полные
обращения crate::program::ConstraintModeV1 во всех трёх отмеченных местах на
импортированный тип.
- Around line 316-400: Reduce duplication in
assert_public_assessment_matches_core by extracting exact-family and WCAG-family
helpers, such as assert_exact_matches and assert_wcag_matches, each accepting
the expected VerdictV1. Keep the outer match exhaustive over public/core
assessment families and pass the appropriate verdict from the Pass and Violation
branches, preserving all existing field, binding, and measurement assertions.

In `@crates/labcolors-core/src/program.rs`:
- Around line 4057-4064: Переместите тест
operation_scope_is_a_zero_sized_borrow_marker из compile_error_projection_tests
в отдельный тестовый модуль, посвящённый operations или BorrowScopeV1, сохранив
его проверки без изменений.
- Around line 2745-2769: Добавьте комментарий-инвариант непосредственно перед
полем xyz_bits в TristimulusSampleV1: поясните, что XYZ хранится как u64-биты
намеренно вместо f64 для побитового сравнения и стабильных PartialEq/Hash при
диагностике, включая значения NaN.
- Around line 901-915: Объедини соседние шаблоны Self::MissingTargetSource,
Self::DuplicateTargetCandidate и Self::DuplicateTargetCandidateSignal с
предыдущей веткой match в primary_handle, поскольку все возвращают
Some(Handle::Target(*target)). Сохрани неизменными остальные варианты и
семантику сопоставления.
- Around line 315-343: Update from_core so the
NumericDomainError::HueOutOfRange/InternalInvariant branch preserves the already
computed field witness instead of setting field to None; keep reason unset while
returning the known AppearanceContextFieldV1 value for diagnostics.
- Around line 2443-2480: Сделайте CertificatesV1 самосогласованным, устранив
независимое хранение len и values: храните только последовательность
присутствующих сертификатов и вычисляйте оставшуюся длину по её фактическому
содержимому либо гарантируйте, что next всегда возвращает элемент до исчерпания.
Обновите new, next и size_hint так, чтобы пара (None, Some(_)) не могла нарушить
контракт ExactSizeIterator в release-сборке.

In `@crates/labcolors-core/tests/program_boundary.rs`:
- Around line 181-184: В сигнатуре owner_mismatch_is_a_closed_public_error
используйте уже импортированный UpdateErrorV1 вместо полного пути
labcolors_core::program::UpdateErrorV1, сохранив остальную проверку без
изменений.
🪄 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: dfed30f5-d3dc-4c64-b8f0-d19901572777

📥 Commits

Reviewing files that changed from the base of the PR and between f574140 and 08f103f.

📒 Files selected for processing (12)
  • crates/labcolors-core/contracts/point-support-reference-surplus-q55-bps-proof-v1.json
  • crates/labcolors-core/src/constraints/mod.rs
  • crates/labcolors-core/src/generic_boundary_tests.rs
  • crates/labcolors-core/src/lib.rs
  • crates/labcolors-core/src/observation.rs
  • crates/labcolors-core/src/package_bridge.rs
  • crates/labcolors-core/src/program.rs
  • crates/labcolors-core/src/program_mixed_evaluator_tests.rs
  • crates/labcolors-core/src/program_session.rs
  • crates/labcolors-core/tests/program_boundary.rs
  • crates/labcolors-core/tests/program_public_api.rs
  • scripts/verify_point_support_surplus.py
💤 Files with no reviewable changes (1)
  • crates/labcolors-core/src/package_bridge.rs

Comment thread crates/labcolors-core/src/generic_boundary_tests.rs
Comment thread crates/labcolors-core/src/generic_boundary_tests.rs Outdated
Comment thread crates/labcolors-core/src/program_mixed_evaluator_tests.rs
Comment thread crates/labcolors-core/src/program_mixed_evaluator_tests.rs
Comment thread crates/labcolors-core/src/program.rs
Comment thread crates/labcolors-core/src/program.rs
Comment thread crates/labcolors-core/src/program.rs
Comment thread crates/labcolors-core/src/program.rs
Comment thread crates/labcolors-core/src/program.rs
Comment thread crates/labcolors-core/tests/program_boundary.rs

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Пожалуйста, проверьте только follow-up de5359954c3c9de99844ae5eb2cc0c29ed67d6e4 после исправления и разрешения всех 10 предыдущих замечаний. Это второй и последний цикл ревью данного промежуточного stacked PR.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

@lemone112 Проверю только follow-up-коммит de5359954c3c9de99844ae5eb2cc0c29ed67d6e4 — с учётом того, что 10 предыдущих замечаний уже исправлены и разрешены.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

lemone112 added a commit that referenced this pull request Jul 25, 2026
…fact

The exact-length gate still pinned 376830B from
`canonical-authored-program-lowerer` (#456, run 29971399220). This slice
grew the runtime artifact to 376985B and did not carry the re-pin that
every earlier stacked slice performed (#450, #452, #454, #456), so the
gate has rejected this head and every head above it.

The +155B is attributable to this slice alone: runs 30115821523 (#457),
30124467410 (#458), 30125634830 (#459), 30129537515 (#460) and
30136346868 (#461) all measure exactly 376985B, so #458-#461 contribute
zero bytes to the artifact and were failing only on the inherited pin.

The new measurement is the CI run for this exact head
(39ee0a7), not a local build: the
canonical platform is linux-x64 and a local arm64 build only produces a
DIAGNOSTIC result. The budget file's own SHA-256 is re-pinned in the
checker so the drift gate keeps rejecting unattributed edits.

Co-Authored-By: Claude <noreply@anthropic.com>
@lemone112
lemone112 force-pushed the agent/session-schema-ssot branch from f574140 to cdba3fb Compare July 25, 2026 17:01
@lemone112
lemone112 force-pushed the agent/public-program-api branch from de53599 to eea30db Compare July 25, 2026 17:01
@lemone112
lemone112 force-pushed the agent/session-schema-ssot branch from cdba3fb to 35472cb Compare July 26, 2026 04:18
@lemone112
lemone112 force-pushed the agent/public-program-api branch from eea30db to b66387e Compare July 26, 2026 04:18
@lemone112
lemone112 force-pushed the agent/public-program-api branch from b66387e to 92f8376 Compare July 26, 2026 07:01
lemone112 added a commit that referenced this pull request Jul 26, 2026
* feat(core): compile generic point-render sessions

* fix(core): satisfy format and all-target lint gates

* perf(core): recycle point-render session buffers

* style(core): format reusable session buffers

* feat(lcs): execute sealed sRGB8 tristimulus derivation

* style(lcs): format sealed tristimulus slice

* feat(lcs): derive versioned appearance views

* style(lcs): canonicalize Oklab coefficient

* feat(core): expose typed terminal program path

* fix(core): satisfy terminal Program quality gates

* feat(lcs): bind private output projection registry

* style(core): canonicalize release module order

* fix(core): scope private registry lint firewall

* fix(core): harden terminal Program admission

* style(core): match pinned Rust formatter

* feat(core): bind F0 release descriptors

* perf(core): add linear canonical surface ingestion

* refactor(core): unify terminal physical identities

* perf(core): prebind terminal evaluation slots

* perf(core): make present ingestion lazy and borrowed

* refactor(core): remove per-port surface mutation

* feat(core): evaluate typed constraints and emit terminal paints

* feat(core): bind observation groups to runtime streams

* refactor(core): share one encoded point Paint value

* refactor(core): share revision-bound observation state

- admit correlated scenario sets once behind shared immutable backing
- make joint selection domain-safe, linear, and ownership-retryable
- refresh source-bound release proof gates

* fix(ci): bind V2a budget to measured artifact

- keep allocation tests ownership-preserving without a large Result closure
- pin the zero-headroom WASM ratchet to the reproducible V2a artifact

* refactor(core): remove superseded Program runtime

Keep only the private Program compiler/lowering payload for the direct sole-Session bridge.
Delete the duplicate owner, lifecycle, output materialization, and test evaluator scaffolding.
Pin the hard cut with a negative facade gate and refresh the exact point-support source receipt.

* feat(core): execute compiled plans through sole Session

Replace the point-support-specific lifecycle with one sealed monomorphized Session, attach reusable CompiledProgram epochs through strong ownership, and retain complete case-by-constraint reports. Bind every decision to the exact admitted observation before atomic commit and refresh release proof pins.

* feat(core): bind Program assessments to context-bound LCS

* Hard-delete Pair taxonomy from shipping surfaces

* Compile typed finite targets into Program sessions

* quarantine unsupported Display P3 promises

* core: make compiled programs the sole session-generation owner

* core: close the evaluator union and package session bridge

* core: derive a typed CAM16-UCS occurrence view

* core: lower authored physical declarations into the canonical Program

* core: bind Program content identity

* core: name versioned identity discriminants

* fix(ci): re-pin the runtime WASM budget to this slice's measured artifact

The exact-length gate still pinned 376830B from
`canonical-authored-program-lowerer` (#456, run 29971399220). This slice
grew the runtime artifact to 376985B and did not carry the re-pin that
every earlier stacked slice performed (#450, #452, #454, #456), so the
gate has rejected this head and every head above it.

The +155B is attributable to this slice alone: runs 30115821523 (#457),
30124467410 (#458), 30125634830 (#459), 30129537515 (#460) and
30136346868 (#461) all measure exactly 376985B, so #458-#461 contribute
zero bytes to the artifact and were failing only on the inherited pin.

The new measurement is the CI run for this exact head
(39ee0a7), not a local build: the
canonical platform is linux-x64 and a local arm64 build only produces a
DIAGNOSTIC result. The budget file's own SHA-256 is re-pinned in the
checker so the drift gate keeps rejecting unattributed edits.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(ci): re-bind the point-support source capsule to this slice's cone

This slice moves files inside the point-support semantic cone, so the capsule
digest and the committed surplus proof move with it. Both are now regenerated in
the same commit that causes the drift, matching the convention the rest of the
stack follows; previously the re-bind was batched at #460, which left #457-#459
fail-closed on their own heads and made the stack unmergeable in order.

Numerical review: every proof field is unchanged. Only the source-binding
identities move -- the file hashes of the cone files this slice edits, the
resulting closure digest, the verifier hash and the rolled-up payload hash.
The surplus mathematics is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>

* core: project complete program certificate evidence

* fix(ci): re-bind the point-support source capsule to this slice's cone

This slice moves files inside the point-support semantic cone, so the capsule
digest and the committed surplus proof move with it. Both are now regenerated in
the same commit that causes the drift, matching the convention the rest of the
stack follows; previously the re-bind was batched at #460, which left #457-#459
fail-closed on their own heads and made the stack unmergeable in order.

Numerical review: every proof field is unchanged. Only the source-binding
identities move -- the file hashes of the cone files this slice edits, the
resulting closure digest, the verifier hash and the rolled-up payload hash.
The surplus mathematics is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>

* core: bind Program operations to exact owner snapshots

* fix(ci): re-bind the point-support source capsule to this slice's cone

This slice moves files inside the point-support semantic cone, so the capsule
digest and the committed surplus proof move with it. Both are now regenerated in
the same commit that causes the drift, matching the convention the rest of the
stack follows; previously the re-bind was batched at #460, which left #457-#459
fail-closed on their own heads and made the stack unmergeable in order.

Numerical review: every proof field is unchanged. Only the source-binding
identities move -- the file hashes of the cone files this slice edits, the
resulting closure digest, the verifier hash and the rolled-up payload hash.
The surplus mathematics is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>

* core: single-own compiled observation schemas

* chore(proof): document Python 3.9 zip invariant

* core: define the public Program API

* core: address Program API review

* fix(ci): re-bind public Program proof capsule

* test: close compile-fail sentinel escape

* core: make joint order non-empty by construction and bound evidence cells

`AdmittedFiniteJointOrderV1` stored one flat tuple slice, so an empty
admitted order was representable and the evaluation path carried a
runtime `state_count == 0 -> InternalInvariant` guard to reject it. The
guard proved nothing about the type; it only re-checked a property the
constructor already enforced.

Split the order into `first + rest`. Non-emptiness becomes structural,
`state_count()` is total, and the `InternalInvariant` branch in
`prepare_program_evaluation_buffers` is deleted rather than left dead.
The `joint_state_count: Option<usize>` parameter disappears with it:
cell counts are now derived from the epoch itself.

The same pass stops reserving an exhaustive-conflict buffer that no
constraint can ever fill. `can_conflict` is false when every compiled
constraint is report-only, so a report-only program no longer reserves
`cases x constraints x states` cells and no longer reports
`ResourceExhausted` for a conflict it cannot produce.

`OwnerV1::evidence_cell_bounds` exposes the same arithmetic as a pure
preflight, with `EvidenceBoundsErrorV1::CardinalityOverflow` as the only
closed failure. It creates no Session and mutates no state.

Verified locally on the CI-pinned toolchain: full workspace tests green,
`cargo fmt --all --check` and `cargo clippy --workspace --all-targets --
-D warnings` clean.

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: explain packed proof invariants

* core: fail closed without current Program evidence

* core: revoke outputs on unknown session handoff

* core: keep incomplete Program crate-private

* perf: bind smaller private Program wasm

* core: make staged Program unexportable

* ci: explain rustdoc surface mismatch

---------

Co-authored-by: Claude <noreply@anthropic.com>
@lemone112

Copy link
Copy Markdown
Collaborator Author

Superseded by the reviewed cumulative squash merge #465 (24fd1f4). The lower stacked branch was intentionally not merged on its own because its intermediate head was not the safe terminal public boundary.

@lemone112 lemone112 closed this Jul 26, 2026
@lemone112
lemone112 deleted the agent/public-program-api branch July 26, 2026 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant