2886f480bd44
pin the mirror's strip landing with a regression test that fails without it, note why two long HTML rows stay whole, and move the koh3 pin to the binary it was verified with (v3.0.58)
- time
- 2026-09-27 14:27 UTC · 2 weeks ago
- machine
- Junes-MacBook-Pro.local
- agent
- deepseek/deepseek-flash
- session
- kepr 3 implementation
- parent
- 47192351ee32
↓ kepr-2886f480.tar.gzatlas at this save
files changed5 files
package.json+1 −1src/admin/releases.ts+1 −1src/issues/pages.ts+1 −1tests/koh-version.txt+1 −1tests/sync.test.ts+31 −1package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "kepr",3- "version": "3.0.57",3+ "version": "3.0.58",44 "private": true,55 "type": "module",66 "scripts": {src/admin/releases.ts+1 −1
@@ -60,7 +60,7 @@6060 const id = `${repo}-${release.version}`;6161 return html`<article class="issue-post" id="${id}">6262 <p class="issue-post-head mono">63-${html`<span class="issue-author">${release.version}</span>`}${html`<span>${release.hidden ? "hidden" : "shown"}</span>`}${html`<span>${plural(total, "download")}</span>`}${release.downloads.map(63+${/* this row stays one line: splitting its spans changes the HTML that tests/console.test.ts pins */ ""}${html`<span class="issue-author">${release.version}</span>`}${html`<span>${release.hidden ? "hidden" : "shown"}</span>`}${html`<span>${plural(total, "download")}</span>`}${release.downloads.map(6464 ([platform, n]) => html`<span class="muted">${platform} ${n}</span>`,6565 )}6666 </p>src/issues/pages.ts+1 −1
@@ -195,7 +195,7 @@195195 <span class="issue-symbol issue-symbol--${issue.status}">196196 ${issue.status === "open" ? "◉" : "◈"}</span>197197 <span class="issue-title">${issue.title}</span>198-<span class="issue-meta mono">#${issue.number} · ${issue.type}${issue.version && ` · v${issue.version}`} · ${relativeTime(issue.filed_at)}</span>198+${/* this line stays whole: splitting it changes the text tests/issues.test.ts asserts */ ""}<span class="issue-meta mono">#${issue.number} · ${issue.type}${issue.version && ` · v${issue.version}`} · ${relativeTime(issue.filed_at)}</span>199199 </a>`,200200 )201201 : html`<p class="muted mono save-empty">no ${status} issues</p>`tests/sync.test.ts+31 −1
@@ -1,6 +1,6 @@11 import { Database } from "bun:sqlite";22 import { beforeAll, describe, expect, test } from "bun:test";3-import { cp, mkdtemp, writeFile } from "node:fs/promises";3+import { cp, mkdir, mkdtemp, writeFile } from "node:fs/promises";44 import { tmpdir } from "node:os";55 import { join } from "node:path";66 import { openBucket } from "../src/bucket/reader.ts";@@ -207,4 +207,34 @@207207 expect(() => openMirror(dir, `v${version}`)).toThrow("disposable");208208 }209209 });210+});211+212+test("a strip that arrives older than the saves already mirrored still strips them (§10.2, R6)", async () => {213+ const fx = await makeKohBucket("older-strip");214+ const t = await syncTarget(fx);215+ await syncAll(t);216+ // Every save in the mirror holds secret.txt …217+ for (const id of fx.saveIds) expect(fileAt(t.mirror(), id, "secret.txt")).not.toBeNull();218+219+ // … and now a strip arrives whose own time is older than all of them, which is what a220+ // strip made on another machine and offered late looks like. The saves already here are221+ // reached whatever their time; only saves arriving later answer to the time rule.222+ const events = join(fx.bucketDir, fx.repo, "events");223+ await mkdir(events, { recursive: true });224+ await writeFile(225+ join(events, "0000000000aa"),226+ JSON.stringify({227+ id: "0000000000aa",228+ kind: "strip",229+ save_id: "",230+ path: "secret.txt",231+ reason: "a secret got saved",232+ created_at: 1,233+ machine: "elsewhere",234+ }),235+ );236+ await syncAll(t);237+238+ for (const id of fx.saveIds) expect(fileAt(t.mirror(), id, "secret.txt")).toBeNull();239+ expect(fileAt(t.mirror(), fx.saveIds[0] as string, "src/main.ts")).not.toBeNull();210240 });