@cello-protocol/daemon 0.0.167 → 0.0.169

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 (80) hide show
  1. package/dist/daemon.d.ts.map +1 -1
  2. package/dist/daemon.js +115 -254
  3. package/dist/daemon.js.map +1 -1
  4. package/dist/document-amendment-store.d.ts +94 -46
  5. package/dist/document-amendment-store.d.ts.map +1 -1
  6. package/dist/document-amendment-store.js +217 -102
  7. package/dist/document-amendment-store.js.map +1 -1
  8. package/dist/document-delivery-transport.d.ts +41 -52
  9. package/dist/document-delivery-transport.d.ts.map +1 -1
  10. package/dist/document-delivery-transport.js +6 -156
  11. package/dist/document-delivery-transport.js.map +1 -1
  12. package/dist/document-frame-router.d.ts +13 -17
  13. package/dist/document-frame-router.d.ts.map +1 -1
  14. package/dist/document-frame-router.js +21 -93
  15. package/dist/document-frame-router.js.map +1 -1
  16. package/dist/document-handlers.d.ts +1 -1
  17. package/dist/document-handlers.d.ts.map +1 -1
  18. package/dist/document-handlers.js +471 -466
  19. package/dist/document-handlers.js.map +1 -1
  20. package/dist/document-handshake.d.ts +4 -1
  21. package/dist/document-handshake.d.ts.map +1 -1
  22. package/dist/document-handshake.js +3 -1
  23. package/dist/document-handshake.js.map +1 -1
  24. package/dist/document-inbound.d.ts +18 -5
  25. package/dist/document-inbound.d.ts.map +1 -1
  26. package/dist/document-inbound.js +94 -110
  27. package/dist/document-inbound.js.map +1 -1
  28. package/dist/document-layer.d.ts +28 -67
  29. package/dist/document-layer.d.ts.map +1 -1
  30. package/dist/document-layer.js +670 -565
  31. package/dist/document-layer.js.map +1 -1
  32. package/dist/document-lifecycle.d.ts +11 -157
  33. package/dist/document-lifecycle.d.ts.map +1 -1
  34. package/dist/document-lifecycle.js +26 -561
  35. package/dist/document-lifecycle.js.map +1 -1
  36. package/dist/document-publish.d.ts +13 -0
  37. package/dist/document-publish.d.ts.map +1 -1
  38. package/dist/document-publish.js +19 -11
  39. package/dist/document-publish.js.map +1 -1
  40. package/dist/document-reconcile-engine.d.ts +66 -0
  41. package/dist/document-reconcile-engine.d.ts.map +1 -0
  42. package/dist/document-reconcile-engine.js +225 -0
  43. package/dist/document-reconcile-engine.js.map +1 -0
  44. package/dist/document-reconcile-scheduler.d.ts +91 -0
  45. package/dist/document-reconcile-scheduler.d.ts.map +1 -0
  46. package/dist/document-reconcile-scheduler.js +153 -0
  47. package/dist/document-reconcile-scheduler.js.map +1 -0
  48. package/dist/document-rejection.d.ts +2 -0
  49. package/dist/document-rejection.d.ts.map +1 -1
  50. package/dist/document-rejection.js +5 -1
  51. package/dist/document-rejection.js.map +1 -1
  52. package/dist/document-store.d.ts +18 -220
  53. package/dist/document-store.d.ts.map +1 -1
  54. package/dist/document-store.js +95 -717
  55. package/dist/document-store.js.map +1 -1
  56. package/dist/initiate-session-handler.d.ts +5 -0
  57. package/dist/initiate-session-handler.d.ts.map +1 -1
  58. package/dist/initiate-session-handler.js +1 -0
  59. package/dist/initiate-session-handler.js.map +1 -1
  60. package/package.json +5 -5
  61. package/dist/delivery-sweep-bound.d.ts +0 -79
  62. package/dist/delivery-sweep-bound.d.ts.map +0 -1
  63. package/dist/delivery-sweep-bound.js +0 -109
  64. package/dist/delivery-sweep-bound.js.map +0 -1
  65. package/dist/document-ack-inbound.d.ts +0 -71
  66. package/dist/document-ack-inbound.d.ts.map +0 -1
  67. package/dist/document-ack-inbound.js +0 -210
  68. package/dist/document-ack-inbound.js.map +0 -1
  69. package/dist/document-control-notifier.d.ts +0 -107
  70. package/dist/document-control-notifier.d.ts.map +0 -1
  71. package/dist/document-control-notifier.js +0 -137
  72. package/dist/document-control-notifier.js.map +0 -1
  73. package/dist/document-delivery.d.ts +0 -229
  74. package/dist/document-delivery.d.ts.map +0 -1
  75. package/dist/document-delivery.js +0 -449
  76. package/dist/document-delivery.js.map +0 -1
  77. package/dist/document-join-store.d.ts +0 -80
  78. package/dist/document-join-store.d.ts.map +0 -1
  79. package/dist/document-join-store.js +0 -197
  80. package/dist/document-join-store.js.map +0 -1
@@ -1,229 +0,0 @@
1
- /**
2
- * DOD-DOC-DELIVERY-1 — daemon-autonomous delivery (§16.4).
3
- *
4
- * Publish writes the envelope to the log and returns. Delivery is somebody else's job, and that
5
- * somebody is this worker: it derives what is pending FROM THE LOG, checks the peer is reachable
6
- * before dialing, opens or reuses a session itself, delivers, and records the ack — with zero agent
7
- * attention on either end. Two agents in opposite time zones sync overnight without either agent
8
- * doing anything.
9
- *
10
- * ── PENDING IS DERIVED, NEVER HELD ────────────────────────────────────────────────────────────
11
- *
12
- * "Unacknowledged envelopes I authored" is a WHERE clause over the log, and that is the whole
13
- * definition. A queue in memory does not survive a restart — the daemon is a long-running local
14
- * process that gets restarted routinely — and a queue in its own table is a second source of truth
15
- * that can disagree with the log about what was sent. The attempt counter and the next-attempt
16
- * time live on the envelope row for the same reason: a backoff that resets on restart is not a
17
- * backoff, and a daemon restarting in a reconnect loop would hammer an unreachable peer at full
18
- * rate forever.
19
- *
20
- * ── WHY LOOKUP BEFORE DIAL ────────────────────────────────────────────────────────────────────
21
- *
22
- * §16.4's design is presence-driven push, but there is no presence subscription today (parked,
23
- * M14-P4). Without one, the honest substitute is: ask the directory whether the peer is reachable,
24
- * and if it is not, do not burn a dial — schedule a retry on a capped backoff. Dialing an offline
25
- * peer to find out it is offline is the same information at much higher cost, and it is the cost
26
- * that would be paid on every pending envelope, on every tick, for as long as the peer is away.
27
- */
28
- import type { DocumentStore, DocumentEnvelopeRow } from "./document-store.js";
29
- import type { Logger } from "./types.js";
30
- /**
31
- * The transport seam. Narrow on purpose (M4 rule: add to an interface only when a failing test or
32
- * a production behaviour requires it) — the worker's job is scheduling and bookkeeping, and every
33
- * dial-level concern belongs to the adapter behind this.
34
- */
35
- export interface DocumentDeliveryTransport {
36
- /**
37
- * Is the peer reachable right now? `discovery_lookup` today. Returns false rather than throwing
38
- * for an ordinary "not online"; a throw means the LOOKUP failed, which is a different fact and
39
- * must not be recorded as the peer being away.
40
- */
41
- isPeerReachable(peerAgentId: string, correlationId: string): Promise<{
42
- reachable: boolean;
43
- unknownAgent: boolean;
44
- }>;
45
- /**
46
- * Deliver one envelope over a session the transport opens or reuses (§16.4: daemon-chooses by
47
- * default; `sessionHint` is the one case with audit value — the agent is mid-conversation about
48
- * the document and wants the discussion and the change in one sealed record).
49
- */
50
- /**
51
- * `ok` means the peer's daemon ANSWERED about this envelope — it is not "the peer liked it".
52
- * `admitted: false` is a rejection (§3.2's `0x05`), and a rejection IS an ack for delivery
53
- * purposes: the peer has decided, so there is nothing left to retry. Without the distinction the
54
- * adapter has to map a rejection onto one of two lies — `ok: true` makes the delivery record say
55
- * the peer admitted content it refused, and `ok: false` redelivers an envelope the peer has
56
- * already ruled on, forever, re-triggering their gate and their retry counter until the document
57
- * stalls for reasons the operator cannot see.
58
- *
59
- * `sessionOpened` distinguishes a session this delivery opened from one it reused — the audit
60
- * distinction §16.4 cares about, and unrecoverable after the fact.
61
- */
62
- /**
63
- * Send already-encoded bytes to a peer over the same open-or-reuse-then-seal path `deliver` uses.
64
- *
65
- * Exists for the frames that are NOT in the envelope log and therefore have no delivery record to
66
- * schedule: a proposal (there is no document yet), an ack, a rejection. Those still have to reach
67
- * the peer, and the alternative — a second implementation of session acquisition — would drift on
68
- * exactly the things that matter here: which session gets reused, and whether one this daemon
69
- * opened gets sealed.
70
- *
71
- * `documentId` is for the log line only; nothing about the send depends on it.
72
- */
73
- sendBytes(input: {
74
- peerAgentId: string;
75
- documentId: string;
76
- bytes: Uint8Array;
77
- sessionHint?: string;
78
- correlationId: string;
79
- /**
80
- * The witnessed leaf DOMAIN. Defaults to the document kind (0x04); a refusal passes 0x05.
81
- * Only the caller knows which frame it is holding, and the directory's legibility rules
82
- * discriminate on it — see `DOCUMENT_LEAF_KIND` in document-delivery-transport.ts.
83
- */
84
- leafKind?: number;
85
- }): Promise<{
86
- ok: true;
87
- sessionId: string;
88
- sessionOpened: boolean;
89
- /**
90
- * The relay took it because the holder had no live counterparty — it is NOT with them yet.
91
- * Only a caller that has no ack frame needs this, and for those `ok` alone is a lie.
92
- */
93
- parked?: boolean;
94
- } | {
95
- ok: false;
96
- reason: string;
97
- detail?: string;
98
- }>;
99
- deliver(input: {
100
- peerAgentId: string;
101
- documentId: string;
102
- envelope: DocumentEnvelopeRow;
103
- sessionHint?: string;
104
- correlationId: string;
105
- /**
106
- * How long THIS envelope may hold an opened session waiting for the peer's ack.
107
- *
108
- * A BUDGET SPENT ACROSS THE PASS, not a per-envelope allowance. The wait is awaited inside
109
- * three nested sequential loops — agents, then documents, then envelopes — so a fixed 10s each
110
- * meant a backlog of 100 to one silent peer could burn ~1000 seconds during which NO other
111
- * agent's documents were swept at all. And a peer that never acks is the ordinary case during a
112
- * version rollout, which this repo does continuously because both sides float `latest`.
113
- *
114
- * Zero means do not wait. The seal still happens; only the grace is skipped.
115
- */
116
- ackGraceMs: number;
117
- }): Promise<{
118
- ok: true;
119
- sessionId: string;
120
- sessionOpened: boolean;
121
- /**
122
- * `true` admitted, `false` rejected — both are ACKS, the peer has decided. `null` means the
123
- * envelope LEFT (or was parked for an offline peer) and no answer has come back yet.
124
- *
125
- * The third state is not hedging; both two-valued answers are dishonest for a send whose
126
- * outcome is unknown. `true` marks the envelope acknowledged in the log while the peer may
127
- * never have applied it — and the log being right about what the peer holds is the entire
128
- * reason pending is derived from it. `false` counts a send that WORKED as a failure and
129
- * re-sends content already in flight.
130
- */
131
- admitted: boolean | null;
132
- /**
133
- * The relay took it because the peer had no live counterparty on that session.
134
- *
135
- * Distinct from `admitted: null`, which covers both a live send awaiting an answer and this.
136
- * The two want different retry schedules and were given the same one — see the scheduling
137
- * branch in `#run`.
138
- */
139
- parked: boolean;
140
- rejectionReason?: string;
141
- } | {
142
- ok: false;
143
- reason: string;
144
- detail?: string;
145
- }>;
146
- }
147
- /**
148
- * Backoff schedule in ms: ~1s, 5s, 30s, 2m, 10m, then the last entry repeats.
149
- *
150
- * The final entry IS the cap — there is no separate ceiling constant. There was one, set to 900s,
151
- * and it was unreachable: the index clamp meant the schedule never produced a value above 600s, so
152
- * the exported "cap" was a number the code could not emit and the tests were using it as a synonym
153
- * for "much later". A documented limit the implementation cannot reach is worse than none.
154
- *
155
- * Capped at all because the peer coming back online is the event we are waiting for and it can
156
- * happen at any moment — an uncapped curve leaves a peer that returned after a long absence waiting
157
- * hours for a delivery that has been ready the whole time.
158
- */
159
- /**
160
- * Total ack-grace one sweep pass may spend, across every agent, document and envelope in it.
161
- *
162
- * The wait exists so a session we opened is not torn down before the peer's answer arrives. It is
163
- * capped as a PASS budget because the loops it sits inside are sequential: a per-envelope allowance
164
- * meant one silent peer with a backlog could hold the sweep for the better part of an hour, and the
165
- * only symptom would be other agents' documents quietly not syncing.
166
- *
167
- * 30s ≈ three full graces. Enough for the ordinary case (one or two opened sessions per pass, ack
168
- * back in well under a second) without letting an unresponsive peer own the pass.
169
- */
170
- export declare const DELIVERY_ACK_GRACE_BUDGET_MS = 30000;
171
- export declare const DELIVERY_BACKOFF_MS: readonly [1000, 5000, 30000, 120000, 600000];
172
- export declare const DELIVERY_BACKOFF_CAP_MS: 5000 | 1000 | 30000 | 120000 | 600000;
173
- /**
174
- * How long to wait for an ACK after a SUCCESSFUL send, before sending again.
175
- *
176
- * Deliberately NOT the failure backoff. "How long do I wait after a failure" and "how long do I
177
- * wait for an answer" are different questions, and reusing the first for the second re-sent a
178
- * successfully-delivered envelope one second later — and every resend is not free: `sendContent`
179
- * witnesses a message-leaf hash to the relay and appends a leaf to the session chain, so a
180
- * never-acked envelope would pollute the peer's sealed conversation record forever.
181
- */
182
- export declare const DELIVERY_ACK_TIMEOUT_MS: 5000 | 1000 | 30000 | 120000 | 600000;
183
- /**
184
- * How many times an envelope may be SENT without ever being acknowledged before the document
185
- * stalls.
186
- *
187
- * A peer that will never answer must eventually stop being treated as a transient. Without a
188
- * ceiling, an envelope sent to a peer whose client cannot ack — which is every peer until the
189
- * inbound handler ships on both sides — is re-sent forever and is indistinguishable, in the log
190
- * and in `list`, from one that is about to land.
191
- */
192
- export declare const DELIVERY_MAX_UNACKED_SENDS = 5;
193
- /**
194
- * A document whose peer cannot be resolved is not transient, so it gets the cap immediately rather
195
- * than climbing to it — but it DOES get scheduled. See the `no_peer` branch.
196
- */
197
- export declare const DELIVERY_UNRESOLVABLE_RETRY_MS: 5000 | 1000 | 30000 | 120000 | 600000;
198
- export declare function backoffFor(attempts: number): number;
199
- export interface DeliveryTickResult {
200
- attempted: number;
201
- delivered: number;
202
- /** Sent (or parked) with no answer yet — in flight, neither done nor failed. */
203
- sent: number;
204
- /** Answered but refused. Acked all the same — the peer has decided. */
205
- rejected: number;
206
- deferred: number;
207
- failed: number;
208
- }
209
- export declare class DocumentDelivery {
210
- #private;
211
- constructor(store: DocumentStore, transport: DocumentDeliveryTransport, logger: Logger);
212
- /**
213
- * One pass over what is due. Returns counts rather than throwing on a per-envelope failure: one
214
- * unreachable peer must not stop delivery to every other peer, which is precisely the "works
215
- * only when all nodes are healthy" shape the project forbids.
216
- */
217
- /**
218
- * One pass over what is due, PER (document, holder). Returns counts rather than throwing on a
219
- * per-target failure: one unreachable HOLDER must not stop delivery to any other — the same
220
- * "works only when all nodes are healthy" shape the project forbids, now per holder.
221
- */
222
- tick(ownerAgentId: string, holdersFor: (documentId: string) => string[] | null, nowMs: number, opts?: {
223
- sessionHints?: ReadonlyMap<string, string>;
224
- correlationId?: string;
225
- /** Our own wire sender id. Defaults to the owner key for callers whose ids coincide. */
226
- senderAgentId?: string;
227
- }): Promise<DeliveryTickResult>;
228
- }
229
- //# sourceMappingURL=document-delivery.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"document-delivery.d.ts","sourceRoot":"","sources":["../src/document-delivery.ts"],"names":[],"mappings":"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"}