@fungi.computer/bird-dog 0.2.1 → 0.3.0

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/dist/effect.d.ts CHANGED
@@ -23,18 +23,37 @@ export declare const BirdDogSystemIdentitySchema: Schema.Struct<{
23
23
  }>;
24
24
  /** The most characters a reply's failure diagnostic may carry. */
25
25
  export declare const BIRD_DOG_DIAGNOSTIC_MAX_LENGTH = 200;
26
+ /** The most open items one reply names as waiting on its recipient. */
27
+ export declare const BIRD_DOG_WAITING_MAX_ITEMS = 8;
28
+ /**
29
+ * One open item of the replying Session that waits on this reply's recipient.
30
+ * BirdDog carries the three bounded fields; the replying host owns their
31
+ * meaning and the recipient host owns every decision about them.
32
+ */
33
+ export declare const BirdDogWaitingItemSchema: Schema.Struct<{
34
+ readonly itemId: Schema.String;
35
+ readonly kind: Schema.String;
36
+ readonly summary: Schema.String;
37
+ }>;
26
38
  /**
27
39
  * Parser for the settlement facts a reply carries beside its content: the
28
- * replying Session's command, its exact Watchdog outcome and, for work that did
29
- * not complete, the Session's bounded terminal diagnostic.
40
+ * replying Session's command, its exact Watchdog outcome, for work that did
41
+ * not complete the Session's bounded terminal diagnostic and, when the
42
+ * replying host names any, the open items now waiting on the recipient.
30
43
  */
31
44
  export declare const SettledBirdDogReplySchema: Schema.Struct<{
32
45
  readonly commandId: Schema.String;
33
46
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
34
47
  readonly diagnostic: Schema.optionalKey<Schema.String>;
48
+ readonly waitingOnYou: Schema.optionalKey<Schema.$Array<Schema.Struct<{
49
+ readonly itemId: Schema.String;
50
+ readonly kind: Schema.String;
51
+ readonly summary: Schema.String;
52
+ }>>>;
35
53
  }>;
36
54
  /** A terminal delivery failure, correlated by the original mail key only. */
37
55
  export declare const BirdDogUndeliverableReasonSchema: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
56
+ /** Parser for a terminal delivery failure reply. */
38
57
  export declare const UndeliverableBirdDogReplySchema: Schema.Struct<{
39
58
  readonly outcome: Schema.Literal<"undeliverable">;
40
59
  readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
@@ -44,10 +63,16 @@ export declare const AcceptedBirdDogReplySchema: Schema.Struct<{
44
63
  readonly outcome: Schema.Literal<"accepted">;
45
64
  readonly commandId: Schema.String;
46
65
  }>;
66
+ /** Parser for any reply: settled, accepted or undeliverable. */
47
67
  export declare const BirdDogReplySchema: Schema.Union<readonly [Schema.Struct<{
48
68
  readonly commandId: Schema.String;
49
69
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
50
70
  readonly diagnostic: Schema.optionalKey<Schema.String>;
71
+ readonly waitingOnYou: Schema.optionalKey<Schema.$Array<Schema.Struct<{
72
+ readonly itemId: Schema.String;
73
+ readonly kind: Schema.String;
74
+ readonly summary: Schema.String;
75
+ }>>>;
51
76
  }>, Schema.Struct<{
52
77
  readonly outcome: Schema.Literal<"undeliverable">;
53
78
  readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
@@ -63,6 +88,7 @@ export declare const BirdDogReplySchema: Schema.Union<readonly [Schema.Struct<{
63
88
  * line is cut, so a cut never exposes part of one.
64
89
  */
65
90
  export declare function boundedDiagnostic(text: string): string | undefined;
91
+ /** Parser for addressed Agent mail, from an Agent or from the Hub system. */
66
92
  export declare const BirdDogMailSchema: Schema.Union<readonly [Schema.Struct<{
67
93
  readonly from: Schema.Struct<{
68
94
  readonly kind: Schema.Literal<"agent">;
@@ -74,6 +100,11 @@ export declare const BirdDogMailSchema: Schema.Union<readonly [Schema.Struct<{
74
100
  readonly commandId: Schema.String;
75
101
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
76
102
  readonly diagnostic: Schema.optionalKey<Schema.String>;
103
+ readonly waitingOnYou: Schema.optionalKey<Schema.$Array<Schema.Struct<{
104
+ readonly itemId: Schema.String;
105
+ readonly kind: Schema.String;
106
+ readonly summary: Schema.String;
107
+ }>>>;
77
108
  }>, Schema.Struct<{
78
109
  readonly outcome: Schema.Literal<"accepted">;
79
110
  readonly commandId: Schema.String;
@@ -146,6 +177,11 @@ export declare const BirdDogAgentJobPayloadSchema: Schema.Struct<{
146
177
  readonly commandId: Schema.String;
147
178
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
148
179
  readonly diagnostic: Schema.optionalKey<Schema.String>;
180
+ readonly waitingOnYou: Schema.optionalKey<Schema.$Array<Schema.Struct<{
181
+ readonly itemId: Schema.String;
182
+ readonly kind: Schema.String;
183
+ readonly summary: Schema.String;
184
+ }>>>;
149
185
  }>, Schema.Struct<{
150
186
  readonly outcome: Schema.Literal<"accepted">;
151
187
  readonly commandId: Schema.String;
@@ -214,6 +250,11 @@ export declare const BirdDogAgentJobInputSchema: Schema.Struct<{
214
250
  readonly commandId: Schema.String;
215
251
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
216
252
  readonly diagnostic: Schema.optionalKey<Schema.String>;
253
+ readonly waitingOnYou: Schema.optionalKey<Schema.$Array<Schema.Struct<{
254
+ readonly itemId: Schema.String;
255
+ readonly kind: Schema.String;
256
+ readonly summary: Schema.String;
257
+ }>>>;
217
258
  }>, Schema.Struct<{
218
259
  readonly outcome: Schema.Literal<"accepted">;
219
260
  readonly commandId: Schema.String;
@@ -307,9 +348,15 @@ export declare const decodeAgentJob: (job: WatchdogStoredJob) => BirdDogAgentJob
307
348
  /**
308
349
  * Build the replies owed by one settlement for a host-owned Post transport.
309
350
  * Each reply carries the settled content verbatim (or, when there is none, one
310
- * sentence naming the outcome, so the reply is always admissible text) and its
311
- * settlement facts as typed fields; the recipient's host authenticates them and decides how they
312
- * are presented. A reply never carries the settled work's host metadata.
351
+ * sentence naming the outcome and its diagnostic, so the reply is always
352
+ * admissible text) and its settlement facts as typed fields; the recipient's
353
+ * host authenticates them and decides how they are presented. A reply never
354
+ * carries the settled work's host metadata.
355
+ *
356
+ * Work a delegator's mail admitted replies to that mail under its `:reply:`
357
+ * key. Any other settled work, whatever started its turn, is a report to the
358
+ * Session's delegator of record, when the host names one (it does so once the
359
+ * Session is idle), under the delegator mail's `:report:` key.
313
360
  */
314
361
  export declare function settlementReplies(settlement: BirdDogSettlement, createdAt: number): readonly BirdDogMail[];
315
362
  /** Build the recipient's one stable acceptance notice for one original mail. */
package/dist/effect.js CHANGED
@@ -27,10 +27,23 @@ export const BirdDogSystemIdentitySchema = Schema.Struct({
27
27
  });
28
28
  /** The most characters a reply's failure diagnostic may carry. */
29
29
  export const BIRD_DOG_DIAGNOSTIC_MAX_LENGTH = 200;
30
+ /** The most open items one reply names as waiting on its recipient. */
31
+ export const BIRD_DOG_WAITING_MAX_ITEMS = 8;
32
+ /**
33
+ * One open item of the replying Session that waits on this reply's recipient.
34
+ * BirdDog carries the three bounded fields; the replying host owns their
35
+ * meaning and the recipient host owns every decision about them.
36
+ */
37
+ export const BirdDogWaitingItemSchema = Schema.Struct({
38
+ itemId: Identifier,
39
+ kind: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(64)),
40
+ summary: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(200)),
41
+ });
30
42
  /**
31
43
  * Parser for the settlement facts a reply carries beside its content: the
32
- * replying Session's command, its exact Watchdog outcome and, for work that did
33
- * not complete, the Session's bounded terminal diagnostic.
44
+ * replying Session's command, its exact Watchdog outcome, for work that did
45
+ * not complete the Session's bounded terminal diagnostic and, when the
46
+ * replying host names any, the open items now waiting on the recipient.
34
47
  */
35
48
  export const SettledBirdDogReplySchema = Schema.Struct({
36
49
  commandId: Identifier,
@@ -42,12 +55,14 @@ export const SettledBirdDogReplySchema = Schema.Struct({
42
55
  "outcome_unknown",
43
56
  ]),
44
57
  diagnostic: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(BIRD_DOG_DIAGNOSTIC_MAX_LENGTH))),
58
+ waitingOnYou: Schema.optionalKey(Schema.Array(BirdDogWaitingItemSchema).check(Schema.isMinLength(1), Schema.isMaxLength(BIRD_DOG_WAITING_MAX_ITEMS))),
45
59
  });
46
60
  /** A terminal delivery failure, correlated by the original mail key only. */
47
61
  export const BirdDogUndeliverableReasonSchema = Schema.Literals([
48
62
  "recipient_offline",
49
63
  "recipient_left",
50
64
  ]);
65
+ /** Parser for a terminal delivery failure reply. */
51
66
  export const UndeliverableBirdDogReplySchema = Schema.Struct({
52
67
  outcome: Schema.Literal("undeliverable"),
53
68
  reason: BirdDogUndeliverableReasonSchema,
@@ -57,6 +72,7 @@ export const AcceptedBirdDogReplySchema = Schema.Struct({
57
72
  outcome: Schema.Literal("accepted"),
58
73
  commandId: Identifier,
59
74
  });
75
+ /** Parser for any reply: settled, accepted or undeliverable. */
60
76
  export const BirdDogReplySchema = Schema.Union([
61
77
  SettledBirdDogReplySchema,
62
78
  UndeliverableBirdDogReplySchema,
@@ -106,6 +122,7 @@ const BirdDogMailFields = {
106
122
  /** The sender's opaque host metadata; BirdDog never reads it. */
107
123
  meta: Schema.optionalKey(Schema.Json),
108
124
  };
125
+ /** Parser for addressed Agent mail, from an Agent or from the Hub system. */
109
126
  export const BirdDogMailSchema = Schema.Union([
110
127
  Schema.Struct({
111
128
  ...BirdDogMailFields,
@@ -179,13 +196,23 @@ export const decodeAgentJob = (job) => Schema.decodeUnknownSync(BirdDogAgentJobP
179
196
  /**
180
197
  * Build the replies owed by one settlement for a host-owned Post transport.
181
198
  * Each reply carries the settled content verbatim (or, when there is none, one
182
- * sentence naming the outcome, so the reply is always admissible text) and its
183
- * settlement facts as typed fields; the recipient's host authenticates them and decides how they
184
- * are presented. A reply never carries the settled work's host metadata.
199
+ * sentence naming the outcome and its diagnostic, so the reply is always
200
+ * admissible text) and its settlement facts as typed fields; the recipient's
201
+ * host authenticates them and decides how they are presented. A reply never
202
+ * carries the settled work's host metadata.
203
+ *
204
+ * Work a delegator's mail admitted replies to that mail under its `:reply:`
205
+ * key. Any other settled work, whatever started its turn, is a report to the
206
+ * Session's delegator of record, when the host names one (it does so once the
207
+ * Session is idle), under the delegator mail's `:report:` key.
185
208
  */
186
209
  export function settlementReplies(settlement, createdAt) {
187
210
  const { work, mail } = decodeAgentJob(settlement.job);
188
- if (mail === undefined)
211
+ const answered = mail !== undefined && mail.replyTo.length > 0;
212
+ const owed = answered
213
+ ? { key: mail.key, agentId: mail.to.agentId, replyTo: mail.replyTo }
214
+ : settlement.delegator;
215
+ if (owed === undefined)
189
216
  return [];
190
217
  const outcome = settlement.job.outcome;
191
218
  const diagnostic = outcome === "completed" ||
@@ -193,17 +220,29 @@ export function settlementReplies(settlement, createdAt) {
193
220
  settlement.diagnostic === undefined
194
221
  ? undefined
195
222
  : boundedDiagnostic(settlement.diagnostic);
196
- const reply = Schema.decodeUnknownSync(SettledBirdDogReplySchema)(diagnostic === undefined
197
- ? { commandId: work.commandFactId, outcome }
198
- : { commandId: work.commandFactId, outcome, diagnostic });
199
- return mail.replyTo.map((destination, index) => ({
200
- key: `${mail.key}:reply:${String(index)}`,
223
+ const facts = { commandId: work.commandFactId, outcome };
224
+ if (diagnostic !== undefined)
225
+ facts.diagnostic = diagnostic;
226
+ if (settlement.waitingOnYou !== undefined &&
227
+ settlement.waitingOnYou.length > 0)
228
+ facts.waitingOnYou = settlement.waitingOnYou;
229
+ const reply = Schema.decodeUnknownSync(SettledBirdDogReplySchema)(facts);
230
+ return owed.replyTo.map((destination, index) => ({
231
+ key: answered
232
+ ? `${owed.key}:reply:${String(index)}`
233
+ : `${owed.key}:report:${work.commandFactId}:${String(index)}`,
201
234
  to: destination,
202
- from: { ...mail.to, sessionId: work.sessionId },
235
+ from: {
236
+ kind: "agent",
237
+ agentId: owed.agentId,
238
+ sessionId: work.sessionId,
239
+ },
203
240
  replyTo: [],
204
241
  content: settlement.content.length > 0
205
242
  ? settlement.content
206
- : `The delegated work ended ${outcome} without reply text.`,
243
+ : `The delegated work ended ${outcome}${diagnostic === undefined
244
+ ? " without reply text."
245
+ : `: ${diagnostic}`}`,
207
246
  createdAt,
208
247
  reply,
209
248
  }));
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export type BirdDogReply = Readonly<{
33
33
  outcome: "completed" | "failed" | "interrupted" | "cancelled" | "outcome_unknown";
34
34
  /** Bounded terminal diagnostic for work that did not complete or cancel. */
35
35
  diagnostic?: string;
36
+ /** Open items of the replying Session that now wait on this recipient. */
37
+ waitingOnYou?: readonly BirdDogWaitingItem[];
36
38
  }> | Readonly<{
37
39
  outcome: "undeliverable";
38
40
  reason: "recipient_offline" | "recipient_left";
@@ -125,10 +127,24 @@ export type BirdDogOptions = Readonly<{
125
127
  /** Return the host's current wall-clock time in milliseconds. */
126
128
  now: () => number;
127
129
  }>;
130
+ /**
131
+ * Who sent a Session its work first: the mail that opened the relationship.
132
+ * `agentId` is the Session's own Agent, the author of every report.
133
+ */
134
+ export type BirdDogDelegator = Readonly<{
135
+ key: string;
136
+ agentId: string;
137
+ replyTo: readonly BirdDogAgentReference[];
138
+ }>;
128
139
  /** Completed generic work plus the content owed to its correspondents. */
129
140
  export type BirdDogSettlement = Readonly<{
130
141
  job: WatchdogSettledJob;
131
142
  content: string;
143
+ /**
144
+ * The Session's delegator of record, named only when this settlement leaves
145
+ * the Session idle. Work without a replying mail of its own reports to it.
146
+ */
147
+ delegator?: BirdDogDelegator;
132
148
  /**
133
149
  * The Session's recorded terminal diagnostic. Replies carry it, bounded by
134
150
  * `boundedDiagnostic`, only for failed, interrupted and outcome_unknown work.
@@ -139,6 +155,17 @@ export type BirdDogSettlement = Readonly<{
139
155
  * example, naming who cancelled). Replies never carry it.
140
156
  */
141
157
  meta?: BirdDogMeta;
158
+ /**
159
+ * Open items of the settled Session that now wait on the correspondent this
160
+ * work came from. Replies carry them beside the settlement facts.
161
+ */
162
+ waitingOnYou?: readonly BirdDogWaitingItem[];
163
+ }>;
164
+ /** One open item named by a reply as waiting on its recipient. */
165
+ export type BirdDogWaitingItem = Readonly<{
166
+ itemId: string;
167
+ kind: string;
168
+ summary: string;
142
169
  }>;
143
170
  /** Durable reply delivery behind the mail-room interface. */
144
171
  export type BirdDogRuntime = Readonly<{
@@ -89,6 +89,7 @@ Effect host ports for the durable mail room.
89
89
  ```ts
90
90
  type BirdDogEffect = Readonly<{
91
91
  fanOut: (settlement) => Effect.Effect<void, BirdDogError>;
92
+ postMail?: (mail) => Effect.Effect<void, BirdDogError>;
92
93
  drainOutbox: () => Effect.Effect<void, BirdDogError>;
93
94
  nextWakeAt: () => Effect.Effect<number | undefined, BirdDogError>;
94
95
  }>;
@@ -98,6 +99,16 @@ Effect-native durable reply delivery.
98
99
 
99
100
  ## Variables
100
101
 
102
+ ### BIRD\_DOG\_MAIL\_CONTENT\_MAX\_BYTES
103
+
104
+ ```ts
105
+ const BIRD_DOG_MAIL_CONTENT_MAX_BYTES: number;
106
+ ```
107
+
108
+ The maximum UTF-8 size of one mail body.
109
+
110
+ ---
111
+
101
112
  ### BirdDogAgentReferenceSchema
102
113
 
103
114
  ```ts
@@ -112,6 +123,33 @@ Parser for an ordinary agent Session address.
112
123
 
113
124
  ---
114
125
 
126
+ ### BirdDogAgentRecipientReferenceSchema
127
+
128
+ ```ts
129
+ const BirdDogAgentRecipientReferenceSchema: Struct<{
130
+ kind: Literal<"agent">;
131
+ agentId: String;
132
+ sessionId: optionalKey<String>;
133
+ }>;
134
+ ```
135
+
136
+ An addressed Agent may create its first Session when accepting this mail.
137
+
138
+ ---
139
+
140
+ ### BirdDogSystemIdentitySchema
141
+
142
+ ```ts
143
+ const BirdDogSystemIdentitySchema: Struct<{
144
+ kind: Literal<"system">;
145
+ systemId: Literal<"hub">;
146
+ }>;
147
+ ```
148
+
149
+ The Hub's stable system identity for a terminal offline disposition.
150
+
151
+ ---
152
+
115
153
  ### BIRD\_DOG\_DIAGNOSTIC\_MAX\_LENGTH
116
154
 
117
155
  ```ts
@@ -122,10 +160,36 @@ The most characters a reply's failure diagnostic may carry.
122
160
 
123
161
  ---
124
162
 
125
- ### BirdDogReplySchema
163
+ ### BIRD\_DOG\_WAITING\_MAX\_ITEMS
126
164
 
127
165
  ```ts
128
- const BirdDogReplySchema: Struct<{
166
+ const BIRD_DOG_WAITING_MAX_ITEMS: 8 = 8;
167
+ ```
168
+
169
+ The most open items one reply names as waiting on its recipient.
170
+
171
+ ---
172
+
173
+ ### BirdDogWaitingItemSchema
174
+
175
+ ```ts
176
+ const BirdDogWaitingItemSchema: Struct<{
177
+ itemId: String;
178
+ kind: String;
179
+ summary: String;
180
+ }>;
181
+ ```
182
+
183
+ One open item of the replying Session that waits on this reply's recipient.
184
+ BirdDog carries the three bounded fields; the replying host owns their meaning
185
+ and the recipient host owns every decision about them.
186
+
187
+ ---
188
+
189
+ ### SettledBirdDogReplySchema
190
+
191
+ ```ts
192
+ const SettledBirdDogReplySchema: Struct<{
129
193
  commandId: String;
130
194
  outcome: Literals<
131
195
  readonly [
@@ -137,41 +201,68 @@ const BirdDogReplySchema: Struct<{
137
201
  ]
138
202
  >;
139
203
  diagnostic: optionalKey<String>;
204
+ waitingOnYou: optionalKey<
205
+ $Array<
206
+ Struct<{
207
+ itemId: String;
208
+ kind: String;
209
+ summary: String;
210
+ }>
211
+ >
212
+ >;
140
213
  }>;
141
214
  ```
142
215
 
143
216
  Parser for the settlement facts a reply carries beside its content: the replying
144
- Session's command, its exact Watchdog outcome and, for work that did not
145
- complete, the Session's bounded terminal diagnostic.
217
+ Session's command, its exact Watchdog outcome, for work that did not complete
218
+ the Session's bounded terminal diagnostic and, when the replying host names any,
219
+ the open items now waiting on the recipient.
146
220
 
147
221
  ---
148
222
 
149
- ### BirdDogMailSchema
223
+ ### BirdDogUndeliverableReasonSchema
150
224
 
151
225
  ```ts
152
- const BirdDogMailSchema: Struct<{
153
- key: String;
154
- to: Struct<{
155
- kind: Literal<"agent">;
156
- agentId: String;
157
- sessionId: String;
158
- }>;
159
- from: Struct<{
160
- kind: Literal<"agent">;
161
- agentId: String;
162
- sessionId: String;
163
- }>;
164
- replyTo: $Array<
165
- Struct<{
166
- kind: Literal<"agent">;
167
- agentId: String;
168
- sessionId: String;
169
- }>
170
- >;
171
- content: String;
172
- createdAt: Number;
173
- meta: optionalKey<Codec<Json, Json, never, never>>;
174
- reply: optionalKey<
226
+ const BirdDogUndeliverableReasonSchema: Literals<
227
+ readonly ["recipient_offline", "recipient_left"]
228
+ >;
229
+ ```
230
+
231
+ A terminal delivery failure, correlated by the original mail key only.
232
+
233
+ ---
234
+
235
+ ### UndeliverableBirdDogReplySchema
236
+
237
+ ```ts
238
+ const UndeliverableBirdDogReplySchema: Struct<{
239
+ outcome: Literal<"undeliverable">;
240
+ reason: Literals<readonly ["recipient_offline", "recipient_left"]>;
241
+ }>;
242
+ ```
243
+
244
+ Parser for a terminal delivery failure reply.
245
+
246
+ ---
247
+
248
+ ### AcceptedBirdDogReplySchema
249
+
250
+ ```ts
251
+ const AcceptedBirdDogReplySchema: Struct<{
252
+ outcome: Literal<"accepted">;
253
+ commandId: String;
254
+ }>;
255
+ ```
256
+
257
+ Recipient acceptance, before the command has settled.
258
+
259
+ ---
260
+
261
+ ### BirdDogReplySchema
262
+
263
+ ```ts
264
+ const BirdDogReplySchema: Union<
265
+ readonly [
175
266
  Struct<{
176
267
  commandId: String;
177
268
  outcome: Literals<
@@ -184,12 +275,94 @@ const BirdDogMailSchema: Struct<{
184
275
  ]
185
276
  >;
186
277
  diagnostic: optionalKey<String>;
187
- }>
188
- >;
189
- }>;
278
+ waitingOnYou: optionalKey<
279
+ $Array<
280
+ Struct<{
281
+ itemId: String;
282
+ kind: String;
283
+ summary: String;
284
+ }>
285
+ >
286
+ >;
287
+ }>,
288
+ Struct<{
289
+ outcome: Literal<"undeliverable">;
290
+ reason: Literals<readonly ["recipient_offline", "recipient_left"]>;
291
+ }>,
292
+ Struct<{
293
+ outcome: Literal<"accepted">;
294
+ commandId: String;
295
+ }>,
296
+ ]
297
+ >;
298
+ ```
299
+
300
+ Parser for any reply: settled, accepted or undeliverable.
301
+
302
+ ---
303
+
304
+ ### BirdDogMailSchema
305
+
306
+ ```ts
307
+ const BirdDogMailSchema: Union<readonly [Struct<{
308
+ key: String;
309
+ to: Struct<{
310
+ kind: Literal<"agent">;
311
+ agentId: String;
312
+ sessionId: optionalKey<String>;
313
+ }>;
314
+ replyTo: $Array<Struct<{
315
+ kind: Literal<"agent">;
316
+ agentId: String;
317
+ sessionId: String;
318
+ }>>;
319
+ content: String;
320
+ createdAt: Number;
321
+ meta: optionalKey<Codec<Json, Json, never, never>>;
322
+ from: Struct<{
323
+ kind: Literal<"agent">;
324
+ agentId: String;
325
+ sessionId: String;
326
+ }>;
327
+ reply: optionalKey<Union<readonly [Struct<{
328
+ commandId: String;
329
+ outcome: Literals<readonly [..., ..., ..., ..., ...]>;
330
+ diagnostic: optionalKey<String>;
331
+ waitingOnYou: optionalKey<$Array<...>>;
332
+ }>, Struct<{
333
+ outcome: Literal<"accepted">;
334
+ commandId: String;
335
+ }>, Struct<{
336
+ outcome: Literal<"undeliverable">;
337
+ reason: Literal<"recipient_left">;
338
+ }>]>>;
339
+ }>, Struct<{
340
+ key: String;
341
+ to: Struct<{
342
+ kind: Literal<"agent">;
343
+ agentId: String;
344
+ sessionId: optionalKey<String>;
345
+ }>;
346
+ replyTo: $Array<Struct<{
347
+ kind: Literal<"agent">;
348
+ agentId: String;
349
+ sessionId: String;
350
+ }>>;
351
+ content: String;
352
+ createdAt: Number;
353
+ meta: optionalKey<Codec<Json, Json, never, never>>;
354
+ from: Struct<{
355
+ kind: Literal<"system">;
356
+ systemId: Literal<"hub">;
357
+ }>;
358
+ reply: Struct<{
359
+ outcome: Literal<"undeliverable">;
360
+ reason: Literal<"recipient_offline">;
361
+ }>;
362
+ }>]>;
190
363
  ```
191
364
 
192
- Parser for addressed agent correspondence.
365
+ Parser for addressed Agent mail, from an Agent or from the Hub system.
193
366
 
194
367
  ---
195
368
 
@@ -217,49 +390,54 @@ Parser for accepted Session work.
217
390
  ```ts
218
391
  const BirdDogAgentJobPayloadSchema: Struct<{
219
392
  work: Struct<{
220
- sessionId: String;
221
- commandFactId: String;
393
+ sessionId: String;
394
+ commandFactId: String;
222
395
  }>;
223
- mail: optional<
224
- Struct<{
225
- key: String;
226
- to: Struct<{
396
+ mail: optional<Union<readonly [Struct<{
397
+ key: String;
398
+ to: Struct<{
227
399
  kind: Literal<"agent">;
228
400
  agentId: String;
401
+ sessionId: optionalKey<String>;
402
+ }>;
403
+ replyTo: $Array<Struct<{
404
+ kind: Literal<...>;
405
+ agentId: String;
229
406
  sessionId: String;
230
- }>;
231
- from: Struct<{
407
+ }>>;
408
+ content: String;
409
+ createdAt: Number;
410
+ meta: optionalKey<Codec<Json, Json, never, never>>;
411
+ from: Struct<{
232
412
  kind: Literal<"agent">;
233
413
  agentId: String;
234
414
  sessionId: String;
235
- }>;
236
- replyTo: $Array<
237
- Struct<{
238
- kind: Literal<"agent">;
239
- agentId: String;
240
- sessionId: String;
241
- }>
242
- >;
243
- content: String;
244
- createdAt: Number;
245
- meta: optionalKey<Codec<Json, Json, never, never>>;
246
- reply: optionalKey<
247
- Struct<{
248
- commandId: String;
249
- outcome: Literals<
250
- readonly [
251
- "completed",
252
- "failed",
253
- "interrupted",
254
- "cancelled",
255
- "outcome_unknown",
256
- ]
257
- >;
258
- diagnostic: optionalKey<String>;
259
- }>
260
- >;
261
- }>
262
- >;
415
+ }>;
416
+ reply: optionalKey<Union<readonly [Struct<...>, Struct<...>, Struct<...>]>>;
417
+ }>, Struct<{
418
+ key: String;
419
+ to: Struct<{
420
+ kind: Literal<"agent">;
421
+ agentId: String;
422
+ sessionId: optionalKey<String>;
423
+ }>;
424
+ replyTo: $Array<Struct<{
425
+ kind: Literal<...>;
426
+ agentId: String;
427
+ sessionId: String;
428
+ }>>;
429
+ content: String;
430
+ createdAt: Number;
431
+ meta: optionalKey<Codec<Json, Json, never, never>>;
432
+ from: Struct<{
433
+ kind: Literal<"system">;
434
+ systemId: Literal<"hub">;
435
+ }>;
436
+ reply: Struct<{
437
+ outcome: Literal<"undeliverable">;
438
+ reason: Literal<"recipient_offline">;
439
+ }>;
440
+ }>]>>;
263
441
  }>;
264
442
  ```
265
443
 
@@ -272,55 +450,58 @@ Parser for the payload that Watchdog stores without interpretation.
272
450
  ```ts
273
451
  const BirdDogAgentJobInputSchema: Struct<{
274
452
  work: Struct<{
275
- jobId: String;
276
- sessionId: String;
277
- commandFactId: String;
278
- recovery: optional<
279
- Struct<{
453
+ jobId: String;
454
+ sessionId: String;
455
+ commandFactId: String;
456
+ recovery: optional<Struct<{
280
457
  maxRecoveries: Int;
281
- }>
282
- >;
458
+ }>>;
283
459
  }>;
284
- mail: optional<
285
- Struct<{
286
- key: String;
287
- to: Struct<{
460
+ mail: optional<Union<readonly [Struct<{
461
+ key: String;
462
+ to: Struct<{
288
463
  kind: Literal<"agent">;
289
464
  agentId: String;
465
+ sessionId: optionalKey<String>;
466
+ }>;
467
+ replyTo: $Array<Struct<{
468
+ kind: Literal<...>;
469
+ agentId: String;
290
470
  sessionId: String;
291
- }>;
292
- from: Struct<{
471
+ }>>;
472
+ content: String;
473
+ createdAt: Number;
474
+ meta: optionalKey<Codec<Json, Json, never, never>>;
475
+ from: Struct<{
293
476
  kind: Literal<"agent">;
294
477
  agentId: String;
295
478
  sessionId: String;
296
- }>;
297
- replyTo: $Array<
298
- Struct<{
299
- kind: Literal<"agent">;
300
- agentId: String;
301
- sessionId: String;
302
- }>
303
- >;
304
- content: String;
305
- createdAt: Number;
306
- meta: optionalKey<Codec<Json, Json, never, never>>;
307
- reply: optionalKey<
308
- Struct<{
309
- commandId: String;
310
- outcome: Literals<
311
- readonly [
312
- "completed",
313
- "failed",
314
- "interrupted",
315
- "cancelled",
316
- "outcome_unknown",
317
- ]
318
- >;
319
- diagnostic: optionalKey<String>;
320
- }>
321
- >;
322
- }>
323
- >;
479
+ }>;
480
+ reply: optionalKey<Union<readonly [Struct<...>, Struct<...>, Struct<...>]>>;
481
+ }>, Struct<{
482
+ key: String;
483
+ to: Struct<{
484
+ kind: Literal<"agent">;
485
+ agentId: String;
486
+ sessionId: optionalKey<String>;
487
+ }>;
488
+ replyTo: $Array<Struct<{
489
+ kind: Literal<...>;
490
+ agentId: String;
491
+ sessionId: String;
492
+ }>>;
493
+ content: String;
494
+ createdAt: Number;
495
+ meta: optionalKey<Codec<Json, Json, never, never>>;
496
+ from: Struct<{
497
+ kind: Literal<"system">;
498
+ systemId: Literal<"hub">;
499
+ }>;
500
+ reply: Struct<{
501
+ outcome: Literal<"undeliverable">;
502
+ reason: Literal<"recipient_offline">;
503
+ }>;
504
+ }>]>>;
324
505
  }>;
325
506
  ```
326
507
 
@@ -406,35 +587,20 @@ Decode the opaque payload at BirdDog's side of the Watchdog seam.
406
587
  ### settlementReplies()
407
588
 
408
589
  ```ts
409
- function settlementReplies(
410
- settlement,
411
- createdAt,
412
- ): readonly Readonly<{
413
- key: string;
414
- to: BirdDogAgentReference;
415
- from: BirdDogAgentReference;
416
- replyTo: readonly Readonly<{
417
- kind: "agent";
418
- agentId: string;
419
- sessionId: string;
420
- }>[];
421
- content: string;
422
- createdAt: number;
423
- meta?: Json;
424
- reply?: Readonly<{
425
- commandId: string;
426
- outcome:
427
- "failed" | "completed" | "interrupted" | "cancelled" | "outcome_unknown";
428
- diagnostic?: string;
429
- }>;
430
- }>[];
590
+ function settlementReplies(settlement, createdAt): readonly BirdDogMail[];
431
591
  ```
432
592
 
433
593
  Build the replies owed by one settlement for a host-owned Post transport. Each
434
594
  reply carries the settled content verbatim (or, when there is none, one sentence
435
- naming the outcome, so the reply is always admissible text) and its settlement
436
- facts as typed fields; the recipient's host authenticates them and decides how
437
- they are presented. A reply never carries the settled work's host metadata.
595
+ naming the outcome and its diagnostic, so the reply is always admissible text)
596
+ and its settlement facts as typed fields; the recipient's host authenticates
597
+ them and decides how they are presented. A reply never carries the settled
598
+ work's host metadata.
599
+
600
+ Work a delegator's mail admitted replies to that mail under its `:reply:` key.
601
+ Any other settled work, whatever started its turn, is a report to the Session's
602
+ delegator of record, when the host names one (it does so once the Session is
603
+ idle), under the delegator mail's `:report:` key.
438
604
 
439
605
  #### Parameters
440
606
 
@@ -445,14 +611,30 @@ they are presented. A reply never carries the settled work's host metadata.
445
611
 
446
612
  #### Returns
447
613
 
448
- readonly `Readonly`\<\{ `key`: `string`; `to`:
449
- [`BirdDogAgentReference`](index.md#birddogagentreference); `from`:
450
- [`BirdDogAgentReference`](index.md#birddogagentreference); `replyTo`: readonly
451
- `Readonly`\<\{ `kind`: `"agent"`; `agentId`: `string`; `sessionId`: `string`;
452
- \}\>[]; `content`: `string`; `createdAt`: `number`; `meta?`: `Json`; `reply?`:
453
- `Readonly`\<\{ `commandId`: `string`; `outcome`: `"failed"` \| `"completed"` \|
454
- `"interrupted"` \| `"cancelled"` \| `"outcome_unknown"`; `diagnostic?`:
455
- `string`; \}\>; \}\>[]
614
+ readonly [`BirdDogMail`](index.md#birddogmail)[]
615
+
616
+ ---
617
+
618
+ ### acceptedNotice()
619
+
620
+ ```ts
621
+ function acceptedNotice(mail, sessionId, commandId, createdAt): BirdDogMail;
622
+ ```
623
+
624
+ Build the recipient's one stable acceptance notice for one original mail.
625
+
626
+ #### Parameters
627
+
628
+ | Parameter | Type |
629
+ | ----------- | ------------------------------------- |
630
+ | `mail` | [`BirdDogMail`](index.md#birddogmail) |
631
+ | `sessionId` | `string` |
632
+ | `commandId` | `string` |
633
+ | `createdAt` | `number` |
634
+
635
+ #### Returns
636
+
637
+ [`BirdDogMail`](index.md#birddogmail)
456
638
 
457
639
  ---
458
640
 
@@ -483,6 +665,7 @@ Delivered receipts and exhausted dead letters stay but owe nothing.
483
665
  function make(options): Effect<
484
666
  Readonly<{
485
667
  fanOut: (settlement) => Effect<void, BirdDogError>;
668
+ postMail?: (mail) => Effect<void, BirdDogError>;
486
669
  drainOutbox: () => Effect<void, BirdDogError>;
487
670
  nextWakeAt: () => Effect<number | undefined, BirdDogError>;
488
671
  }>
@@ -500,6 +683,7 @@ Construct BirdDog's Effect-native mail room over Post's shared outbox.
500
683
  #### Returns
501
684
 
502
685
  `Effect`\<`Readonly`\<\{ `fanOut`: (`settlement`) => `Effect`\<`void`,
686
+ [`BirdDogError`](#birddogerror)\>; `postMail?`: (`mail`) => `Effect`\<`void`,
503
687
  [`BirdDogError`](#birddogerror)\>; `drainOutbox`: () => `Effect`\<`void`,
504
688
  [`BirdDogError`](#birddogerror)\>; `nextWakeAt`: () => `Effect`\<`number` \|
505
689
  `undefined`, [`BirdDogError`](#birddogerror)\>; \}\>\>
package/docs/api/index.md CHANGED
@@ -24,42 +24,118 @@ An ordinary agent Session address. Relationships between agents live elsewhere.
24
24
 
25
25
  ---
26
26
 
27
- ### BirdDogMail
27
+ ### BirdDogAgentRecipientReference
28
28
 
29
29
  ```ts
30
- type BirdDogMail = Readonly<{
31
- key: string;
32
- to: BirdDogAgentReference;
33
- from: BirdDogAgentReference;
34
- replyTo: readonly BirdDogAgentReference[];
35
- content: string;
36
- createdAt: number;
37
- meta?: BirdDogMeta;
38
- reply?: BirdDogReply;
30
+ type BirdDogAgentRecipientReference = Readonly<{
31
+ kind: "agent";
32
+ agentId: string;
33
+ sessionId?: string;
39
34
  }>;
40
35
  ```
41
36
 
42
- Addressed agent correspondence carried with durable work when a reply is owed.
37
+ An addressed Agent whose first Session may be created on acceptance.
43
38
 
44
39
  ---
45
40
 
46
- ### BirdDogReply
41
+ ### BirdDogSystemIdentity
47
42
 
48
43
  ```ts
49
- type BirdDogReply = Readonly<{
50
- commandId: string;
51
- outcome:
52
- "completed" | "failed" | "interrupted" | "cancelled" | "outcome_unknown";
53
- diagnostic?: string;
44
+ type BirdDogSystemIdentity = Readonly<{
45
+ kind: "system";
46
+ systemId: "hub";
54
47
  }>;
55
48
  ```
56
49
 
50
+ The Hub's stable system identity for a terminal offline disposition.
51
+
52
+ ---
53
+
54
+ ### BirdDogReply
55
+
56
+ ```ts
57
+ type BirdDogReply =
58
+ | Readonly<{
59
+ commandId: string;
60
+ outcome: "accepted";
61
+ }>
62
+ | Readonly<{
63
+ commandId: string;
64
+ outcome:
65
+ | "completed"
66
+ | "failed"
67
+ | "interrupted"
68
+ | "cancelled"
69
+ | "outcome_unknown";
70
+ diagnostic?: string;
71
+ waitingOnYou?: readonly BirdDogWaitingItem[];
72
+ }>
73
+ | Readonly<{
74
+ outcome: "undeliverable";
75
+ reason: "recipient_offline" | "recipient_left";
76
+ }>;
77
+ ```
78
+
57
79
  What a reply reports about the settled work beside its content. The recipient's
58
80
  host trusts these facts only after it authenticates the reply against the mail
59
81
  it sent.
60
82
 
61
83
  ---
62
84
 
85
+ ### BirdDogAgentReply
86
+
87
+ ```ts
88
+ type BirdDogAgentReply =
89
+ | Exclude<
90
+ BirdDogReply,
91
+ {
92
+ outcome: "undeliverable";
93
+ }
94
+ >
95
+ | Readonly<{
96
+ outcome: "undeliverable";
97
+ reason: "recipient_left";
98
+ }>;
99
+ ```
100
+
101
+ Facts an Agent may author; the Hub owns recipient-offline disposition.
102
+
103
+ ---
104
+
105
+ ### BirdDogMail
106
+
107
+ ```ts
108
+ type BirdDogMail =
109
+ | Readonly<{
110
+ key: string;
111
+ to: BirdDogAgentRecipientReference;
112
+ replyTo: readonly BirdDogAgentReference[];
113
+ content: string;
114
+ createdAt: number;
115
+ meta?: BirdDogMeta;
116
+ from: BirdDogAgentReference;
117
+ reply?: BirdDogAgentReply;
118
+ }>
119
+ | Readonly<{
120
+ key: string;
121
+ to: BirdDogAgentRecipientReference;
122
+ replyTo: readonly BirdDogAgentReference[];
123
+ content: string;
124
+ createdAt: number;
125
+ meta?: BirdDogMeta;
126
+ from: BirdDogSystemIdentity;
127
+ reply: Readonly<{
128
+ outcome: "undeliverable";
129
+ reason: "recipient_offline";
130
+ }>;
131
+ }>;
132
+ ```
133
+
134
+ Addressed correspondence. Agents author ordinary replies and recipient-left
135
+ notices; only the Hub system authors recipient-offline dispositions.
136
+
137
+ ---
138
+
63
139
  ### BirdDogMeta
64
140
 
65
141
  ```ts
@@ -154,14 +230,31 @@ Host ports for BirdDog's durable mail delivery.
154
230
 
155
231
  ---
156
232
 
233
+ ### BirdDogDelegator
234
+
235
+ ```ts
236
+ type BirdDogDelegator = Readonly<{
237
+ key: string;
238
+ agentId: string;
239
+ replyTo: readonly BirdDogAgentReference[];
240
+ }>;
241
+ ```
242
+
243
+ Who sent a Session its work first: the mail that opened the relationship.
244
+ `agentId` is the Session's own Agent, the author of every report.
245
+
246
+ ---
247
+
157
248
  ### BirdDogSettlement
158
249
 
159
250
  ```ts
160
251
  type BirdDogSettlement = Readonly<{
161
252
  job: WatchdogSettledJob;
162
253
  content: string;
254
+ delegator?: BirdDogDelegator;
163
255
  diagnostic?: string;
164
256
  meta?: BirdDogMeta;
257
+ waitingOnYou?: readonly BirdDogWaitingItem[];
165
258
  }>;
166
259
  ```
167
260
 
@@ -169,6 +262,20 @@ Completed generic work plus the content owed to its correspondents.
169
262
 
170
263
  ---
171
264
 
265
+ ### BirdDogWaitingItem
266
+
267
+ ```ts
268
+ type BirdDogWaitingItem = Readonly<{
269
+ itemId: string;
270
+ kind: string;
271
+ summary: string;
272
+ }>;
273
+ ```
274
+
275
+ One open item named by a reply as waiting on its recipient.
276
+
277
+ ---
278
+
172
279
  ### BirdDogRuntime
173
280
 
174
281
  ```ts
@@ -203,3 +310,24 @@ const BirdDog: BirdDogApi;
203
310
  ```
204
311
 
205
312
  Agent-aware mail translation over Watchdog's payload-blind job grammar.
313
+
314
+ ## Functions
315
+
316
+ ### undeliverableReply()
317
+
318
+ ```ts
319
+ function undeliverableReply(original, createdAt): BirdDogMail;
320
+ ```
321
+
322
+ Construct the one stable system reply correlated to the exact sent letter.
323
+
324
+ #### Parameters
325
+
326
+ | Parameter | Type |
327
+ | ----------- | ----------------------------- |
328
+ | `original` | [`BirdDogMail`](#birddogmail) |
329
+ | `createdAt` | `number` |
330
+
331
+ #### Returns
332
+
333
+ [`BirdDogMail`](#birddogmail)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fungi.computer/bird-dog",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "author": "Levi <levi@technomancy.dev>",
5
5
  "description": "Durable addressed agent mail over generic Watchdog work",
6
6
  "type": "module",