feat: add calibration v2 autofocus foundation

This commit is contained in:
fy59 2026-09-03 14:00:07 +02:00
parent 038cc64032
commit 34c6a82b35
22 changed files with 903 additions and 82 deletions

View file

@ -81,13 +81,19 @@ Detailed subcontracts remain defined by their canonical documents. This file
must not duplicate every S3 substage, scientific threshold, migration detail, must not duplicate every S3 substage, scientific threshold, migration detail,
or persistence format. or persistence format.
Project DB v25 is the current additive operational schema. It preserves v24 RAW batch, the v23 Project DB v25 is an additive operational schema in the retained lineage. It preserves v24 RAW batch, the v23
optical overlay and the v22 scientific/persistence foundation. Its additive purpose is typed durable optical overlay and the v22 scientific/persistence foundation. Its additive purpose is typed durable
persistence for `features.extract.batch/1` through `feature_extract_batch_tasks`; it adds no persistence for `features.extract.batch/1` through `feature_extract_batch_tasks`; it adds no
scientific identity and must not reinterpret historical rows. The v25 Feature-batch path has completed scientific identity and must not reinterpret historical rows. The v25 Feature-batch path has completed
its retained real A6000 proof. Historical references to older Project DB versions remain valid where its retained real A6000 proof. Historical references to older Project DB versions remain valid where
they describe the actual historical contract or migration path. they describe the actual historical contract or migration path.
Project DB v27 is the current additive operational schema. It preserves the v22 scientific/
persistence foundation, v23 optical overlay, v24 RAW batch, v25 Feature batch and v26 exact
Capture geometric-state/applicability foundation. Its v27 focus-domain rows are generic bounded
exact-token machinery with no historical backfill and no device-specific physical applicability
claim. Future schema changes beyond v27 require explicit human authorization.
The global maintenance implementation, fresh portable/Vulkan/sanitizer/ The global maintenance implementation, fresh portable/Vulkan/sanitizer/
concurrency validation and independent final review are acquired. Its lifecycle concurrency validation and independent final review are acquired. Its lifecycle
is `GLOBAL_MAINTENANCE_AUDIT=PASS/FROZEN`. The review independently passed the is `GLOBAL_MAINTENANCE_AUDIT=PASS/FROZEN`. The review independently passed the
@ -802,7 +808,7 @@ For Project DB:
must not reinterpret scientific history; must not reinterpret scientific history;
- v25 is the additive Feature-batch migration for `features.extract.batch/1` and - v25 is the additive Feature-batch migration for `features.extract.batch/1` and
must preserve v22/v23/v24 identities, rows and semantics; must preserve v22/v23/v24 identities, rows and semantics;
- future schema-version changes beyond the current v25 head require - future schema-version changes beyond the current v27 head require
explicit human authorization; explicit human authorization;
- migrations must be additive unless a different migration is explicitly - migrations must be additive unless a different migration is explicitly
authorized; authorized;
@ -1020,7 +1026,7 @@ Every completed ticket report must include:
STOP and request a human decision only when resolution requires: STOP and request a human decision only when resolution requires:
- changing a FROZEN scientific contract; - changing a FROZEN scientific contract;
- changing Project DB schema/version beyond the current v25 head without - changing Project DB schema/version beyond the current v27 head without
prior authorization; prior authorization;
- introducing a genuinely new subsystem outside authorized scope; - introducing a genuinely new subsystem outside authorized scope;
- files outside the authorized scope; - files outside the authorized scope;

View file

@ -30,7 +30,7 @@ progressive observations and constraints
### Current Project Database ### Current Project Database
The current Project DB schema is **v26**. The current Project DB schema is **v27**.
The current head is additive: The current head is additive:
@ -40,6 +40,7 @@ v23 Generic optical-context overlay
v24 raw.develop.batch/1 persistence v24 raw.develop.batch/1 persistence
v25 features.extract.batch/1 persistence v25 features.extract.batch/1 persistence
v26 Capture geometric state and exact calibration applicability v26 Capture geometric state and exact calibration applicability
v27 Generic bounded exact-token focus domains
``` ```
Earlier schema versions remain valid historical contracts where their own documentation says so. Earlier schema versions remain valid historical contracts where their own documentation says so.
@ -121,7 +122,7 @@ The following major foundations are implemented and validated at their documente
- **Calibration Solver Preflight v1 — PASS** - **Calibration Solver Preflight v1 — PASS**
- **Calibration Evidence Solver v1 — IMPLEMENTED / VALIDATED** - **Calibration Evidence Solver v1 — IMPLEMENTED / VALIDATED**
- **Calibration Tooling planarity alignment — PASS / FROZEN** - **Calibration Tooling planarity alignment — PASS / FROZEN**
- **Project DB v24/v25/v26 operational overlays — IMPLEMENTED / VALIDATED** - **Project DB v24/v25/v26/v27 operational overlays — IMPLEMENTED / VALIDATED**
- raw.develop.batch/1 durable selected-execution path - raw.develop.batch/1 durable selected-execution path
- features.extract.batch/1 durable selected-execution path - features.extract.batch/1 durable selected-execution path

View file

@ -4,14 +4,14 @@
```text ```text
DOCUMENTATION_INDEX=CURRENT DOCUMENTATION_INDEX=CURRENT
CURRENT_PROJECT_DB_SCHEMA=v26 CURRENT_PROJECT_DB_SCHEMA=v27
CURRENT_PRODUCTION_TASK_KINDS=16 CURRENT_PRODUCTION_TASK_KINDS=16
REAL_S21_TRACKS=PASS/FROZEN REAL_S21_TRACKS=PASS/FROZEN
REAL_A6000_PRE_SFM=PASS/FROZEN REAL_A6000_PRE_SFM=PASS/FROZEN
PRODUCT_DEFINITION_V1=PASS/FROZEN PRODUCT_DEFINITION_V1=PASS/FROZEN
PROMPT_TREE=CURRENT PROMPT_TREE=CURRENT
CURRENT_NEXT=AUTOFOCUS_V2_FOUNDATION CURRENT_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
This index separates current authority, historical evidence and future product-definition work. This index separates current authority, historical evidence and future product-definition work.
@ -35,7 +35,7 @@ quote an exact API, DDL or constant.
## Current repository state ## Current repository state
```text ```text
Project DB head v26 Project DB head v27
Production Task kinds 16 Production Task kinds 16
v22 selected scientific execution foundation v22 selected scientific execution foundation
@ -43,6 +43,7 @@ v23 generic optical-context overlay
v24 raw.develop.batch/1 persistence v24 raw.develop.batch/1 persistence
v25 features.extract.batch/1 persistence v25 features.extract.batch/1 persistence
v26 Capture geometric state/applicability v26 Capture geometric state/applicability
v27 generic bounded exact-token focus domains
``` ```
Canonical resource objective: Canonical resource objective:

View file

@ -265,6 +265,36 @@ Historical EXIF/MakerNote values such as Sony `FocusPosition2` or derived
`FocusDistance2` may inform experiment design. They are not by themselves `FocusDistance2` may inform experiment design. They are not by themselves
physical calibration evidence. physical calibration evidence.
The implemented generic Stage E foundation represents a validated discrete
domain as:
```text
existing exact calibration applicability
+ positive domain format/version
+ nonzero retained-evidence/provenance SHA-256
+ exact complete exemplar state for every non-focus geometry field
+ 1..64 explicit opaque observed focus tokens
```
The 64-token limit is an operational persistence/API bound, not a scientific
focus range. Domain membership is exact token equality. Tokens have no numeric
distance, order, magnitude, adjacency or EXIF interpretation, and the generic
machinery performs no interpolation or extrapolation. The target configuration
and every non-focus geometric-state and provenance field must exactly match the
exemplar. Unknown/incomplete focus remains `CALIBRATION_REQUIRED`.
An exact applicability and its attached domain retain one applicability and
calibration identity. Candidate enumeration deduplicates that identity if both
the exact exemplar state and a domain member match. Distinct overlapping
applicabilities remain ambiguous and produce `SELECTION_REQUIRED`.
This generic representation does not itself validate a real device domain.
In particular:
```text
A6000_E_PZ_16_50_AF_APPLICABILITY=BLOCKED_BY_PHYSICAL_VALIDATION
```
### 9.3 Discrete focus bands ### 9.3 Discrete focus bands
If one calibration is not valid across the complete autofocus range, v2 may If one calibration is not valid across the complete autofocus range, v2 may

View file

@ -7,7 +7,7 @@ span schema versions. Historical sections remain authoritative for the version t
present-tense statements in this document use the current schema head. present-tense statements in this document use the current schema head.
```text ```text
CURRENT_PROJECT_DB_SCHEMA=v26 CURRENT_PROJECT_DB_SCHEMA=v27
``` ```
The current head is additive: The current head is additive:
@ -18,10 +18,11 @@ v23 Generic optical-context overlay IMPLEMENTED / VALI
v24 raw.develop.batch/1 persistence IMPLEMENTED / VALIDATED v24 raw.develop.batch/1 persistence IMPLEMENTED / VALIDATED
v25 features.extract.batch/1 persistence IMPLEMENTED / VALIDATED v25 features.extract.batch/1 persistence IMPLEMENTED / VALIDATED
v26 Capture geometric state and exact calibration applicability PASS / FROZEN v26 Capture geometric state and exact calibration applicability PASS / FROZEN
v27 Generic exact-token focus-domain applicability PASS / FROZEN
``` ```
Project DB v26 preserves the scientific and persistence meaning of every earlier retained row. No Project DB v27 preserves the scientific and persistence meaning of every earlier retained row. No
migration from v22 through v26 backfills scientific identity, infers camera/lens identity, invents migration from v22 through v27 backfills scientific identity, infers camera/lens identity, invents
calibration, rewrites Capture identity, or changes historical Task payload interpretation. calibration, rewrites Capture identity, or changes historical Task payload interpretation.
The current real A6000 pre-SfM proof completed the v24 RAW-batch and v25 Feature-batch paths before The current real A6000 pre-SfM proof completed the v24 RAW-batch and v25 Feature-batch paths before
@ -233,6 +234,37 @@ The v1 optical-profile and calibration-selection APIs/tables remain unchanged.
The v26 tables are a separate additive foundation; they do not attach a Sparse The v26 tables are a separate additive foundation; they do not attach a Sparse
calibration scope or transition a selected execution to `READY`. calibration scope or transition a selected execution to `READY`.
### Project DB v27 - generic validated focus domains
**PASS / FROZEN.**
The v26 -> v27 migration is transactional, additive and DDL-only. It creates
empty `optical_focus_domains_v2` and `optical_focus_domain_tokens_v2` tables.
Historical focus observations are not physical validation, so migration
creates no inferred domain, token member, applicability, selection or
calibration identity.
A v27 domain attaches to one existing v26 applicability. It durably retains a
positive version, a nonzero 32-byte retained-evidence/provenance digest and a
bounded set of 1..64 distinct opaque focus tokens. Tokens are stored in
deterministic lexical order, but scientific matching is exact byte-for-byte
token membership; there is no numeric distance/range comparison, EXIF
assumption, interpolation or extrapolation. The operational 64-token capacity
is not a scientific dataset or focus-range limit.
Resolution preserves the v26 zero/one/many contract while enumerating the
distinct union of exact v26 matches and eligible domain matches. A domain match
requires the exact configuration, exact complete exemplar state for every
non-focus geometry/provenance field, observed target focus and exact token
membership. Exact and domain paths for the same applicability are deduplicated;
different overlapping applicabilities produce `SELECTION_REQUIRED`. The
existing v2 selection API remains immutable/idempotent and accepts a domain
applicability only while it is exactly eligible.
This schema is generic machinery, not device-specific autofocus evidence.
`A6000_E_PZ_16_50_AF_APPLICABILITY=BLOCKED_BY_PHYSICAL_VALIDATION` remains in
force.
## Optical TUI workflow ## Optical TUI workflow
The optical TUI uses bounded public APIs and does not write SQLite directly. It can: The optical TUI uses bounded public APIs and does not write SQLite directly. It can:
@ -893,6 +925,7 @@ v22 -> v23 generic optical-context overlay
v23 -> v24 selected RAW-batch Task persistence v23 -> v24 selected RAW-batch Task persistence
v24 -> v25 selected Feature-batch Task persistence v24 -> v25 selected Feature-batch Task persistence
v25 -> v26 Capture geometric state + exact calibration applicability v25 -> v26 Capture geometric state + exact calibration applicability
v26 -> v27 generic bounded exact-token focus domains
``` ```
Historical version-specific contracts remain valid for the rows and checkpoints they describe. Historical version-specific contracts remain valid for the rows and checkpoints they describe.
@ -900,9 +933,9 @@ An older version number is not stale when the text explicitly describes historic
## Opening and migration ## Opening and migration
An empty Project DB is created and migrated through the complete known chain to v26. An empty Project DB is created and migrated through the complete known chain to v27.
A supported historical DB is migrated sequentially to v26. Each migration is transactional. A A supported historical DB is migrated sequentially to v27. Each migration is transactional. A
migration failure rolls back both newly created objects and the schema-version marker for that step, migration failure rolls back both newly created objects and the schema-version marker for that step,
leaving the prior version complete and retryable. leaving the prior version complete and retryable.
@ -913,7 +946,7 @@ The implementation rejects:
- impossible version/storage-class combinations; - impossible version/storage-class combinations;
- malformed required durable relationships. - malformed required durable relationships.
The migration implementation must recognize only the known sequential range through v26. It must not The migration implementation must recognize only the known sequential range through v27. It must not
skip an intermediate contract. skip an intermediate contract.
Important rollback properties retained from historical tests include: Important rollback properties retained from historical tests include:
@ -927,6 +960,7 @@ Important rollback properties retained from historical tests include:
- v24 failure leaves no partial RAW-batch table/marker and a true v23; - v24 failure leaves no partial RAW-batch table/marker and a true v23;
- v25 failure leaves no partial Feature-batch table/marker and a true v24. - v25 failure leaves no partial Feature-batch table/marker and a true v24.
- v26 failure leaves no partial geometric-state/applicability tables or marker and a true v25. - v26 failure leaves no partial geometric-state/applicability tables or marker and a true v25.
- v27 failure leaves no partial focus-domain tables or marker and a true v26.
Exact executable migration SQL is owned by `src/project_db.c`. Documentation may summarize it, but Exact executable migration SQL is owned by `src/project_db.c`. Documentation may summarize it, but
must not contradict the source or the FROZEN migration tests. must not contradict the source or the FROZEN migration tests.
@ -1089,20 +1123,21 @@ must not be silently reinterpreted as a scientific dataset limit.
## Status summary ## Status summary
```text ```text
CURRENT_PROJECT_DB_SCHEMA=v26 CURRENT_PROJECT_DB_SCHEMA=v27
v22 selected scientific execution foundation PASS/FROZEN v22 selected scientific execution foundation PASS/FROZEN
v23 generic optical-context overlay IMPLEMENTED/VALIDATED/REVIEWED v23 generic optical-context overlay IMPLEMENTED/VALIDATED/REVIEWED
v24 raw.develop.batch/1 persistence IMPLEMENTED/VALIDATED v24 raw.develop.batch/1 persistence IMPLEMENTED/VALIDATED
v25 features.extract.batch/1 persistence IMPLEMENTED/VALIDATED v25 features.extract.batch/1 persistence IMPLEMENTED/VALIDATED
v26 Capture geometric state/applicability PASS/FROZEN v26 Capture geometric state/applicability PASS/FROZEN
v27 generic exact-token focus domains PASS/FROZEN
REAL_S21_TRACKS PASS/FROZEN REAL_S21_TRACKS PASS/FROZEN
REAL_A6000_PRE_SFM PASS/FROZEN REAL_A6000_PRE_SFM PASS/FROZEN
``` ```
Current Project DB opens and migrates supported historical databases through the sequential known Current Project DB opens and migrates supported historical databases through the sequential known
chain to v26. chain to v27.
Historical contracts for Candidate Pair, Matcher, Geometric Verification, Tracks, Sparse SfM, Historical contracts for Candidate Pair, Matcher, Geometric Verification, Tracks, Sparse SfM,
Phase H, Capture/Asset Provenance, campaign execution, Photo Quality and selected scientific Phase H, Capture/Asset Provenance, campaign execution, Photo Quality and selected scientific
@ -1119,4 +1154,4 @@ No current Project DB migration:
- creates a generic dependency DAG; - creates a generic dependency DAG;
- persists active Resource Governor reservations. - persists active Resource Governor reservations.
Future schema changes beyond v26 require explicit human authorization. Future schema changes beyond v27 require explicit human authorization.

View file

@ -111,7 +111,7 @@ This document may freeze a product requirement while its implementation remains
The following existing boundaries are consumed as-is: The following existing boundaries are consumed as-is:
```text ```text
Project DB head v26 Project DB head v27
Production Task kinds 16 Production Task kinds 16
Capture / Asset Provenance PASS/FROZEN Capture / Asset Provenance PASS/FROZEN
Acquisition / campaign execution PASS/FROZEN Acquisition / campaign execution PASS/FROZEN

View file

@ -11,7 +11,7 @@ It must not be used to reinterpret FROZEN scientific evidence.
## Current repository state ## Current repository state
```text ```text
Project DB current schema v26 Project DB current schema v27
Production Task kinds 16 Production Task kinds 16
GLOBAL_MAINTENANCE_AUDIT PASS/FROZEN GLOBAL_MAINTENANCE_AUDIT PASS/FROZEN
REAL_S21_TRACKS PASS/FROZEN REAL_S21_TRACKS PASS/FROZEN
@ -24,7 +24,7 @@ SOURCE_COMMENT_AUDIT PASS
PRODUCT_DEFINITION PASS/FROZEN PRODUCT_DEFINITION PASS/FROZEN
PROMPT_TREE CURRENT PROMPT_TREE CURRENT
USER_FACING_UI_LANGUAGE_NORMALIZATION PASS USER_FACING_UI_LANGUAGE_NORMALIZATION PASS
CURRENT_NEXT AUTOFOCUS_V2_FOUNDATION CURRENT_NEXT PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
The current Project DB head is additive: The current Project DB head is additive:
@ -35,6 +35,7 @@ v23 generic optical-context overlay
v24 raw.develop.batch/1 persistence v24 raw.develop.batch/1 persistence
v25 features.extract.batch/1 persistence v25 features.extract.batch/1 persistence
v26 Capture geometric state + exact calibration applicability v26 Capture geometric state + exact calibration applicability
v27 generic bounded exact-token focus domains
``` ```
Historical references to earlier versions remain valid when they describe the state of their own Historical references to earlier versions remain valid when they describe the state of their own
@ -539,8 +540,10 @@ additive L3DCALB2/Tooling/Bootstrap v2 now retains independent group-local prove
complete exact selected-image coverage, and attaches one existing per-image scope only after complete complete exact selected-image coverage, and attaches one existing per-image scope only after complete
publication. `CALIBRATION_WORKFLOW_V2=PASS/FROZEN`: the workflow now proves exact Capture/state publication. `CALIBRATION_WORKFLOW_V2=PASS/FROZEN`: the workflow now proves exact Capture/state
applicability and matching per-image calibration IDs before its sole final scope attachment. The next applicability and matching per-image calibration IDs before its sole final scope attachment. The next
dependency is the generic adaptive-settings/autofocus foundation. Device-specific autofocus envelopes dependency is physical autofocus/optical applicability validation and a dedicated calibrated real
remain blocked until physical evidence validates them. campaign. The generic adaptive-settings audit and bounded exact-token autofocus foundation are
PASS/FROZEN. Device-specific autofocus envelopes remain blocked until physical evidence validates
them.
Calibration Tooling v1 consumes an already acquired Science v1 evidence bundle, validates the bounded Calibration Tooling v1 consumes an already acquired Science v1 evidence bundle, validates the bounded
contract and produces deterministic `L3DCALB1` v1. contract and produces deterministic `L3DCALB1` v1.
@ -934,12 +937,16 @@ SOURCE_COMMENT_AUDIT PASS
SOURCE_COMMENT_REMEDIATION PASS SOURCE_COMMENT_REMEDIATION PASS
PRODUCT_DEFINITION_V1 PASS/FROZEN PRODUCT_DEFINITION_V1 PASS/FROZEN
PROMPT_TREE CURRENT PROMPT_TREE CURRENT
CALIBRATION_EVIDENCE_SOLVER_V1 IMPLEMENTED/VALIDATED CALIBRATION_SCIENCE_V2 PASS/FROZEN
CALIBRATION_TOOLING_ALIGNMENT PASS/FROZEN CALIBRATION_V2_HETEROGENEOUS_OPTICS PASS/FROZEN
CURRENT_NEXT DEDICATED_PHYSICAL_CALIBRATED_REAL_CAMPAIGN CALIBRATION_WORKFLOW_V2 PASS/FROZEN
ADAPTIVE_CAPTURE_SETTINGS_CONTRACT PASS/FROZEN
AUTOFOCUS_V2_FOUNDATION PASS/FROZEN
CURRENT_NEXT PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
Implementation proceeds only through explicitly human-authorized tranches under `prompt.md` and the Implementation proceeds only through explicitly human-authorized tranches under `prompt.md` and the
numbered `prompt/` execution contract. The current authorized dependency is the final usable numbered `prompt/` execution contract. The current dependency is physical autofocus/optical
calibration workflow; its next missing sub-boundary composes the FROZEN Tooling applicability validation for real equipment, followed by a dedicated calibrated real campaign.
and Bootstrap importer to reach truthful READY from the validated binding. Generic autofocus applicability machinery is available, but the real
A6000 + E PZ 16-50 autofocus applicability remains blocked until physical evidence validates it.

View file

@ -15,6 +15,10 @@ enum {
LARDON3D_OPTICAL_TEXT_CAPACITY = 128, LARDON3D_OPTICAL_TEXT_CAPACITY = 128,
LARDON3D_OPTICAL_PROVENANCE_CAPACITY = 256, LARDON3D_OPTICAL_PROVENANCE_CAPACITY = 256,
LARDON3D_OPTICAL_PAGE_MAX = 128, LARDON3D_OPTICAL_PAGE_MAX = 128,
LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE = 32,
/* This is an operational persistence/API bound, not a scientific focus
* range. Every member remains one opaque exact observation token. */
LARDON3D_OPTICAL_FOCUS_DOMAIN_TOKEN_MAX = 64,
}; };
typedef enum { typedef enum {
@ -171,6 +175,19 @@ typedef struct {
uint64_t exemplar_capture_id; uint64_t exemplar_capture_id;
} Lardon3DOpticalCalibrationApplicabilityV2; } Lardon3DOpticalCalibrationApplicabilityV2;
typedef struct {
uint64_t focus_domain_id;
/* The v26 applicability retains calibration/configuration identity and its
* exemplar retains the exact complete non-focus geometric tuple. */
uint64_t applicability_id;
uint64_t calibration_profile_id;
uint64_t optical_configuration_id;
uint64_t exemplar_capture_id;
uint32_t domain_version;
unsigned char evidence_sha256[LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE];
uint32_t token_count;
} Lardon3DOpticalFocusDomainV2;
typedef struct { typedef struct {
Lardon3DOpticalCalibrationResolutionKind kind; Lardon3DOpticalCalibrationResolutionKind kind;
uint64_t applicability_id; uint64_t applicability_id;
@ -333,15 +350,35 @@ Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create(
uint64_t exemplar_capture_id, uint64_t exemplar_capture_id,
Lardon3DOpticalCalibrationApplicabilityV2 *output); Lardon3DOpticalCalibrationApplicabilityV2 *output);
/* Resolution counts exact valid applicability rows. NONE is CALIBRATION_REQUIRED, /* Attach one physically validated discrete focus domain to an existing exact
* ONE is RESOLVED, and MANY is SELECTION_REQUIRED. All are successful outcomes. */ * v26 applicability. evidence_sha256 must be a nonzero retained-evidence or
* provenance digest. focus_tokens contains 1..FOCUS_DOMAIN_TOKEN_MAX distinct,
* nonempty, NUL-terminated opaque tokens; the call borrows the array and
* strings only for its duration. Members are stored as a deterministic exact
* set: order has no meaning, exact retry is idempotent, and conflicting reuse
* of the applicability is CONSTRAINT. The API performs no numeric conversion,
* EXIF interpretation, interpolation, extrapolation, or physical validation.
* output is mandatory. On OK, it receives the durable focus domain and its
* attached applicability identity; for valid calls it is zeroed on non-OK. */
Lardon3DProjectDbResult lardon3d_optical_focus_domain_v2_create(
Lardon3DProjectDb *database, uint64_t applicability_id,
uint32_t domain_version,
const unsigned char evidence_sha256[LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE],
const char *const *focus_tokens, size_t token_count,
Lardon3DOpticalFocusDomainV2 *output);
/* Resolution counts distinct eligible applicability rows: exact v26 state
* matches plus v27 domains whose non-focus geometry is exact and whose focus
* token is an exact member. NONE is CALIBRATION_REQUIRED, ONE is RESOLVED, and
* MANY is SELECTION_REQUIRED. All are successful outcomes. */
Lardon3DProjectDbResult lardon3d_optical_capture_calibration_resolve_v2( Lardon3DProjectDbResult lardon3d_optical_capture_calibration_resolve_v2(
Lardon3DProjectDb *database, uint64_t capture_id, Lardon3DProjectDb *database, uint64_t capture_id,
Lardon3DOpticalCalibrationResolutionV2 *output); Lardon3DOpticalCalibrationResolutionV2 *output);
/* Selection requires a complete observed geometric-state tuple and an exactly /* Selection requires a complete observed geometric-state tuple and an
* compatible applicability; UNKNOWN in any geometry-relevant field is a * applicability currently eligible by exact v26 match or exact v27 domain
* CONSTRAINT. The first selection is immutable, exact retry is idempotent, and * membership; UNKNOWN in any geometry-relevant field is a CONSTRAINT. The
* a conflicting applicability is rejected without changing the selection. */ * first selection is immutable, exact retry is idempotent, and a conflicting
* applicability is rejected without changing the selection. */
Lardon3DProjectDbResult lardon3d_optical_capture_calibration_select_v2( Lardon3DProjectDbResult lardon3d_optical_capture_calibration_select_v2(
Lardon3DProjectDb *database, uint64_t capture_id, uint64_t applicability_id); Lardon3DProjectDb *database, uint64_t capture_id, uint64_t applicability_id);
/* Loads the Capture's durable v2 selection without creating or changing it. /* Loads the Capture's durable v2 selection without creating or changing it.

View file

@ -11,10 +11,10 @@
#include <lardon3d/sparse_sfm_incremental.h> #include <lardon3d/sparse_sfm_incremental.h>
enum { enum {
/* v26 additively stores Capture-owned observed geometric state and exact /* v27 additively stores validated focus domains as bounded sets of exact
* calibration applicability. Migration does not infer state from v23 * observed tokens attached to v26 applicability. Migration creates no
* configuration or historical calibration selections. */ * domain or token from historical geometric state. */
LARDON3D_PROJECT_DB_SCHEMA_VERSION = 26, LARDON3D_PROJECT_DB_SCHEMA_VERSION = 27,
LARDON3D_PROJECT_DB_ID_CAPACITY = 65, LARDON3D_PROJECT_DB_ID_CAPACITY = 65,
LARDON3D_PROJECT_DB_KIND_CAPACITY = 65, LARDON3D_PROJECT_DB_KIND_CAPACITY = 65,
LARDON3D_PROJECT_DB_PATH_CAPACITY = 4096, LARDON3D_PROJECT_DB_PATH_CAPACITY = 4096,

View file

@ -79,7 +79,7 @@ Do not return after each file. Do not repeat global A-to-Z audits when unchanged
This contract was prepared against the repository state that declares: This contract was prepared against the repository state that declares:
```text ```text
CURRENT_PROJECT_DB_SCHEMA=v26 CURRENT_PROJECT_DB_SCHEMA=v27
PRODUCTION_TASK_KINDS=16 PRODUCTION_TASK_KINDS=16
PRODUCT_DEFINITION_V1=PASS/FROZEN PRODUCT_DEFINITION_V1=PASS/FROZEN
PROMPT_TREE=NEXT PROMPT_TREE=NEXT

View file

@ -3,10 +3,10 @@
## Status ## Status
```text ```text
CURRENT_PROJECT_DB_SCHEMA=v26 CURRENT_PROJECT_DB_SCHEMA=v27
PRODUCTION_TASK_KINDS=16 PRODUCTION_TASK_KINDS=16
USER_FACING_UI_LANGUAGE_NORMALIZATION=PASS USER_FACING_UI_LANGUAGE_NORMALIZATION=PASS
CURRENT_IMPLEMENTATION_CURSOR=ADAPTIVE_CAPTURE_SETTINGS_AND_AUTOFOCUS_V2_FOUNDATION CURRENT_IMPLEMENTATION_CURSOR=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
## Authority ## Authority
@ -16,7 +16,7 @@ CURRENT_IMPLEMENTATION_CURSOR=ADAPTIVE_CAPTURE_SETTINGS_AND_AUTOFOCUS_V2_FOUNDAT
## CURRENT ## CURRENT
```text ```text
Project DB head v26 Project DB head v27
Production Task kinds 16 Production Task kinds 16
Feature Store IMPLEMENTED Feature Store IMPLEMENTED
Visual Index IMPLEMENTED Visual Index IMPLEMENTED
@ -39,8 +39,8 @@ Calibration Science v2 heterogeneous optics PASS/FROZEN
Calibration v2 optical-state foundation PASS/FROZEN Calibration v2 optical-state foundation PASS/FROZEN
Calibration v2 heterogeneous publication PASS/FROZEN Calibration v2 heterogeneous publication PASS/FROZEN
Calibration Workflow v2 PASS/FROZEN Calibration Workflow v2 PASS/FROZEN
Adaptive capture settings semantics PLANNED Adaptive capture settings semantics PASS/FROZEN
Autofocus v2 foundation PLANNED Autofocus v2 foundation PASS/FROZEN
Calibration Tooling planarity alignment PASS/FROZEN Calibration Tooling planarity alignment PASS/FROZEN
``` ```

View file

@ -21,9 +21,9 @@ CALIBRATION_SCIENCE_V2=PASS/FROZEN
CALIBRATION_V2_HETEROGENEOUS_OPTICS=PASS/FROZEN CALIBRATION_V2_HETEROGENEOUS_OPTICS=PASS/FROZEN
CALIBRATION_V2_HETEROGENEOUS_CALIBRATION_PUBLICATION=PASS/FROZEN CALIBRATION_V2_HETEROGENEOUS_CALIBRATION_PUBLICATION=PASS/FROZEN
CALIBRATION_V2_WORKFLOW_READY=PASS/FROZEN CALIBRATION_V2_WORKFLOW_READY=PASS/FROZEN
ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PLANNED ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PASS/FROZEN
AUTOFOCUS_V2_FOUNDATION=PLANNED AUTOFOCUS_V2_FOUNDATION=PASS/FROZEN
CURRENT_CALIBRATION_NEXT=AUTOFOCUS_V2_FOUNDATION CURRENT_CALIBRATION_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
## Authority ## Authority

View file

@ -6,7 +6,7 @@
IMPLEMENTATION_ORDER=DEPENDENCY_DRIVEN IMPLEMENTATION_ORDER=DEPENDENCY_DRIVEN
IMPLEMENTATION_AUTHORIZATION=NO IMPLEMENTATION_AUTHORIZATION=NO
STEP_0_USER_FACING_LANGUAGE_NORMALIZATION=PASS STEP_0_USER_FACING_LANGUAGE_NORMALIZATION=PASS
CURRENT_NEXT=AUTOFOCUS_V2_FOUNDATION CURRENT_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
``` ```
## Authority ## Authority
@ -25,8 +25,8 @@ Default dependency order:
3. Calibration v2 heterogeneous-optics persistence foundation — PASS/FROZEN; 3. Calibration v2 heterogeneous-optics persistence foundation — PASS/FROZEN;
4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN; 4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN;
5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN; 5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN;
6. Adaptive capture settings / generic autofocus foundation — CURRENT; 6. Adaptive capture settings / generic autofocus foundation — PASS/FROZEN;
7. physical autofocus/optical applicability validation and dedicated calibrated real campaign; 7. physical autofocus/optical applicability validation and dedicated calibrated real campaign — CURRENT;
8. real Sparse SfM proof; 8. real Sparse SfM proof;
9. durable Dense/OpenMVS orchestration; 9. durable Dense/OpenMVS orchestration;
10. mesh / refinement / texturing / export; 10. mesh / refinement / texturing / export;

View file

@ -2338,6 +2338,21 @@ static const char exact_state_predicate[] =
"t.decoded_geometry_state=e.decoded_geometry_state AND " "t.decoded_geometry_state=e.decoded_geometry_state AND "
"t.decoded_width=e.decoded_width AND t.decoded_height=e.decoded_height"; "t.decoded_width=e.decoded_width AND t.decoded_height=e.decoded_height";
/* A discrete focus domain varies only the exact opaque focus token. Every
other geometry and observation-provenance field remains exemplar-exact. */
static const char exact_nonfocus_state_predicate[] =
"t.optical_configuration_id=e.optical_configuration_id AND "
"t.state_version=e.state_version AND t.provenance=e.provenance AND "
"t.aperture_state=e.aperture_state AND t.aperture_x1000=e.aperture_x1000 "
"AND t.stabilization=e.stabilization AND t.crop_state=e.crop_state AND "
"t.crop_observation=e.crop_observation AND "
"t.pipeline_state=e.pipeline_state AND "
"t.pipeline_observation=e.pipeline_observation AND "
"t.representation_state=e.representation_state AND "
"t.representation_observation=e.representation_observation AND "
"t.decoded_geometry_state=e.decoded_geometry_state AND "
"t.decoded_width=e.decoded_width AND t.decoded_height=e.decoded_height";
Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create( Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create(
Lardon3DProjectDb *database, uint64_t calibration_profile_id, Lardon3DProjectDb *database, uint64_t calibration_profile_id,
uint64_t exemplar_capture_id, uint64_t exemplar_capture_id,
@ -2429,8 +2444,230 @@ Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create(
return result; return result;
} }
static bool focus_domain_digest_valid(
const unsigned char digest[LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE]) {
if (!digest)
return false;
for (size_t index = 0; index < LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE;
++index)
if (digest[index] != 0)
return true;
return false;
}
static bool focus_domain_tokens_valid(const char *const *tokens, size_t count) {
if (!tokens || count == 0 ||
count > LARDON3D_OPTICAL_FOCUS_DOMAIN_TOKEN_MAX)
return false;
for (size_t index = 0; index < count; ++index) {
if (!optical_text(tokens[index], LARDON3D_OPTICAL_TEXT_CAPACITY, false))
return false;
for (size_t previous = 0; previous < index; ++previous)
if (strcmp(tokens[index], tokens[previous]) == 0)
return false;
}
return true;
}
Lardon3DProjectDbResult lardon3d_optical_focus_domain_v2_create(
Lardon3DProjectDb *database, uint64_t applicability_id,
uint32_t domain_version,
const unsigned char evidence_sha256[LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE],
const char *const *focus_tokens, size_t token_count,
Lardon3DOpticalFocusDomainV2 *output) {
if (output)
memset(output, 0, sizeof(*output));
if (!database || !optical_id(applicability_id) || domain_version == 0 ||
!focus_domain_digest_valid(evidence_sha256) ||
!focus_domain_tokens_valid(focus_tokens, token_count) || !output)
return LARDON3D_PROJECT_DB_INVALID_ARGUMENT;
/* Canonical lexical order makes a domain's durable representation
independent of caller ordering while retaining tokens byte-for-byte. */
const char *ordered[LARDON3D_OPTICAL_FOCUS_DOMAIN_TOKEN_MAX];
for (size_t index = 0; index < token_count; ++index) {
size_t position = index;
while (position > 0 && strcmp(focus_tokens[index], ordered[position - 1]) < 0) {
ordered[position] = ordered[position - 1];
--position;
}
ordered[position] = focus_tokens[index];
}
(void)pthread_mutex_lock(&database->mutex);
Lardon3DProjectDbResult result = execute(
database, "BEGIN IMMEDIATE", "begin optical focus domain v2");
sqlite3_stmt *statement = NULL;
uint64_t calibration_profile_id = 0;
uint64_t optical_configuration_id = 0;
uint64_t exemplar_capture_id = 0;
if (result == LARDON3D_PROJECT_DB_OK)
result = prepare(
database,
"SELECT calibration_profile_id,optical_configuration_id,"
"exemplar_capture_id FROM optical_calibration_applicabilities_v2 "
"WHERE applicability_id=?1",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)applicability_id);
int code = sqlite3_step(statement);
if (code == SQLITE_DONE)
result = LARDON3D_PROJECT_DB_NOT_FOUND;
else if (code != SQLITE_ROW)
result = sqlite_result(database, code, "load focus domain applicability");
else if (sqlite3_column_type(statement, 0) != SQLITE_INTEGER ||
sqlite3_column_type(statement, 1) != SQLITE_INTEGER ||
sqlite3_column_type(statement, 2) != SQLITE_INTEGER ||
sqlite3_column_int64(statement, 0) <= 0 ||
sqlite3_column_int64(statement, 1) <= 0 ||
sqlite3_column_int64(statement, 2) <= 0)
result = LARDON3D_PROJECT_DB_CORRUPT;
else {
calibration_profile_id = (uint64_t)sqlite3_column_int64(statement, 0);
optical_configuration_id = (uint64_t)sqlite3_column_int64(statement, 1);
exemplar_capture_id = (uint64_t)sqlite3_column_int64(statement, 2);
if (sqlite3_step(statement) != SQLITE_DONE)
result = LARDON3D_PROJECT_DB_CORRUPT;
}
}
(void)sqlite3_finalize(statement);
statement = NULL;
if (result == LARDON3D_PROJECT_DB_OK)
result = prepare(
database,
"INSERT OR IGNORE INTO optical_focus_domains_v2(applicability_id,"
"domain_version,evidence_sha256,token_count) VALUES(?1,?2,?3,?4)",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)applicability_id);
sqlite3_bind_int64(statement, 2, (sqlite3_int64)domain_version);
sqlite3_bind_blob(statement, 3, evidence_sha256,
LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE,
SQLITE_TRANSIENT);
sqlite3_bind_int64(statement, 4, (sqlite3_int64)token_count);
result = step_done(database, statement, "insert optical focus domain v2");
statement = NULL;
}
uint64_t focus_domain_id = 0;
if (result == LARDON3D_PROJECT_DB_OK)
result = prepare(
database,
"SELECT focus_domain_id,domain_version,evidence_sha256,token_count FROM "
"optical_focus_domains_v2 WHERE applicability_id=?1",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)applicability_id);
int code = sqlite3_step(statement);
if (code != SQLITE_ROW)
result = code == SQLITE_DONE
? LARDON3D_PROJECT_DB_CORRUPT
: sqlite_result(database, code, "load optical focus domain v2");
else {
sqlite3_int64 stored_id = sqlite3_column_int64(statement, 0);
sqlite3_int64 stored_version = sqlite3_column_int64(statement, 1);
sqlite3_int64 stored_count = sqlite3_column_int64(statement, 3);
const unsigned char *stored_digest = sqlite3_column_blob(statement, 2);
if (sqlite3_column_type(statement, 0) != SQLITE_INTEGER ||
sqlite3_column_type(statement, 1) != SQLITE_INTEGER ||
sqlite3_column_type(statement, 2) != SQLITE_BLOB ||
sqlite3_column_type(statement, 3) != SQLITE_INTEGER || stored_id <= 0 ||
stored_version <= 0 || stored_version > UINT32_MAX ||
sqlite3_column_bytes(statement, 2) !=
LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE ||
!focus_domain_digest_valid(stored_digest) || stored_count <= 0 ||
stored_count > LARDON3D_OPTICAL_FOCUS_DOMAIN_TOKEN_MAX) {
result = LARDON3D_PROJECT_DB_CORRUPT;
} else if (stored_version != (sqlite3_int64)domain_version ||
memcmp(stored_digest, evidence_sha256,
LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE) != 0 ||
stored_count != (sqlite3_int64)token_count) {
result = LARDON3D_PROJECT_DB_CONSTRAINT;
} else {
focus_domain_id = (uint64_t)stored_id;
if (sqlite3_step(statement) != SQLITE_DONE)
result = LARDON3D_PROJECT_DB_CORRUPT;
}
}
}
(void)sqlite3_finalize(statement);
statement = NULL;
for (size_t index = 0; index < token_count &&
result == LARDON3D_PROJECT_DB_OK;
++index) {
result = prepare(
database,
"INSERT OR IGNORE INTO optical_focus_domain_tokens_v2 "
"VALUES(?1,?2,?3)",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)focus_domain_id);
sqlite3_bind_int64(statement, 2, (sqlite3_int64)index);
sqlite3_bind_text(statement, 3, ordered[index], -1, SQLITE_TRANSIENT);
result = step_done(database, statement, "insert focus domain token v2");
statement = NULL;
}
}
if (result == LARDON3D_PROJECT_DB_OK)
result = prepare(
database,
"SELECT token_ordinal,focus_token FROM optical_focus_domain_tokens_v2 "
"WHERE focus_domain_id=?1 ORDER BY token_ordinal",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)focus_domain_id);
for (size_t index = 0; index < token_count; ++index) {
int code = sqlite3_step(statement);
if (code != SQLITE_ROW) {
result = code == SQLITE_DONE ? LARDON3D_PROJECT_DB_CORRUPT
: sqlite_result(database, code,
"load focus domain token v2");
break;
}
if (sqlite3_column_type(statement, 0) != SQLITE_INTEGER ||
sqlite3_column_int64(statement, 0) != (sqlite3_int64)index ||
sqlite3_column_type(statement, 1) != SQLITE_TEXT ||
sqlite3_column_bytes(statement, 1) <= 0 ||
sqlite3_column_bytes(statement, 1) >= LARDON3D_OPTICAL_TEXT_CAPACITY) {
result = LARDON3D_PROJECT_DB_CORRUPT;
break;
}
if (!optical_column_equals(statement, 1, ordered[index])) {
result = LARDON3D_PROJECT_DB_CONSTRAINT;
break;
}
}
if (result == LARDON3D_PROJECT_DB_OK &&
sqlite3_step(statement) != SQLITE_DONE)
result = LARDON3D_PROJECT_DB_CORRUPT;
}
(void)sqlite3_finalize(statement);
result = optical_commit_or_rollback(database, result,
"commit optical focus domain v2",
"rollback optical focus domain v2");
(void)pthread_mutex_unlock(&database->mutex);
if (result == LARDON3D_PROJECT_DB_OK) {
output->focus_domain_id = focus_domain_id;
output->applicability_id = applicability_id;
output->calibration_profile_id = calibration_profile_id;
output->optical_configuration_id = optical_configuration_id;
output->exemplar_capture_id = exemplar_capture_id;
output->domain_version = domain_version;
memcpy(output->evidence_sha256, evidence_sha256,
LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE);
output->token_count = (uint32_t)token_count;
} else {
memset(output, 0, sizeof(*output));
}
return result;
}
static Lardon3DProjectDbResult static Lardon3DProjectDbResult
exact_candidates_locked(Lardon3DProjectDb *database, uint64_t capture_id, applicability_candidates_locked(Lardon3DProjectDb *database,
uint64_t capture_id,
uint64_t required_applicability, uint64_t required_applicability,
Lardon3DOpticalCalibrationResolutionV2 *output, Lardon3DOpticalCalibrationResolutionV2 *output,
size_t *count) { size_t *count) {
@ -2461,13 +2698,58 @@ exact_candidates_locked(Lardon3DProjectDb *database, uint64_t capture_id,
(void)sqlite3_finalize(validation); (void)sqlite3_finalize(validation);
if (result != LARDON3D_PROJECT_DB_OK) if (result != LARDON3D_PROJECT_DB_OK)
return result; return result;
validation = NULL;
char query[1800]; /* Domain rows are retained scientific evidence. Broken dependencies,
incomplete exemplars or token-set corruption must fail closed before
enumeration; a domain never supplies evidence missing from its exemplar. */
result = prepare(
database,
"SELECT d.focus_domain_id FROM optical_focus_domains_v2 d LEFT JOIN "
"optical_calibration_applicabilities_v2 a ON "
"a.applicability_id=d.applicability_id LEFT JOIN capture_geometric_states e "
"ON e.capture_id=a.exemplar_capture_id AND "
"e.optical_configuration_id=a.optical_configuration_id WHERE "
"a.applicability_id IS NULL OR (a.optical_configuration_id=(SELECT "
"optical_configuration_id FROM capture_geometric_states WHERE capture_id=?1) "
"AND (e.capture_id IS NULL OR e.focus_state!=2 OR e.aperture_state!=2 OR "
"e.stabilization=0 OR e.crop_state!=2 OR e.pipeline_state!=2 OR "
"e.representation_state!=2 OR e.decoded_geometry_state!=2 OR "
"typeof(d.domain_version)!='integer' OR d.domain_version<=0 OR "
"typeof(d.evidence_sha256)!='blob' OR length(d.evidence_sha256)!=32 OR "
"d.evidence_sha256=zeroblob(32) OR typeof(d.token_count)!='integer' OR "
"d.token_count<=0 OR d.token_count>64 OR d.token_count!=(SELECT COUNT(*) "
"FROM optical_focus_domain_tokens_v2 k WHERE "
"k.focus_domain_id=d.focus_domain_id) OR (SELECT MIN(k.token_ordinal) FROM "
"optical_focus_domain_tokens_v2 k WHERE k.focus_domain_id=d.focus_domain_id)"
"!=0 OR (SELECT MAX(k.token_ordinal) FROM optical_focus_domain_tokens_v2 k "
"WHERE k.focus_domain_id=d.focus_domain_id)!=d.token_count-1 OR EXISTS("
"SELECT 1 FROM optical_focus_domain_tokens_v2 k WHERE "
"k.focus_domain_id=d.focus_domain_id AND (typeof(k.token_ordinal)!='integer' "
"OR k.token_ordinal<0 OR k.token_ordinal>=64 OR "
"typeof(k.focus_token)!='text' OR length(k.focus_token)=0 OR "
"length(k.focus_token)>=128)))) LIMIT 1",
&validation);
if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(validation, 1, (sqlite3_int64)capture_id);
int code = sqlite3_step(validation);
if (code == SQLITE_ROW)
result = LARDON3D_PROJECT_DB_CORRUPT;
else if (code != SQLITE_DONE)
result = sqlite_result(database, code, "validate optical focus domain v2");
}
(void)sqlite3_finalize(validation);
if (result != LARDON3D_PROJECT_DB_OK)
return result;
char query[4096];
int length = snprintf( int length = snprintf(
query, sizeof(query), query, sizeof(query),
"SELECT " "SELECT applicability_id,calibration_profile_id,sparse_calibration_id "
"a.applicability_id,a.calibration_profile_id,p.sparse_calibration_id " "FROM (SELECT a.applicability_id AS applicability_id,"
"FROM capture_geometric_states t JOIN " "a.calibration_profile_id AS calibration_profile_id,"
"p.sparse_calibration_id AS sparse_calibration_id FROM "
"capture_geometric_states t JOIN "
"optical_calibration_applicabilities_v2 a ON " "optical_calibration_applicabilities_v2 a ON "
"a.optical_configuration_id=t.optical_configuration_id JOIN " "a.optical_configuration_id=t.optical_configuration_id JOIN "
"capture_geometric_states e ON e.capture_id=a.exemplar_capture_id JOIN " "capture_geometric_states e ON e.capture_id=a.exemplar_capture_id JOIN "
@ -2475,16 +2757,28 @@ exact_candidates_locked(Lardon3DProjectDb *database, uint64_t capture_id,
"p.calibration_profile_id=a.calibration_profile_id AND " "p.calibration_profile_id=a.calibration_profile_id AND "
"p.optical_configuration_id=a.optical_configuration_id JOIN " "p.optical_configuration_id=a.optical_configuration_id JOIN "
"sparse_calibrations s ON s.calibration_id=p.sparse_calibration_id WHERE " "sparse_calibrations s ON s.calibration_id=p.sparse_calibration_id WHERE "
"t.capture_id=?1 AND %s%s ORDER BY a.applicability_id LIMIT 2", "t.capture_id=?1 AND %s UNION SELECT a.applicability_id,"
exact_state_predicate, "a.calibration_profile_id,p.sparse_calibration_id FROM "
required_applicability ? " AND a.applicability_id=?2" : ""); "capture_geometric_states t JOIN optical_focus_domains_v2 d ON "
"1=1 JOIN optical_calibration_applicabilities_v2 a ON "
"a.applicability_id=d.applicability_id AND "
"a.optical_configuration_id=t.optical_configuration_id JOIN "
"capture_geometric_states e ON e.capture_id=a.exemplar_capture_id JOIN "
"optical_focus_domain_tokens_v2 k ON "
"k.focus_domain_id=d.focus_domain_id AND "
"k.focus_token=t.focus_observation JOIN optical_calibration_profiles p ON "
"p.calibration_profile_id=a.calibration_profile_id AND "
"p.optical_configuration_id=a.optical_configuration_id JOIN "
"sparse_calibrations s ON s.calibration_id=p.sparse_calibration_id WHERE "
"t.capture_id=?1 AND t.focus_state=2 AND %s) candidates WHERE "
"(?2=0 OR applicability_id=?2) ORDER BY applicability_id LIMIT 2",
exact_state_predicate, exact_nonfocus_state_predicate);
sqlite3_stmt *statement = NULL; sqlite3_stmt *statement = NULL;
result = length < 0 || (size_t)length >= sizeof(query) result = length < 0 || (size_t)length >= sizeof(query)
? LARDON3D_PROJECT_DB_IO_ERROR ? LARDON3D_PROJECT_DB_IO_ERROR
: prepare(database, query, &statement); : prepare(database, query, &statement);
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id); sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
if (required_applicability)
sqlite3_bind_int64(statement, 2, (sqlite3_int64)required_applicability); sqlite3_bind_int64(statement, 2, (sqlite3_int64)required_applicability);
int code; int code;
*count = 0; *count = 0;
@ -2556,7 +2850,8 @@ Lardon3DProjectDbResult lardon3d_optical_capture_calibration_resolve_v2(
return result; return result;
(void)pthread_mutex_lock(&database->mutex); (void)pthread_mutex_lock(&database->mutex);
size_t count = 0; size_t count = 0;
result = exact_candidates_locked(database, capture_id, 0, output, &count); result = applicability_candidates_locked(database, capture_id, 0, output,
&count);
(void)pthread_mutex_unlock(&database->mutex); (void)pthread_mutex_unlock(&database->mutex);
if (result != LARDON3D_PROJECT_DB_OK) { if (result != LARDON3D_PROJECT_DB_OK) {
memset(output, 0, sizeof(*output)); memset(output, 0, sizeof(*output));
@ -2585,8 +2880,9 @@ lardon3d_optical_capture_calibration_select_v2(Lardon3DProjectDb *database,
Lardon3DProjectDbResult result = execute( Lardon3DProjectDbResult result = execute(
database, "BEGIN IMMEDIATE", "begin Capture calibration selection v2"); database, "BEGIN IMMEDIATE", "begin Capture calibration selection v2");
if (result == LARDON3D_PROJECT_DB_OK) if (result == LARDON3D_PROJECT_DB_OK)
result = exact_candidates_locked(database, capture_id, applicability_id, result = applicability_candidates_locked(database, capture_id,
&candidate, &count); applicability_id, &candidate,
&count);
if (result == LARDON3D_PROJECT_DB_OK && count != 1) if (result == LARDON3D_PROJECT_DB_OK && count != 1)
result = LARDON3D_PROJECT_DB_CONSTRAINT; result = LARDON3D_PROJECT_DB_CONSTRAINT;
Lardon3DOpticalCaptureGeometricState state = {0}; Lardon3DOpticalCaptureGeometricState state = {0};
@ -2688,7 +2984,7 @@ Lardon3DProjectDbResult lardon3d_optical_capture_calibration_selection_load_v2(
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
Lardon3DOpticalCalibrationResolutionV2 candidate = {0}; Lardon3DOpticalCalibrationResolutionV2 candidate = {0};
size_t count = 0; size_t count = 0;
result = exact_candidates_locked( result = applicability_candidates_locked(
database, capture_id, output->applicability_id, &candidate, &count); database, capture_id, output->applicability_id, &candidate, &count);
if (result == LARDON3D_PROJECT_DB_OK && if (result == LARDON3D_PROJECT_DB_OK &&
(count != 1 || (count != 1 ||

View file

@ -960,6 +960,29 @@ static const char schema_optical_geometric_state_v26[] =
"optical_calibration_applicabilities_v2(applicability_id,calibration_" "optical_calibration_applicabilities_v2(applicability_id,calibration_"
"profile_id,optical_configuration_id));"; "profile_id,optical_configuration_id));";
/* PERSISTENCE CONTRACT v27: a focus domain is evidence attached to one v26
applicability, not a numeric focus interval or a new calibration identity.
Token order is canonical insertion order only; matching is exact text
equality. DDL-only migration cannot infer a domain from historical tokens. */
static const char schema_optical_focus_domains_v27[] =
"CREATE TABLE optical_focus_domains_v2("
"focus_domain_id INTEGER PRIMARY KEY AUTOINCREMENT CHECK(focus_domain_id>0),"
"applicability_id INTEGER NOT NULL UNIQUE REFERENCES "
"optical_calibration_applicabilities_v2(applicability_id),"
"domain_version INTEGER NOT NULL CHECK(domain_version>0 "
"AND domain_version<=4294967295),evidence_sha256 BLOB NOT NULL "
"CHECK(typeof(evidence_sha256)='blob' AND length(evidence_sha256)=32 AND "
"evidence_sha256!=zeroblob(32)),token_count INTEGER NOT NULL "
"CHECK(token_count>0 AND token_count<=64));"
"CREATE TABLE optical_focus_domain_tokens_v2(focus_domain_id INTEGER NOT NULL "
"REFERENCES optical_focus_domains_v2(focus_domain_id) ON DELETE CASCADE,"
"token_ordinal INTEGER NOT NULL CHECK(token_ordinal>=0 AND token_ordinal<64),"
"focus_token TEXT NOT NULL CHECK(typeof(focus_token)='text' AND "
"length(focus_token)>0 AND length(focus_token)<128),PRIMARY KEY(focus_domain_id,"
"token_ordinal),UNIQUE(focus_domain_id,focus_token));"
"CREATE INDEX optical_focus_domain_tokens_v2_token_idx ON "
"optical_focus_domain_tokens_v2(focus_token,focus_domain_id);";
static void copy_error(char destination[LARDON3D_PROJECT_DB_ERROR_CAPACITY], const char *text) { static void copy_error(char destination[LARDON3D_PROJECT_DB_ERROR_CAPACITY], const char *text) {
if (destination) { if (destination) {
(void)snprintf(destination, LARDON3D_PROJECT_DB_ERROR_CAPACITY, "%s", text ? text : ""); (void)snprintf(destination, LARDON3D_PROJECT_DB_ERROR_CAPACITY, "%s", text ? text : "");
@ -1053,7 +1076,8 @@ static Lardon3DProjectDbResult migrate(Lardon3DProjectDb *database, unsigned int
from_version != 12 && from_version != 13 && from_version != 14 && from_version != 12 && from_version != 13 && from_version != 14 &&
from_version != 15 && from_version != 16 && from_version != 17 && from_version != 18 && from_version != 15 && from_version != 16 && from_version != 17 && from_version != 18 &&
from_version != 19 && from_version != 20 && from_version != 21 && from_version != 22 && from_version != 19 && from_version != 20 && from_version != 21 && from_version != 22 &&
from_version != 23 && from_version != 24 && from_version != 25) { from_version != 23 && from_version != 24 && from_version != 25 &&
from_version != 26) {
return LARDON3D_PROJECT_DB_CORRUPT; return LARDON3D_PROJECT_DB_CORRUPT;
} }
Lardon3DProjectDbResult result = execute(database, "BEGIN IMMEDIATE", "begin migration"); Lardon3DProjectDbResult result = execute(database, "BEGIN IMMEDIATE", "begin migration");
@ -1579,6 +1603,27 @@ static Lardon3DProjectDbResult migrate(Lardon3DProjectDb *database, unsigned int
result = LARDON3D_PROJECT_DB_CORRUPT; result = LARDON3D_PROJECT_DB_CORRUPT;
} }
} }
if (result == LARDON3D_PROJECT_DB_OK && from_version < 27) {
/* A v26 focus token is only an observation. It is never sufficient
physical evidence to manufacture an applicability domain. */
result = execute(database, schema_optical_focus_domains_v27,
"migrate optical focus domains v26 to v27");
#ifdef LARDON3D_PROJECT_DB_TESTING
if (result == LARDON3D_PROJECT_DB_OK &&
getenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V27"))
result = execute(database, "INSERT INTO missing_v27_test_table VALUES(1)",
"forced migration v27 failure");
#endif
if (result == LARDON3D_PROJECT_DB_OK) {
result = execute(database,
"UPDATE metadata SET value=27 WHERE "
"key='schema_version' AND value=26",
"finish schema v27 migration");
if (result == LARDON3D_PROJECT_DB_OK &&
sqlite3_changes(database->connection) != 1)
result = LARDON3D_PROJECT_DB_CORRUPT;
}
}
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
result = execute(database, "COMMIT", "commit migration"); result = execute(database, "COMMIT", "commit migration");
} }
@ -1736,7 +1781,9 @@ Lardon3DProjectDbResult lardon3d_project_db_open(const char *path, Lardon3DProje
"capture_calibration_selections"}; "capture_calibration_selections"};
const char *required_v26[] = {"capture_geometric_states", const char *required_v26[] = {"capture_geometric_states",
"optical_calibration_applicabilities_v2", "optical_calibration_applicabilities_v2",
"capture_calibration_selections_v2"}; "capture_calibration_selections_v2",
"optical_focus_domains_v2",
"optical_focus_domain_tokens_v2"};
for (size_t index = 0; index < sizeof(required) / sizeof(required[0]) && for (size_t index = 0; index < sizeof(required) / sizeof(required[0]) &&
result == LARDON3D_PROJECT_DB_OK; result == LARDON3D_PROJECT_DB_OK;
++index) { ++index) {
@ -1751,7 +1798,7 @@ Lardon3DProjectDbResult lardon3d_project_db_open(const char *path, Lardon3DProje
++index) { ++index) {
if (!table_exists(database->connection, required_v26[index])) { if (!table_exists(database->connection, required_v26[index])) {
copy_error(database->error, copy_error(database->error,
"Current Project DB v26 schema is incomplete."); "Current Project DB v27 optical schema is incomplete.");
result = LARDON3D_PROJECT_DB_CORRUPT; result = LARDON3D_PROJECT_DB_CORRUPT;
} }
} }

View file

@ -172,6 +172,11 @@ static bool create_v11_database(const char *path) {
lardon3d_project_db_close(database); lardon3d_project_db_close(database);
return execute_sql(path, return execute_sql(path,
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;"
"DROP TABLE IF EXISTS optical_focus_domains_v2;"
"DROP TABLE IF EXISTS capture_calibration_selections_v2;"
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;"
"DROP TABLE IF EXISTS capture_geometric_states;"
"DROP TABLE IF EXISTS feature_extract_batch_tasks;" "DROP TABLE IF EXISTS feature_extract_batch_tasks;"
"DROP TABLE IF EXISTS raw_development_batch_tasks;" "DROP TABLE IF EXISTS raw_development_batch_tasks;"
"DROP TABLE IF EXISTS capture_calibration_selections;" "DROP TABLE IF EXISTS capture_calibration_selections;"

View file

@ -878,6 +878,11 @@ static bool run_task_test(void) {
CHECK(exec_sql( CHECK(exec_sql(
database_path, database_path,
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;"
"DROP TABLE IF EXISTS optical_focus_domains_v2;"
"DROP TABLE IF EXISTS capture_calibration_selections_v2;"
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;"
"DROP TABLE IF EXISTS capture_geometric_states;"
"DROP TABLE IF EXISTS feature_extract_batch_tasks;" "DROP TABLE IF EXISTS feature_extract_batch_tasks;"
"DROP TABLE IF EXISTS raw_development_batch_tasks;" "DROP TABLE IF EXISTS raw_development_batch_tasks;"
"DROP TABLE IF EXISTS capture_calibration_selections;" "DROP TABLE IF EXISTS capture_calibration_selections;"

View file

@ -54,7 +54,12 @@ static bool create_v9_database(const char *path) {
static const char sql[] = static const char sql[] =
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
/* This database is a true v9 fixture, not a current database whose /* This database is a true v9 fixture, not a current database whose
metadata alone was relabelled while additive v20-v25 objects survived. */ metadata alone was relabelled while later additive objects survived. */
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;"
"DROP TABLE IF EXISTS optical_focus_domains_v2;"
"DROP TABLE IF EXISTS capture_calibration_selections_v2;"
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;"
"DROP TABLE IF EXISTS capture_geometric_states;"
"DROP TABLE IF EXISTS feature_extract_batch_tasks;" "DROP TABLE IF EXISTS feature_extract_batch_tasks;"
"DROP TABLE IF EXISTS raw_development_batch_tasks;" "DROP TABLE IF EXISTS raw_development_batch_tasks;"
"DROP TABLE IF EXISTS capture_calibration_selections;" "DROP TABLE IF EXISTS capture_calibration_selections;"

View file

@ -360,6 +360,11 @@ static bool downgrade_project_to_historical_v10(const char *database_path) {
} }
static const char sql[] = static const char sql[] =
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;"
"DROP TABLE IF EXISTS optical_focus_domains_v2;"
"DROP TABLE IF EXISTS capture_calibration_selections_v2;"
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;"
"DROP TABLE IF EXISTS capture_geometric_states;"
"DROP TABLE IF EXISTS feature_extract_batch_tasks;" "DROP TABLE IF EXISTS feature_extract_batch_tasks;"
"DROP TABLE IF EXISTS raw_development_batch_tasks;" "DROP TABLE IF EXISTS raw_development_batch_tasks;"
"DROP TABLE IF EXISTS selected_execution_items;" "DROP TABLE IF EXISTS selected_execution_items;"

View file

@ -1147,6 +1147,8 @@ static bool downgrade_to_v22_fixture(const char *path) {
return raw_sql( return raw_sql(
path, path,
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;"
"DROP TABLE IF EXISTS optical_focus_domains_v2;"
"DROP TABLE IF EXISTS capture_calibration_selections_v2;" "DROP TABLE IF EXISTS capture_calibration_selections_v2;"
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;" "DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;"
"DROP TABLE IF EXISTS capture_geometric_states;" "DROP TABLE IF EXISTS capture_geometric_states;"
@ -1407,6 +1409,8 @@ static bool test_v26_exact_geometric_applicability(void) {
*/ */
CHECK(raw_sql( CHECK(raw_sql(
path, "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;" path, "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"DROP TABLE capture_calibration_selections_v2;" "DROP TABLE capture_calibration_selections_v2;"
"DROP TABLE optical_calibration_applicabilities_v2;" "DROP TABLE optical_calibration_applicabilities_v2;"
"DROP TABLE capture_geometric_states;" "DROP TABLE capture_geometric_states;"
@ -1432,6 +1436,296 @@ static bool test_v26_exact_geometric_applicability(void) {
return true; return true;
} }
static Lardon3DOpticalCaptureGeometricState complete_focus_state(
uint64_t capture_id, uint64_t configuration_id, const char *focus_token) {
Lardon3DOpticalCaptureGeometricState state = {
.capture_id = capture_id,
.optical_configuration_id = configuration_id,
.state_version = 1,
.provenance = LARDON3D_OPTICAL_GEOMETRIC_STATE_METADATA,
.focus_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.aperture_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.aperture_x1000 = 5600,
.stabilization = LARDON3D_OPTICAL_STABILIZATION_OFF,
.crop_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.pipeline_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.representation_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.decoded_geometry_state = LARDON3D_OPTICAL_OBSERVATION_OBSERVED,
.decoded_width = 6000,
.decoded_height = 4000,
};
(void)snprintf(state.focus_observation, sizeof(state.focus_observation),
"%s", focus_token);
memcpy(state.crop_observation, "full-sensor", sizeof("full-sensor"));
memcpy(state.pipeline_observation, "raw-policy-v1",
sizeof("raw-policy-v1"));
memcpy(state.representation_observation, "L3DRAWD1-png",
sizeof("L3DRAWD1-png"));
return state;
}
static bool test_v27_discrete_focus_domains(void) {
char directory[64];
char path[256];
CHECK(make_database_path(directory, path));
Lardon3DProjectDb *database = NULL;
char error[LARDON3D_PROJECT_DB_ERROR_CAPACITY];
CHECK(lardon3d_project_db_open(path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
RepairOpticalFixture fixture;
CHECK(seed_repair_optical_fixture(database, &fixture));
Lardon3DOpticalConfiguration base_configuration;
CHECK(lardon3d_optical_configuration_load(
database, fixture.configuration_id, &base_configuration) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalCameraBodyProfile other_body_input = {0};
memcpy(other_body_input.manufacturer, "Generic", sizeof("Generic"));
memcpy(other_body_input.model, "Other body", sizeof("Other body"));
memcpy(other_body_input.name, "Other body profile",
sizeof("Other body profile"));
Lardon3DOpticalCameraBodyProfile other_body;
CHECK(lardon3d_optical_camera_body_create(database, &other_body_input,
&other_body) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalLensProfile other_lens_input = {
.interface_kind = LARDON3D_OPTICAL_LENS_ELECTRONIC,
.focal_range_kind = LARDON3D_OPTICAL_FOCAL_RANGE_PRIME,
.minimum_focal_um = 16000,
.maximum_focal_um = 16000,
};
memcpy(other_lens_input.manufacturer, "Generic", sizeof("Generic"));
memcpy(other_lens_input.model, "Other lens", sizeof("Other lens"));
memcpy(other_lens_input.name, "Other lens profile",
sizeof("Other lens profile"));
Lardon3DOpticalLensProfile other_lens;
CHECK(lardon3d_optical_lens_create(database, &other_lens_input, &other_lens) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalConfiguration configuration_input = {
.camera_body_profile_id = other_body.camera_body_profile_id,
.lens_profile_id = base_configuration.lens_profile_id,
.has_focal_length = true,
.focal_length_um = 16000,
};
Lardon3DOpticalConfiguration other_body_configuration;
CHECK(lardon3d_optical_configuration_create(
database, &configuration_input, &other_body_configuration) ==
LARDON3D_PROJECT_DB_OK);
configuration_input.camera_body_profile_id =
base_configuration.camera_body_profile_id;
configuration_input.lens_profile_id = other_lens.lens_profile_id;
Lardon3DOpticalConfiguration other_lens_configuration;
CHECK(lardon3d_optical_configuration_create(
database, &configuration_input, &other_lens_configuration) ==
LARDON3D_PROJECT_DB_OK);
enum { TARGET_COUNT = 5 };
Lardon3DProjectDbCapture targets[TARGET_COUNT];
for (size_t index = 0; index < TARGET_COUNT; ++index)
CHECK(lardon3d_project_db_create_capture(database, fixture.scanset_id,
(uint32_t)(index + 2),
&targets[index]) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, fixture.capture_id, fixture.configuration_id) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, targets[0].capture_id, fixture.configuration_id) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, targets[1].capture_id, fixture.configuration_id) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, targets[2].capture_id,
fixture.alternate_configuration_id) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, targets[3].capture_id,
other_body_configuration.optical_configuration_id) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_assign_explicit(
database, targets[4].capture_id,
other_lens_configuration.optical_configuration_id) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalCaptureGeometricState state = complete_focus_state(
fixture.capture_id, fixture.configuration_id, "synthetic-focus-a");
Lardon3DOpticalCaptureGeometricState stored;
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
state = complete_focus_state(
targets[3].capture_id,
other_body_configuration.optical_configuration_id, "synthetic-focus-b");
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
state = complete_focus_state(
targets[4].capture_id,
other_lens_configuration.optical_configuration_id, "synthetic-focus-b");
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
state = complete_focus_state(targets[0].capture_id, fixture.configuration_id,
"synthetic-focus-b");
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
state = complete_focus_state(targets[1].capture_id, fixture.configuration_id,
"synthetic-focus-outside");
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
/* The identical focus token at another focal configuration must not cross
the exact body/lens/focal applicability boundary. */
state = complete_focus_state(targets[2].capture_id,
fixture.alternate_configuration_id,
"synthetic-focus-b");
CHECK(lardon3d_optical_capture_geometric_state_create(
database, &state, &stored) == LARDON3D_PROJECT_DB_OK);
Lardon3DSparseCalibration calibration;
CHECK(create_sparse_calibration(database, 0xd1, 6000, 4000, &calibration));
Lardon3DOpticalCalibrationProfile profile_input = {
.optical_configuration_id = fixture.configuration_id,
.sparse_calibration_id = calibration.calibration_id,
.profile_version = 2,
.applicability = LARDON3D_OPTICAL_CALIBRATION_EXACT_CONFIGURATION,
.created_at = 200,
};
memcpy(profile_input.name, "focus domain A", sizeof("focus domain A"));
memcpy(profile_input.provenance, "synthetic physical evidence",
sizeof("synthetic physical evidence"));
Lardon3DOpticalCalibrationProfile profile_a;
CHECK(lardon3d_optical_calibration_profile_create(
database, &profile_input, &profile_a) == LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalCalibrationApplicabilityV2 applicability_a;
CHECK(lardon3d_optical_calibration_applicability_v2_create(
database, profile_a.calibration_profile_id, fixture.capture_id,
&applicability_a) == LARDON3D_PROJECT_DB_OK);
const char *tokens[] = {"synthetic-focus-b", "synthetic-focus-a"};
unsigned char evidence[LARDON3D_OPTICAL_FOCUS_DOMAIN_DIGEST_SIZE] = {0};
evidence[0] = 0x71;
Lardon3DOpticalFocusDomainV2 domain_a;
CHECK(lardon3d_optical_focus_domain_v2_create(
database, applicability_a.applicability_id, 1, evidence, tokens,
2, &domain_a) == LARDON3D_PROJECT_DB_OK &&
domain_a.token_count == 2);
const char *retry_tokens[] = {"synthetic-focus-a", "synthetic-focus-b"};
Lardon3DOpticalFocusDomainV2 domain_retry;
CHECK(lardon3d_optical_focus_domain_v2_create(
database, applicability_a.applicability_id, 1, evidence,
retry_tokens, 2, &domain_retry) == LARDON3D_PROJECT_DB_OK &&
domain_retry.focus_domain_id == domain_a.focus_domain_id);
evidence[1] = 1;
CHECK(lardon3d_optical_focus_domain_v2_create(
database, applicability_a.applicability_id, 1, evidence,
retry_tokens, 2, &domain_retry) == LARDON3D_PROJECT_DB_CONSTRAINT &&
domain_retry.focus_domain_id == 0);
evidence[1] = 0;
Lardon3DOpticalCalibrationResolutionV2 resolution;
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[0].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_RESOLVED &&
resolution.applicability_id == applicability_a.applicability_id);
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[1].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_REQUIRED);
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[2].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_REQUIRED);
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[3].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_REQUIRED);
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[4].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_REQUIRED);
/* A domain cannot repair incomplete exemplar evidence. Corrupting the
schema-valid focus state must fail closed before candidate enumeration. */
lardon3d_project_db_close(database);
database = NULL;
char corruption[512];
int corruption_bytes = snprintf(
corruption, sizeof(corruption),
"UPDATE capture_geometric_states SET focus_state=1,"
"focus_observation='' WHERE capture_id=%llu;",
(unsigned long long)fixture.capture_id);
CHECK(corruption_bytes > 0 &&
(size_t)corruption_bytes < sizeof(corruption) &&
raw_sql(path, corruption));
CHECK(lardon3d_project_db_open(path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
memset(&resolution, 0x7f, sizeof(resolution));
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[0].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_CORRUPT &&
resolution.kind == 0 &&
resolution.applicability_id == 0);
lardon3d_project_db_close(database);
database = NULL;
corruption_bytes = snprintf(
corruption, sizeof(corruption),
"UPDATE capture_geometric_states SET focus_state=2,"
"focus_observation='synthetic-focus-a' WHERE capture_id=%llu;",
(unsigned long long)fixture.capture_id);
CHECK(corruption_bytes > 0 &&
(size_t)corruption_bytes < sizeof(corruption) &&
raw_sql(path, corruption));
CHECK(lardon3d_project_db_open(path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
memcpy(profile_input.name, "focus domain B", sizeof("focus domain B"));
Lardon3DOpticalCalibrationProfile profile_b;
CHECK(lardon3d_optical_calibration_profile_create(
database, &profile_input, &profile_b) == LARDON3D_PROJECT_DB_OK);
Lardon3DOpticalCalibrationApplicabilityV2 applicability_b;
CHECK(lardon3d_optical_calibration_applicability_v2_create(
database, profile_b.calibration_profile_id, fixture.capture_id,
&applicability_b) == LARDON3D_PROJECT_DB_OK);
evidence[0] = 0x72;
const char *overlap_tokens[] = {"synthetic-focus-b"};
Lardon3DOpticalFocusDomainV2 domain_b;
CHECK(lardon3d_optical_focus_domain_v2_create(
database, applicability_b.applicability_id, 1, evidence,
overlap_tokens, 1, &domain_b) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_calibration_resolve_v2(
database, targets[0].capture_id, &resolution) ==
LARDON3D_PROJECT_DB_OK &&
resolution.kind == LARDON3D_OPTICAL_CALIBRATION_SELECTION_REQUIRED);
CHECK(lardon3d_optical_capture_calibration_select_v2(
database, targets[0].capture_id,
applicability_a.applicability_id) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_optical_capture_calibration_select_v2(
database, targets[0].capture_id,
applicability_a.applicability_id) == LARDON3D_PROJECT_DB_OK);
lardon3d_project_db_close(database);
/* v26 contains observations but no retained physical-domain evidence. The
additive migration must recreate empty domain tables without inference. */
CHECK(raw_sql(path, "PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
"DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"UPDATE metadata SET value=26 WHERE key='schema_version';"
"COMMIT;"));
database = NULL;
CHECK(lardon3d_project_db_open(path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
lardon3d_project_db_close(database);
sqlite3_int64 count = -1;
CHECK(raw_integer(path, "SELECT COUNT(*) FROM optical_focus_domains_v2",
&count) &&
count == 0);
CHECK(raw_integer(path,
"SELECT COUNT(*) FROM optical_focus_domain_tokens_v2",
&count) &&
count == 0);
CHECK(unlink(path) == 0);
CHECK(rmdir(directory) == 0);
return true;
}
static bool test_migration_rollback_retry_and_equivalence(void) { static bool test_migration_rollback_retry_and_equivalence(void) {
char migrated_directory[64]; char migrated_directory[64];
char migrated_path[256]; char migrated_path[256];
@ -1507,6 +1801,8 @@ static bool test_migration_rollback_retry_and_equivalence(void) {
"capture_geometric_states", "capture_geometric_states",
"optical_calibration_applicabilities_v2", "optical_calibration_applicabilities_v2",
"capture_calibration_selections_v2", "capture_calibration_selections_v2",
"optical_focus_domains_v2",
"optical_focus_domain_tokens_v2",
}; };
char query[256]; char query[256];
for (size_t index = 0; index < sizeof(empty_tables) / sizeof(empty_tables[0]); for (size_t index = 0; index < sizeof(empty_tables) / sizeof(empty_tables[0]);
@ -1543,6 +1839,9 @@ static bool test_migration_rollback_retry_and_equivalence(void) {
"optical_calibration_applicabilities_v2", "optical_calibration_applicabilities_v2",
"optical_calibration_applicabilities_v2_config_idx", "optical_calibration_applicabilities_v2_config_idx",
"capture_calibration_selections_v2", "capture_calibration_selections_v2",
"optical_focus_domains_v2",
"optical_focus_domain_tokens_v2",
"optical_focus_domain_tokens_v2_token_idx",
}; };
char migrated_sql[8192]; char migrated_sql[8192];
char fresh_sql[8192]; char fresh_sql[8192];
@ -1564,6 +1863,7 @@ static bool test_migration_rollback_retry_and_equivalence(void) {
int main(void) { int main(void) {
return test_profiles_assignments_and_calibrations() && return test_profiles_assignments_and_calibrations() &&
test_v26_exact_geometric_applicability() && test_v26_exact_geometric_applicability() &&
test_v27_discrete_focus_domains() &&
test_calibration_conflict_result_contract() && test_calibration_conflict_result_contract() &&
test_calibration_dependency_corruption_precedence() && test_calibration_dependency_corruption_precedence() &&
test_campaign_request_corruption_prevents_optics_mutation() && test_campaign_request_corruption_prevents_optics_mutation() &&

View file

@ -22,9 +22,14 @@
} while (0) } while (0)
/* Historical migration fixtures are produced from a temporary current DB. /* Historical migration fixtures are produced from a temporary current DB.
* Remove every additive v23/v24/v25 object first so the fixture really is historical * Remove every additive v23..v27 object first so the fixture really is
* rather than a lower version number with future tables left behind. */ * historical rather than a lower version number with future tables left behind. */
#define DROP_OPTICAL_V23_SQL \ #define DROP_OPTICAL_V23_SQL \
"DROP TABLE IF EXISTS optical_focus_domain_tokens_v2;" \
"DROP TABLE IF EXISTS optical_focus_domains_v2;" \
"DROP TABLE IF EXISTS capture_calibration_selections_v2;" \
"DROP TABLE IF EXISTS optical_calibration_applicabilities_v2;" \
"DROP TABLE IF EXISTS capture_geometric_states;" \
"DROP TABLE IF EXISTS feature_extract_batch_tasks;" \ "DROP TABLE IF EXISTS feature_extract_batch_tasks;" \
"DROP TABLE IF EXISTS raw_development_batch_tasks;" \ "DROP TABLE IF EXISTS raw_development_batch_tasks;" \
"DROP TABLE IF EXISTS capture_calibration_selections;" \ "DROP TABLE IF EXISTS capture_calibration_selections;" \
@ -129,12 +134,12 @@ static bool create_future_database(const char *path) {
if (sqlite3_open(path, &connection) != SQLITE_OK) { if (sqlite3_open(path, &connection) != SQLITE_OK) {
return false; return false;
} }
bool ok = char *sql = sqlite3_mprintf(
sqlite3_exec(
connection,
"CREATE TABLE metadata(key TEXT PRIMARY KEY,value INTEGER NOT NULL);" "CREATE TABLE metadata(key TEXT PRIMARY KEY,value INTEGER NOT NULL);"
"INSERT INTO metadata VALUES('schema_version',26);", "INSERT INTO metadata VALUES('schema_version',%u);",
NULL, NULL, NULL) == SQLITE_OK; LARDON3D_PROJECT_DB_SCHEMA_VERSION + 1U);
bool ok = sql && sqlite3_exec(connection, sql, NULL, NULL, NULL) == SQLITE_OK;
sqlite3_free(sql);
return sqlite3_close(connection) == SQLITE_OK && ok; return sqlite3_close(connection) == SQLITE_OK && ok;
} }
@ -963,12 +968,18 @@ static bool run_test(void) {
char error[LARDON3D_PROJECT_DB_ERROR_CAPACITY]; char error[LARDON3D_PROJECT_DB_ERROR_CAPACITY];
Lardon3DProjectDb *database = NULL; Lardon3DProjectDb *database = NULL;
/* v25 is DDL-only: an injected failure rolls back table and marker, and a /* Remove later empty overlays to form a true v24 fixture. The v25 injected
* retry creates no fabricated association or historical cursor. */ * failure must roll back its table/marker, and retry through current head
* creates no fabricated association, observation, domain, or cursor. */
CHECK(lardon3d_project_db_open(v24_path, &database, error) == LARDON3D_PROJECT_DB_OK); CHECK(lardon3d_project_db_open(v24_path, &database, error) == LARDON3D_PROJECT_DB_OK);
lardon3d_project_db_close(database); lardon3d_project_db_close(database);
database = NULL; database = NULL;
CHECK(execute_test_sql(v24_path, CHECK(execute_test_sql(v24_path,
"DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"DROP TABLE capture_calibration_selections_v2;"
"DROP TABLE optical_calibration_applicabilities_v2;"
"DROP TABLE capture_geometric_states;"
"DROP TABLE feature_extract_batch_tasks;" "DROP TABLE feature_extract_batch_tasks;"
"UPDATE metadata SET value=24 WHERE key='schema_version';")); "UPDATE metadata SET value=24 WHERE key='schema_version';"));
CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V25", "1", 1) == 0); CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V25", "1", 1) == 0);
@ -987,6 +998,26 @@ static bool run_test(void) {
lardon3d_project_db_close(database); lardon3d_project_db_close(database);
database = NULL; database = NULL;
CHECK(query_integer(v24_path, "SELECT count(*) FROM feature_extract_batch_tasks", 0)); CHECK(query_integer(v24_path, "SELECT count(*) FROM feature_extract_batch_tasks", 0));
CHECK(execute_test_sql(v24_path,
"DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"UPDATE metadata SET value=26 WHERE key='schema_version';"));
CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V27", "1", 1) == 0);
CHECK(lardon3d_project_db_open(v24_path, &database, error) !=
LARDON3D_PROJECT_DB_OK);
CHECK(database == NULL);
CHECK(unsetenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V27") == 0);
CHECK(query_integer(v24_path,
"SELECT value FROM metadata WHERE key='schema_version'", 26));
CHECK(query_integer(v24_path,
"SELECT count(*) FROM sqlite_master WHERE type='table' AND name IN "
"('optical_focus_domains_v2','optical_focus_domain_tokens_v2')", 0));
CHECK(lardon3d_project_db_open(v24_path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_schema_version(database) ==
LARDON3D_PROJECT_DB_SCHEMA_VERSION);
lardon3d_project_db_close(database);
database = NULL;
CHECK(lardon3d_project_db_open(database_path, &database, error) == CHECK(lardon3d_project_db_open(database_path, &database, error) ==
LARDON3D_PROJECT_DB_OK); LARDON3D_PROJECT_DB_OK);
CHECK(database && lardon3d_project_db_schema_version(database) == CHECK(database && lardon3d_project_db_schema_version(database) ==

View file

@ -64,6 +64,11 @@ static bool seed_v21(const char *path) {
"INSERT INTO sparse_calibration_scope_images VALUES(1,1,1);" "INSERT INTO sparse_calibration_scope_images VALUES(1,1,1);"
/* This fixture is a true v21 database; future additive objects must not /* This fixture is a true v21 database; future additive objects must not
remain merely because it was generated from a temporary current DB. */ remain merely because it was generated from a temporary current DB. */
"DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"DROP TABLE capture_calibration_selections_v2;"
"DROP TABLE optical_calibration_applicabilities_v2;"
"DROP TABLE capture_geometric_states;"
"DROP TABLE feature_extract_batch_tasks;" "DROP TABLE feature_extract_batch_tasks;"
"DROP TABLE raw_development_batch_tasks;" "DROP TABLE raw_development_batch_tasks;"
"DROP TABLE capture_calibration_selections;" "DROP TABLE capture_calibration_selections;"
@ -110,7 +115,12 @@ static bool run(void) {
CHECK(sql(path, "SELECT 1 FROM raw_development_batch_tasks WHERE 0;")); CHECK(sql(path, "SELECT 1 FROM raw_development_batch_tasks WHERE 0;"));
lardon3d_project_db_close(database); lardon3d_project_db_close(database);
database = NULL; database = NULL;
CHECK(sql(path, "DROP TABLE feature_extract_batch_tasks;" CHECK(sql(path, "DROP TABLE optical_focus_domain_tokens_v2;"
"DROP TABLE optical_focus_domains_v2;"
"DROP TABLE capture_calibration_selections_v2;"
"DROP TABLE optical_calibration_applicabilities_v2;"
"DROP TABLE capture_geometric_states;"
"DROP TABLE feature_extract_batch_tasks;"
"DROP TABLE raw_development_batch_tasks;" "DROP TABLE raw_development_batch_tasks;"
"UPDATE metadata SET value=23 WHERE key='schema_version';")); "UPDATE metadata SET value=23 WHERE key='schema_version';"));
CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V24", "1", 1) == 0); CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V24", "1", 1) == 0);