feat: add calibration v2 autofocus foundation
This commit is contained in:
parent
038cc64032
commit
34c6a82b35
22 changed files with 903 additions and 82 deletions
12
AGENTS.md
12
AGENTS.md
|
|
@ -81,13 +81,19 @@ Detailed subcontracts remain defined by their canonical documents. This file
|
|||
must not duplicate every S3 substage, scientific threshold, migration detail,
|
||||
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
|
||||
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
|
||||
its retained real A6000 proof. Historical references to older Project DB versions remain valid where
|
||||
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/
|
||||
concurrency validation and independent final review are acquired. Its lifecycle
|
||||
is `GLOBAL_MAINTENANCE_AUDIT=PASS/FROZEN`. The review independently passed the
|
||||
|
|
@ -802,7 +808,7 @@ For Project DB:
|
|||
must not reinterpret scientific history;
|
||||
- v25 is the additive Feature-batch migration for `features.extract.batch/1` and
|
||||
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;
|
||||
- migrations must be additive unless a different migration is explicitly
|
||||
authorized;
|
||||
|
|
@ -1020,7 +1026,7 @@ Every completed ticket report must include:
|
|||
STOP and request a human decision only when resolution requires:
|
||||
|
||||
- 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;
|
||||
- introducing a genuinely new subsystem outside authorized scope;
|
||||
- files outside the authorized scope;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ progressive observations and constraints
|
|||
|
||||
### Current Project Database
|
||||
|
||||
The current Project DB schema is **v26**.
|
||||
The current Project DB schema is **v27**.
|
||||
|
||||
The current head is additive:
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ v23 Generic optical-context overlay
|
|||
v24 raw.develop.batch/1 persistence
|
||||
v25 features.extract.batch/1 persistence
|
||||
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.
|
||||
|
|
@ -121,7 +122,7 @@ The following major foundations are implemented and validated at their documente
|
|||
- **Calibration Solver Preflight v1 — PASS**
|
||||
- **Calibration Evidence Solver v1 — IMPLEMENTED / VALIDATED**
|
||||
- **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
|
||||
- features.extract.batch/1 durable selected-execution path
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
```text
|
||||
DOCUMENTATION_INDEX=CURRENT
|
||||
CURRENT_PROJECT_DB_SCHEMA=v26
|
||||
CURRENT_PROJECT_DB_SCHEMA=v27
|
||||
CURRENT_PRODUCTION_TASK_KINDS=16
|
||||
|
||||
REAL_S21_TRACKS=PASS/FROZEN
|
||||
REAL_A6000_PRE_SFM=PASS/FROZEN
|
||||
PRODUCT_DEFINITION_V1=PASS/FROZEN
|
||||
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.
|
||||
|
|
@ -35,7 +35,7 @@ quote an exact API, DDL or constant.
|
|||
## Current repository state
|
||||
|
||||
```text
|
||||
Project DB head v26
|
||||
Project DB head v27
|
||||
Production Task kinds 16
|
||||
|
||||
v22 selected scientific execution foundation
|
||||
|
|
@ -43,6 +43,7 @@ v23 generic optical-context overlay
|
|||
v24 raw.develop.batch/1 persistence
|
||||
v25 features.extract.batch/1 persistence
|
||||
v26 Capture geometric state/applicability
|
||||
v27 generic bounded exact-token focus domains
|
||||
```
|
||||
|
||||
Canonical resource objective:
|
||||
|
|
|
|||
|
|
@ -265,6 +265,36 @@ Historical EXIF/MakerNote values such as Sony `FocusPosition2` or derived
|
|||
`FocusDistance2` may inform experiment design. They are not by themselves
|
||||
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
|
||||
|
||||
If one calibration is not valid across the complete autofocus range, v2 may
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
```text
|
||||
CURRENT_PROJECT_DB_SCHEMA=v26
|
||||
CURRENT_PROJECT_DB_SCHEMA=v27
|
||||
```
|
||||
|
||||
The current head is additive:
|
||||
|
|
@ -18,10 +18,11 @@ v23 Generic optical-context overlay IMPLEMENTED / VALI
|
|||
v24 raw.develop.batch/1 persistence IMPLEMENTED / VALIDATED
|
||||
v25 features.extract.batch/1 persistence IMPLEMENTED / VALIDATED
|
||||
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
|
||||
migration from v22 through v26 backfills scientific identity, infers camera/lens identity, invents
|
||||
Project DB v27 preserves the scientific and persistence meaning of every earlier retained row. No
|
||||
migration from v22 through v27 backfills scientific identity, infers camera/lens identity, invents
|
||||
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
|
||||
|
|
@ -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
|
||||
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
|
||||
|
||||
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
|
||||
v24 -> v25 selected Feature-batch Task persistence
|
||||
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.
|
||||
|
|
@ -900,9 +933,9 @@ An older version number is not stale when the text explicitly describes historic
|
|||
|
||||
## 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,
|
||||
leaving the prior version complete and retryable.
|
||||
|
||||
|
|
@ -913,7 +946,7 @@ The implementation rejects:
|
|||
- impossible version/storage-class combinations;
|
||||
- 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.
|
||||
|
||||
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;
|
||||
- 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.
|
||||
- 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
|
||||
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
|
||||
|
||||
```text
|
||||
CURRENT_PROJECT_DB_SCHEMA=v26
|
||||
CURRENT_PROJECT_DB_SCHEMA=v27
|
||||
|
||||
v22 selected scientific execution foundation PASS/FROZEN
|
||||
v23 generic optical-context overlay IMPLEMENTED/VALIDATED/REVIEWED
|
||||
v24 raw.develop.batch/1 persistence IMPLEMENTED/VALIDATED
|
||||
v25 features.extract.batch/1 persistence IMPLEMENTED/VALIDATED
|
||||
v26 Capture geometric state/applicability PASS/FROZEN
|
||||
v27 generic exact-token focus domains PASS/FROZEN
|
||||
|
||||
REAL_S21_TRACKS PASS/FROZEN
|
||||
REAL_A6000_PRE_SFM PASS/FROZEN
|
||||
```
|
||||
|
||||
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,
|
||||
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;
|
||||
- persists active Resource Governor reservations.
|
||||
|
||||
Future schema changes beyond v26 require explicit human authorization.
|
||||
Future schema changes beyond v27 require explicit human authorization.
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ This document may freeze a product requirement while its implementation remains
|
|||
The following existing boundaries are consumed as-is:
|
||||
|
||||
```text
|
||||
Project DB head v26
|
||||
Project DB head v27
|
||||
Production Task kinds 16
|
||||
Capture / Asset Provenance PASS/FROZEN
|
||||
Acquisition / campaign execution PASS/FROZEN
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ It must not be used to reinterpret FROZEN scientific evidence.
|
|||
## Current repository state
|
||||
|
||||
```text
|
||||
Project DB current schema v26
|
||||
Project DB current schema v27
|
||||
Production Task kinds 16
|
||||
GLOBAL_MAINTENANCE_AUDIT PASS/FROZEN
|
||||
REAL_S21_TRACKS PASS/FROZEN
|
||||
|
|
@ -24,7 +24,7 @@ SOURCE_COMMENT_AUDIT PASS
|
|||
PRODUCT_DEFINITION PASS/FROZEN
|
||||
PROMPT_TREE CURRENT
|
||||
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:
|
||||
|
|
@ -35,6 +35,7 @@ v23 generic optical-context overlay
|
|||
v24 raw.develop.batch/1 persistence
|
||||
v25 features.extract.batch/1 persistence
|
||||
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
|
||||
|
|
@ -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
|
||||
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
|
||||
dependency is the generic adaptive-settings/autofocus foundation. Device-specific autofocus envelopes
|
||||
remain blocked until physical evidence validates them.
|
||||
dependency is physical autofocus/optical applicability validation and a dedicated calibrated real
|
||||
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
|
||||
contract and produces deterministic `L3DCALB1` v1.
|
||||
|
|
@ -934,12 +937,16 @@ SOURCE_COMMENT_AUDIT PASS
|
|||
SOURCE_COMMENT_REMEDIATION PASS
|
||||
PRODUCT_DEFINITION_V1 PASS/FROZEN
|
||||
PROMPT_TREE CURRENT
|
||||
CALIBRATION_EVIDENCE_SOLVER_V1 IMPLEMENTED/VALIDATED
|
||||
CALIBRATION_TOOLING_ALIGNMENT PASS/FROZEN
|
||||
CURRENT_NEXT DEDICATED_PHYSICAL_CALIBRATED_REAL_CAMPAIGN
|
||||
CALIBRATION_SCIENCE_V2 PASS/FROZEN
|
||||
CALIBRATION_V2_HETEROGENEOUS_OPTICS PASS/FROZEN
|
||||
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
|
||||
numbered `prompt/` execution contract. The current authorized dependency is the final usable
|
||||
calibration workflow; its next missing sub-boundary composes the FROZEN Tooling
|
||||
and Bootstrap importer to reach truthful READY from the validated binding.
|
||||
numbered `prompt/` execution contract. The current dependency is physical autofocus/optical
|
||||
applicability validation for real equipment, followed by a dedicated calibrated real campaign.
|
||||
Generic autofocus applicability machinery is available, but the real
|
||||
A6000 + E PZ 16-50 autofocus applicability remains blocked until physical evidence validates it.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ enum {
|
|||
LARDON3D_OPTICAL_TEXT_CAPACITY = 128,
|
||||
LARDON3D_OPTICAL_PROVENANCE_CAPACITY = 256,
|
||||
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 {
|
||||
|
|
@ -171,6 +175,19 @@ typedef struct {
|
|||
uint64_t exemplar_capture_id;
|
||||
} 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 {
|
||||
Lardon3DOpticalCalibrationResolutionKind kind;
|
||||
uint64_t applicability_id;
|
||||
|
|
@ -333,15 +350,35 @@ Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create(
|
|||
uint64_t exemplar_capture_id,
|
||||
Lardon3DOpticalCalibrationApplicabilityV2 *output);
|
||||
|
||||
/* Resolution counts exact valid applicability rows. NONE is CALIBRATION_REQUIRED,
|
||||
* ONE is RESOLVED, and MANY is SELECTION_REQUIRED. All are successful outcomes. */
|
||||
/* Attach one physically validated discrete focus domain to an existing exact
|
||||
* 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(
|
||||
Lardon3DProjectDb *database, uint64_t capture_id,
|
||||
Lardon3DOpticalCalibrationResolutionV2 *output);
|
||||
/* Selection requires a complete observed geometric-state tuple and an exactly
|
||||
* compatible applicability; UNKNOWN in any geometry-relevant field is a
|
||||
* CONSTRAINT. The first selection is immutable, exact retry is idempotent, and
|
||||
* a conflicting applicability is rejected without changing the selection. */
|
||||
/* Selection requires a complete observed geometric-state tuple and an
|
||||
* applicability currently eligible by exact v26 match or exact v27 domain
|
||||
* membership; UNKNOWN in any geometry-relevant field is a CONSTRAINT. The
|
||||
* 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(
|
||||
Lardon3DProjectDb *database, uint64_t capture_id, uint64_t applicability_id);
|
||||
/* Loads the Capture's durable v2 selection without creating or changing it.
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
#include <lardon3d/sparse_sfm_incremental.h>
|
||||
|
||||
enum {
|
||||
/* v26 additively stores Capture-owned observed geometric state and exact
|
||||
* calibration applicability. Migration does not infer state from v23
|
||||
* configuration or historical calibration selections. */
|
||||
LARDON3D_PROJECT_DB_SCHEMA_VERSION = 26,
|
||||
/* v27 additively stores validated focus domains as bounded sets of exact
|
||||
* observed tokens attached to v26 applicability. Migration creates no
|
||||
* domain or token from historical geometric state. */
|
||||
LARDON3D_PROJECT_DB_SCHEMA_VERSION = 27,
|
||||
LARDON3D_PROJECT_DB_ID_CAPACITY = 65,
|
||||
LARDON3D_PROJECT_DB_KIND_CAPACITY = 65,
|
||||
LARDON3D_PROJECT_DB_PATH_CAPACITY = 4096,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
```text
|
||||
CURRENT_PROJECT_DB_SCHEMA=v26
|
||||
CURRENT_PROJECT_DB_SCHEMA=v27
|
||||
PRODUCTION_TASK_KINDS=16
|
||||
PRODUCT_DEFINITION_V1=PASS/FROZEN
|
||||
PROMPT_TREE=NEXT
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
## Status
|
||||
|
||||
```text
|
||||
CURRENT_PROJECT_DB_SCHEMA=v26
|
||||
CURRENT_PROJECT_DB_SCHEMA=v27
|
||||
PRODUCTION_TASK_KINDS=16
|
||||
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
|
||||
|
|
@ -16,7 +16,7 @@ CURRENT_IMPLEMENTATION_CURSOR=ADAPTIVE_CAPTURE_SETTINGS_AND_AUTOFOCUS_V2_FOUNDAT
|
|||
## CURRENT
|
||||
|
||||
```text
|
||||
Project DB head v26
|
||||
Project DB head v27
|
||||
Production Task kinds 16
|
||||
Feature Store IMPLEMENTED
|
||||
Visual Index IMPLEMENTED
|
||||
|
|
@ -39,8 +39,8 @@ Calibration Science v2 heterogeneous optics PASS/FROZEN
|
|||
Calibration v2 optical-state foundation PASS/FROZEN
|
||||
Calibration v2 heterogeneous publication PASS/FROZEN
|
||||
Calibration Workflow v2 PASS/FROZEN
|
||||
Adaptive capture settings semantics PLANNED
|
||||
Autofocus v2 foundation PLANNED
|
||||
Adaptive capture settings semantics PASS/FROZEN
|
||||
Autofocus v2 foundation PASS/FROZEN
|
||||
Calibration Tooling planarity alignment PASS/FROZEN
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ CALIBRATION_SCIENCE_V2=PASS/FROZEN
|
|||
CALIBRATION_V2_HETEROGENEOUS_OPTICS=PASS/FROZEN
|
||||
CALIBRATION_V2_HETEROGENEOUS_CALIBRATION_PUBLICATION=PASS/FROZEN
|
||||
CALIBRATION_V2_WORKFLOW_READY=PASS/FROZEN
|
||||
ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PLANNED
|
||||
AUTOFOCUS_V2_FOUNDATION=PLANNED
|
||||
CURRENT_CALIBRATION_NEXT=AUTOFOCUS_V2_FOUNDATION
|
||||
ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PASS/FROZEN
|
||||
AUTOFOCUS_V2_FOUNDATION=PASS/FROZEN
|
||||
CURRENT_CALIBRATION_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
|
||||
```
|
||||
|
||||
## Authority
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
IMPLEMENTATION_ORDER=DEPENDENCY_DRIVEN
|
||||
IMPLEMENTATION_AUTHORIZATION=NO
|
||||
STEP_0_USER_FACING_LANGUAGE_NORMALIZATION=PASS
|
||||
CURRENT_NEXT=AUTOFOCUS_V2_FOUNDATION
|
||||
CURRENT_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
|
||||
```
|
||||
|
||||
## Authority
|
||||
|
|
@ -25,8 +25,8 @@ Default dependency order:
|
|||
3. Calibration v2 heterogeneous-optics persistence foundation — PASS/FROZEN;
|
||||
4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN;
|
||||
5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN;
|
||||
6. Adaptive capture settings / generic autofocus foundation — CURRENT;
|
||||
7. physical autofocus/optical applicability validation and dedicated calibrated real campaign;
|
||||
6. Adaptive capture settings / generic autofocus foundation — PASS/FROZEN;
|
||||
7. physical autofocus/optical applicability validation and dedicated calibrated real campaign — CURRENT;
|
||||
8. real Sparse SfM proof;
|
||||
9. durable Dense/OpenMVS orchestration;
|
||||
10. mesh / refinement / texturing / export;
|
||||
|
|
|
|||
|
|
@ -2338,6 +2338,21 @@ static const char exact_state_predicate[] =
|
|||
"t.decoded_geometry_state=e.decoded_geometry_state AND "
|
||||
"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(
|
||||
Lardon3DProjectDb *database, uint64_t calibration_profile_id,
|
||||
uint64_t exemplar_capture_id,
|
||||
|
|
@ -2429,8 +2444,230 @@ Lardon3DProjectDbResult lardon3d_optical_calibration_applicability_v2_create(
|
|||
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
|
||||
exact_candidates_locked(Lardon3DProjectDb *database, uint64_t capture_id,
|
||||
applicability_candidates_locked(Lardon3DProjectDb *database,
|
||||
uint64_t capture_id,
|
||||
uint64_t required_applicability,
|
||||
Lardon3DOpticalCalibrationResolutionV2 *output,
|
||||
size_t *count) {
|
||||
|
|
@ -2461,13 +2698,58 @@ exact_candidates_locked(Lardon3DProjectDb *database, uint64_t capture_id,
|
|||
(void)sqlite3_finalize(validation);
|
||||
if (result != LARDON3D_PROJECT_DB_OK)
|
||||
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(
|
||||
query, sizeof(query),
|
||||
"SELECT "
|
||||
"a.applicability_id,a.calibration_profile_id,p.sparse_calibration_id "
|
||||
"FROM capture_geometric_states t JOIN "
|
||||
"SELECT applicability_id,calibration_profile_id,sparse_calibration_id "
|
||||
"FROM (SELECT a.applicability_id AS applicability_id,"
|
||||
"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 "
|
||||
"a.optical_configuration_id=t.optical_configuration_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.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 %s%s ORDER BY a.applicability_id LIMIT 2",
|
||||
exact_state_predicate,
|
||||
required_applicability ? " AND a.applicability_id=?2" : "");
|
||||
"t.capture_id=?1 AND %s UNION SELECT a.applicability_id,"
|
||||
"a.calibration_profile_id,p.sparse_calibration_id FROM "
|
||||
"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;
|
||||
result = length < 0 || (size_t)length >= sizeof(query)
|
||||
? LARDON3D_PROJECT_DB_IO_ERROR
|
||||
: prepare(database, query, &statement);
|
||||
if (result == LARDON3D_PROJECT_DB_OK) {
|
||||
sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
|
||||
if (required_applicability)
|
||||
sqlite3_bind_int64(statement, 2, (sqlite3_int64)required_applicability);
|
||||
int code;
|
||||
*count = 0;
|
||||
|
|
@ -2556,7 +2850,8 @@ Lardon3DProjectDbResult lardon3d_optical_capture_calibration_resolve_v2(
|
|||
return result;
|
||||
(void)pthread_mutex_lock(&database->mutex);
|
||||
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);
|
||||
if (result != LARDON3D_PROJECT_DB_OK) {
|
||||
memset(output, 0, sizeof(*output));
|
||||
|
|
@ -2585,8 +2880,9 @@ lardon3d_optical_capture_calibration_select_v2(Lardon3DProjectDb *database,
|
|||
Lardon3DProjectDbResult result = execute(
|
||||
database, "BEGIN IMMEDIATE", "begin Capture calibration selection v2");
|
||||
if (result == LARDON3D_PROJECT_DB_OK)
|
||||
result = exact_candidates_locked(database, capture_id, applicability_id,
|
||||
&candidate, &count);
|
||||
result = applicability_candidates_locked(database, capture_id,
|
||||
applicability_id, &candidate,
|
||||
&count);
|
||||
if (result == LARDON3D_PROJECT_DB_OK && count != 1)
|
||||
result = LARDON3D_PROJECT_DB_CONSTRAINT;
|
||||
Lardon3DOpticalCaptureGeometricState state = {0};
|
||||
|
|
@ -2688,7 +2984,7 @@ Lardon3DProjectDbResult lardon3d_optical_capture_calibration_selection_load_v2(
|
|||
if (result == LARDON3D_PROJECT_DB_OK) {
|
||||
Lardon3DOpticalCalibrationResolutionV2 candidate = {0};
|
||||
size_t count = 0;
|
||||
result = exact_candidates_locked(
|
||||
result = applicability_candidates_locked(
|
||||
database, capture_id, output->applicability_id, &candidate, &count);
|
||||
if (result == LARDON3D_PROJECT_DB_OK &&
|
||||
(count != 1 ||
|
||||
|
|
|
|||
|
|
@ -960,6 +960,29 @@ static const char schema_optical_geometric_state_v26[] =
|
|||
"optical_calibration_applicabilities_v2(applicability_id,calibration_"
|
||||
"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) {
|
||||
if (destination) {
|
||||
(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 != 15 && from_version != 16 && from_version != 17 && from_version != 18 &&
|
||||
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;
|
||||
}
|
||||
Lardon3DProjectDbResult result = execute(database, "BEGIN IMMEDIATE", "begin migration");
|
||||
|
|
@ -1579,6 +1603,27 @@ static Lardon3DProjectDbResult migrate(Lardon3DProjectDb *database, unsigned int
|
|||
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) {
|
||||
result = execute(database, "COMMIT", "commit migration");
|
||||
}
|
||||
|
|
@ -1736,7 +1781,9 @@ Lardon3DProjectDbResult lardon3d_project_db_open(const char *path, Lardon3DProje
|
|||
"capture_calibration_selections"};
|
||||
const char *required_v26[] = {"capture_geometric_states",
|
||||
"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]) &&
|
||||
result == LARDON3D_PROJECT_DB_OK;
|
||||
++index) {
|
||||
|
|
@ -1751,7 +1798,7 @@ Lardon3DProjectDbResult lardon3d_project_db_open(const char *path, Lardon3DProje
|
|||
++index) {
|
||||
if (!table_exists(database->connection, required_v26[index])) {
|
||||
copy_error(database->error,
|
||||
"Current Project DB v26 schema is incomplete.");
|
||||
"Current Project DB v27 optical schema is incomplete.");
|
||||
result = LARDON3D_PROJECT_DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,11 @@ static bool create_v11_database(const char *path) {
|
|||
lardon3d_project_db_close(database);
|
||||
return execute_sql(path,
|
||||
"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 raw_development_batch_tasks;"
|
||||
"DROP TABLE IF EXISTS capture_calibration_selections;"
|
||||
|
|
|
|||
|
|
@ -878,6 +878,11 @@ static bool run_task_test(void) {
|
|||
CHECK(exec_sql(
|
||||
database_path,
|
||||
"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 raw_development_batch_tasks;"
|
||||
"DROP TABLE IF EXISTS capture_calibration_selections;"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,12 @@ static bool create_v9_database(const char *path) {
|
|||
static const char sql[] =
|
||||
"PRAGMA foreign_keys=OFF;BEGIN IMMEDIATE;"
|
||||
/* 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 raw_development_batch_tasks;"
|
||||
"DROP TABLE IF EXISTS capture_calibration_selections;"
|
||||
|
|
|
|||
|
|
@ -360,6 +360,11 @@ static bool downgrade_project_to_historical_v10(const char *database_path) {
|
|||
}
|
||||
static const char sql[] =
|
||||
"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 raw_development_batch_tasks;"
|
||||
"DROP TABLE IF EXISTS selected_execution_items;"
|
||||
|
|
|
|||
|
|
@ -1147,6 +1147,8 @@ static bool downgrade_to_v22_fixture(const char *path) {
|
|||
return raw_sql(
|
||||
path,
|
||||
"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;"
|
||||
|
|
@ -1407,6 +1409,8 @@ static bool test_v26_exact_geometric_applicability(void) {
|
|||
*/
|
||||
CHECK(raw_sql(
|
||||
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 optical_calibration_applicabilities_v2;"
|
||||
"DROP TABLE capture_geometric_states;"
|
||||
|
|
@ -1432,6 +1436,296 @@ static bool test_v26_exact_geometric_applicability(void) {
|
|||
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) {
|
||||
char migrated_directory[64];
|
||||
char migrated_path[256];
|
||||
|
|
@ -1507,6 +1801,8 @@ static bool test_migration_rollback_retry_and_equivalence(void) {
|
|||
"capture_geometric_states",
|
||||
"optical_calibration_applicabilities_v2",
|
||||
"capture_calibration_selections_v2",
|
||||
"optical_focus_domains_v2",
|
||||
"optical_focus_domain_tokens_v2",
|
||||
};
|
||||
char query[256];
|
||||
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_config_idx",
|
||||
"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 fresh_sql[8192];
|
||||
|
|
@ -1564,6 +1863,7 @@ static bool test_migration_rollback_retry_and_equivalence(void) {
|
|||
int main(void) {
|
||||
return test_profiles_assignments_and_calibrations() &&
|
||||
test_v26_exact_geometric_applicability() &&
|
||||
test_v27_discrete_focus_domains() &&
|
||||
test_calibration_conflict_result_contract() &&
|
||||
test_calibration_dependency_corruption_precedence() &&
|
||||
test_campaign_request_corruption_prevents_optics_mutation() &&
|
||||
|
|
|
|||
|
|
@ -22,9 +22,14 @@
|
|||
} while (0)
|
||||
|
||||
/* Historical migration fixtures are produced from a temporary current DB.
|
||||
* Remove every additive v23/v24/v25 object first so the fixture really is historical
|
||||
* rather than a lower version number with future tables left behind. */
|
||||
* Remove every additive v23..v27 object first so the fixture really is
|
||||
* historical rather than a lower version number with future tables left behind. */
|
||||
#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 raw_development_batch_tasks;" \
|
||||
"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) {
|
||||
return false;
|
||||
}
|
||||
bool ok =
|
||||
sqlite3_exec(
|
||||
connection,
|
||||
char *sql = sqlite3_mprintf(
|
||||
"CREATE TABLE metadata(key TEXT PRIMARY KEY,value INTEGER NOT NULL);"
|
||||
"INSERT INTO metadata VALUES('schema_version',26);",
|
||||
NULL, NULL, NULL) == SQLITE_OK;
|
||||
"INSERT INTO metadata VALUES('schema_version',%u);",
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -963,12 +968,18 @@ static bool run_test(void) {
|
|||
|
||||
char error[LARDON3D_PROJECT_DB_ERROR_CAPACITY];
|
||||
Lardon3DProjectDb *database = NULL;
|
||||
/* v25 is DDL-only: an injected failure rolls back table and marker, and a
|
||||
* retry creates no fabricated association or historical cursor. */
|
||||
/* Remove later empty overlays to form a true v24 fixture. The v25 injected
|
||||
* 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);
|
||||
lardon3d_project_db_close(database);
|
||||
database = NULL;
|
||||
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;"
|
||||
"UPDATE metadata SET value=24 WHERE key='schema_version';"));
|
||||
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);
|
||||
database = NULL;
|
||||
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) ==
|
||||
LARDON3D_PROJECT_DB_OK);
|
||||
CHECK(database && lardon3d_project_db_schema_version(database) ==
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ static bool seed_v21(const char *path) {
|
|||
"INSERT INTO sparse_calibration_scope_images VALUES(1,1,1);"
|
||||
/* This fixture is a true v21 database; future additive objects must not
|
||||
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 raw_development_batch_tasks;"
|
||||
"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;"));
|
||||
lardon3d_project_db_close(database);
|
||||
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;"
|
||||
"UPDATE metadata SET value=23 WHERE key='schema_version';"));
|
||||
CHECK(setenv("LARDON3D_TEST_PROJECT_DB_FAIL_MIGRATION_V24", "1", 1) == 0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue