@fungi.computer/bird-dog 0.2.0 → 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
@@ -16,20 +16,44 @@ export declare const BirdDogAgentRecipientReferenceSchema: Schema.Struct<{
16
16
  readonly agentId: Schema.String;
17
17
  readonly sessionId: Schema.optionalKey<Schema.String>;
18
18
  }>;
19
+ /** The Hub's stable system identity for a terminal offline disposition. */
20
+ export declare const BirdDogSystemIdentitySchema: Schema.Struct<{
21
+ readonly kind: Schema.Literal<"system">;
22
+ readonly systemId: Schema.Literal<"hub">;
23
+ }>;
19
24
  /** The most characters a reply's failure diagnostic may carry. */
20
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
+ }>;
21
38
  /**
22
39
  * Parser for the settlement facts a reply carries beside its content: the
23
- * replying Session's command, its exact Watchdog outcome and, for work that did
24
- * 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.
25
43
  */
26
44
  export declare const SettledBirdDogReplySchema: Schema.Struct<{
27
45
  readonly commandId: Schema.String;
28
46
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
29
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
+ }>>>;
30
53
  }>;
31
54
  /** A terminal delivery failure, correlated by the original mail key only. */
32
55
  export declare const BirdDogUndeliverableReasonSchema: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
56
+ /** Parser for a terminal delivery failure reply. */
33
57
  export declare const UndeliverableBirdDogReplySchema: Schema.Struct<{
34
58
  readonly outcome: Schema.Literal<"undeliverable">;
35
59
  readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
@@ -39,10 +63,16 @@ export declare const AcceptedBirdDogReplySchema: Schema.Struct<{
39
63
  readonly outcome: Schema.Literal<"accepted">;
40
64
  readonly commandId: Schema.String;
41
65
  }>;
66
+ /** Parser for any reply: settled, accepted or undeliverable. */
42
67
  export declare const BirdDogReplySchema: Schema.Union<readonly [Schema.Struct<{
43
68
  readonly commandId: Schema.String;
44
69
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
45
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
+ }>>>;
46
76
  }>, Schema.Struct<{
47
77
  readonly outcome: Schema.Literal<"undeliverable">;
48
78
  readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
@@ -58,6 +88,7 @@ export declare const BirdDogReplySchema: Schema.Union<readonly [Schema.Struct<{
58
88
  * line is cut, so a cut never exposes part of one.
59
89
  */
60
90
  export declare function boundedDiagnostic(text: string): string | undefined;
91
+ /** Parser for addressed Agent mail, from an Agent or from the Hub system. */
61
92
  export declare const BirdDogMailSchema: Schema.Union<readonly [Schema.Struct<{
62
93
  readonly from: Schema.Struct<{
63
94
  readonly kind: Schema.Literal<"agent">;
@@ -69,12 +100,17 @@ export declare const BirdDogMailSchema: Schema.Union<readonly [Schema.Struct<{
69
100
  readonly commandId: Schema.String;
70
101
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
71
102
  readonly diagnostic: Schema.optionalKey<Schema.String>;
72
- }>, Schema.Struct<{
73
- readonly outcome: Schema.Literal<"undeliverable">;
74
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
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
+ }>>>;
75
108
  }>, Schema.Struct<{
76
109
  readonly outcome: Schema.Literal<"accepted">;
77
110
  readonly commandId: Schema.String;
111
+ }>, Schema.Struct<{
112
+ readonly outcome: Schema.Literal<"undeliverable">;
113
+ readonly reason: Schema.Literal<"recipient_left">;
78
114
  }>]>>;
79
115
  readonly key: Schema.String;
80
116
  readonly to: Schema.Struct<{
@@ -92,14 +128,13 @@ export declare const BirdDogMailSchema: Schema.Union<readonly [Schema.Struct<{
92
128
  readonly meta: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
93
129
  }>, Schema.Struct<{
94
130
  readonly from: Schema.Struct<{
95
- readonly kind: Schema.Literal<"agent">;
96
- readonly agentId: Schema.String;
97
- readonly sessionId: Schema.optionalKey<Schema.String>;
131
+ readonly kind: Schema.Literal<"system">;
132
+ readonly systemId: Schema.Literal<"hub">;
98
133
  }>;
99
- /** An unstarted recipient can only author an undeliverable reply. */
134
+ /** Only the Hub may author this offline disposition. */
100
135
  readonly reply: Schema.Struct<{
101
136
  readonly outcome: Schema.Literal<"undeliverable">;
102
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
137
+ readonly reason: Schema.Literal<"recipient_offline">;
103
138
  }>;
104
139
  readonly key: Schema.String;
105
140
  readonly to: Schema.Struct<{
@@ -142,12 +177,17 @@ export declare const BirdDogAgentJobPayloadSchema: Schema.Struct<{
142
177
  readonly commandId: Schema.String;
143
178
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
144
179
  readonly diagnostic: Schema.optionalKey<Schema.String>;
145
- }>, Schema.Struct<{
146
- readonly outcome: Schema.Literal<"undeliverable">;
147
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
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
+ }>>>;
148
185
  }>, Schema.Struct<{
149
186
  readonly outcome: Schema.Literal<"accepted">;
150
187
  readonly commandId: Schema.String;
188
+ }>, Schema.Struct<{
189
+ readonly outcome: Schema.Literal<"undeliverable">;
190
+ readonly reason: Schema.Literal<"recipient_left">;
151
191
  }>]>>;
152
192
  readonly key: Schema.String;
153
193
  readonly to: Schema.Struct<{
@@ -165,14 +205,13 @@ export declare const BirdDogAgentJobPayloadSchema: Schema.Struct<{
165
205
  readonly meta: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
166
206
  }>, Schema.Struct<{
167
207
  readonly from: Schema.Struct<{
168
- readonly kind: Schema.Literal<"agent">;
169
- readonly agentId: Schema.String;
170
- readonly sessionId: Schema.optionalKey<Schema.String>;
208
+ readonly kind: Schema.Literal<"system">;
209
+ readonly systemId: Schema.Literal<"hub">;
171
210
  }>;
172
- /** An unstarted recipient can only author an undeliverable reply. */
211
+ /** Only the Hub may author this offline disposition. */
173
212
  readonly reply: Schema.Struct<{
174
213
  readonly outcome: Schema.Literal<"undeliverable">;
175
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
214
+ readonly reason: Schema.Literal<"recipient_offline">;
176
215
  }>;
177
216
  readonly key: Schema.String;
178
217
  readonly to: Schema.Struct<{
@@ -211,12 +250,17 @@ export declare const BirdDogAgentJobInputSchema: Schema.Struct<{
211
250
  readonly commandId: Schema.String;
212
251
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
213
252
  readonly diagnostic: Schema.optionalKey<Schema.String>;
214
- }>, Schema.Struct<{
215
- readonly outcome: Schema.Literal<"undeliverable">;
216
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
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;
261
+ }>, Schema.Struct<{
262
+ readonly outcome: Schema.Literal<"undeliverable">;
263
+ readonly reason: Schema.Literal<"recipient_left">;
220
264
  }>]>>;
221
265
  readonly key: Schema.String;
222
266
  readonly to: Schema.Struct<{
@@ -234,14 +278,13 @@ export declare const BirdDogAgentJobInputSchema: Schema.Struct<{
234
278
  readonly meta: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
235
279
  }>, Schema.Struct<{
236
280
  readonly from: Schema.Struct<{
237
- readonly kind: Schema.Literal<"agent">;
238
- readonly agentId: Schema.String;
239
- readonly sessionId: Schema.optionalKey<Schema.String>;
281
+ readonly kind: Schema.Literal<"system">;
282
+ readonly systemId: Schema.Literal<"hub">;
240
283
  }>;
241
- /** An unstarted recipient can only author an undeliverable reply. */
284
+ /** Only the Hub may author this offline disposition. */
242
285
  readonly reply: Schema.Struct<{
243
286
  readonly outcome: Schema.Literal<"undeliverable">;
244
- readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
287
+ readonly reason: Schema.Literal<"recipient_offline">;
245
288
  }>;
246
289
  readonly key: Schema.String;
247
290
  readonly to: Schema.Struct<{
@@ -305,9 +348,15 @@ export declare const decodeAgentJob: (job: WatchdogStoredJob) => BirdDogAgentJob
305
348
  /**
306
349
  * Build the replies owed by one settlement for a host-owned Post transport.
307
350
  * Each reply carries the settled content verbatim (or, when there is none, one
308
- * sentence naming the outcome, so the reply is always admissible text) and its
309
- * settlement facts as typed fields; the recipient's host authenticates them and decides how they
310
- * 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.
311
360
  */
312
361
  export declare function settlementReplies(settlement: BirdDogSettlement, createdAt: number): readonly BirdDogMail[];
313
362
  /** Build the recipient's one stable acceptance notice for one original mail. */
package/dist/effect.js CHANGED
@@ -20,12 +20,30 @@ export const BirdDogAgentRecipientReferenceSchema = Schema.Struct({
20
20
  agentId: Identifier,
21
21
  sessionId: Schema.optionalKey(Identifier),
22
22
  });
23
+ /** The Hub's stable system identity for a terminal offline disposition. */
24
+ export const BirdDogSystemIdentitySchema = Schema.Struct({
25
+ kind: Schema.Literal("system"),
26
+ systemId: Schema.Literal("hub"),
27
+ });
23
28
  /** The most characters a reply's failure diagnostic may carry. */
24
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
+ });
25
42
  /**
26
43
  * Parser for the settlement facts a reply carries beside its content: the
27
- * replying Session's command, its exact Watchdog outcome and, for work that did
28
- * 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.
29
47
  */
30
48
  export const SettledBirdDogReplySchema = Schema.Struct({
31
49
  commandId: Identifier,
@@ -37,12 +55,14 @@ export const SettledBirdDogReplySchema = Schema.Struct({
37
55
  "outcome_unknown",
38
56
  ]),
39
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))),
40
59
  });
41
60
  /** A terminal delivery failure, correlated by the original mail key only. */
42
61
  export const BirdDogUndeliverableReasonSchema = Schema.Literals([
43
62
  "recipient_offline",
44
63
  "recipient_left",
45
64
  ]);
65
+ /** Parser for a terminal delivery failure reply. */
46
66
  export const UndeliverableBirdDogReplySchema = Schema.Struct({
47
67
  outcome: Schema.Literal("undeliverable"),
48
68
  reason: BirdDogUndeliverableReasonSchema,
@@ -52,11 +72,20 @@ export const AcceptedBirdDogReplySchema = Schema.Struct({
52
72
  outcome: Schema.Literal("accepted"),
53
73
  commandId: Identifier,
54
74
  });
75
+ /** Parser for any reply: settled, accepted or undeliverable. */
55
76
  export const BirdDogReplySchema = Schema.Union([
56
77
  SettledBirdDogReplySchema,
57
78
  UndeliverableBirdDogReplySchema,
58
79
  AcceptedBirdDogReplySchema,
59
80
  ]);
81
+ const BirdDogAgentReplySchema = Schema.Union([
82
+ SettledBirdDogReplySchema,
83
+ AcceptedBirdDogReplySchema,
84
+ Schema.Struct({
85
+ outcome: Schema.Literal("undeliverable"),
86
+ reason: Schema.Literal("recipient_left"),
87
+ }),
88
+ ]);
60
89
  const REDACTED = "[redacted]";
61
90
  // An authorization scheme's credential, e.g. `Bearer <token>`.
62
91
  const schemeCredential = /\b(bearer|basic)\s+[^\s"',;]+/giu;
@@ -93,18 +122,22 @@ const BirdDogMailFields = {
93
122
  /** The sender's opaque host metadata; BirdDog never reads it. */
94
123
  meta: Schema.optionalKey(Schema.Json),
95
124
  };
125
+ /** Parser for addressed Agent mail, from an Agent or from the Hub system. */
96
126
  export const BirdDogMailSchema = Schema.Union([
97
127
  Schema.Struct({
98
128
  ...BirdDogMailFields,
99
129
  from: BirdDogAgentReferenceSchema,
100
130
  /** Settlement or acceptance facts, present only on a reply. */
101
- reply: Schema.optionalKey(BirdDogReplySchema),
131
+ reply: Schema.optionalKey(BirdDogAgentReplySchema),
102
132
  }),
103
133
  Schema.Struct({
104
134
  ...BirdDogMailFields,
105
- from: BirdDogAgentRecipientReferenceSchema,
106
- /** An unstarted recipient can only author an undeliverable reply. */
107
- reply: UndeliverableBirdDogReplySchema,
135
+ from: BirdDogSystemIdentitySchema,
136
+ /** Only the Hub may author this offline disposition. */
137
+ reply: Schema.Struct({
138
+ outcome: Schema.Literal("undeliverable"),
139
+ reason: Schema.Literal("recipient_offline"),
140
+ }),
108
141
  }),
109
142
  ]);
110
143
  /** Parser for accepted Session work. */
@@ -163,13 +196,23 @@ export const decodeAgentJob = (job) => Schema.decodeUnknownSync(BirdDogAgentJobP
163
196
  /**
164
197
  * Build the replies owed by one settlement for a host-owned Post transport.
165
198
  * Each reply carries the settled content verbatim (or, when there is none, one
166
- * sentence naming the outcome, so the reply is always admissible text) and its
167
- * settlement facts as typed fields; the recipient's host authenticates them and decides how they
168
- * 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.
169
208
  */
170
209
  export function settlementReplies(settlement, createdAt) {
171
210
  const { work, mail } = decodeAgentJob(settlement.job);
172
- 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)
173
216
  return [];
174
217
  const outcome = settlement.job.outcome;
175
218
  const diagnostic = outcome === "completed" ||
@@ -177,17 +220,29 @@ export function settlementReplies(settlement, createdAt) {
177
220
  settlement.diagnostic === undefined
178
221
  ? undefined
179
222
  : boundedDiagnostic(settlement.diagnostic);
180
- const reply = Schema.decodeUnknownSync(BirdDogReplySchema)(diagnostic === undefined
181
- ? { commandId: work.commandFactId, outcome }
182
- : { commandId: work.commandFactId, outcome, diagnostic });
183
- return mail.replyTo.map((destination, index) => ({
184
- 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)}`,
185
234
  to: destination,
186
- from: { ...mail.to, sessionId: work.sessionId },
235
+ from: {
236
+ kind: "agent",
237
+ agentId: owed.agentId,
238
+ sessionId: work.sessionId,
239
+ },
187
240
  replyTo: [],
188
241
  content: settlement.content.length > 0
189
242
  ? settlement.content
190
- : `The delegated work ended ${outcome} without reply text.`,
243
+ : `The delegated work ended ${outcome}${diagnostic === undefined
244
+ ? " without reply text."
245
+ : `: ${diagnostic}`}`,
191
246
  createdAt,
192
247
  reply,
193
248
  }));
package/dist/index.d.ts CHANGED
@@ -12,6 +12,11 @@ export type BirdDogAgentRecipientReference = Readonly<{
12
12
  agentId: string;
13
13
  sessionId?: string;
14
14
  }>;
15
+ /** The Hub's stable system identity for a terminal offline disposition. */
16
+ export type BirdDogSystemIdentity = Readonly<{
17
+ kind: "system";
18
+ systemId: "hub";
19
+ }>;
15
20
  /**
16
21
  * What a reply reports about the settled work beside its content. The
17
22
  * recipient's host trusts these facts only after it authenticates the reply
@@ -28,11 +33,23 @@ export type BirdDogReply = Readonly<{
28
33
  outcome: "completed" | "failed" | "interrupted" | "cancelled" | "outcome_unknown";
29
34
  /** Bounded terminal diagnostic for work that did not complete or cancel. */
30
35
  diagnostic?: string;
36
+ /** Open items of the replying Session that now wait on this recipient. */
37
+ waitingOnYou?: readonly BirdDogWaitingItem[];
31
38
  }> | Readonly<{
32
39
  outcome: "undeliverable";
33
40
  reason: "recipient_offline" | "recipient_left";
34
41
  }>;
35
- /** Addressed mail; an unstarted Agent may author only an undeliverable reply. */
42
+ /** Facts an Agent may author; the Hub owns recipient-offline disposition. */
43
+ export type BirdDogAgentReply = Exclude<BirdDogReply, {
44
+ outcome: "undeliverable";
45
+ }> | Readonly<{
46
+ outcome: "undeliverable";
47
+ reason: "recipient_left";
48
+ }>;
49
+ /**
50
+ * Addressed correspondence. Agents author ordinary replies and recipient-left
51
+ * notices; only the Hub system authors recipient-offline dispositions.
52
+ */
36
53
  export type BirdDogMail = Readonly<{
37
54
  key: string;
38
55
  to: BirdDogAgentRecipientReference;
@@ -43,7 +60,7 @@ export type BirdDogMail = Readonly<{
43
60
  meta?: BirdDogMeta;
44
61
  from: BirdDogAgentReference;
45
62
  /** Settlement or acceptance facts, present only on a reply. */
46
- reply?: BirdDogReply;
63
+ reply?: BirdDogAgentReply;
47
64
  }> | Readonly<{
48
65
  key: string;
49
66
  to: BirdDogAgentRecipientReference;
@@ -52,12 +69,15 @@ export type BirdDogMail = Readonly<{
52
69
  createdAt: number;
53
70
  /** The sender's opaque host metadata; BirdDog never reads it. */
54
71
  meta?: BirdDogMeta;
55
- /** No Session exists when a never-started recipient is undeliverable. */
56
- from: BirdDogAgentRecipientReference;
57
- reply: Extract<BirdDogReply, {
72
+ /** The Hub owns offline disposition authorship, not the recipient. */
73
+ from: BirdDogSystemIdentity;
74
+ reply: Readonly<{
58
75
  outcome: "undeliverable";
76
+ reason: "recipient_offline";
59
77
  }>;
60
78
  }>;
79
+ /** Construct the one stable system reply correlated to the exact sent letter. */
80
+ export declare function undeliverableReply(original: BirdDogMail, createdAt: number): BirdDogMail;
61
81
  /** Opaque JSON a host attached to the work; BirdDog only carries it. */
62
82
  export type BirdDogMeta = typeof Schema.Json.Type;
63
83
  /** The accepted Session work BirdDog points at from an opaque Watchdog job. */
@@ -107,10 +127,24 @@ export type BirdDogOptions = Readonly<{
107
127
  /** Return the host's current wall-clock time in milliseconds. */
108
128
  now: () => number;
109
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
+ }>;
110
139
  /** Completed generic work plus the content owed to its correspondents. */
111
140
  export type BirdDogSettlement = Readonly<{
112
141
  job: WatchdogSettledJob;
113
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;
114
148
  /**
115
149
  * The Session's recorded terminal diagnostic. Replies carry it, bounded by
116
150
  * `boundedDiagnostic`, only for failed, interrupted and outcome_unknown work.
@@ -121,6 +155,17 @@ export type BirdDogSettlement = Readonly<{
121
155
  * example, naming who cancelled). Replies never carry it.
122
156
  */
123
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;
124
169
  }>;
125
170
  /** Durable reply delivery behind the mail-room interface. */
126
171
  export type BirdDogRuntime = Readonly<{
package/dist/index.js CHANGED
@@ -1,5 +1,19 @@
1
1
  import { agentJobFromInput, decodeAgentJob } from "./effect.js";
2
2
  import { createPromiseBirdDog } from "./internal/promise-mail-room.js";
3
+ /** Construct the one stable system reply correlated to the exact sent letter. */
4
+ export function undeliverableReply(original, createdAt) {
5
+ if (original.reply !== undefined || original.from.kind !== "agent")
6
+ throw new Error("A reply cannot receive another undeliverable disposition");
7
+ return {
8
+ key: `${original.key}:reply:0`,
9
+ from: { kind: "system", systemId: "hub" },
10
+ to: original.from,
11
+ replyTo: [],
12
+ content: "undeliverable",
13
+ createdAt,
14
+ reply: { outcome: "undeliverable", reason: "recipient_offline" },
15
+ };
16
+ }
3
17
  /** Agent-aware mail translation over Watchdog's payload-blind job grammar. */
4
18
  export const BirdDog = Object.freeze({
5
19
  agentJob: agentJobFromInput,
@@ -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.0",
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",