@supersuit/suggest-a-change 0.1.5 → 0.1.6
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.
- package/CHANGELOG.md +4 -0
- package/dist/client/outbox.d.ts +2 -0
- package/dist/client/outbox.js +5 -2
- package/package.json +1 -1
- package/src/client/outbox.ts +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.6 (2026-10-15)
|
|
4
|
+
|
|
5
|
+
- **Writes made in the same millisecond leave the phone in the order they were made.** `enqueue` stamps each op with `seq`, and the queue sorts by `at`, then `seq`, then id. Before, ties fell to the id, so a screen that saved a draft and then asked for it to be prepared in one tick sent the prepare first about half the time, and the receiver prepared the draft as it had been.
|
|
6
|
+
|
|
3
7
|
## 0.1.5 (2026-10-14)
|
|
4
8
|
|
|
5
9
|
- **The agent is Pluma.** Every word a person reads now names Pluma, the agent formerly called Freeda: "With Pluma", "Goes to <owner> and Pluma", "Pluma picks it up". The status key `with-freeda` is unchanged, so stored reports and older clients still read. A copy of the contract vendored elsewhere must be taken again: these are new bytes.
|
package/dist/client/outbox.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface Op {
|
|
|
9
9
|
/** The id of the write this one belongs to (a part's report or follow-up). While that write is refused, this one is held, not sent. */
|
|
10
10
|
parent?: string;
|
|
11
11
|
at: number;
|
|
12
|
+
/** The order this phone made it in, among writes with the same `at`. Written by enqueue. */
|
|
13
|
+
seq?: number;
|
|
12
14
|
error?: string;
|
|
13
15
|
}
|
|
14
16
|
export type Sent = 'done' | {
|
package/dist/client/outbox.js
CHANGED
|
@@ -5,8 +5,11 @@ export function makeOutbox({ store, send, reach }) {
|
|
|
5
5
|
// the new write existed. Measured on the phone: without this, a second answer sat on the phone
|
|
6
6
|
// until the 15 s tick.
|
|
7
7
|
let again = false;
|
|
8
|
+
// Two writes in one millisecond (a save, then the step that reads it) keep the order they were made
|
|
9
|
+
// in. Ordering them by id instead sent the second first about half the time.
|
|
10
|
+
let made = 0;
|
|
8
11
|
async function pending() {
|
|
9
|
-
return (await store.all('outbox')).map((r) => r.value).sort((a, b) => a.at - b.at || a.id.localeCompare(b.id));
|
|
12
|
+
return (await store.all('outbox')).map((r) => r.value).sort((a, b) => a.at - b.at || (a.seq ?? 0) - (b.seq ?? 0) || a.id.localeCompare(b.id));
|
|
10
13
|
}
|
|
11
14
|
async function tell(landed) {
|
|
12
15
|
const all = await pending();
|
|
@@ -56,7 +59,7 @@ export function makeOutbox({ store, send, reach }) {
|
|
|
56
59
|
}
|
|
57
60
|
return {
|
|
58
61
|
pending,
|
|
59
|
-
async enqueue(op) { await store.put('outbox', op.id, op); await tell(); },
|
|
62
|
+
async enqueue(op) { await store.put('outbox', op.id, { ...op, seq: op.seq ?? ++made }); await tell(); },
|
|
60
63
|
drain() {
|
|
61
64
|
if (running) {
|
|
62
65
|
again = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supersuit/suggest-a-change",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "The report format and flow behind a Suggest a change button: what a report is, who acts at each step, the screens, and the check every app runs. The contract has zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/client/outbox.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface Op {
|
|
|
18
18
|
/** The id of the write this one belongs to (a part's report or follow-up). While that write is refused, this one is held, not sent. */
|
|
19
19
|
parent?: string
|
|
20
20
|
at: number
|
|
21
|
+
/** The order this phone made it in, among writes with the same `at`. Written by enqueue. */
|
|
22
|
+
seq?: number
|
|
21
23
|
error?: string
|
|
22
24
|
}
|
|
23
25
|
export type Sent = 'done' | { refused: string }
|
|
@@ -30,9 +32,12 @@ export function makeOutbox({ store, send, reach }: { store: Store; send(op: Op):
|
|
|
30
32
|
// the new write existed. Measured on the phone: without this, a second answer sat on the phone
|
|
31
33
|
// until the 15 s tick.
|
|
32
34
|
let again = false
|
|
35
|
+
// Two writes in one millisecond (a save, then the step that reads it) keep the order they were made
|
|
36
|
+
// in. Ordering them by id instead sent the second first about half the time.
|
|
37
|
+
let made = 0
|
|
33
38
|
|
|
34
39
|
async function pending(): Promise<Op[]> {
|
|
35
|
-
return (await store.all<Op>('outbox')).map((r) => r.value).sort((a, b) => a.at - b.at || a.id.localeCompare(b.id))
|
|
40
|
+
return (await store.all<Op>('outbox')).map((r) => r.value).sort((a, b) => a.at - b.at || (a.seq ?? 0) - (b.seq ?? 0) || a.id.localeCompare(b.id))
|
|
36
41
|
}
|
|
37
42
|
async function tell(landed?: string) {
|
|
38
43
|
const all = await pending()
|
|
@@ -69,7 +74,7 @@ export function makeOutbox({ store, send, reach }: { store: Store; send(op: Op):
|
|
|
69
74
|
}
|
|
70
75
|
return {
|
|
71
76
|
pending,
|
|
72
|
-
async enqueue(op: Op) { await store.put('outbox', op.id, op); await tell() },
|
|
77
|
+
async enqueue(op: Op) { await store.put('outbox', op.id, { ...op, seq: op.seq ?? ++made }); await tell() },
|
|
73
78
|
drain(): Promise<void> {
|
|
74
79
|
if (running) { again = true; return running }
|
|
75
80
|
return (running = run().finally(() => { running = null }))
|