diff --git a/deployment/receipts/HOLOLAKE-DEVELOPMENT-AUTO-FINALIZER-20260805.json b/deployment/receipts/HOLOLAKE-DEVELOPMENT-AUTO-FINALIZER-20260805.json index 8a733f5..129e757 100644 --- a/deployment/receipts/HOLOLAKE-DEVELOPMENT-AUTO-FINALIZER-20260805.json +++ b/deployment/receipts/HOLOLAKE-DEVELOPMENT-AUTO-FINALIZER-20260805.json @@ -30,8 +30,8 @@ "any failed gate leaves the development lane unfinished" ], "source_sha256": { - "finalizer": "cddd6c99073c1bcd40a6681f8ee8e3abeee681f01ba199ea4e92bcb08bdc742e", - "tests": "fd335df335278b16e5c89dcf6014b46577227e4c3fe0408f98ff5088153ddd54" + "finalizer": "ff29851847ec779c8f120d29d4614a361c3e47184939069d0f0cf3d7b50b52f4", + "tests": "39e70be546c54c1e315bd5d8447947b79fb1a0b67416cc2acd0f0a7027075bd0" }, "runtime_sha256": { "bootstrap": "ee28b04e2832819a04e79a0407852fc139f16cf11f3e9b9a5687a061e890dd71", @@ -39,7 +39,7 @@ "publish_policy": "10bc53c439479c67f5b59685a29e221e0db2baab48ceb26c8369ca75c1427330" }, "verification": { - "finalizer_node_tests": "PASS_100_8_OF_8", + "finalizer_node_tests": "PASS_100_9_OF_9", "continuity_guard_self_test": "PASS_100", "source_and_runtime_syntax": "PASS_100", "environment_audit": { diff --git a/server-tools/lake-lamp-continuity-guard/finalize-development.mjs b/server-tools/lake-lamp-continuity-guard/finalize-development.mjs index dc107d5..bfbf630 100644 --- a/server-tools/lake-lamp-continuity-guard/finalize-development.mjs +++ b/server-tools/lake-lamp-continuity-guard/finalize-development.mjs @@ -133,6 +133,10 @@ export function safeCacheRelative(worktree, candidate) { return { absolute, relative }; } +export function isJsonRecordName(name) { + return String(name).endsWith(".json") && !String(name).startsWith("._"); +} + function run(file, args, options = {}) { return execFileSync(file, args, { cwd: options.cwd, @@ -164,7 +168,7 @@ function listOwnedLeases(storeRoot, developmentId) { if (!fs.existsSync(directory)) return []; return fs .readdirSync(directory) - .filter((name) => name.endsWith(".json")) + .filter(isJsonRecordName) .map((name) => readJson(path.join(directory, name))) .filter((lease) => lease.development_id === developmentId); } diff --git a/server-tools/lake-lamp-continuity-guard/finalize-development.test.mjs b/server-tools/lake-lamp-continuity-guard/finalize-development.test.mjs index e90358b..484995f 100644 --- a/server-tools/lake-lamp-continuity-guard/finalize-development.test.mjs +++ b/server-tools/lake-lamp-continuity-guard/finalize-development.test.mjs @@ -4,6 +4,7 @@ import os from "node:os"; import path from "node:path"; import test from "node:test"; import { + isJsonRecordName, normalizeBranch, normalizeCodeChannelRepository, normalizeReceipt, @@ -76,3 +77,9 @@ test("cache deletion scope accepts only exact allowlisted descendants", () => { test("embedded finalizer self-test passes", () => { assert.deepEqual(selfTest(), { result: "PASS_100" }); }); + +test("macOS AppleDouble sidecars are never parsed as JSON records", () => { + assert.equal(isJsonRecordName("lease.json"), true); + assert.equal(isJsonRecordName("._lease.json"), false); + assert.equal(isJsonRecordName("lease.txt"), false); +});