Expose asset timestamp probe boundary

This commit is contained in:
2026-06-12 16:54:42 +02:00
parent b9b0663546
commit a6b01c2d12
5 changed files with 48 additions and 15 deletions

View File

@@ -242,6 +242,11 @@ agent or engineer to remove them without reconstructing context from chat.
`plan_asset_file_load` wrapper still performs the retained `stat` probe for `plan_asset_file_load` wrapper still performs the retained `stat` probe for
mtime platforms until asset/file watching is owned by injected storage mtime platforms until asset/file watching is owned by injected storage
services. services.
- 2026-06-12: DEBT-0054 was narrowed again. The retained mtime probe is now an
explicit `pp_platform_api::probe_asset_file_timestamp` boundary with missing
and existing file coverage, and `plan_asset_file_load_for_platform` consumes
that probe instead of owning the `stat` call inline. Injected file-watch or
storage services still need to own the live probe before the debt closes.
- 2026-06-05: DEBT-0056 was narrowed. `src/asset.h` no longer exposes Android - 2026-06-05: DEBT-0056 was narrowed. `src/asset.h` no longer exposes Android
SDK types or forward declarations; retained Android asset-manager and asset SDK types or forward declarations; retained Android asset-manager and asset
handles are stored as opaque pointers and cast only inside `src/asset.cpp`, handles are stored as opaque pointers and cast only inside `src/asset.cpp`,

View File

@@ -644,6 +644,8 @@ mobile platform keyboard bridges continue.
`pano_cli plan-cursor-visibility` exposes the app-core cursor visibility `pano_cli plan-cursor-visibility` exposes the app-core cursor visibility
decision used by live canvas cursor requests before retained desktop platform decision used by live canvas cursor requests before retained desktop platform
cursor bridges continue. cursor bridges continue.
`pp_platform_api::probe_asset_file_timestamp` now owns the retained asset mtime
probe used by layout reload planning, with missing/existing file coverage.
`pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write` expose the `pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write` expose the
app-core clipboard text decisions used by live clipboard get/set requests app-core clipboard text decisions used by live clipboard get/set requests
before retained platform clipboard bridges continue. before retained platform clipboard bridges continue.

View File

@@ -5,6 +5,19 @@
namespace pp::platform { namespace pp::platform {
AssetFileTimestampProbe probe_asset_file_timestamp(std::string_view absolute_path)
{
struct stat file_info {};
const std::string path(absolute_path);
if (stat(path.c_str(), &file_info) != 0)
return {};
return {
true,
static_cast<std::int64_t>(file_info.st_mtime),
};
}
AssetFileLoadDecision plan_asset_file_load_with_probe( AssetFileLoadDecision plan_asset_file_load_with_probe(
PlatformFamily family, PlatformFamily family,
bool already_loaded, bool already_loaded,
@@ -43,25 +56,11 @@ AssetFileLoadDecision plan_asset_file_load_for_platform(
{}); {});
} }
struct stat file_info {};
const std::string path(absolute_path);
if (stat(path.c_str(), &file_info) != 0)
{
return plan_asset_file_load_with_probe(
family,
already_loaded,
previous_last_write_time,
{});
}
return plan_asset_file_load_with_probe( return plan_asset_file_load_with_probe(
family, family,
already_loaded, already_loaded,
previous_last_write_time, previous_last_write_time,
{ probe_asset_file_timestamp(absolute_path));
true,
static_cast<std::int64_t>(file_info.st_mtime),
});
} }
AssetFileLoadDecision plan_asset_file_load( AssetFileLoadDecision plan_asset_file_load(

View File

@@ -18,6 +18,9 @@ struct AssetFileTimestampProbe {
std::int64_t last_write_time = 0; std::int64_t last_write_time = 0;
}; };
[[nodiscard]] AssetFileTimestampProbe probe_asset_file_timestamp(
std::string_view absolute_path);
[[nodiscard]] AssetFileLoadDecision plan_asset_file_load_with_probe( [[nodiscard]] AssetFileLoadDecision plan_asset_file_load_with_probe(
PlatformFamily family, PlatformFamily family,
bool already_loaded, bool already_loaded,

View File

@@ -799,6 +799,27 @@ void asset_file_load_policy_preserves_platform_reload_behavior(pp::tests::Harnes
std::filesystem::remove(temp_path); std::filesystem::remove(temp_path);
} }
void asset_file_load_policy_exposes_timestamp_probe(pp::tests::Harness& harness)
{
const auto temp_path = std::filesystem::temp_directory_path()
/ "panopainter-platform-api-timestamp-probe.xml";
std::filesystem::remove(temp_path);
const auto missing = pp::platform::probe_asset_file_timestamp(temp_path.string());
PP_EXPECT(harness, !missing.file_exists);
{
std::ofstream file(temp_path);
file << "<layouts />";
}
const auto existing = pp::platform::probe_asset_file_timestamp(temp_path.string());
PP_EXPECT(harness, existing.file_exists);
PP_EXPECT(harness, existing.last_write_time > 0);
std::filesystem::remove(temp_path);
}
void asset_file_load_policy_preserves_family_reload_behavior(pp::tests::Harness& harness) void asset_file_load_policy_preserves_family_reload_behavior(pp::tests::Harness& harness)
{ {
const auto missing_desktop = pp::platform::plan_asset_file_load_with_probe( const auto missing_desktop = pp::platform::plan_asset_file_load_with_probe(
@@ -1074,6 +1095,9 @@ int main()
harness.run( harness.run(
"asset file load policy preserves platform reload behavior", "asset file load policy preserves platform reload behavior",
asset_file_load_policy_preserves_platform_reload_behavior); asset_file_load_policy_preserves_platform_reload_behavior);
harness.run(
"asset file load policy exposes timestamp probe",
asset_file_load_policy_exposes_timestamp_probe);
harness.run( harness.run(
"asset file load policy preserves family reload behavior", "asset file load policy preserves family reload behavior",
asset_file_load_policy_preserves_family_reload_behavior); asset_file_load_policy_preserves_family_reload_behavior);