@femtomc/mu-agent 26.2.100 → 26.2.102

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.
@@ -1,3 +1,4 @@
1
+ import { type HudDoc } from "@femtomc/mu-core";
1
2
  import { z } from "zod";
2
3
  import { CommandContextResolver } from "./command_context.js";
3
4
  import { type CreateMuSessionOpts, type MuSession } from "./session_factory.js";
@@ -58,6 +59,170 @@ export type OperatorApprovedCommand = z.infer<typeof OperatorApprovedCommandSche
58
59
  export declare const OperatorBackendTurnResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
59
60
  kind: z.ZodLiteral<"respond">;
60
61
  message: z.ZodString;
62
+ hud_docs: z.ZodOptional<z.ZodArray<z.ZodObject<{
63
+ v: z.ZodDefault<z.ZodLiteral<1>>;
64
+ hud_id: z.ZodString;
65
+ title: z.ZodString;
66
+ title_style: z.ZodOptional<z.ZodObject<{
67
+ weight: z.ZodOptional<z.ZodEnum<{
68
+ normal: "normal";
69
+ strong: "strong";
70
+ }>>;
71
+ italic: z.ZodOptional<z.ZodBoolean>;
72
+ code: z.ZodOptional<z.ZodBoolean>;
73
+ }, z.core.$strict>>;
74
+ scope: z.ZodDefault<z.ZodNullable<z.ZodString>>;
75
+ chips: z.ZodDefault<z.ZodArray<z.ZodObject<{
76
+ key: z.ZodString;
77
+ label: z.ZodString;
78
+ tone: z.ZodOptional<z.ZodEnum<{
79
+ error: "error";
80
+ info: "info";
81
+ success: "success";
82
+ warning: "warning";
83
+ muted: "muted";
84
+ accent: "accent";
85
+ dim: "dim";
86
+ }>>;
87
+ style: z.ZodOptional<z.ZodObject<{
88
+ weight: z.ZodOptional<z.ZodEnum<{
89
+ normal: "normal";
90
+ strong: "strong";
91
+ }>>;
92
+ italic: z.ZodOptional<z.ZodBoolean>;
93
+ code: z.ZodOptional<z.ZodBoolean>;
94
+ }, z.core.$strict>>;
95
+ }, z.core.$strict>>>;
96
+ sections: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
97
+ kind: z.ZodLiteral<"kv">;
98
+ title: z.ZodOptional<z.ZodString>;
99
+ title_style: z.ZodOptional<z.ZodObject<{
100
+ weight: z.ZodOptional<z.ZodEnum<{
101
+ normal: "normal";
102
+ strong: "strong";
103
+ }>>;
104
+ italic: z.ZodOptional<z.ZodBoolean>;
105
+ code: z.ZodOptional<z.ZodBoolean>;
106
+ }, z.core.$strict>>;
107
+ items: z.ZodDefault<z.ZodArray<z.ZodObject<{
108
+ key: z.ZodString;
109
+ label: z.ZodString;
110
+ value: z.ZodString;
111
+ tone: z.ZodOptional<z.ZodEnum<{
112
+ error: "error";
113
+ info: "info";
114
+ success: "success";
115
+ warning: "warning";
116
+ muted: "muted";
117
+ accent: "accent";
118
+ dim: "dim";
119
+ }>>;
120
+ value_style: z.ZodOptional<z.ZodObject<{
121
+ weight: z.ZodOptional<z.ZodEnum<{
122
+ normal: "normal";
123
+ strong: "strong";
124
+ }>>;
125
+ italic: z.ZodOptional<z.ZodBoolean>;
126
+ code: z.ZodOptional<z.ZodBoolean>;
127
+ }, z.core.$strict>>;
128
+ }, z.core.$strict>>>;
129
+ }, z.core.$strict>, z.ZodObject<{
130
+ kind: z.ZodLiteral<"checklist">;
131
+ title: z.ZodOptional<z.ZodString>;
132
+ title_style: z.ZodOptional<z.ZodObject<{
133
+ weight: z.ZodOptional<z.ZodEnum<{
134
+ normal: "normal";
135
+ strong: "strong";
136
+ }>>;
137
+ italic: z.ZodOptional<z.ZodBoolean>;
138
+ code: z.ZodOptional<z.ZodBoolean>;
139
+ }, z.core.$strict>>;
140
+ items: z.ZodDefault<z.ZodArray<z.ZodObject<{
141
+ id: z.ZodString;
142
+ label: z.ZodString;
143
+ done: z.ZodBoolean;
144
+ style: z.ZodOptional<z.ZodObject<{
145
+ weight: z.ZodOptional<z.ZodEnum<{
146
+ normal: "normal";
147
+ strong: "strong";
148
+ }>>;
149
+ italic: z.ZodOptional<z.ZodBoolean>;
150
+ code: z.ZodOptional<z.ZodBoolean>;
151
+ }, z.core.$strict>>;
152
+ }, z.core.$strict>>>;
153
+ }, z.core.$strict>, z.ZodObject<{
154
+ kind: z.ZodLiteral<"activity">;
155
+ title: z.ZodOptional<z.ZodString>;
156
+ title_style: z.ZodOptional<z.ZodObject<{
157
+ weight: z.ZodOptional<z.ZodEnum<{
158
+ normal: "normal";
159
+ strong: "strong";
160
+ }>>;
161
+ italic: z.ZodOptional<z.ZodBoolean>;
162
+ code: z.ZodOptional<z.ZodBoolean>;
163
+ }, z.core.$strict>>;
164
+ lines: z.ZodDefault<z.ZodArray<z.ZodString>>;
165
+ }, z.core.$strict>, z.ZodObject<{
166
+ kind: z.ZodLiteral<"text">;
167
+ title: z.ZodOptional<z.ZodString>;
168
+ title_style: z.ZodOptional<z.ZodObject<{
169
+ weight: z.ZodOptional<z.ZodEnum<{
170
+ normal: "normal";
171
+ strong: "strong";
172
+ }>>;
173
+ italic: z.ZodOptional<z.ZodBoolean>;
174
+ code: z.ZodOptional<z.ZodBoolean>;
175
+ }, z.core.$strict>>;
176
+ text: z.ZodString;
177
+ tone: z.ZodOptional<z.ZodEnum<{
178
+ error: "error";
179
+ info: "info";
180
+ success: "success";
181
+ warning: "warning";
182
+ muted: "muted";
183
+ accent: "accent";
184
+ dim: "dim";
185
+ }>>;
186
+ style: z.ZodOptional<z.ZodObject<{
187
+ weight: z.ZodOptional<z.ZodEnum<{
188
+ normal: "normal";
189
+ strong: "strong";
190
+ }>>;
191
+ italic: z.ZodOptional<z.ZodBoolean>;
192
+ code: z.ZodOptional<z.ZodBoolean>;
193
+ }, z.core.$strict>>;
194
+ }, z.core.$strict>], "kind">>>;
195
+ actions: z.ZodDefault<z.ZodArray<z.ZodObject<{
196
+ id: z.ZodString;
197
+ label: z.ZodString;
198
+ command_text: z.ZodString;
199
+ kind: z.ZodOptional<z.ZodEnum<{
200
+ primary: "primary";
201
+ secondary: "secondary";
202
+ danger: "danger";
203
+ }>>;
204
+ style: z.ZodOptional<z.ZodObject<{
205
+ weight: z.ZodOptional<z.ZodEnum<{
206
+ normal: "normal";
207
+ strong: "strong";
208
+ }>>;
209
+ italic: z.ZodOptional<z.ZodBoolean>;
210
+ code: z.ZodOptional<z.ZodBoolean>;
211
+ }, z.core.$strict>>;
212
+ }, z.core.$strict>>>;
213
+ snapshot_compact: z.ZodString;
214
+ snapshot_style: z.ZodOptional<z.ZodObject<{
215
+ weight: z.ZodOptional<z.ZodEnum<{
216
+ normal: "normal";
217
+ strong: "strong";
218
+ }>>;
219
+ italic: z.ZodOptional<z.ZodBoolean>;
220
+ code: z.ZodOptional<z.ZodBoolean>;
221
+ }, z.core.$strict>>;
222
+ snapshot_multiline: z.ZodOptional<z.ZodString>;
223
+ updated_at_ms: z.ZodNumber;
224
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
225
+ }, z.core.$strict>>>;
61
226
  }, z.core.$strip>, z.ZodObject<{
62
227
  kind: z.ZodLiteral<"command">;
63
228
  command: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -95,6 +260,170 @@ export declare const OperatorBackendTurnResultSchema: z.ZodDiscriminatedUnion<[z
95
260
  kind: z.ZodLiteral<"operator_thinking_set">;
96
261
  thinking: z.ZodString;
97
262
  }, z.core.$strip>], "kind">;
263
+ hud_docs: z.ZodOptional<z.ZodArray<z.ZodObject<{
264
+ v: z.ZodDefault<z.ZodLiteral<1>>;
265
+ hud_id: z.ZodString;
266
+ title: z.ZodString;
267
+ title_style: z.ZodOptional<z.ZodObject<{
268
+ weight: z.ZodOptional<z.ZodEnum<{
269
+ normal: "normal";
270
+ strong: "strong";
271
+ }>>;
272
+ italic: z.ZodOptional<z.ZodBoolean>;
273
+ code: z.ZodOptional<z.ZodBoolean>;
274
+ }, z.core.$strict>>;
275
+ scope: z.ZodDefault<z.ZodNullable<z.ZodString>>;
276
+ chips: z.ZodDefault<z.ZodArray<z.ZodObject<{
277
+ key: z.ZodString;
278
+ label: z.ZodString;
279
+ tone: z.ZodOptional<z.ZodEnum<{
280
+ error: "error";
281
+ info: "info";
282
+ success: "success";
283
+ warning: "warning";
284
+ muted: "muted";
285
+ accent: "accent";
286
+ dim: "dim";
287
+ }>>;
288
+ style: z.ZodOptional<z.ZodObject<{
289
+ weight: z.ZodOptional<z.ZodEnum<{
290
+ normal: "normal";
291
+ strong: "strong";
292
+ }>>;
293
+ italic: z.ZodOptional<z.ZodBoolean>;
294
+ code: z.ZodOptional<z.ZodBoolean>;
295
+ }, z.core.$strict>>;
296
+ }, z.core.$strict>>>;
297
+ sections: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
298
+ kind: z.ZodLiteral<"kv">;
299
+ title: z.ZodOptional<z.ZodString>;
300
+ title_style: z.ZodOptional<z.ZodObject<{
301
+ weight: z.ZodOptional<z.ZodEnum<{
302
+ normal: "normal";
303
+ strong: "strong";
304
+ }>>;
305
+ italic: z.ZodOptional<z.ZodBoolean>;
306
+ code: z.ZodOptional<z.ZodBoolean>;
307
+ }, z.core.$strict>>;
308
+ items: z.ZodDefault<z.ZodArray<z.ZodObject<{
309
+ key: z.ZodString;
310
+ label: z.ZodString;
311
+ value: z.ZodString;
312
+ tone: z.ZodOptional<z.ZodEnum<{
313
+ error: "error";
314
+ info: "info";
315
+ success: "success";
316
+ warning: "warning";
317
+ muted: "muted";
318
+ accent: "accent";
319
+ dim: "dim";
320
+ }>>;
321
+ value_style: z.ZodOptional<z.ZodObject<{
322
+ weight: z.ZodOptional<z.ZodEnum<{
323
+ normal: "normal";
324
+ strong: "strong";
325
+ }>>;
326
+ italic: z.ZodOptional<z.ZodBoolean>;
327
+ code: z.ZodOptional<z.ZodBoolean>;
328
+ }, z.core.$strict>>;
329
+ }, z.core.$strict>>>;
330
+ }, z.core.$strict>, z.ZodObject<{
331
+ kind: z.ZodLiteral<"checklist">;
332
+ title: z.ZodOptional<z.ZodString>;
333
+ title_style: z.ZodOptional<z.ZodObject<{
334
+ weight: z.ZodOptional<z.ZodEnum<{
335
+ normal: "normal";
336
+ strong: "strong";
337
+ }>>;
338
+ italic: z.ZodOptional<z.ZodBoolean>;
339
+ code: z.ZodOptional<z.ZodBoolean>;
340
+ }, z.core.$strict>>;
341
+ items: z.ZodDefault<z.ZodArray<z.ZodObject<{
342
+ id: z.ZodString;
343
+ label: z.ZodString;
344
+ done: z.ZodBoolean;
345
+ style: z.ZodOptional<z.ZodObject<{
346
+ weight: z.ZodOptional<z.ZodEnum<{
347
+ normal: "normal";
348
+ strong: "strong";
349
+ }>>;
350
+ italic: z.ZodOptional<z.ZodBoolean>;
351
+ code: z.ZodOptional<z.ZodBoolean>;
352
+ }, z.core.$strict>>;
353
+ }, z.core.$strict>>>;
354
+ }, z.core.$strict>, z.ZodObject<{
355
+ kind: z.ZodLiteral<"activity">;
356
+ title: z.ZodOptional<z.ZodString>;
357
+ title_style: z.ZodOptional<z.ZodObject<{
358
+ weight: z.ZodOptional<z.ZodEnum<{
359
+ normal: "normal";
360
+ strong: "strong";
361
+ }>>;
362
+ italic: z.ZodOptional<z.ZodBoolean>;
363
+ code: z.ZodOptional<z.ZodBoolean>;
364
+ }, z.core.$strict>>;
365
+ lines: z.ZodDefault<z.ZodArray<z.ZodString>>;
366
+ }, z.core.$strict>, z.ZodObject<{
367
+ kind: z.ZodLiteral<"text">;
368
+ title: z.ZodOptional<z.ZodString>;
369
+ title_style: z.ZodOptional<z.ZodObject<{
370
+ weight: z.ZodOptional<z.ZodEnum<{
371
+ normal: "normal";
372
+ strong: "strong";
373
+ }>>;
374
+ italic: z.ZodOptional<z.ZodBoolean>;
375
+ code: z.ZodOptional<z.ZodBoolean>;
376
+ }, z.core.$strict>>;
377
+ text: z.ZodString;
378
+ tone: z.ZodOptional<z.ZodEnum<{
379
+ error: "error";
380
+ info: "info";
381
+ success: "success";
382
+ warning: "warning";
383
+ muted: "muted";
384
+ accent: "accent";
385
+ dim: "dim";
386
+ }>>;
387
+ style: z.ZodOptional<z.ZodObject<{
388
+ weight: z.ZodOptional<z.ZodEnum<{
389
+ normal: "normal";
390
+ strong: "strong";
391
+ }>>;
392
+ italic: z.ZodOptional<z.ZodBoolean>;
393
+ code: z.ZodOptional<z.ZodBoolean>;
394
+ }, z.core.$strict>>;
395
+ }, z.core.$strict>], "kind">>>;
396
+ actions: z.ZodDefault<z.ZodArray<z.ZodObject<{
397
+ id: z.ZodString;
398
+ label: z.ZodString;
399
+ command_text: z.ZodString;
400
+ kind: z.ZodOptional<z.ZodEnum<{
401
+ primary: "primary";
402
+ secondary: "secondary";
403
+ danger: "danger";
404
+ }>>;
405
+ style: z.ZodOptional<z.ZodObject<{
406
+ weight: z.ZodOptional<z.ZodEnum<{
407
+ normal: "normal";
408
+ strong: "strong";
409
+ }>>;
410
+ italic: z.ZodOptional<z.ZodBoolean>;
411
+ code: z.ZodOptional<z.ZodBoolean>;
412
+ }, z.core.$strict>>;
413
+ }, z.core.$strict>>>;
414
+ snapshot_compact: z.ZodString;
415
+ snapshot_style: z.ZodOptional<z.ZodObject<{
416
+ weight: z.ZodOptional<z.ZodEnum<{
417
+ normal: "normal";
418
+ strong: "strong";
419
+ }>>;
420
+ italic: z.ZodOptional<z.ZodBoolean>;
421
+ code: z.ZodOptional<z.ZodBoolean>;
422
+ }, z.core.$strict>>;
423
+ snapshot_multiline: z.ZodOptional<z.ZodString>;
424
+ updated_at_ms: z.ZodNumber;
425
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
426
+ }, z.core.$strict>>>;
98
427
  }, z.core.$strip>], "kind">;
99
428
  export type OperatorBackendTurnResult = z.infer<typeof OperatorBackendTurnResultSchema>;
100
429
  export type OperatorBackendTurnInput = {
@@ -111,11 +440,13 @@ export interface MessagingOperatorBackend {
111
440
  export type OperatorDecision = {
112
441
  kind: "response";
113
442
  message: string;
443
+ hud_docs?: HudDoc[];
114
444
  operatorSessionId: string;
115
445
  operatorTurnId: string;
116
446
  } | {
117
447
  kind: "command";
118
448
  commandText: string;
449
+ hud_docs?: HudDoc[];
119
450
  operatorSessionId: string;
120
451
  operatorTurnId: string;
121
452
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
package/dist/operator.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { HudDocSchema, normalizeHudDocs } from "@femtomc/mu-core";
1
2
  import { appendJsonl, getStorePaths, readJsonl } from "@femtomc/mu-core/node";
2
3
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
4
  import { dirname, join } from "node:path";
@@ -6,6 +7,7 @@ import { CommandContextResolver } from "./command_context.js";
6
7
  import { createMuSession } from "./session_factory.js";
7
8
  import { DEFAULT_OPERATOR_SYSTEM_PROMPT } from "./default_prompts.js";
8
9
  const OPERATOR_RESPONSE_MAX_CHARS = 12_000;
10
+ const OPERATOR_TURN_HUD_DOCS_MAX = 16;
9
11
  const SAFE_RESPONSE_RE = new RegExp(`^[\\s\\S]{1,${OPERATOR_RESPONSE_MAX_CHARS}}$`);
10
12
  const OPERATOR_TIMEOUT_MIN_MS = 1_000;
11
13
  const OPERATOR_TIMEOUT_HARD_CAP_MS = 10 * 60 * 1_000;
@@ -42,9 +44,18 @@ export const OperatorApprovedCommandSchema = z.discriminatedUnion("kind", [
42
44
  thinking: z.string().trim().min(1),
43
45
  }),
44
46
  ]);
47
+ const OperatorTurnHudDocsSchema = z.array(HudDocSchema).max(OPERATOR_TURN_HUD_DOCS_MAX).optional();
45
48
  export const OperatorBackendTurnResultSchema = z.discriminatedUnion("kind", [
46
- z.object({ kind: z.literal("respond"), message: z.string().trim().min(1).max(OPERATOR_RESPONSE_MAX_CHARS) }),
47
- z.object({ kind: z.literal("command"), command: OperatorApprovedCommandSchema }),
49
+ z.object({
50
+ kind: z.literal("respond"),
51
+ message: z.string().trim().min(1).max(OPERATOR_RESPONSE_MAX_CHARS),
52
+ hud_docs: OperatorTurnHudDocsSchema,
53
+ }),
54
+ z.object({
55
+ kind: z.literal("command"),
56
+ command: OperatorApprovedCommandSchema,
57
+ hud_docs: OperatorTurnHudDocsSchema,
58
+ }),
48
59
  ]);
49
60
  function normalizeArg(arg) {
50
61
  return arg.trim();
@@ -244,6 +255,43 @@ function nonEmptyString(value) {
244
255
  const trimmed = value.trim();
245
256
  return trimmed.length > 0 ? trimmed : null;
246
257
  }
258
+ function isHudToolName(toolName) {
259
+ const normalized = toolName.trim().toLowerCase();
260
+ return normalized === "mu_hud";
261
+ }
262
+ function extractHudDocsFromToolResult(result) {
263
+ const rec = asRecord(result);
264
+ if (!rec) {
265
+ return [];
266
+ }
267
+ const details = asRecord(rec.details);
268
+ const candidates = [];
269
+ const topLevelHudDocs = rec.hud_docs;
270
+ if (Array.isArray(topLevelHudDocs)) {
271
+ candidates.push(...topLevelHudDocs);
272
+ }
273
+ if (details) {
274
+ const detailHudDocs = details.hud_docs;
275
+ if (Array.isArray(detailHudDocs)) {
276
+ candidates.push(...detailHudDocs);
277
+ }
278
+ }
279
+ return normalizeHudDocs(candidates, { maxDocs: OPERATOR_TURN_HUD_DOCS_MAX });
280
+ }
281
+ function collectHudDocsFromToolExecutionEvent(event) {
282
+ const rec = asRecord(event);
283
+ if (!rec) {
284
+ return [];
285
+ }
286
+ if (nonEmptyString(rec.type) !== "tool_execution_end") {
287
+ return [];
288
+ }
289
+ const toolName = nonEmptyString(rec.toolName);
290
+ if (!toolName || !isHudToolName(toolName)) {
291
+ return [];
292
+ }
293
+ return extractHudDocsFromToolResult(rec.result);
294
+ }
247
295
  function finiteInt(value) {
248
296
  if (typeof value !== "number" || !Number.isFinite(value)) {
249
297
  return null;
@@ -574,6 +622,7 @@ export class MessagingOperatorRuntime {
574
622
  return {
575
623
  kind: "response",
576
624
  message,
625
+ ...(backendResult.hud_docs && backendResult.hud_docs.length > 0 ? { hud_docs: backendResult.hud_docs } : {}),
577
626
  operatorSessionId: sessionId,
578
627
  operatorTurnId: turnId,
579
628
  };
@@ -594,6 +643,7 @@ export class MessagingOperatorRuntime {
594
643
  return {
595
644
  kind: "command",
596
645
  commandText: approved.commandText,
646
+ ...(backendResult.hud_docs && backendResult.hud_docs.length > 0 ? { hud_docs: backendResult.hud_docs } : {}),
597
647
  operatorSessionId: sessionId,
598
648
  operatorTurnId: turnId,
599
649
  };
@@ -905,6 +955,7 @@ export class PiMessagingOperatorBackend {
905
955
  const session = sessionRecord.session;
906
956
  let assistantText = "";
907
957
  let capturedCommand = null;
958
+ let capturedHudDocs = [];
908
959
  const unsub = session.subscribe((event) => {
909
960
  // Capture assistant text for fallback responses.
910
961
  if (event?.type === "message_end" && event?.message?.role === "assistant") {
@@ -933,6 +984,12 @@ export class PiMessagingOperatorBackend {
933
984
  capturedCommand = parsed.data;
934
985
  }
935
986
  }
987
+ const hudDocs = collectHudDocsFromToolExecutionEvent(event);
988
+ if (hudDocs.length > 0) {
989
+ capturedHudDocs = normalizeHudDocs([...capturedHudDocs, ...hudDocs], {
990
+ maxDocs: OPERATOR_TURN_HUD_DOCS_MAX,
991
+ });
992
+ }
936
993
  });
937
994
  const promptText = buildOperatorPrompt(input);
938
995
  const promptOnce = async () => {
@@ -970,6 +1027,7 @@ export class PiMessagingOperatorBackend {
970
1027
  await session.agent.waitForIdle();
971
1028
  assistantText = "";
972
1029
  capturedCommand = null;
1030
+ capturedHudDocs = [];
973
1031
  await promptOnce();
974
1032
  }
975
1033
  }
@@ -993,6 +1051,9 @@ export class PiMessagingOperatorBackend {
993
1051
  command: capturedCommand,
994
1052
  messagePreview: assistantText,
995
1053
  });
1054
+ if (capturedHudDocs.length > 0) {
1055
+ return { kind: "command", command: capturedCommand, hud_docs: capturedHudDocs };
1056
+ }
996
1057
  return { kind: "command", command: capturedCommand };
997
1058
  }
998
1059
  // Otherwise treat the assistant text as a plain response.
@@ -1009,6 +1070,9 @@ export class PiMessagingOperatorBackend {
1009
1070
  outcome: "respond",
1010
1071
  messagePreview: responseMessage,
1011
1072
  });
1073
+ if (capturedHudDocs.length > 0) {
1074
+ return { kind: "respond", message: responseMessage, hud_docs: capturedHudDocs };
1075
+ }
1012
1076
  return { kind: "respond", message: responseMessage };
1013
1077
  }
1014
1078
  dispose() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@femtomc/mu-agent",
3
- "version": "26.2.100",
3
+ "version": "26.2.102",
4
4
  "description": "Shared operator runtime for mu assistant sessions and serve extensions.",
5
5
  "keywords": [
6
6
  "mu",
@@ -24,7 +24,7 @@
24
24
  "themes/**"
25
25
  ],
26
26
  "dependencies": {
27
- "@femtomc/mu-core": "26.2.100",
27
+ "@femtomc/mu-core": "26.2.102",
28
28
  "@mariozechner/pi-agent-core": "^0.53.0",
29
29
  "@mariozechner/pi-ai": "^0.53.0",
30
30
  "@mariozechner/pi-coding-agent": "^0.53.0",
@@ -13,6 +13,7 @@ Use this skill when the user asks to schedule, inspect, tune, or debug `mu heart
13
13
  - [Preflight checks](#preflight-checks)
14
14
  - [Heartbeat lifecycle workflow](#heartbeat-lifecycle-workflow)
15
15
  - [Prompt design for bounded ticks](#prompt-design-for-bounded-ticks)
16
+ - [Reusable status-voice snippet](#reusable-status-voice-snippet)
16
17
  - [Diagnostics and recovery](#diagnostics-and-recovery)
17
18
  - [Evaluation scenarios](#evaluation-scenarios)
18
19
 
@@ -107,15 +108,39 @@ Good pattern:
107
108
  - inspect queue/state
108
109
  - do exactly one action
109
110
  - verify
110
- - summarize progress
111
+ - report project-level progress as a titled status note plus a concise narrative paragraph
112
+ - narrative should cover project context, what milestone moved, impact, overall progress, and next step
113
+ - keep low-level queue/worker internals out of default reporting; include them only for blocker/anomaly diagnosis
111
114
  - exit
112
115
 
113
116
  Example bounded prompt:
114
117
 
115
118
  ```text
116
- Review ready issues under root <root-id>. Perform exactly one bounded step:
117
- claim/work one ready issue (or report blocked), verify state, post concise progress,
118
- then exit.
119
+ Review issues under root <root-id>. Perform exactly one bounded orchestration step,
120
+ verify state, then report for a human as:
121
+ - a short title that summarizes status
122
+ - one concise paragraph: project context, what moved this pass, impact,
123
+ where the project stands overall, and what comes next
124
+ Only include queue/worker details if diagnosing a blocker/anomaly.
125
+ Then exit.
126
+ ```
127
+
128
+ ## Reusable status-voice snippet
129
+
130
+ Use this copy/paste block in heartbeat prompts when updates should be written for
131
+ non-operator humans:
132
+
133
+ ```text
134
+ Write the update as a short status note for a human reader.
135
+ - First line: a plain-language title that captures the status.
136
+ - Then one concise paragraph explaining:
137
+ - what this project is trying to achieve,
138
+ - what meaningful milestone moved in this pass,
139
+ - what impact that creates (or what precondition was completed),
140
+ - where the overall project stands,
141
+ - what comes next and why it matters.
142
+ Avoid low-level orchestration internals by default (queue snapshots, worker/session IDs,
143
+ packet mechanics, raw issue-ID lists). Include them only when diagnosing a blocker/anomaly.
119
144
  ```
120
145
 
121
146
  For hierarchical DAG execution, pair this skill with:
@@ -161,7 +186,7 @@ mu store tail cp_outbox --limit 30 --pretty
161
186
 
162
187
  1. **Periodic progress heartbeat**
163
188
  - Setup: heartbeat created with bounded control-loop prompt and `--every-ms 15000`.
164
- - Expected: each wake performs one bounded pass and exits; no unbounded run behavior.
189
+ - Expected: each wake performs one bounded pass, emits a high-level titled narrative status update, and exits; no unbounded run behavior.
165
190
 
166
191
  2. **Event-driven heartbeat mode**
167
192
  - Setup: heartbeat created/updated with `--every-ms 0`.
@@ -164,6 +164,7 @@ mu issues dep <step-a> blocks <step-b>
164
164
  - Scoped authority: mutate only current issue and descendants.
165
165
  - Non-executable containers/questions must not retain `node:agent`.
166
166
  - Forum updates are append-only and resumable (`START`/`RESULT` packets).
167
+ - Orchestrator progress packets are human-facing and objective-linked: use a clear status title plus concise narrative paragraph (project context, milestone moved, impact, overall progress, next step); include low-level queue/worker internals only for blocker/anomaly diagnosis.
167
168
  - Every executable issue closes with explicit outcome.
168
169
  - `mu issues validate <root-id>` must pass before declaring completion.
169
170
 
@@ -192,7 +193,7 @@ Worker/orchestrator passes always choose one primitive at a time:
192
193
  2. Choose one primitive (`ask` | `expand` | `complete` | orchestration primitive)
193
194
  3. Apply
194
195
  4. Verify (`get`, `children`, `ready`, `validate`)
195
- 5. Log concise progress to forum
196
+ 5. Log human-facing progress to forum as a titled narrative update (context -> milestone moved -> impact -> overall progress -> next), using the reusable status-voice style from `heartbeats`
196
197
  6. Exit bounded pass
197
198
 
198
199
  ## Minimal bootstrap template