diff --git a/scripts/test_dependency_invalidation.sh b/scripts/test_dependency_invalidation.sh index 1139266..5944a9e 100755 --- a/scripts/test_dependency_invalidation.sh +++ b/scripts/test_dependency_invalidation.sh @@ -69,6 +69,18 @@ if [[ "$(http_marker)" != *"dependency-marker-a"* ]]; then exit 1 fi +# The load-graph signature is content-addressed. A byte-identical dependency +# touch must invalidate stat caches without recompiling its parent artifact. +parent_wasm="$cache_dir/parent.uce.wasm" +parent_wasm_identity=$(stat -c '%y:%s' "$parent_wasm") +sleep 1.1 +touch "$source_dir/child.uce" +assert_marker parent dependency-marker-a +if [[ "$(stat -c '%y:%s' "$parent_wasm")" != "$parent_wasm_identity" ]]; then + echo "byte-identical dependency touch recompiled the parent artifact" >&2 + exit 1 +fi + printf '%s\n' 'CLI(Request& context) { print("readable-source-marker"); }' >"$source_dir/unreadable.uce" chmod 000 "$source_dir/unreadable.uce" if unreadable_output=$(scripts/uce-cli --get "/$test_name/unreadable.uce" __uce_expected_source_read_failure=1 2>&1); then @@ -112,7 +124,6 @@ assert_marker parent dependency-marker-b # A proactive rebuild owns these same per-unit locks. While it publishes fresh # artifacts, requests must use the last complete artifacts instead of waiting # across the transitive graph. Atomic publication keeps those artifacts safe. -parent_wasm="$cache_dir/parent.uce.wasm" child_wasm="$cache_dir/child.uce.wasm" ( exec 8>"$parent_wasm.lock" diff --git a/src/lib/compiler.cpp b/src/lib/compiler.cpp index 6d150d4..7e0b0ea 100644 --- a/src/lib/compiler.cpp +++ b/src/lib/compiler.cpp @@ -497,7 +497,10 @@ SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, Share state.current_input_signature != "" && state.metadata_input_signature == state.current_input_signature ); - state.required_time = std::max({state.source_time, state.setup_template_time, state.compiler_abi_time}); + // Source and setup-template freshness is content-addressed by the input + // signature. Keep the executable timestamp as the independent codegen + // boundary, but do not rebuild byte-identical sources after a touch/restore. + state.required_time = state.compiler_abi_time; // Native .so execution has been removed; compile freshness is the wasm // side-module freshness. state.compiled_time = file_mtime(su->wasm_name);