Surfaced by PR #35 (closed — its perf premise was synthetic and os.replace widened file mode 600→644, verified). The underlying point is real and worth doing properly.
bin/idstack-learnings-delete:42-43 truncates in place. An interrupt mid-write leaves the learnings log truncated or empty — the file is the user's accumulated project memory, so this is data loss, not an inconvenience.
Do it the way bin/idstack-manifest-merge:126-141 already does: tempfile.mkstemp in the learnings dir, shutil.copymode the original mode onto the temp before the replace (this is what #35 got wrong), os.replace, unlink on exception.
Ships with a test asserting mode is preserved.
Surfaced by PR #35 (closed — its perf premise was synthetic and
os.replacewidened file mode 600→644, verified). The underlying point is real and worth doing properly.bin/idstack-learnings-delete:42-43truncates in place. An interrupt mid-write leaves the learnings log truncated or empty — the file is the user's accumulated project memory, so this is data loss, not an inconvenience.Do it the way
bin/idstack-manifest-merge:126-141already does:tempfile.mkstempin the learnings dir,shutil.copymodethe original mode onto the temp before the replace (this is what #35 got wrong),os.replace, unlink on exception.Ships with a test asserting mode is preserved.