Skip to content

Commit 1990bcb

Browse files
committed
feat: publish 0.2.0-dev inspection baseline
Source Dev commit: 1abda6db7e4fb74a411c1e03dd8d44ad7f510607 Public product paths and curated version metadata only; pre-existing original worktree changes remain preserved outside this commit.
1 parent 5426f43 commit 1990bcb

212 files changed

Lines changed: 25223 additions & 5442 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ released; publication state is owned by the release and version policy.
4343
- Added deterministic connected-region detection and metrics with explicit
4444
source-bound masks, Four/Eight connectivity, Workbench evidence, and Runner
4545
golden verification.
46+
- Added bounded 2D height-image alignment over immutable reference and moving
47+
C3D snapshots, with explicit software pose and acceptance evidence.
48+
- Added deterministic rigid-pose preparation from ordered point pairs and
49+
constrained all-correspondence best-fit alignment with residual evidence.
50+
- Added bounded height-field background removal/subtraction and nearest-distance
51+
point-cloud filtering, each with separate derived-output identity and replay
52+
evidence.
53+
- Added selected connected-region component preparation that preserves exact
54+
source-grid cells and missing values in a separate derived raw-height output.
4655
- Added a typed HeightMap integration exchange and consumer smoke path with
4756
explicit acknowledgement, result publication, and Run Record evidence.
4857

OpenVisionLab.ThreeDStudio.slnx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@
1414
<Project Path="src/OpenVisionLab.ThreeD.Viewer/OpenVisionLab.ThreeD.Viewer.csproj" />
1515
<Project Path="src/OpenVisionLab.ThreeDStudio/OpenVisionLab.ThreeDStudio.csproj" />
1616
<Project Path="tests/OpenVisionLab.ThreeD.Data.Tests/OpenVisionLab.ThreeD.Data.Tests.csproj" />
17-
<Project Path="tests/OpenVisionLab.ThreeD.Reporting.Tests/OpenVisionLab.ThreeD.Reporting.Tests.csproj" />
1817
</Solution>

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ This project is maintained using explicit version numbers.
2424

2525
### Recent version history
2626

27-
#### `v0.2.0-dev` (2026-08-27)
28-
29-
- Adds the deterministic 3D integration and connected-region inspection
30-
workflows alongside the existing recipe and evidence loop.
27+
#### `v0.2.0-dev` (2026-08-28)
28+
29+
- Adds deterministic 3D integration, connected-region analysis, height-image
30+
alignment, and rigid-pose preparation workflows.
31+
- Adds bounded background preparation for height fields and identified point
32+
clouds, with explicit derived-output identity and replay evidence.
33+
- Keeps the current development line software-only and does not claim physical
34+
calibration or production metrology.
3135

3236
## Start here
3337

scripts/verify-vision-sdk-package.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ Set-StrictMode -Version Latest
99
$ErrorActionPreference = "Stop"
1010

1111
if ([string]::IsNullOrWhiteSpace($PackagePath)) {
12-
$PackagePath = Join-Path $PSScriptRoot "..\third_party\OpenVisionLabVisionSdk\OpenVisionLab.Vision3D.3.0.1-dev.20260826.domain-mask.1.nupkg"
12+
$PackagePath = Join-Path $PSScriptRoot "..\third_party\OpenVisionLabVisionSdk\OpenVisionLab.Vision3D.3.0.1-dev.20260828.point-cloud-background-filter.1.nupkg"
1313
}
1414

1515
if ([string]::IsNullOrWhiteSpace($ChecksumPath)) {
16-
$ChecksumPath = Join-Path $PSScriptRoot "..\third_party\OpenVisionLabVisionSdk\OpenVisionLab.Vision3D.3.0.1-dev.20260826.domain-mask.1.nupkg.sha256"
16+
$ChecksumPath = Join-Path $PSScriptRoot "..\third_party\OpenVisionLabVisionSdk\OpenVisionLab.Vision3D.3.0.1-dev.20260828.point-cloud-background-filter.1.nupkg.sha256"
1717
}
1818

1919
function Write-VerificationReport {
@@ -84,7 +84,7 @@ try {
8484
$id = [string]$metadata.id
8585
$version = [string]$metadata.version
8686
$sourceCommit = [string]$repository.commit
87-
if ($id -ne "OpenVisionLab.Vision3D" -or $version -ne "3.0.1-dev.20260826.domain-mask.1" -or $sourceCommit -ne "db8b8a281dd028c62fabfc49febcde9b4d345d37") {
87+
if ($id -ne "OpenVisionLab.Vision3D" -or $version -ne "3.0.1-dev.20260828.point-cloud-background-filter.1" -or $sourceCommit -ne "35f1eef6626db710ac18452cd1e729530f2c0f2f") {
8888
throw "OpenVisionLab Vision SDK package metadata mismatch. id=$id version=$version sourceCommit=$sourceCommit"
8989
}
9090

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System.Globalization;
2+
3+
namespace OpenVisionLab.ThreeD.Core;
4+
5+
/// <summary>
6+
/// Stable reason codes for the source-quality gate used by product routing.
7+
/// The gate is deliberately narrower than source identity readiness: tools that
8+
/// own their own selection or typed-artifact contract remain routable when they
9+
/// do not require a complete source grid.
10+
/// </summary>
11+
public enum SourceQualityToolGateReason
12+
{
13+
Allowed,
14+
NotApplicable,
15+
ReportUnavailable,
16+
ReportError,
17+
MissingDiagnostics,
18+
GridDiagnosticsError,
19+
NoValidSamples,
20+
SourceIdentityMismatch
21+
}
22+
23+
public sealed record SourceQualityToolGateResult(
24+
bool IsAllowed,
25+
SourceQualityToolGateReason Reason,
26+
string Detail)
27+
{
28+
public bool IsBlocked => !IsAllowed;
29+
}
30+
31+
public static class SourceQualityToolGate
32+
{
33+
private static readonly HashSet<string> GridQualityTools = new(
34+
[
35+
"filter",
36+
"level-surface",
37+
"remove-outlier-pixels",
38+
"roi-crop",
39+
"completeness-grid"
40+
],
41+
StringComparer.OrdinalIgnoreCase);
42+
43+
public static bool RequiresSourceQuality(string? toolId) =>
44+
toolId is not null && GridQualityTools.Contains(toolId);
45+
46+
public static SourceQualityToolGateResult Evaluate(
47+
string? toolId,
48+
string? inputContract,
49+
SourceQualityReport? report,
50+
string? reportError = null,
51+
string? expectedSourceEntityId = null,
52+
string? expectedSourceContentSha256 = null)
53+
{
54+
if (!RequiresSourceQuality(toolId)
55+
|| !IsRawSourceContract(inputContract))
56+
{
57+
return new(
58+
true,
59+
SourceQualityToolGateReason.NotApplicable,
60+
"Source Quality gate is not required for this typed input route.");
61+
}
62+
63+
if (report is null)
64+
{
65+
return string.IsNullOrWhiteSpace(reportError)
66+
? new(
67+
false,
68+
SourceQualityToolGateReason.ReportUnavailable,
69+
"Source Quality is unavailable; this source route is blocked until the current report is ready.")
70+
: new(
71+
false,
72+
SourceQualityToolGateReason.ReportError,
73+
$"Source Quality failed closed: {reportError.Trim()}");
74+
}
75+
76+
if (!string.IsNullOrWhiteSpace(expectedSourceEntityId)
77+
&& !string.Equals(
78+
expectedSourceEntityId,
79+
report.Source.EntityId,
80+
StringComparison.OrdinalIgnoreCase))
81+
{
82+
return new(
83+
false,
84+
SourceQualityToolGateReason.SourceIdentityMismatch,
85+
$"Source Quality belongs to source '{report.Source.EntityId}', not the current source '{expectedSourceEntityId}'. Reload Source Quality before routing.");
86+
}
87+
88+
if (!string.IsNullOrWhiteSpace(expectedSourceContentSha256)
89+
&& !string.Equals(
90+
expectedSourceContentSha256,
91+
report.Source.ContentSha256,
92+
StringComparison.OrdinalIgnoreCase))
93+
{
94+
return new(
95+
false,
96+
SourceQualityToolGateReason.SourceIdentityMismatch,
97+
"Source Quality content identity does not match the current source binding. Reload Source Quality before routing.");
98+
}
99+
100+
if (report.GridDiagnostics is null)
101+
{
102+
return new(
103+
false,
104+
SourceQualityToolGateReason.MissingDiagnostics,
105+
"Source Quality has no current grid diagnostics; this source route is blocked until diagnostics are available.");
106+
}
107+
108+
var failedCheck = report.GridDiagnostics.Checks.FirstOrDefault(check =>
109+
check.State == SourceQualityGridDiagnosticState.Error);
110+
if (report.GridDiagnostics.State == SourceQualityGridDiagnosticState.Error
111+
|| failedCheck is not null)
112+
{
113+
var detail = failedCheck is null
114+
? "Source Quality grid diagnostics failed."
115+
: $"Source Quality grid diagnostics failed at {failedCheck.Code}: {failedCheck.Message}";
116+
return new(
117+
false,
118+
SourceQualityToolGateReason.GridDiagnosticsError,
119+
detail);
120+
}
121+
122+
if (report.Coverage.ValidSampleCount <= 0)
123+
{
124+
return new(
125+
false,
126+
SourceQualityToolGateReason.NoValidSamples,
127+
"Source Quality reports no valid height samples; this source route is blocked.");
128+
}
129+
130+
return new(
131+
true,
132+
SourceQualityToolGateReason.Allowed,
133+
report.Coverage.MissingSampleCount > 0
134+
? "Source Quality is valid; the tool's declared missing-sample policy remains responsible for the missing mask."
135+
: "Source Quality is valid for this source route.");
136+
}
137+
138+
private static bool IsRawSourceContract(string? inputContract) =>
139+
string.Equals(inputContract, "SourceC3D / RawHeightField", StringComparison.Ordinal)
140+
|| string.Equals(inputContract, "RawHeightField", StringComparison.Ordinal);
141+
}
142+
143+
/// <summary>
144+
/// Numeric before/after evidence for one derived height-field preparation
145+
/// artifact. Outlier evidence is nullable because most preparation tools do not
146+
/// classify outliers; null is reported as not evaluated rather than fabricated as
147+
/// zero.
148+
/// </summary>
149+
public sealed record SourceQualityDelta(
150+
string SourceEntityId,
151+
string SourceContentSha256,
152+
string DerivedEntityId,
153+
string DerivedContentSha256,
154+
string SourceRootSourceSha256,
155+
string DerivedRootSourceSha256,
156+
long BeforeValidSampleCount,
157+
long AfterValidSampleCount,
158+
long BeforeMissingSampleCount,
159+
long AfterMissingSampleCount,
160+
long? DetectedOutlierCount,
161+
string OutlierEvidence)
162+
{
163+
public long ValidSampleDelta => AfterValidSampleCount - BeforeValidSampleCount;
164+
public long MissingSampleDelta => AfterMissingSampleCount - BeforeMissingSampleCount;
165+
166+
public bool SourceIdentityRetained =>
167+
string.Equals(SourceRootSourceSha256, DerivedRootSourceSha256, StringComparison.OrdinalIgnoreCase);
168+
169+
public string Summary => string.Create(
170+
CultureInfo.InvariantCulture,
171+
$"quality delta | valid {FormatSigned(ValidSampleDelta)} | missing {FormatSigned(MissingSampleDelta)} | outliers {FormatOutliers()}");
172+
173+
private string FormatOutliers() => DetectedOutlierCount is { } count
174+
? count.ToString("N0", CultureInfo.InvariantCulture)
175+
: OutlierEvidence;
176+
177+
private static string FormatSigned(long value) => value switch
178+
{
179+
> 0 => $"+{value.ToString("N0", CultureInfo.InvariantCulture)}",
180+
< 0 => value.ToString("N0", CultureInfo.InvariantCulture),
181+
_ => "0"
182+
};
183+
}

src/OpenVisionLab.ThreeD.Core/Contracts/Inspection/C3DCompletenessGridContracts.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,6 @@ public sealed record C3DCompletenessGridMetricOutput(
308308
int PassedCellCount = 0,
309309
int FailedCellCount = 0,
310310
ResultStatus AggregateStatus = ResultStatus.Warning,
311-
IReadOnlyList<C3DCompletenessCellOverlay>? CellOverlays = null);
311+
IReadOnlyList<C3DCompletenessCellOverlay>? CellOverlays = null,
312+
string? InspectionRegionArtifactId = null,
313+
string? InspectionRegionArtifactContentSha256 = null);

0 commit comments

Comments
 (0)