@bongos/core 1.21.47 → 1.21.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,122 +0,0 @@
1
- // tests/feedback_latest.mjs — /feedback's resolver works with no bongos-app/ source (task 1004356).
2
- //
3
- // scripts/gds/feedback-latest.js used to require bongos-app/src/handoff.js, which left
4
- // this repo when the desktop apps moved off-repo (ADR 0098), so the script crashed at
5
- // startup and /feedback was dead. resolveLatest + feedbackBaseDir now live in the script.
6
- // This pins the ADR 0087 `latest` contract against a temp base dir: latest.json wins,
7
- // the latest/ symlink is optional, and with neither the reader self-heals by scanning for
8
- // the newest dir holding a prompt.md. Frames come back as absolute paths, never bytes.
9
- //
10
- // Run: node --test tests/feedback_latest.mjs
11
-
12
- import { test } from 'node:test';
13
- import assert from 'node:assert/strict';
14
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync, utimesSync } from 'node:fs';
15
- import { spawnSync } from 'node:child_process';
16
- import { createRequire } from 'node:module';
17
- import os from 'node:os';
18
- import path from 'node:path';
19
- import { fileURLToPath } from 'node:url';
20
-
21
- const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
22
- const SCRIPT = path.join(ROOT, 'scripts', 'gds', 'feedback-latest.js');
23
- const { resolveLatest, feedbackBaseDir } = createRequire(import.meta.url)(SCRIPT);
24
-
25
- function tempBase(t) {
26
- const base = mkdtempSync(path.join(os.tmpdir(), 'feedback-latest-'));
27
- t.after(() => rmSync(base, { recursive: true, force: true }));
28
- return base;
29
- }
30
-
31
- // A bundle dir as bundle.js writes it: prompt.md citing its frames by absolute path.
32
- function writeBundle(base, id, { frames = [], mtime } = {}) {
33
- const dir = path.join(base, id);
34
- mkdirSync(dir, { recursive: true });
35
- const refs = frames.map((f) => `![${f}](${path.join(dir, f)})`).join('\n');
36
- writeFileSync(path.join(dir, 'prompt.md'), `# Walkthrough ${id}\n\n${refs}\n`);
37
- for (const f of frames) writeFileSync(path.join(dir, f), 'png');
38
- if (mtime) utimesSync(path.join(dir, 'prompt.md'), mtime, mtime);
39
- return dir;
40
- }
41
-
42
- test('the script no longer depends on the off-repo bongos-app source', () => {
43
- assert.equal(feedbackBaseDir(), path.join(os.homedir(), 'CloudBongos', 'feedback'));
44
- const r = spawnSync(process.execPath, [SCRIPT, '--json', '--base', path.join(os.tmpdir(), 'no-such-feedback-dir-1004356')], { encoding: 'utf8' });
45
- assert.equal(r.status, 0, r.stderr);
46
- assert.equal(JSON.parse(r.stdout).ok, false);
47
- });
48
-
49
- test('an empty or missing base dir resolves to null', async (t) => {
50
- const base = tempBase(t);
51
- assert.equal(await resolveLatest(base), null);
52
- mkdirSync(path.join(base, 'not-a-bundle')); // a dir with no prompt.md is not a bundle
53
- assert.equal(await resolveLatest(base), null);
54
- assert.equal(await resolveLatest(path.join(base, 'missing')), null);
55
- });
56
-
57
- test('latest.json is authoritative over a newer dir', async (t) => {
58
- const base = tempBase(t);
59
- const old = writeBundle(base, '2026-09-01-a', { frames: ['f2.png', 'f1.png'], mtime: new Date('2026-09-01') });
60
- writeBundle(base, '2026-09-02-b', { mtime: new Date('2026-09-02') });
61
- writeFileSync(path.join(base, 'latest.json'), JSON.stringify({ id: '2026-09-01-a', dir: old }));
62
-
63
- const latest = await resolveLatest(base);
64
- assert.equal(latest.id, '2026-09-01-a');
65
- assert.equal(latest.dir, old);
66
- assert.equal(latest.promptPath, path.join(old, 'prompt.md'));
67
- assert.match(latest.promptMarkdown, /# Walkthrough 2026-09-01-a/);
68
- // In the order prompt.md cites them, absolute.
69
- assert.deepEqual(latest.imagePaths, [path.join(old, 'f2.png'), path.join(old, 'f1.png')]);
70
- for (const p of latest.imagePaths) assert.ok(path.isAbsolute(p));
71
- });
72
-
73
- test('a pointer naming only an id resolves under the base dir', async (t) => {
74
- const base = tempBase(t);
75
- const dir = writeBundle(base, 'only-id', { mtime: new Date('2026-09-01') });
76
- writeBundle(base, 'newer', { mtime: new Date('2026-09-05') });
77
- writeFileSync(path.join(base, 'latest.json'), JSON.stringify({ id: 'only-id' }));
78
- assert.equal((await resolveLatest(base)).dir, dir);
79
- });
80
-
81
- test('a stale or corrupt pointer self-heals to the newest bundle', async (t) => {
82
- const base = tempBase(t);
83
- writeBundle(base, 'older', { mtime: new Date('2026-09-01') });
84
- const newest = writeBundle(base, 'newest', { mtime: new Date('2026-09-03') });
85
-
86
- writeFileSync(path.join(base, 'latest.json'), JSON.stringify({ id: 'deleted-bundle' }));
87
- assert.equal((await resolveLatest(base)).dir, newest);
88
-
89
- writeFileSync(path.join(base, 'latest.json'), '{not json');
90
- assert.equal((await resolveLatest(base)).dir, newest);
91
-
92
- rmSync(path.join(base, 'latest.json'));
93
- assert.equal((await resolveLatest(base)).dir, newest);
94
- });
95
-
96
- test('unreferenced frames in the bundle are still listed; missing refs are dropped', async (t) => {
97
- const base = tempBase(t);
98
- const dir = writeBundle(base, 'b', { frames: ['cited.png'] });
99
- mkdirSync(path.join(dir, 'frames'));
100
- writeFileSync(path.join(dir, 'frames', 'extra.jpg'), 'jpg');
101
- writeFileSync(path.join(dir, 'prompt.md'),
102
- `![a](${path.join(dir, 'cited.png')})\n![gone](${path.join(dir, 'gone.png')})\n`);
103
- const latest = await resolveLatest(base);
104
- assert.deepEqual(latest.imagePaths, [path.join(dir, 'cited.png'), path.join(dir, 'frames', 'extra.jpg')]);
105
- });
106
-
107
- test('the CLI prints the prompt body and each frame path', (t) => {
108
- const base = tempBase(t);
109
- const dir = writeBundle(base, 'cli', { frames: ['shot.png'] });
110
- writeFileSync(path.join(base, 'latest.json'), JSON.stringify({ id: 'cli', dir }));
111
-
112
- const text = spawnSync(process.execPath, [SCRIPT, '--base', base], { encoding: 'utf8' });
113
- assert.equal(text.status, 0, text.stderr);
114
- assert.match(text.stdout, /# Walkthrough cli/);
115
- assert.ok(text.stdout.split('\n').includes(path.join(dir, 'shot.png')));
116
-
117
- const json = spawnSync(process.execPath, [SCRIPT, '--json', `--base=${base}`], { encoding: 'utf8' });
118
- const out = JSON.parse(json.stdout);
119
- assert.equal(out.ok, true);
120
- assert.equal(out.id, 'cli');
121
- assert.deepEqual(out.imagePaths, [path.join(dir, 'shot.png')]);
122
- });