From 68a92c39ff373b1c5dd892dbdc894a70cebcd54a Mon Sep 17 00:00:00 2001 From: martbost Date: Tue, 22 Sep 2026 10:19:12 -0500 Subject: [PATCH] Milestones: a recorded mark stays done whatever its stamp The done-check read the stored value, so a mark recorded as 0 counted as never celebrated. Seeding the already-passed hundreds that way would have made the site announce "400 members" to a channel watching 528. It now tests that the mark is present at all. Caught before it posted; the live state has been re-stamped either way. Co-Authored-By: Claude Opus 5 --- snapshot.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snapshot.js b/snapshot.js index 26520bc..54a9784 100644 --- a/snapshot.js +++ b/snapshot.js @@ -153,7 +153,9 @@ async function milestoneTick() { const sc = X.siteConfig(); if (!sc.telegramBotToken) return null; const st = state(); const done = st.milestones || {}; const count = await memberCount(); - const due = marksUpTo(count).filter(m => !done[m]); + // presence of the key is what counts, never its value: a mark recorded as 0 (or any other + // falsy stamp) must stay done, or the ladder back-posts a number the site passed long ago + const due = marksUpTo(count).filter(m => !Object.prototype.hasOwnProperty.call(done, m)); if (!due.length) return null; const mark = due[due.length - 1]; const text = composeMilestone(mark, await gather(), sc.telegramCtaUrl);