@femtomc/mu-agent 26.2.99 → 26.2.101
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/README.md +8 -4
- package/dist/extensions/hud.d.ts +4 -0
- package/dist/extensions/hud.d.ts.map +1 -0
- package/dist/extensions/hud.js +282 -0
- package/dist/extensions/index.d.ts +1 -2
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +1 -2
- package/dist/extensions/mu-operator.d.ts.map +1 -1
- package/dist/extensions/mu-operator.js +2 -4
- package/dist/extensions/mu-serve.d.ts.map +1 -1
- package/dist/extensions/mu-serve.js +2 -4
- package/dist/operator.d.ts +155 -0
- package/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +66 -2
- package/package.json +2 -2
- package/prompts/skills/heartbeats/SKILL.md +30 -5
- package/prompts/skills/hierarchical-work-protocol/SKILL.md +2 -1
- package/prompts/skills/hud/SKILL.md +169 -0
- package/prompts/skills/mu/SKILL.md +1 -1
- package/prompts/skills/planning/SKILL.md +42 -45
- package/prompts/skills/subagents/SKILL.md +39 -16
- package/dist/extensions/hud-mode.d.ts +0 -8
- package/dist/extensions/hud-mode.d.ts.map +0 -1
- package/dist/extensions/hud-mode.js +0 -21
- package/dist/extensions/planning-ui.d.ts +0 -4
- package/dist/extensions/planning-ui.d.ts.map +0 -1
- package/dist/extensions/planning-ui.js +0 -866
- package/dist/extensions/subagents-ui.d.ts +0 -4
- package/dist/extensions/subagents-ui.d.ts.map +0 -1
- package/dist/extensions/subagents-ui.js +0 -1409
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({
|
|
47
|
-
|
|
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.
|
|
3
|
+
"version": "26.2.101",
|
|
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.
|
|
27
|
+
"@femtomc/mu-core": "26.2.101",
|
|
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
|
-
-
|
|
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
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
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
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hud
|
|
3
|
+
description: "Defines HUD usage for `mu_hud` and `/mu hud`, including doc schema patterns, deterministic update rules, and rendering-safe conventions."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# hud
|
|
7
|
+
|
|
8
|
+
Use this skill whenever you need to publish, update, or inspect HUD state.
|
|
9
|
+
|
|
10
|
+
This skill is the canonical HUD reference for:
|
|
11
|
+
|
|
12
|
+
- `mu_hud` tool calls (structured HUD state)
|
|
13
|
+
- `/mu hud ...` command usage (inspection/control)
|
|
14
|
+
- `HudDoc` conventions that render well in TUI/Slack/Telegram
|
|
15
|
+
|
|
16
|
+
## Contents
|
|
17
|
+
|
|
18
|
+
- [Core contract](#core-contract)
|
|
19
|
+
- [HudDoc shape](#huddoc-shape)
|
|
20
|
+
- [Recommended turn loop](#recommended-turn-loop)
|
|
21
|
+
- [Planning and subagents profiles](#planning-and-subagents-profiles)
|
|
22
|
+
- [Determinism and rendering limits](#determinism-and-rendering-limits)
|
|
23
|
+
- [Evaluation scenarios](#evaluation-scenarios)
|
|
24
|
+
|
|
25
|
+
## Core contract
|
|
26
|
+
|
|
27
|
+
### Tool (`mu_hud`)
|
|
28
|
+
|
|
29
|
+
Actions:
|
|
30
|
+
|
|
31
|
+
- `status`, `snapshot`
|
|
32
|
+
- `on`, `off`, `toggle`
|
|
33
|
+
- `set`, `update`, `replace`, `remove`, `clear`
|
|
34
|
+
|
|
35
|
+
Key params:
|
|
36
|
+
|
|
37
|
+
- `doc` (for `set`/`update`)
|
|
38
|
+
- `docs` (for `replace`)
|
|
39
|
+
- `hud_id` (for `remove`)
|
|
40
|
+
- `snapshot_format` (`compact` or `multiline`)
|
|
41
|
+
|
|
42
|
+
Notes:
|
|
43
|
+
|
|
44
|
+
- `set` and `update` are both upsert-style single-doc writes.
|
|
45
|
+
- `replace` is whole-inventory replacement.
|
|
46
|
+
- Tool results include normalized `hud_docs` for downstream transport/rendering.
|
|
47
|
+
|
|
48
|
+
### Command (`/mu hud ...`)
|
|
49
|
+
|
|
50
|
+
Supported subcommands:
|
|
51
|
+
|
|
52
|
+
- `/mu hud status`
|
|
53
|
+
- `/mu hud snapshot [compact|multiline]`
|
|
54
|
+
- `/mu hud on|off|toggle`
|
|
55
|
+
- `/mu hud clear`
|
|
56
|
+
- `/mu hud remove <hud-id>`
|
|
57
|
+
|
|
58
|
+
Use the tool (`mu_hud`) for structured doc writes.
|
|
59
|
+
|
|
60
|
+
## HudDoc shape
|
|
61
|
+
|
|
62
|
+
HUD docs are validated against `HudDoc` (`@femtomc/mu-core`).
|
|
63
|
+
|
|
64
|
+
Minimum practical fields:
|
|
65
|
+
|
|
66
|
+
- `v: 1`
|
|
67
|
+
- `hud_id: <non-empty>`
|
|
68
|
+
- `title: <non-empty>`
|
|
69
|
+
- `snapshot_compact: <non-empty>`
|
|
70
|
+
- `updated_at_ms: <int>`
|
|
71
|
+
|
|
72
|
+
Common optional fields:
|
|
73
|
+
|
|
74
|
+
- `scope` (for root/session/issue scoping)
|
|
75
|
+
- `chips` (`[{key,label,tone?}]`)
|
|
76
|
+
- `sections`:
|
|
77
|
+
- `kv` (key/value)
|
|
78
|
+
- `checklist` (checkbox-style progress)
|
|
79
|
+
- `activity` (recent lines)
|
|
80
|
+
- `text` (free text)
|
|
81
|
+
- `actions` (`[{id,label,command_text,kind?}]`)
|
|
82
|
+
- `metadata` (machine-readable extras)
|
|
83
|
+
|
|
84
|
+
Example checklist doc:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"action": "set",
|
|
89
|
+
"doc": {
|
|
90
|
+
"v": 1,
|
|
91
|
+
"hud_id": "planning",
|
|
92
|
+
"title": "Planning HUD",
|
|
93
|
+
"scope": "mu-root-123",
|
|
94
|
+
"chips": [
|
|
95
|
+
{ "key": "phase", "label": "phase:drafting", "tone": "accent" },
|
|
96
|
+
{ "key": "steps", "label": "steps:2/5", "tone": "dim" }
|
|
97
|
+
],
|
|
98
|
+
"sections": [
|
|
99
|
+
{
|
|
100
|
+
"kind": "checklist",
|
|
101
|
+
"title": "Checklist",
|
|
102
|
+
"items": [
|
|
103
|
+
{ "id": "1", "label": "Investigate", "done": true },
|
|
104
|
+
{ "id": "2", "label": "Draft DAG", "done": true },
|
|
105
|
+
{ "id": "3", "label": "Review", "done": false }
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"actions": [
|
|
110
|
+
{ "id": "snapshot", "label": "Snapshot", "command_text": "/mu hud snapshot", "kind": "secondary" }
|
|
111
|
+
],
|
|
112
|
+
"snapshot_compact": "HUD(plan) · phase=drafting · steps=2/5",
|
|
113
|
+
"updated_at_ms": 1771853115000,
|
|
114
|
+
"metadata": { "phase": "drafting" }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Recommended turn loop
|
|
120
|
+
|
|
121
|
+
1. Ensure HUD is on:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{"action":"on"}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
2. Upsert exactly the docs you own (`set`/`update`).
|
|
128
|
+
3. Emit compact snapshot for user-facing status:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{"action":"snapshot","snapshot_format":"compact"}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
4. Keep response text and HUD state aligned (no contradictions).
|
|
135
|
+
|
|
136
|
+
## Planning and subagents profiles
|
|
137
|
+
|
|
138
|
+
Use profile-specific `hud_id` values:
|
|
139
|
+
|
|
140
|
+
- planning profile: `hud_id: "planning"`
|
|
141
|
+
- subagents profile: `hud_id: "subagents"`
|
|
142
|
+
|
|
143
|
+
Treat these as conventions layered on top of this generic contract.
|
|
144
|
+
|
|
145
|
+
## Determinism and rendering limits
|
|
146
|
+
|
|
147
|
+
- Keep one canonical doc per `hud_id`.
|
|
148
|
+
- Keep `updated_at_ms` monotonic for each `hud_id`.
|
|
149
|
+
- Prefer a small doc set (usually 1–3 docs total) for channel readability.
|
|
150
|
+
- Keep command actions concise; long commands may degrade to text-only fallbacks on some channels.
|
|
151
|
+
- Assume channel renderers cap docs/actions/lines; put critical state in `snapshot_compact` and first section items.
|
|
152
|
+
|
|
153
|
+
If behavior is unclear, inspect implementation/tests before guessing:
|
|
154
|
+
|
|
155
|
+
- `packages/core/src/hud.ts`
|
|
156
|
+
- `packages/agent/src/extensions/hud.ts`
|
|
157
|
+
- `packages/server/src/control_plane.ts`
|
|
158
|
+
- `packages/agent/test/hud_tool.test.ts`
|
|
159
|
+
|
|
160
|
+
## Evaluation scenarios
|
|
161
|
+
|
|
162
|
+
1. **Planning review turn**
|
|
163
|
+
- Expected: `planning` doc updates phase/checklist/waiting state, then emits compact snapshot.
|
|
164
|
+
|
|
165
|
+
2. **Subagents orchestration pass**
|
|
166
|
+
- Expected: `subagents` doc updates queue/activity/chips after each bounded pass.
|
|
167
|
+
|
|
168
|
+
3. **HUD reset handoff**
|
|
169
|
+
- Expected: after phase completion, HUD is cleared or removed by `hud_id`, and status reflects no stale docs.
|
|
@@ -98,7 +98,7 @@ mu session <session-id>
|
|
|
98
98
|
mu turn --session-kind operator --session-id <session-id> --body "<follow-up>"
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
In attached terminal operator chat, `/mu` helpers are available (`/mu events`, `/mu
|
|
101
|
+
In attached terminal operator chat, `/mu` helpers are available (`/mu events`, `/mu hud ...`, `/mu help`).
|
|
102
102
|
|
|
103
103
|
## Durable automation handoff
|
|
104
104
|
|
|
@@ -10,6 +10,7 @@ Use this skill when the user asks for planning, decomposition, or a staged execu
|
|
|
10
10
|
## Contents
|
|
11
11
|
|
|
12
12
|
- [Planning HUD is required](#planning-hud-is-required)
|
|
13
|
+
- [HUD skill dependency](#hud-skill-dependency)
|
|
13
14
|
- [Shared protocol dependency](#shared-protocol-dependency)
|
|
14
15
|
- [Core contract](#core-contract)
|
|
15
16
|
- [Suggested workflow](#suggested-workflow)
|
|
@@ -28,10 +29,17 @@ For this skill, the planning HUD is the primary status/communication surface.
|
|
|
28
29
|
|
|
29
30
|
Default per-turn HUD loop:
|
|
30
31
|
|
|
31
|
-
1.
|
|
32
|
-
2.
|
|
32
|
+
1. Emit a fresh `planning` HUD doc (`mu_hud` action `set` or `update`) with current `phase`, `waiting_on_user`, `next_action`, `blocker`, and `confidence` in sections/metadata.
|
|
33
|
+
2. Keep checklist progress and root issue linkage synchronized with the live issue DAG.
|
|
33
34
|
3. Emit `snapshot` (`compact` or `multiline`) and reflect it in your response.
|
|
34
35
|
|
|
36
|
+
## HUD skill dependency
|
|
37
|
+
|
|
38
|
+
Before emitting or mutating planning HUD state, load **`hud`** and follow its canonical contract.
|
|
39
|
+
|
|
40
|
+
- Treat `hud` as source-of-truth for generic `mu_hud` actions, `HudDoc` shape, and rendering constraints.
|
|
41
|
+
- This planning skill defines planning-specific conventions only (for example `hud_id: "planning"`, planning phases, checklist semantics).
|
|
42
|
+
|
|
35
43
|
## Shared protocol dependency
|
|
36
44
|
|
|
37
45
|
This skill plans DAGs for execution by `subagents`, so planning must follow the
|
|
@@ -58,6 +66,7 @@ Do not invent alternate protocol names or tag schemas.
|
|
|
58
66
|
- Add clear titles, scope, acceptance criteria, and protocol tags.
|
|
59
67
|
|
|
60
68
|
3. **Drive communication through the planning HUD**
|
|
69
|
+
- Load `hud` and use its canonical `mu_hud`/`HudDoc` contract.
|
|
61
70
|
- Treat HUD state as the canonical short status line for planning.
|
|
62
71
|
- Keep `phase`, `waiting_on_user`, `next_action`, `blocker`, and `confidence` current.
|
|
63
72
|
- Ensure HUD state and your natural-language response never contradict each other.
|
|
@@ -72,6 +81,10 @@ Do not invent alternate protocol names or tag schemas.
|
|
|
72
81
|
- Update issues/dependencies and re-present deltas.
|
|
73
82
|
- Do not begin broad execution until the user signals satisfaction.
|
|
74
83
|
|
|
84
|
+
6. **After user approval, ask user about next steps**
|
|
85
|
+
- On user acceptance of the plan, turn the planning HUD off.
|
|
86
|
+
- Read the `subagents` skill and offer to supervise subagents to execute the plan.
|
|
87
|
+
|
|
75
88
|
## Suggested workflow
|
|
76
89
|
|
|
77
90
|
### A) Investigation pass
|
|
@@ -86,46 +99,36 @@ mu memory search --query "<topic>" --limit 30
|
|
|
86
99
|
Bootstrap HUD immediately (interactive operator session):
|
|
87
100
|
|
|
88
101
|
```text
|
|
89
|
-
/mu
|
|
90
|
-
/mu
|
|
91
|
-
/mu
|
|
92
|
-
/mu plan confidence medium
|
|
93
|
-
/mu plan next "Investigate constraints and gather evidence"
|
|
94
|
-
/mu plan snapshot
|
|
102
|
+
/mu hud on
|
|
103
|
+
/mu hud status
|
|
104
|
+
/mu hud snapshot
|
|
95
105
|
```
|
|
96
106
|
|
|
97
107
|
Tool contract (preferred when tools are available):
|
|
98
108
|
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
- `confidence`: `low|medium|high`
|
|
111
|
-
- `steps`: string[]
|
|
112
|
-
- `step_updates`: array of `{index, done?, label?}`
|
|
109
|
+
- Canonical contract: see skill `hud`
|
|
110
|
+
- Tool: `mu_hud`
|
|
111
|
+
- Actions: `status`, `snapshot`, `on`, `off`, `toggle`, `set`, `update`, `replace`, `remove`, `clear`
|
|
112
|
+
- Planning convention: maintain a HUD doc with `hud_id: "planning"`
|
|
113
|
+
- Suggested planning doc structure:
|
|
114
|
+
- `title`: `Planning HUD`
|
|
115
|
+
- chips: `phase:<...>`, `steps:<done>/<total>`, `waiting:<yes|no>`, `conf:<low|medium|high>`
|
|
116
|
+
- sections:
|
|
117
|
+
- `kv` status block (`phase`, `root`, `waiting_on_user`, `confidence`, `next_action`, `blocker`)
|
|
118
|
+
- `checklist` block for plan milestones
|
|
119
|
+
- actions: include useful follow-ups (for example, `snapshot`)
|
|
113
120
|
|
|
114
121
|
Example tool calls:
|
|
115
|
-
-
|
|
116
|
-
- `{"action":"
|
|
117
|
-
-
|
|
118
|
-
- `{"action":"
|
|
119
|
-
- Clear communication fields after user reply:
|
|
120
|
-
- `{"action":"update","waiting_on_user":false,"blocker":"clear","next_action":"Incorporate feedback and re-draft DAG"}`
|
|
121
|
-
- Customize checklist:
|
|
122
|
-
- `{"action":"set_steps","steps":["Investigate","Draft DAG","Review with user","Finalize"]}`
|
|
122
|
+
- Turn HUD on:
|
|
123
|
+
- `{"action":"on"}`
|
|
124
|
+
- Set/replace planning doc after investigation pass:
|
|
125
|
+
- `{"action":"set","doc":{"v":1,"hud_id":"planning","title":"Planning HUD","scope":"mu-root-123","chips":[{"key":"phase","label":"phase:investigating","tone":"dim"},{"key":"steps","label":"steps:1/4","tone":"accent"},{"key":"waiting","label":"waiting:no","tone":"dim"},{"key":"confidence","label":"conf:medium","tone":"accent"}],"sections":[{"kind":"kv","title":"Status","items":[{"key":"phase","label":"phase","value":"investigating"},{"key":"root","label":"root","value":"mu-root-123"},{"key":"waiting","label":"waiting_on_user","value":"no"},{"key":"confidence","label":"confidence","value":"medium"},{"key":"next","label":"next_action","value":"Draft root DAG"},{"key":"blocker","label":"blocker","value":"(none)"}]},{"kind":"checklist","title":"Checklist","items":[{"id":"1","label":"Investigate relevant code/docs/state","done":true},{"id":"2","label":"Create root + child issue DAG","done":false},{"id":"3","label":"Present plan + tradeoffs","done":false},{"id":"4","label":"Refine until approved","done":false}]}],"actions":[{"id":"snapshot","label":"Snapshot","command_text":"/mu hud snapshot","kind":"secondary"}],"snapshot_compact":"HUD(plan) · phase=investigating · steps=1/4 · waiting=no · conf=medium","updated_at_ms":1771853115000,"metadata":{"phase":"investigating","waiting_on_user":false,"confidence":"medium"}}}`
|
|
123
126
|
- Human-facing status line:
|
|
124
127
|
- `{"action":"snapshot","snapshot_format":"compact"}`
|
|
125
128
|
|
|
126
129
|
If HUD behavior is unclear, inspect implementation/tests before guessing:
|
|
127
|
-
- `packages/agent/src/extensions/
|
|
128
|
-
- `packages/agent/test/
|
|
130
|
+
- `packages/agent/src/extensions/hud.ts`
|
|
131
|
+
- `packages/agent/test/hud_tool.test.ts`
|
|
129
132
|
|
|
130
133
|
Also inspect repo files directly (read/bash) for implementation constraints.
|
|
131
134
|
|
|
@@ -186,23 +189,17 @@ mu issues validate "$root_id"
|
|
|
186
189
|
|
|
187
190
|
Required HUD updates during the loop:
|
|
188
191
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
/mu plan check 1
|
|
193
|
-
/mu plan phase waiting-user
|
|
194
|
-
/mu plan waiting on
|
|
195
|
-
/mu plan next "Need your approval on tradeoff A/B"
|
|
196
|
-
/mu plan snapshot
|
|
197
|
-
```
|
|
192
|
+
- Re-emit the `planning` HUD doc with current `phase`, checklist progress, `waiting_on_user`, `next_action`, and `blocker` after each meaningful planning step.
|
|
193
|
+
- Use `{"action":"snapshot","snapshot_format":"compact"}` for concise user-facing HUD lines.
|
|
194
|
+
- Keep `updated_at_ms` monotonic across updates so latest doc wins deterministically.
|
|
198
195
|
|
|
199
196
|
## Effective HUD usage heuristics
|
|
200
197
|
|
|
201
|
-
-
|
|
202
|
-
-
|
|
198
|
+
- Keep one canonical planning doc (`hud_id: "planning"`) and refresh it whenever planning state changes.
|
|
199
|
+
- Keep `updated_at_ms` monotonic so deterministic dedupe/ordering always keeps the latest planning state.
|
|
200
|
+
- Use explicit, concise status fields (`phase`, `waiting_on_user`, `next_action`, `blocker`, `confidence`) in sections/metadata.
|
|
203
201
|
- Keep `next_action` as one concrete action, not a paragraph.
|
|
204
|
-
-
|
|
205
|
-
- Customize checklist steps once scope is understood; check them off as milestones complete.
|
|
202
|
+
- Customize checklist steps once scope is understood; mark them complete as milestones land.
|
|
206
203
|
|
|
207
204
|
## Evaluation scenarios
|
|
208
205
|
|