@indigoai-us/hq-cloud 6.15.30 → 6.15.31

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.
Files changed (119) hide show
  1. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  2. package/dist/bin/sync-runner-company.js +24 -13
  3. package/dist/bin/sync-runner-company.js.map +1 -1
  4. package/dist/bin/sync-runner-company.test.js +0 -71
  5. package/dist/bin/sync-runner-company.test.js.map +1 -1
  6. package/dist/bin/sync-runner-watch-loop.d.ts +0 -10
  7. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  8. package/dist/bin/sync-runner-watch-loop.js +13 -170
  9. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  10. package/dist/bin/sync-runner-watch-routes.d.ts +1 -16
  11. package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -1
  12. package/dist/bin/sync-runner-watch-routes.js +2 -40
  13. package/dist/bin/sync-runner-watch-routes.js.map +1 -1
  14. package/dist/bin/sync-runner-watch-routes.test.js +1 -53
  15. package/dist/bin/sync-runner-watch-routes.test.js.map +1 -1
  16. package/dist/bin/sync-runner.d.ts +3 -15
  17. package/dist/bin/sync-runner.d.ts.map +1 -1
  18. package/dist/bin/sync-runner.js +13 -66
  19. package/dist/bin/sync-runner.js.map +1 -1
  20. package/dist/bin/sync-runner.test.js +13 -433
  21. package/dist/bin/sync-runner.test.js.map +1 -1
  22. package/dist/cli/conflict.d.ts +2 -25
  23. package/dist/cli/conflict.d.ts.map +1 -1
  24. package/dist/cli/conflict.js +4 -29
  25. package/dist/cli/conflict.js.map +1 -1
  26. package/dist/cli/share.d.ts +4 -40
  27. package/dist/cli/share.d.ts.map +1 -1
  28. package/dist/cli/share.js +86 -478
  29. package/dist/cli/share.js.map +1 -1
  30. package/dist/cli/share.test.js +150 -845
  31. package/dist/cli/share.test.js.map +1 -1
  32. package/dist/cli/sync-scope.test.js +18 -147
  33. package/dist/cli/sync-scope.test.js.map +1 -1
  34. package/dist/cli/sync.d.ts +0 -20
  35. package/dist/cli/sync.d.ts.map +1 -1
  36. package/dist/cli/sync.js +29 -261
  37. package/dist/cli/sync.js.map +1 -1
  38. package/dist/cli/sync.test.js +90 -519
  39. package/dist/cli/sync.test.js.map +1 -1
  40. package/dist/journal.d.ts +0 -1
  41. package/dist/journal.d.ts.map +1 -1
  42. package/dist/journal.js +25 -155
  43. package/dist/journal.js.map +1 -1
  44. package/dist/journal.test.js +11 -29
  45. package/dist/journal.test.js.map +1 -1
  46. package/dist/object-io.d.ts +13 -34
  47. package/dist/object-io.d.ts.map +1 -1
  48. package/dist/object-io.js +29 -154
  49. package/dist/object-io.js.map +1 -1
  50. package/dist/outcome-telemetry.d.ts +1 -7
  51. package/dist/outcome-telemetry.d.ts.map +1 -1
  52. package/dist/outcome-telemetry.js +9 -15
  53. package/dist/outcome-telemetry.js.map +1 -1
  54. package/dist/outcome-telemetry.test.js +0 -15
  55. package/dist/outcome-telemetry.test.js.map +1 -1
  56. package/dist/outposts/client.d.ts +2 -2
  57. package/dist/outposts/client.d.ts.map +1 -1
  58. package/dist/outposts/client.js +3 -4
  59. package/dist/outposts/client.js.map +1 -1
  60. package/dist/outposts/command.d.ts.map +1 -1
  61. package/dist/outposts/command.js +6 -9
  62. package/dist/outposts/command.js.map +1 -1
  63. package/dist/outposts/command.test.js +2 -59
  64. package/dist/outposts/command.test.js.map +1 -1
  65. package/dist/outposts/remote-command.d.ts +8 -8
  66. package/dist/outposts/remote-command.d.ts.map +1 -1
  67. package/dist/outposts/remote-command.js +8 -10
  68. package/dist/outposts/remote-command.js.map +1 -1
  69. package/dist/prefix-coalesce.d.ts +0 -14
  70. package/dist/prefix-coalesce.d.ts.map +1 -1
  71. package/dist/prefix-coalesce.js +0 -29
  72. package/dist/prefix-coalesce.js.map +1 -1
  73. package/dist/prefix-coalesce.test.js +1 -22
  74. package/dist/prefix-coalesce.test.js.map +1 -1
  75. package/dist/skill-telemetry.d.ts +1 -6
  76. package/dist/skill-telemetry.d.ts.map +1 -1
  77. package/dist/skill-telemetry.js +8 -14
  78. package/dist/skill-telemetry.js.map +1 -1
  79. package/dist/skill-telemetry.test.js +0 -43
  80. package/dist/skill-telemetry.test.js.map +1 -1
  81. package/dist/sts-credential-refresh.test.js +2 -87
  82. package/dist/sts-credential-refresh.test.js.map +1 -1
  83. package/dist/sync/state-store.d.ts.map +1 -1
  84. package/dist/sync/state-store.js +1 -20
  85. package/dist/sync/state-store.js.map +1 -1
  86. package/dist/sync/state-store.test.js +0 -64
  87. package/dist/sync/state-store.test.js.map +1 -1
  88. package/dist/sync-core.d.ts.map +1 -1
  89. package/dist/sync-core.js +2 -7
  90. package/dist/sync-core.js.map +1 -1
  91. package/dist/sync-core.test.js +0 -36
  92. package/dist/sync-core.test.js.map +1 -1
  93. package/dist/telemetry.d.ts +6 -30
  94. package/dist/telemetry.d.ts.map +1 -1
  95. package/dist/telemetry.js +135 -331
  96. package/dist/telemetry.js.map +1 -1
  97. package/dist/telemetry.test.js +0 -403
  98. package/dist/telemetry.test.js.map +1 -1
  99. package/dist/types.d.ts +3 -26
  100. package/dist/types.d.ts.map +1 -1
  101. package/dist/watcher.d.ts +0 -76
  102. package/dist/watcher.d.ts.map +1 -1
  103. package/dist/watcher.js +3 -105
  104. package/dist/watcher.js.map +1 -1
  105. package/dist/watcher.test.js +1 -165
  106. package/dist/watcher.test.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/bandwidth.d.ts +0 -128
  109. package/dist/bandwidth.d.ts.map +0 -1
  110. package/dist/bandwidth.js +0 -254
  111. package/dist/bandwidth.js.map +0 -1
  112. package/dist/bandwidth.test.d.ts +0 -2
  113. package/dist/bandwidth.test.d.ts.map +0 -1
  114. package/dist/bandwidth.test.js +0 -243
  115. package/dist/bandwidth.test.js.map +0 -1
  116. package/dist/journal-delta-writes.test.d.ts +0 -2
  117. package/dist/journal-delta-writes.test.d.ts.map +0 -1
  118. package/dist/journal-delta-writes.test.js +0 -140
  119. package/dist/journal-delta-writes.test.js.map +0 -1
@@ -1,243 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { BANDWIDTH_PERCENT_ENV, BandwidthGovernor, MAX_BYTES_PER_SEC_ENV, MAX_CONCURRENCY_ENV, MIN_ADAPTIVE_BYTES_PER_SEC, ThroughputEstimator, TokenBucket, parseBandwidthPolicy, } from "./bandwidth.js";
3
- /**
4
- * Virtual clock: `sleep` advances time instantly, so pacing math is asserted
5
- * deterministically with zero wall-clock waits.
6
- */
7
- function virtualClock(startMs = 0) {
8
- let t = startMs;
9
- return {
10
- now: () => t,
11
- sleep: async (ms) => {
12
- t += ms;
13
- },
14
- advance: (ms) => {
15
- t += ms;
16
- },
17
- time: () => t,
18
- };
19
- }
20
- describe("parseBandwidthPolicy", () => {
21
- it("returns all-off for an empty env", () => {
22
- expect(parseBandwidthPolicy({})).toEqual({
23
- maxBytesPerSec: undefined,
24
- percent: undefined,
25
- maxConcurrency: undefined,
26
- });
27
- });
28
- it("parses valid positive integers", () => {
29
- const policy = parseBandwidthPolicy({
30
- [MAX_BYTES_PER_SEC_ENV]: "500000",
31
- [MAX_CONCURRENCY_ENV]: "2",
32
- [BANDWIDTH_PERCENT_ENV]: "50",
33
- });
34
- expect(policy).toEqual({
35
- maxBytesPerSec: 500000,
36
- maxConcurrency: 2,
37
- percent: 50,
38
- });
39
- });
40
- it("treats 0, negative, and non-numeric values as unset (feature off)", () => {
41
- for (const bad of ["0", "-5", "abc", "1.5", "", " ", "1e6"]) {
42
- const policy = parseBandwidthPolicy({
43
- [MAX_BYTES_PER_SEC_ENV]: bad,
44
- [MAX_CONCURRENCY_ENV]: bad,
45
- [BANDWIDTH_PERCENT_ENV]: bad,
46
- });
47
- expect(policy, `input ${JSON.stringify(bad)}`).toEqual({
48
- maxBytesPerSec: undefined,
49
- percent: undefined,
50
- maxConcurrency: undefined,
51
- });
52
- }
53
- });
54
- it("rejects percent outside 1..100 but accepts the bounds", () => {
55
- expect(parseBandwidthPolicy({ [BANDWIDTH_PERCENT_ENV]: "101" }).percent).toBeUndefined();
56
- expect(parseBandwidthPolicy({ [BANDWIDTH_PERCENT_ENV]: "1" }).percent).toBe(1);
57
- expect(parseBandwidthPolicy({ [BANDWIDTH_PERCENT_ENV]: "100" }).percent).toBe(100);
58
- });
59
- });
60
- describe("TokenBucket", () => {
61
- it("passes instantly when the rate is unlimited", async () => {
62
- const clock = virtualClock();
63
- const bucket = new TokenBucket(() => undefined, clock);
64
- await bucket.acquire(10_000_000);
65
- expect(clock.time()).toBe(0);
66
- });
67
- it("paces a sustained transfer at the configured rate (virtual time)", async () => {
68
- const clock = virtualClock();
69
- const rate = 100_000; // B/s
70
- const bucket = new TokenBucket(() => rate, clock);
71
- // 1 MB in 64 KiB chunks at 100 kB/s must take ~10 s. The one-second
72
- // burst allowance shaves at most 1 s off the ideal duration.
73
- const chunk = 64 * 1024;
74
- const total = 1_000_000;
75
- for (let sent = 0; sent < total; sent += chunk) {
76
- await bucket.acquire(Math.min(chunk, total - sent));
77
- }
78
- const ideal = (total / rate) * 1000;
79
- expect(clock.time()).toBeGreaterThanOrEqual(ideal - 1000);
80
- expect(clock.time()).toBeLessThanOrEqual(ideal + 1);
81
- });
82
- it("grants an initial burst of at most one second of tokens", async () => {
83
- const clock = virtualClock();
84
- const bucket = new TokenBucket(() => 1000, clock);
85
- clock.advance(60_000); // long idle must NOT accumulate 60s of tokens
86
- await bucket.acquire(1000); // one second's worth: free (burst)
87
- expect(clock.time()).toBe(60_000);
88
- await bucket.acquire(1000); // next second's worth: must wait ~1s
89
- expect(clock.time()).toBeCloseTo(61_000, 5);
90
- });
91
- it("handles a single acquire larger than the burst", async () => {
92
- const clock = virtualClock();
93
- const bucket = new TokenBucket(() => 1000, clock);
94
- // Fresh bucket starts empty (no free initial burst): 5s of tokens → 5s.
95
- await bucket.acquire(5000);
96
- expect(clock.time()).toBeCloseTo(5000, 5);
97
- });
98
- it("re-reads the rate on every acquire (live retuning)", async () => {
99
- const clock = virtualClock();
100
- let rate = undefined;
101
- const bucket = new TokenBucket(() => rate, clock);
102
- await bucket.acquire(1_000_000); // unlimited: instant
103
- expect(clock.time()).toBe(0);
104
- rate = 1000;
105
- await bucket.acquire(2000); // bucket empty → full 2s deficit at 1 kB/s
106
- expect(clock.time()).toBeCloseTo(2000, 5);
107
- });
108
- });
109
- describe("ThroughputEstimator", () => {
110
- it("is undefined before any observation", () => {
111
- const clock = virtualClock();
112
- expect(new ThroughputEstimator(clock.now).capacityBps()).toBeUndefined();
113
- });
114
- it("reports the max per-second aggregate observed", () => {
115
- const clock = virtualClock(1_000_000);
116
- const est = new ThroughputEstimator(clock.now);
117
- est.record(50_000);
118
- est.record(30_000); // same second → aggregates to 80 kB/s
119
- clock.advance(1000);
120
- est.record(10_000);
121
- expect(est.capacityBps()).toBe(80_000);
122
- });
123
- it("forgets observations older than the 10-minute window", () => {
124
- const clock = virtualClock(1_000_000);
125
- const est = new ThroughputEstimator(clock.now);
126
- est.record(1_000_000);
127
- clock.advance(9 * 60 * 1000);
128
- est.record(5_000);
129
- expect(est.capacityBps()).toBe(1_000_000); // still inside window
130
- clock.advance(2 * 60 * 1000); // old peak now > 10 min ago
131
- expect(est.capacityBps()).toBe(5_000);
132
- });
133
- });
134
- describe("BandwidthGovernor.effectiveRateBps", () => {
135
- it("is undefined (unlimited) with no policy", () => {
136
- expect(new BandwidthGovernor({}).effectiveRateBps()).toBeUndefined();
137
- });
138
- it("uses the fixed cap alone", () => {
139
- expect(new BandwidthGovernor({ maxBytesPerSec: 250_000 }).effectiveRateBps()).toBe(250_000);
140
- });
141
- it("percent mode is unlimited until the link has been observed", () => {
142
- const gov = new BandwidthGovernor({ percent: 50 }, virtualClock());
143
- expect(gov.effectiveRateBps()).toBeUndefined();
144
- });
145
- it("percent mode paces to percent × observed capacity", async () => {
146
- const clock = virtualClock(1_000_000);
147
- const gov = new BandwidthGovernor({ percent: 50 }, clock);
148
- await gov.acquire(1_000_000); // observe ~1 MB/s in one second-bucket
149
- expect(gov.effectiveRateBps()).toBe(500_000);
150
- });
151
- it("floors the adaptive cap at 64 KiB/s", async () => {
152
- const clock = virtualClock(1_000_000);
153
- const gov = new BandwidthGovernor({ percent: 1 }, clock);
154
- await gov.acquire(100_000); // 1% of 100 kB/s = 1 kB/s → floored
155
- expect(gov.effectiveRateBps()).toBe(MIN_ADAPTIVE_BYTES_PER_SEC);
156
- });
157
- it("uses the smaller of fixed and adaptive caps when both are set", async () => {
158
- const clock = virtualClock(1_000_000);
159
- const gov = new BandwidthGovernor({ maxBytesPerSec: 300_000, percent: 50 }, clock);
160
- // No observation yet → fixed cap governs.
161
- expect(gov.effectiveRateBps()).toBe(300_000);
162
- await gov.acquire(1_000_000); // adaptive = 500 kB/s > fixed 300 kB/s
163
- expect(gov.effectiveRateBps()).toBe(300_000);
164
- const gov2 = new BandwidthGovernor({ maxBytesPerSec: 300_000, percent: 10 }, clock);
165
- await gov2.acquire(1_000_000); // adaptive = 100 kB/s < fixed
166
- expect(gov2.effectiveRateBps()).toBe(100_000);
167
- });
168
- });
169
- describe("BandwidthGovernor.throttleBody", () => {
170
- async function* chunks(sizes) {
171
- for (const [i, size] of sizes.entries()) {
172
- yield new Uint8Array(size).fill(i % 256);
173
- }
174
- }
175
- async function drain(body) {
176
- const parts = [];
177
- for await (const c of body)
178
- parts.push(Buffer.from(c));
179
- return Buffer.concat(parts);
180
- }
181
- it("returns the original iterable when pacing is off", () => {
182
- const gov = new BandwidthGovernor({ maxConcurrency: 4 });
183
- const body = chunks([10]);
184
- expect(gov.throttleBody(body)).toBe(body);
185
- });
186
- it("delivers every byte unmodified, in order", async () => {
187
- const clock = virtualClock();
188
- const gov = new BandwidthGovernor({ maxBytesPerSec: 1_000_000 }, clock);
189
- const sizes = [1, 65_536, 3, 100_000, 0, 7];
190
- const expected = await drain(chunks(sizes));
191
- const actual = await drain(gov.throttleBody(chunks(sizes)));
192
- expect(actual.equals(expected)).toBe(true);
193
- });
194
- it("respects the rate cap over a simulated transfer (virtual time)", async () => {
195
- const clock = virtualClock();
196
- const rate = 200_000;
197
- const gov = new BandwidthGovernor({ maxBytesPerSec: rate }, clock);
198
- const sizes = Array.from({ length: 31 }, () => 64 * 1024); // ~2 MB
199
- const total = sizes.reduce((a, b) => a + b, 0);
200
- await drain(gov.throttleBody(chunks(sizes)));
201
- const ideal = (total / rate) * 1000;
202
- expect(clock.time()).toBeGreaterThanOrEqual(ideal - 1000); // burst slack
203
- expect(clock.time()).toBeLessThanOrEqual(ideal + 1);
204
- });
205
- it("aggregates concurrent streams under ONE shared cap", async () => {
206
- const clock = virtualClock();
207
- const rate = 100_000;
208
- const gov = new BandwidthGovernor({ maxBytesPerSec: rate }, clock);
209
- const sizes = Array.from({ length: 8 }, () => 50_000); // 400 kB each
210
- await Promise.all([
211
- drain(gov.throttleBody(chunks(sizes))),
212
- drain(gov.throttleBody(chunks(sizes))),
213
- ]);
214
- const total = 2 * sizes.reduce((a, b) => a + b, 0); // 800 kB combined
215
- const ideal = (total / rate) * 1000;
216
- expect(clock.time()).toBeGreaterThanOrEqual(ideal - 1000);
217
- });
218
- });
219
- describe("BandwidthGovernor.clampConcurrency", () => {
220
- it("passes the pool size through when unset", () => {
221
- expect(new BandwidthGovernor({}).clampConcurrency(64)).toBe(64);
222
- });
223
- it("clamps the pool down but never raises it", () => {
224
- const gov = new BandwidthGovernor({ maxConcurrency: 2 });
225
- expect(gov.clampConcurrency(64)).toBe(2);
226
- expect(gov.clampConcurrency(1)).toBe(1);
227
- const loose = new BandwidthGovernor({ maxConcurrency: 100 });
228
- expect(loose.clampConcurrency(64)).toBe(64);
229
- });
230
- });
231
- describe("BandwidthGovernor.describePolicy", () => {
232
- it("reports off when nothing is configured", () => {
233
- expect(new BandwidthGovernor({}).describePolicy()).toBe("bandwidth governor: off");
234
- });
235
- it("reports the effective policy in one line", () => {
236
- expect(new BandwidthGovernor({
237
- maxBytesPerSec: 500000,
238
- maxConcurrency: 2,
239
- }).describePolicy()).toBe("bandwidth governor: 500000 B/s cap, concurrency 2");
240
- expect(new BandwidthGovernor({ percent: 40 }).describePolicy()).toBe(`bandwidth governor: adaptive 40% of observed link (floor ${MIN_ADAPTIVE_BYTES_PER_SEC} B/s)`);
241
- });
242
- });
243
- //# sourceMappingURL=bandwidth.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bandwidth.test.js","sourceRoot":"","sources":["../src/bandwidth.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=journal-delta-writes.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal-delta-writes.test.d.ts","sourceRoot":"","sources":["../src/journal-delta-writes.test.ts"],"names":[],"mappings":""}
@@ -1,140 +0,0 @@
1
- /**
2
- * Regression tests for the journal's write amplification.
3
- *
4
- * `writeJournal` used to do two full-file rewrites per update: a whole-state
5
- * snapshot via `replaceState`, and a complete copy of the journal in the pre-v3
6
- * JSON format. Measured on a live install, a vault tracking half a million
7
- * files paid 178 MB for each of those, about three times a minute — roughly a
8
- * gigabyte a minute to record edits worth a few hundred bytes.
9
- *
10
- * Both are gone. Updates now append a type-2 delta the store has always been
11
- * able to read, and the JSON path holds a small locator instead of a copy.
12
- *
13
- * The property that matters most is the round trip. An entry left out of a
14
- * delta is *asserted* to be unchanged, so a diff that is too lenient does not
15
- * throw — it silently loses data. Every mutation shape below is therefore
16
- * checked by reading the journal back and comparing it whole.
17
- */
18
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
19
- import * as fs from "fs";
20
- import * as os from "os";
21
- import * as path from "path";
22
- import { writeJournal, readJournal, getJournalPath, listJournals } from "./journal.js";
23
- function entry(over = {}) {
24
- return {
25
- hash: "a".repeat(64),
26
- size: 10,
27
- syncedAt: "2026-01-01T00:00:00.000Z",
28
- direction: "up",
29
- ...over,
30
- };
31
- }
32
- function journal(files, lastSync = "t0") {
33
- return { version: "2", lastSync, files, pulls: [] };
34
- }
35
- /** Serialized size of the file at the legacy journal path. */
36
- function locatorBytes(slug) {
37
- return fs.statSync(getJournalPath(slug)).size;
38
- }
39
- describe("journal delta writes", () => {
40
- let stateDir;
41
- beforeEach(() => {
42
- stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "hq-journal-delta-"));
43
- process.env.HQ_STATE_DIR = stateDir;
44
- });
45
- afterEach(() => {
46
- delete process.env.HQ_STATE_DIR;
47
- fs.rmSync(stateDir, { recursive: true, force: true });
48
- });
49
- // --- the round trip, over every mutation shape --------------------------
50
- it("round-trips an added file", () => {
51
- writeJournal("acme", journal({ "a.md": entry() }));
52
- const next = journal({ "a.md": entry(), "b.md": entry({ size: 20 }) }, "t1");
53
- writeJournal("acme", next);
54
- expect(readJournal("acme")).toEqual(next);
55
- });
56
- it("round-trips a modified file", () => {
57
- writeJournal("acme", journal({ "a.md": entry() }));
58
- const next = journal({ "a.md": entry({ hash: "b".repeat(64), size: 99 }) }, "t1");
59
- writeJournal("acme", next);
60
- expect(readJournal("acme")).toEqual(next);
61
- });
62
- it("round-trips a deleted file", () => {
63
- writeJournal("acme", journal({ "a.md": entry(), "b.md": entry() }));
64
- const next = journal({ "a.md": entry() }, "t1");
65
- writeJournal("acme", next);
66
- expect(readJournal("acme")).toEqual(next);
67
- expect(readJournal("acme").files["b.md"]).toBeUndefined();
68
- });
69
- it("round-trips a change confined to an optional field", () => {
70
- // The comparison must cover every property of an entry, not a hand-picked
71
- // list — a change only to `remoteEtag` still has to reach the delta.
72
- writeJournal("acme", journal({ "a.md": entry() }));
73
- const next = journal({ "a.md": entry({ remoteEtag: "etag-1" }) }, "t1");
74
- writeJournal("acme", next);
75
- expect(readJournal("acme").files["a.md"]?.remoteEtag).toBe("etag-1");
76
- });
77
- it("round-trips removal of an optional field", () => {
78
- writeJournal("acme", journal({ "a.md": entry({ mtimeMs: 5 }) }));
79
- const next = journal({ "a.md": entry() }, "t1");
80
- writeJournal("acme", next);
81
- expect(readJournal("acme").files["a.md"]).not.toHaveProperty("mtimeMs");
82
- });
83
- it("round-trips lastSync on an otherwise unchanged journal", () => {
84
- writeJournal("acme", journal({ "a.md": entry() }, "t0"));
85
- writeJournal("acme", journal({ "a.md": entry() }, "t-later"));
86
- expect(readJournal("acme").lastSync).toBe("t-later");
87
- });
88
- it("survives a long run of successive updates", () => {
89
- writeJournal("acme", journal({}));
90
- const files = {};
91
- for (let i = 0; i < 40; i++) {
92
- files[`f${i}.md`] = entry({ size: i });
93
- if (i % 7 === 3)
94
- delete files[`f${i - 1}.md`];
95
- writeJournal("acme", journal({ ...files }, `t${i}`));
96
- }
97
- expect(readJournal("acme")).toEqual(journal({ ...files }, "t39"));
98
- });
99
- // --- the legacy JSON path is now a locator ------------------------------
100
- it("keeps the legacy path tiny instead of copying the journal into it", () => {
101
- const many = {};
102
- for (let i = 0; i < 4000; i++) {
103
- many[`knowledge/notes/file-${i}-${"x".repeat(60)}.md`] = entry();
104
- }
105
- writeJournal("big", journal(many));
106
- writeJournal("big", journal({ ...many, "one-more.md": entry() }, "t1"));
107
- // A full copy of this journal is hundreds of KB; the locator is bytes.
108
- expect(locatorBytes("big")).toBeLessThan(4096);
109
- // …and the real state is intact.
110
- expect(Object.keys(readJournal("big").files)).toHaveLength(4001);
111
- });
112
- it("replaces a pre-existing full copy in place, reclaiming its space", () => {
113
- // An install upgrading from the old format arrives with a full copy on
114
- // disk. It must be overwritten by an ordinary write — not left to grow, and
115
- // not requiring a separate cleanup step anyone has to remember to run.
116
- writeJournal("upgraded", journal({ "a.md": entry() }));
117
- const bulky = JSON.stringify(journal(Object.fromEntries(Array.from({ length: 3000 }, (_, i) => [`f${i}-${"y".repeat(60)}.md`, entry()]))));
118
- fs.writeFileSync(getJournalPath("upgraded"), bulky);
119
- expect(locatorBytes("upgraded")).toBeGreaterThan(100_000);
120
- writeJournal("upgraded", journal({ "a.md": entry(), "b.md": entry() }, "t1"));
121
- expect(locatorBytes("upgraded")).toBeLessThan(4096);
122
- expect(Object.keys(readJournal("upgraded").files).sort()).toEqual(["a.md", "b.md"]);
123
- });
124
- it("still lets listJournals discover every slug", () => {
125
- // The locator's remaining job: store directories are named by a one-way
126
- // digest, so this filename is the only way to enumerate slugs.
127
- writeJournal("alpha", journal({ "a.md": entry() }));
128
- writeJournal("bravo", journal({ "b.md": entry() }));
129
- writeJournal("charlie", journal({ "c.md": entry() }));
130
- expect(listJournals().map((j) => j.slug)).toEqual(["alpha", "bravo", "charlie"]);
131
- expect(listJournals().find((j) => j.slug === "bravo")?.journal.files).toHaveProperty("b.md");
132
- });
133
- it("does not rewrite the locator once it is in place", () => {
134
- writeJournal("stable", journal({ "a.md": entry() }));
135
- const first = fs.statSync(getJournalPath("stable")).mtimeMs;
136
- writeJournal("stable", journal({ "a.md": entry(), "b.md": entry() }, "t1"));
137
- expect(fs.statSync(getJournalPath("stable")).mtimeMs).toBe(first);
138
- });
139
- });
140
- //# sourceMappingURL=journal-delta-writes.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal-delta-writes.test.js","sourceRoot":"","sources":["../src/journal-delta-writes.test.ts"],"names":[],"mappings":"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"}