oxedyne/daimond/dev/verify_defaults.mjs
5.5 KiB, 1 run
created by r2519314175:351, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | // verify_defaults.mjs — Help and the Optimiser are FEATURES, so everybody gets |
| 2 | // them; but a Diamond somebody deletes stays deleted. |
| 3 | // |
| 4 | // The two default Diamonds were treated as onboarding furniture: seeded only |
| 5 | // into an EMPTY rail, on the reasoning that a person with thirteen Diamonds does |
| 6 | // not want two more. The flag was written either way, so that decision was taken |
| 7 | // once and for ever. The consequence was reported in notes3, by the author, about |
| 8 | // his own app: "I do not see the Daimond Help or Daimond Optimiser diamonds at |
| 9 | // all." He never had an empty rail on the boot that offered them. |
| 10 | // |
| 11 | // They are not furniture. Daimond Help is the only thing that reads the guide |
| 12 | // mirror at `system/guide/`, and the Optimiser is the only thing that reads the |
| 13 | // usage digest at `system/usage/digest.md`. Withholding them withheld two |
| 14 | // features. |
| 15 | // |
| 16 | // What is pinned here, and none of it held before: |
| 17 | // * a rail that already has a Diamond STILL receives the two defaults; |
| 18 | // * booting again does not make a second copy of either; |
| 19 | // * a default the user DELETES stays deleted, because the app must not argue. |
| 20 | // |
| 21 | // Proved against broken code: restore `if ((diamonds || []).length) { ...; return; }` |
| 22 | // at the top of `seedDefaultDiamonds` and the first check goes red. |
| 23 | // |
| 24 | // node dev/verify_defaults.mjs |
| 25 | // |
| 26 | // Needs dev/serve.mjs (DAIMOND_PORT, default 8777). No gateway, no mock LLM. |
| 27 | import fs from 'node:fs'; |
| 28 | import { open, scratch, signInAs } from './harness.mjs'; |
| 29 | |
| 30 | const PROFILE = scratch('pw', 'defaults'); |
| 31 | fs.rmSync(PROFILE, { recursive: true, force: true }); |
| 32 | |
| 33 | let bad = 0; |
| 34 | const check = (pass, name, detail) => { |
| 35 | if (!pass) bad++; |
| 36 | console.log((pass ? ' ok ' : ' FAIL ') + name + (detail ? ' — ' + detail : '')); |
| 37 | }; |
| 38 | |
| 39 | /// The names in the STORE, sorted. The store rather than the rail, because the |
| 40 | /// question here is whether the two Diamonds were CREATED; whether the rail has |
| 41 | /// re-read since is a different property with its own verifier, and mixing the |
| 42 | /// two would make this file fail for reasons that are nothing to do with it. |
| 43 | const names = async () => (JSON.parse(await wasm(async (app) => await app.list_diamonds()))) |
| 44 | .map((d) => d.name).sort(); |
| 45 | |
| 46 | const HELP = 'Daimond Help'; |
| 47 | const OPT = 'Daimond Optimiser'; |
| 48 | |
| 49 | // `defaults: false` removes the two the first boot seeds, so this session owns |
| 50 | // the rail outright and the state below is built rather than inherited. |
| 51 | const s = await open({ name: 'defaults', profile: PROFILE, connect: false, defaults: false }); |
| 52 | const { page } = s; |
| 53 | |
| 54 | /// The store, driven directly, so the fixture is built rather than clicked. |
| 55 | const wasm = (fn, arg) => page.evaluate(async ({ src, arg }) => { |
| 56 | const m = await import('/pkg/oxedyne_daimond.js'); |
| 57 | const app = new m.DaimondApp('http://127.0.0.1/v1/chat/completions', '', 'none', 4096, '', true); |
| 58 | return await (new Function('app', 'arg', `return (${src})(app, arg);`))(app, arg); |
| 59 | }, { src: fn.toString(), arg }); |
| 60 | |
| 61 | /// Reload, sign back in, and let the boot finish. |
| 62 | /// |
| 63 | /// The sign-in is not optional: a reload lands on the LOCK SCREEN, and an app |
| 64 | /// sitting behind it never reaches `seedDefaultDiamonds` at all. Without this the |
| 65 | /// file reported that the defaults were never seeded, on a build that seeds them. |
| 66 | const reboot = async (settle) => { |
| 67 | await page.reload({ waitUntil: 'domcontentloaded' }); |
| 68 | await signInAs(s, 'defaults'); |
| 69 | await page.waitForTimeout(settle); |
| 70 | }; |
| 71 | try { |
| 72 | await page.waitForTimeout(1200); |
| 73 | |
| 74 | // ── A rail that is not empty ───────────────────────────────── |
| 75 | // One Diamond of the user's own, and the OLD flag set with the new one absent: |
| 76 | // that is exactly an account which was using the app when the feature shipped, |
| 77 | // was recorded as having been offered the defaults, and never saw them. |
| 78 | await wasm(async (app) => { await app.create_diamond('Mine'); }); |
| 79 | await reboot(1500); |
| 80 | |
| 81 | await page.evaluate(() => { |
| 82 | localStorage.setItem('daimond-defaults-seeded', '1'); // the old flag, as it was |
| 83 | localStorage.removeItem('daimond-defaults-seeded-2'); // the re-ask |
| 84 | }); |
| 85 | await reboot(2500); |
| 86 | |
| 87 | const after = await names(); |
| 88 | check(after.includes(HELP) && after.includes(OPT), |
| 89 | 'a rail that already holds a Diamond still receives both defaults', JSON.stringify(after)); |
| 90 | check(after.includes('Mine'), 'and the Diamond that was already there is untouched', |
| 91 | JSON.stringify(after)); |
| 92 | |
| 93 | // ── Once, not once per boot ────────────────────────────────── |
| 94 | await reboot(2500); |
| 95 | const twice = await names(); |
| 96 | check(twice.filter((n) => n === HELP).length === 1 |
| 97 | && twice.filter((n) => n === OPT).length === 1, |
| 98 | 'booting again makes no second copy of either', JSON.stringify(twice)); |
| 99 | |
| 100 | // ── A deletion is a decision, and the app must not argue ───── |
| 101 | const gone = await wasm(async (app, name) => { |
| 102 | const rows = JSON.parse(await app.list_diamonds()); |
| 103 | const row = rows.find((d) => d.name === name); |
| 104 | if (!row) return 'no Diamond named ' + name; |
| 105 | await app.delete_diamond(row.id); |
| 106 | return ''; |
| 107 | }, HELP); |
| 108 | if (gone) { |
| 109 | check(false, 'a deleted default stays deleted', 'could not delete it: ' + gone); |
| 110 | } else { |
| 111 | await page.waitForTimeout(700); |
| 112 | await reboot(2500); |
| 113 | const back = await names(); |
| 114 | check(!back.includes(HELP), 'a deleted default stays deleted', JSON.stringify(back)); |
| 115 | check(back.includes(OPT), 'and deleting one does not take the other with it', |
| 116 | JSON.stringify(back)); |
| 117 | } |
| 118 | } finally { |
| 119 | await s.close(); |
| 120 | } |
| 121 | |
| 122 | console.log(bad ? `\n${bad} check(s) FAILED` : '\nall checks passed'); |
| 123 | process.exit(bad ? 1 : 0); |