test: close STEP-076 V4 host API audit
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
# STEP-076 — QBIN2 V4 Core Host API 与 RasterArraySource 接线 v2
|
||||||
|
|
||||||
|
状态:完成
|
||||||
|
|
||||||
|
日期:2026-09-13
|
||||||
|
|
||||||
|
## 目标与基线
|
||||||
|
|
||||||
|
- 开始 HEAD:`ae03d8bfd2813eb5e65074db16018e37c7cff1c4`。
|
||||||
|
- 任务开始前检测到 STEP-062 两处已有 dirty,以及历史 untracked/build 输出;均未修改、暂存、提交或清理。
|
||||||
|
- v1 production 接线保持不变;本 v2 只补 V4 Host API public-path 测试证明与任务文档。
|
||||||
|
|
||||||
|
## 完成项
|
||||||
|
|
||||||
|
- [x] 针对 `RejectedDecode`、`RejectedContract`、`RejectedInvalidFieldKey`、`RejectedStaleRevision`,先由公开 `RasterArraySource` API 建立可 resolve 的 V4 Particle projection;每次 reject 后重新 resolve,并验证 content identity、T0/T1 coordinate、U/V selected-plane storage 与 shared validity storage 仍为同一内容身份。
|
||||||
|
- [x] 保留 v1 三个 Source V4 测试,并新增 `RasterArrayV4HostApiRejectsKeepPublicProjectionStable`;该 suite 已为 4 个测试。
|
||||||
|
- [x] clear 测试先通过公开 V3 `submitInitialRuntimeFieldWindow(...)` 和既有离线 fixture 建立 V3 `field/nextField`。`clearEncodedField`、`clearAllEncodedFields` 后均核验 V3 双端 identity/generation/validTime 不变;V4 resolve 按 fail-closed 返回,重新提交 V4 后既有 binding intent 再次 resolve。
|
||||||
|
- [x] 未调用 `clearHostFields()`;原子性证明未访问 V4 `encodedFieldStore` 私有成员或私有 helper。
|
||||||
|
|
||||||
|
## 修改范围
|
||||||
|
|
||||||
|
- `test/source/raster_array_v4_host_api.test.cpp`
|
||||||
|
- 本 Step、完成报告与 `粒子开发记录.md`
|
||||||
|
- 未修改 production API、Renderer/shader、JNI、Android/RN/Test Host、QBIN decoder 或 Field Runtime/Binding production 代码。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
|
||||||
|
- [x] 真实执行 `cmake --build build-linux-opengl --target mbgl-test-runner -j3`,通过全局 `build-output-throttle`,PASS。
|
||||||
|
- [x] `Source.RasterArrayV4HostApi*`:Running 4,0 failure。
|
||||||
|
- [x] `ParticleFieldBinding.*`:Running 6,0 failure。
|
||||||
|
- [x] `ParticleFieldRuntime.*:ParticleFieldProfileValidator.*`:Running 11,0 failure。
|
||||||
|
- [x] `ParticleQbinV2Decoder.*:ParticleEncodedFieldIngress.*`:Running 24,0 failure。
|
||||||
|
- [x] `Source.ParticleFieldDataAdapter*:Source.RasterArrayTimeline*:Source.HostField*`:Running 11,0 failure。
|
||||||
|
- [x] `git diff --check`:PASS。
|
||||||
|
|
||||||
|
## 边界、阻塞与停止条件
|
||||||
|
|
||||||
|
- 未执行 Android 编译、Gradle/APK、ADB、实体机、Jest 或 iOS/Metal。
|
||||||
|
- 无阻塞;仅完成本任务书的审计收口,停止,不进入下一 Step。
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# STEP-076 QBIN2 V4 Core Host API 与 RasterArraySource 接线 Codex 完成报告 v2
|
||||||
|
|
||||||
|
## 结果
|
||||||
|
|
||||||
|
已完成 v1 独立审计指出的测试证明缺口,未改变任何 production API 或架构。四种指定 V4 reject 都在公共 `RasterArraySource` resolve 路径上证明无 partial mutation;V4 clear 已在真实可观察的 V3 初始窗口存在时,证明不影响 V3 `field/nextField`,且 V4 binding intent 可在重新提交后继续 resolve。
|
||||||
|
|
||||||
|
## 基线与修改
|
||||||
|
|
||||||
|
- 开始 HEAD:`ae03d8bfd2813eb5e65074db16018e37c7cff1c4`。
|
||||||
|
- 实际 production 修改:无。
|
||||||
|
- 实际修改文件:`test/source/raster_array_v4_host_api.test.cpp`、`docs/50_Step记录/STEP-076_QBIN2_V4_CoreHostAPI与RasterArraySource接线_v2.md`、`docs/报告/STEP-076_QBIN2_V4_CoreHostAPI与RasterArraySource接线_Codex完成报告_v2.md`、`粒子开发记录.md`。
|
||||||
|
- 开始时已有 STEP-062 dirty、历史 untracked 与 build 输出均保持原样;本次 scoped commit 不包含它们。
|
||||||
|
|
||||||
|
## 测试证明
|
||||||
|
|
||||||
|
- `RejectedDecode`、`RejectedContract`、`RejectedInvalidFieldKey`、`RejectedStaleRevision`:每次 reject 前后 public Particle projection 均可 resolve;比较了 projection content identity、T0/T1 coordinate、两条 selected plane storage 和 validity storage identity。
|
||||||
|
- `clearEncodedField(...)` 与 `clearAllEncodedFields()`:先用公开 V3 `submitInitialRuntimeFieldWindow(...)` 建立窗口,clear 后 V3 field/nextField 均存在,identity/generation/validTime 不变;V4 resolve 均为 fail-closed;重新提交 V4 后 Color/Particle binding 都可 resolve。
|
||||||
|
- V4 suite 保留原 3 个并新增第 4 个测试;未使用旧 `clearHostFields()`,未读取 V4 Store 私有成员。
|
||||||
|
|
||||||
|
| Filter | 实际 Running | Failure |
|
||||||
|
| --- | ---: | ---: |
|
||||||
|
| `Source.RasterArrayV4HostApi*` | 4 | 0 |
|
||||||
|
| `ParticleFieldBinding.*` | 6 | 0 |
|
||||||
|
| `ParticleFieldRuntime.*:ParticleFieldProfileValidator.*` | 11 | 0 |
|
||||||
|
| `ParticleQbinV2Decoder.*:ParticleEncodedFieldIngress.*` | 24 | 0 |
|
||||||
|
| `Source.ParticleFieldDataAdapter*:Source.RasterArrayTimeline*:Source.HostField*` | 11 | 0 |
|
||||||
|
|
||||||
|
真实执行 `cmake --build build-linux-opengl --target mbgl-test-runner -j3` 并 PASS;所有 noisy build/test 均经全局 `build-output-throttle`。`git diff --check` PASS。
|
||||||
|
|
||||||
|
## 范围与 Git 收尾
|
||||||
|
|
||||||
|
- 未执行 Android 编译/Gradle/APK/ADB/实体机,也未执行 Jest 或 iOS/Metal。
|
||||||
|
- 未修改 Renderer、shader、JNI、Android、RN、Test Host、NavSea、QBIN decoder 或 production Field Runtime/Binding。
|
||||||
|
- scoped commit message:`test: close STEP-076 V4 host API audit`;push target:`origin/particle/main`。实际 commit hash、push result、remote branch 和 Final HEAD 以紧随本报告的 scoped Git 收尾输出为准。
|
||||||
|
- 未完成/阻塞:无;完成后停止,不进入下一 Step。
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <mbgl/particle/ingress/qbin_v2_decoder.hpp>
|
#include <mbgl/particle/ingress/qbin_v2_decoder.hpp>
|
||||||
|
#include <mbgl/particle/field/offline_fixture_particle_adapter.hpp>
|
||||||
#include <mbgl/style/sources/raster_array_source.hpp>
|
#include <mbgl/style/sources/raster_array_source.hpp>
|
||||||
|
#include <mbgl/style/sources/raster_array_source_impl.hpp>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
@@ -101,30 +103,89 @@ void submit(style::RasterArraySource& source, const char* key, const char* id, u
|
|||||||
style::RasterArrayEncodedFieldSubmitResult::AcceptedInserted);
|
style::RasterArrayEncodedFieldSubmitResult::AcceptedInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expectSameParticleProjection(const particle::ParticleProjection& expected,
|
||||||
|
const particle::ParticleProjection& actual) {
|
||||||
|
EXPECT_EQ(actual.contentIdentity, expected.contentIdentity);
|
||||||
|
EXPECT_EQ(actual.contentIdentity.t0Coordinate, expected.contentIdentity.t0Coordinate);
|
||||||
|
EXPECT_EQ(actual.contentIdentity.t1Coordinate, expected.contentIdentity.t1Coordinate);
|
||||||
|
EXPECT_EQ(actual.t0FirstPlaneStorage, expected.t0FirstPlaneStorage);
|
||||||
|
EXPECT_EQ(actual.t1FirstPlaneStorage, expected.t1FirstPlaneStorage);
|
||||||
|
EXPECT_EQ(actual.t0SecondPlaneStorage, expected.t0SecondPlaneStorage);
|
||||||
|
EXPECT_EQ(actual.t1SecondPlaneStorage, expected.t1SecondPlaneStorage);
|
||||||
|
EXPECT_EQ(actual.t0ValidityStorage, expected.t0ValidityStorage);
|
||||||
|
EXPECT_EQ(actual.t1ValidityStorage, expected.t1ValidityStorage);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(Source, RasterArrayV4HostApiRejectsWithoutPartialMutationAndMapsStoreResults) {
|
TEST(Source, RasterArrayV4HostApiRejectsWithoutPartialMutationAndMapsStoreResults) {
|
||||||
style::RasterArraySource source{"v4"}; const auto first = qbin(Base);
|
style::RasterArraySource source{"v4"};
|
||||||
|
const auto first = qbin(Base);
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
||||||
style::RasterArrayEncodedFieldSubmitResult::AcceptedInserted);
|
style::RasterArrayEncodedFieldSubmitResult::AcceptedInserted);
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
||||||
style::RasterArrayEncodedFieldSubmitResult::Duplicate);
|
style::RasterArrayEncodedFieldSubmitResult::Duplicate);
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 2, 2), windContract(), first),
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 2, 2), windContract(), first),
|
||||||
style::RasterArrayEncodedFieldSubmitResult::AcceptedReplacedRevision);
|
style::RasterArrayEncodedFieldSubmitResult::AcceptedReplacedRevision);
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
|
||||||
style::RasterArrayEncodedFieldSubmitResult::RejectedStaleRevision);
|
|
||||||
auto corrupt = first; corrupt[0] = 'X';
|
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 3), windContract(), corrupt),
|
|
||||||
style::RasterArrayEncodedFieldSubmitResult::RejectedDecode);
|
|
||||||
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 3), waveContract(), first),
|
|
||||||
style::RasterArrayEncodedFieldSubmitResult::RejectedContract);
|
|
||||||
EXPECT_EQ(source.submitEncodedField("", metadata("wind", 3), windContract(), first),
|
|
||||||
style::RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey);
|
|
||||||
submit(source, "wind", "wind", Base + Hour, 3);
|
submit(source, "wind", "wind", Base + Hour, 3);
|
||||||
source.setParticleBinding({particle::ParticleBindingMode::VectorComponents, "wind",
|
source.setParticleBinding({particle::ParticleBindingMode::VectorComponents, "wind",
|
||||||
{1, 1, particle::FieldComponent::UEast}, {2, 1, particle::FieldComponent::VNorth}, {}, 1});
|
{1, 1, particle::FieldComponent::UEast}, {2, 1, particle::FieldComponent::VNorth}, {}, 1});
|
||||||
ASSERT_TRUE(source.setRequestedForecastTime(Base + Hour / 2));
|
ASSERT_TRUE(source.setRequestedForecastTime(Base + Hour / 2));
|
||||||
EXPECT_TRUE(source.resolveParticleProjection().accepted());
|
const auto baseline = source.resolveParticleProjection();
|
||||||
|
ASSERT_TRUE(baseline.accepted());
|
||||||
|
|
||||||
|
const auto expectNoPartialMutation = [&] {
|
||||||
|
const auto resolved = source.resolveParticleProjection();
|
||||||
|
ASSERT_TRUE(resolved.accepted());
|
||||||
|
expectSameParticleProjection(*baseline.projection, *resolved.projection);
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), first),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedStaleRevision);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
auto corrupt = first; corrupt[0] = 'X';
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 3), windContract(), corrupt),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedDecode);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 3), waveContract(), first),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedContract);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
EXPECT_EQ(source.submitEncodedField("", metadata("wind", 3), windContract(), first),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Source, RasterArrayV4HostApiRejectsKeepPublicProjectionStable) {
|
||||||
|
style::RasterArraySource source{"v4"};
|
||||||
|
const auto t0 = qbin(Base);
|
||||||
|
const auto t1 = qbin(Base + Hour);
|
||||||
|
submit(source, "wind", "wind", Base, 2);
|
||||||
|
submit(source, "wind", "wind", Base + Hour, 3);
|
||||||
|
source.setParticleBinding({particle::ParticleBindingMode::VectorComponents, "wind",
|
||||||
|
{1, 1, particle::FieldComponent::UEast}, {2, 1, particle::FieldComponent::VNorth}, {}, 1});
|
||||||
|
ASSERT_TRUE(source.setRequestedForecastTime(Base + Hour / 2));
|
||||||
|
const auto baseline = source.resolveParticleProjection();
|
||||||
|
ASSERT_TRUE(baseline.accepted());
|
||||||
|
const auto expectNoPartialMutation = [&] {
|
||||||
|
const auto resolved = source.resolveParticleProjection();
|
||||||
|
ASSERT_TRUE(resolved.accepted());
|
||||||
|
expectSameParticleProjection(*baseline.projection, *resolved.projection);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto corrupt = t1;
|
||||||
|
corrupt[0] = 'X';
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 4), windContract(), corrupt),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedDecode);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 4), waveContract(), t1),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedContract);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
EXPECT_EQ(source.submitEncodedField("", metadata("wind", 4), windContract(), t1),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey);
|
||||||
|
expectNoPartialMutation();
|
||||||
|
EXPECT_EQ(source.submitEncodedField("wind", metadata("wind", 1), windContract(), t0),
|
||||||
|
style::RasterArrayEncodedFieldSubmitResult::RejectedStaleRevision);
|
||||||
|
expectNoPartialMutation();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Source, RasterArrayV4HostApiResolvesIndependentBindingsFromOneForecastClock) {
|
TEST(Source, RasterArrayV4HostApiResolvesIndependentBindingsFromOneForecastClock) {
|
||||||
@@ -154,6 +215,28 @@ TEST(Source, RasterArrayV4HostApiResolvesIndependentBindingsFromOneForecastClock
|
|||||||
|
|
||||||
TEST(Source, RasterArrayV4HostApiClearRetainsBindingsAndNeverTouchesV3) {
|
TEST(Source, RasterArrayV4HostApiClearRetainsBindingsAndNeverTouchesV3) {
|
||||||
style::RasterArraySource source{"v4"};
|
style::RasterArraySource source{"v4"};
|
||||||
|
const auto v3T0 = particle::OfflineFixtureParticleAdapter::load("uniform-east", 71);
|
||||||
|
auto v3T1 = particle::OfflineFixtureParticleAdapter::load("uniform-north", 72);
|
||||||
|
v3T1.validTime = v3T0.validTime + Hour;
|
||||||
|
ASSERT_EQ(source.submitInitialRuntimeFieldWindow(v3T0, v3T1), style::RasterArrayRuntimeFieldUpdateResult::Applied);
|
||||||
|
ASSERT_TRUE(source.impl().field);
|
||||||
|
ASSERT_TRUE(source.impl().nextField);
|
||||||
|
const auto v3FieldIdentity = source.impl().field->fieldID;
|
||||||
|
const auto v3FieldGeneration = source.impl().field->generation;
|
||||||
|
const auto v3FieldValidTime = source.impl().field->validTime;
|
||||||
|
const auto v3NextIdentity = source.impl().nextField->fieldID;
|
||||||
|
const auto v3NextGeneration = source.impl().nextField->generation;
|
||||||
|
const auto v3NextValidTime = source.impl().nextField->validTime;
|
||||||
|
const auto expectV3Unchanged = [&] {
|
||||||
|
ASSERT_TRUE(source.impl().field);
|
||||||
|
ASSERT_TRUE(source.impl().nextField);
|
||||||
|
EXPECT_EQ(source.impl().field->fieldID, v3FieldIdentity);
|
||||||
|
EXPECT_EQ(source.impl().field->generation, v3FieldGeneration);
|
||||||
|
EXPECT_EQ(source.impl().field->validTime, v3FieldValidTime);
|
||||||
|
EXPECT_EQ(source.impl().nextField->fieldID, v3NextIdentity);
|
||||||
|
EXPECT_EQ(source.impl().nextField->generation, v3NextGeneration);
|
||||||
|
EXPECT_EQ(source.impl().nextField->validTime, v3NextValidTime);
|
||||||
|
};
|
||||||
submit(source, "wind", "wind", Base, 1); submit(source, "wind", "wind", Base + Hour, 2);
|
submit(source, "wind", "wind", Base, 1); submit(source, "wind", "wind", Base + Hour, 2);
|
||||||
submit(source, "wave", "wave", Base, 1, true); submit(source, "wave", "wave", Base + 3 * Hour, 2, true);
|
submit(source, "wave", "wave", Base, 1, true); submit(source, "wave", "wave", Base + 3 * Hour, 2, true);
|
||||||
source.setColorBinding({"wave", {99, 0, particle::FieldComponent::None}, particle::FieldValueClass::Scalar, 77});
|
source.setColorBinding({"wave", {99, 0, particle::FieldComponent::None}, particle::FieldValueClass::Scalar, 77});
|
||||||
@@ -162,8 +245,15 @@ TEST(Source, RasterArrayV4HostApiClearRetainsBindingsAndNeverTouchesV3) {
|
|||||||
ASSERT_TRUE(source.setRequestedForecastTime(Base + Hour)); ASSERT_TRUE(source.resolveColorProjection().accepted());
|
ASSERT_TRUE(source.setRequestedForecastTime(Base + Hour)); ASSERT_TRUE(source.resolveColorProjection().accepted());
|
||||||
EXPECT_TRUE(source.clearEncodedField("wave")); EXPECT_TRUE(source.resolveParticleProjection().accepted());
|
EXPECT_TRUE(source.clearEncodedField("wave")); EXPECT_TRUE(source.resolveParticleProjection().accepted());
|
||||||
EXPECT_EQ(source.resolveColorProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
EXPECT_EQ(source.resolveColorProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
||||||
|
expectV3Unchanged();
|
||||||
submit(source, "wave", "wave", Base, 1, true); submit(source, "wave", "wave", Base + 3 * Hour, 2, true);
|
submit(source, "wave", "wave", Base, 1, true); submit(source, "wave", "wave", Base + 3 * Hour, 2, true);
|
||||||
EXPECT_TRUE(source.resolveColorProjection().accepted()); source.clearAllEncodedFields();
|
EXPECT_TRUE(source.resolveColorProjection().accepted()); source.clearAllEncodedFields();
|
||||||
EXPECT_EQ(source.resolveColorProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
EXPECT_EQ(source.resolveColorProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
||||||
EXPECT_EQ(source.resolveParticleProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
EXPECT_EQ(source.resolveParticleProjection().error, particle::BindingProjectionError::FieldSeriesMissing);
|
||||||
|
expectV3Unchanged();
|
||||||
|
submit(source, "wind", "wind", Base, 1); submit(source, "wind", "wind", Base + Hour, 2);
|
||||||
|
submit(source, "wave", "wave", Base, 1, true); submit(source, "wave", "wave", Base + 3 * Hour, 2, true);
|
||||||
|
EXPECT_TRUE(source.resolveColorProjection().accepted());
|
||||||
|
EXPECT_TRUE(source.resolveParticleProjection().accepted());
|
||||||
|
expectV3Unchanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -760,3 +760,9 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
|
|||||||
- `RasterArraySource` 新增完全隔离的 V4 QBIN Host API:submission 严格执行 key/runtime metadata → QBIN decoder → Profile validator → per-field Store,稳定返回 insert/replace/duplicate 与各类 fail-closed rejection;失败不留下 partial Store mutation。
|
- `RasterArraySource` 新增完全隔离的 V4 QBIN Host API:submission 严格执行 key/runtime metadata → QBIN decoder → Profile validator → per-field Store,稳定返回 insert/replace/duplicate 与各类 fail-closed rejection;失败不留下 partial Store mutation。
|
||||||
- V4 owner 独立持有 `EncodedFieldStore`、`ForecastClock`、Color/Particle binding;每个 binding 在 resolve 时按自己的 fieldKey 获得 window/mix。没有 Host T0/T1/MIX API,没有切换 renderer,也未改动 V3 timeline。
|
- V4 owner 独立持有 `EncodedFieldStore`、`ForecastClock`、Color/Particle binding;每个 binding 在 resolve 时按自己的 fieldKey 获得 window/mix。没有 Host T0/T1/MIX API,没有切换 renderer,也未改动 V3 timeline。
|
||||||
- 离线 Source V4 suite 3/3、Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、V3 Source 11/11,均为 0 failure;Linux runner 真实重建、`git diff --check` PASS。Android Gradle/APK/ADB/Jest、iOS/Metal 未执行;STEP-062 dirty 与既有 untracked/build 输出未纳入。
|
- 离线 Source V4 suite 3/3、Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、V3 Source 11/11,均为 0 failure;Linux runner 真实重建、`git diff --check` PASS。Android Gradle/APK/ADB/Jest、iOS/Metal 未执行;STEP-062 dirty 与既有 untracked/build 输出未纳入。
|
||||||
|
|
||||||
|
### 2026-09-13 STEP-076 v2 审计测试收口
|
||||||
|
|
||||||
|
- V4 public-path reject 现在逐项证明 `RejectedDecode`、`RejectedContract`、`RejectedInvalidFieldKey`、`RejectedStaleRevision` 不改变既有可 resolve projection 的 content identity、T0/T1 coordinate、selected U/V plane 与 validity storage identity;未读取 Store 私有状态。
|
||||||
|
- clear 测试先用公开 `submitInitialRuntimeFieldWindow(...)` 建立 V3 `field/nextField`,对 `clearEncodedField`、`clearAllEncodedFields` 和 V4 re-submit 全程核验 V3 identity/generation/validTime 不变;V4 清空后 fail-closed,binding intent 仍可重解。
|
||||||
|
- Linux runner 真实重建 PASS;Source V4 4/4、Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、Source regression 11/11,全部 0 failure,`git diff --check` PASS。未执行 Android 编译/Gradle/APK/ADB/Jest/iOS-Metal;STEP-062 dirty 与历史 untracked/build 输出未纳入 scoped commit。
|
||||||
|
|||||||
Reference in New Issue
Block a user