@femtomc/mu-agent 26.2.90 → 26.2.91

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/operator.js CHANGED
@@ -16,20 +16,6 @@ export const OperatorApprovedCommandSchema = z.discriminatedUnion("kind", [
16
16
  topic: z.string().trim().min(1).optional(),
17
17
  limit: z.number().int().min(1).max(500).optional(),
18
18
  }),
19
- z.object({ kind: z.literal("run_list") }),
20
- z.object({
21
- kind: z.literal("run_status"),
22
- root_issue_id: z.string().trim().min(1).optional(),
23
- }),
24
- z.object({
25
- kind: z.literal("run_resume"),
26
- root_issue_id: z.string().trim().min(1).optional(),
27
- max_steps: z.number().int().min(1).max(500).optional(),
28
- }),
29
- z.object({
30
- kind: z.literal("run_interrupt"),
31
- root_issue_id: z.string().trim().min(1).optional(),
32
- }),
33
19
  z.object({ kind: z.literal("reload") }),
34
20
  z.object({ kind: z.literal("update") }),
35
21
  z.object({ kind: z.literal("operator_config_get") }),
@@ -52,31 +38,18 @@ export const OperatorApprovedCommandSchema = z.discriminatedUnion("kind", [
52
38
  kind: z.literal("operator_thinking_set"),
53
39
  thinking: z.string().trim().min(1),
54
40
  }),
55
- z.object({
56
- kind: z.literal("run_start"),
57
- prompt: z.string().trim().min(1),
58
- max_steps: z.number().int().min(1).max(500).optional(),
59
- }),
60
41
  ]);
61
42
  export const OperatorBackendTurnResultSchema = z.discriminatedUnion("kind", [
62
43
  z.object({ kind: z.literal("respond"), message: z.string().trim().min(1).max(2000) }),
63
44
  z.object({ kind: z.literal("command"), command: OperatorApprovedCommandSchema }),
64
45
  ]);
65
- function splitPromptIntoTokens(prompt) {
66
- return prompt
67
- .split(/\s+/)
68
- .map((token) => token.trim())
69
- .filter((token) => token.length > 0);
70
- }
71
46
  function normalizeArg(arg) {
72
47
  return arg.trim();
73
48
  }
74
49
  export class ApprovedCommandBroker {
75
50
  #contextResolver;
76
- #runTriggersEnabled;
77
51
  constructor(opts = {}) {
78
52
  this.#contextResolver = opts.contextResolver ?? new CommandContextResolver();
79
- this.#runTriggersEnabled = opts.runTriggersEnabled ?? true;
80
53
  }
81
54
  approve(opts) {
82
55
  let commandKey;
@@ -109,42 +82,6 @@ export class ApprovedCommandBroker {
109
82
  }
110
83
  break;
111
84
  }
112
- case "run_list":
113
- commandKey = "run list";
114
- args = [];
115
- break;
116
- case "run_status":
117
- commandKey = "run status";
118
- args = [];
119
- if (opts.proposal.root_issue_id) {
120
- args.push(normalizeArg(opts.proposal.root_issue_id));
121
- }
122
- break;
123
- case "run_resume": {
124
- if (!this.#runTriggersEnabled) {
125
- return { kind: "reject", reason: "operator_action_disallowed", details: "run triggers disabled" };
126
- }
127
- commandKey = "run resume";
128
- args = [];
129
- if (opts.proposal.root_issue_id) {
130
- args.push(normalizeArg(opts.proposal.root_issue_id));
131
- }
132
- if (opts.proposal.max_steps != null) {
133
- args.push(String(Math.trunc(opts.proposal.max_steps)));
134
- }
135
- break;
136
- }
137
- case "run_interrupt": {
138
- if (!this.#runTriggersEnabled) {
139
- return { kind: "reject", reason: "operator_action_disallowed", details: "run triggers disabled" };
140
- }
141
- commandKey = "run interrupt";
142
- args = [];
143
- if (opts.proposal.root_issue_id) {
144
- args.push(normalizeArg(opts.proposal.root_issue_id));
145
- }
146
- break;
147
- }
148
85
  case "reload": {
149
86
  commandKey = "reload";
150
87
  args = [];
@@ -192,14 +129,6 @@ export class ApprovedCommandBroker {
192
129
  args = [normalizeArg(opts.proposal.thinking)];
193
130
  break;
194
131
  }
195
- case "run_start": {
196
- if (!this.#runTriggersEnabled) {
197
- return { kind: "reject", reason: "operator_action_disallowed", details: "run triggers disabled" };
198
- }
199
- commandKey = "run start";
200
- args = splitPromptIntoTokens(opts.proposal.prompt);
201
- break;
202
- }
203
132
  default:
204
133
  return { kind: "reject", reason: "operator_action_disallowed" };
205
134
  }
@@ -234,7 +163,7 @@ function buildOperatorFailureFallbackMessage(code) {
234
163
  return [
235
164
  "I ran into an internal operator formatting/runtime issue and could not complete that turn safely.",
236
165
  `Code: ${code}`,
237
- "You can retry, or use an explicit /mu command (for example: /mu status or /mu run list).",
166
+ "You can retry, or use an explicit /mu command (for example: /mu status or /mu issue list).",
238
167
  ].join("\n");
239
168
  }
240
169
  function conversationKey(inbound, binding) {
@@ -1 +1 @@
1
- {"version":3,"file":"self_documentation.d.ts","sourceRoot":"","sources":["../src/self_documentation.ts"],"names":[],"mappings":"AA8BA,KAAK,eAAe,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAgFF,MAAM,MAAM,eAAe,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,eAAe,EAAE,CAAC;CAClC,CAAC;AAEF,wBAAgB,sBAAsB,IAAI,eAAe,CAiCxD;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAyBvE"}
1
+ {"version":3,"file":"self_documentation.d.ts","sourceRoot":"","sources":["../src/self_documentation.ts"],"names":[],"mappings":"AA8BA,KAAK,eAAe,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AA8EF,MAAM,MAAM,eAAe,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,eAAe,EAAE,CAAC;CAClC,CAAC;AAEF,wBAAgB,sBAAsB,IAAI,eAAe,CAiCxD;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAyBvE"}
@@ -30,7 +30,6 @@ const INSTALLED_PACKAGE_README_LOOKUP = [
30
30
  { packageName: "@femtomc/mu-core", label: "@femtomc/mu-core" },
31
31
  { packageName: "@femtomc/mu-forum", label: "@femtomc/mu-forum" },
32
32
  { packageName: "@femtomc/mu-issue", label: "@femtomc/mu-issue" },
33
- { packageName: "@femtomc/mu-orchestrator", label: "@femtomc/mu-orchestrator" },
34
33
  { packageName: "@femtomc/mu-server", label: "@femtomc/mu-server" },
35
34
  ];
36
35
  const MONOREPO_PACKAGE_README_LOOKUP = [
@@ -39,7 +38,6 @@ const MONOREPO_PACKAGE_README_LOOKUP = [
39
38
  { relPath: join("packages", "core", "README.md"), label: "@femtomc/mu-core" },
40
39
  { relPath: join("packages", "forum", "README.md"), label: "@femtomc/mu-forum" },
41
40
  { relPath: join("packages", "issue", "README.md"), label: "@femtomc/mu-issue" },
42
- { relPath: join("packages", "orchestrator", "README.md"), label: "@femtomc/mu-orchestrator" },
43
41
  { relPath: join("packages", "server", "README.md"), label: "@femtomc/mu-server" },
44
42
  { relPath: join("packages", "cli", "README.md"), label: "@femtomc/mu (CLI)" },
45
43
  { relPath: join("packages", "neovim", "README.md"), label: "mu.nvim" },
@@ -1,7 +1,9 @@
1
1
  import { type CreateMuSessionOpts, type MuSession } from "./session_factory.js";
2
+ export type SessionKind = "operator" | "cp_operator";
3
+ export type SessionExtensionProfile = "operator" | "none";
2
4
  export type SessionTurnRequest = {
3
5
  session_id: string;
4
- session_kind: string | null;
6
+ session_kind: SessionKind | null;
5
7
  body: string;
6
8
  source: string | null;
7
9
  provider: string | null;
@@ -9,11 +11,11 @@ export type SessionTurnRequest = {
9
11
  thinking: string | null;
10
12
  session_file: string | null;
11
13
  session_dir: string | null;
12
- extension_profile: string | null;
14
+ extension_profile: SessionExtensionProfile | null;
13
15
  };
14
16
  export type SessionTurnResult = {
15
17
  session_id: string;
16
- session_kind: string | null;
18
+ session_kind: SessionKind | null;
17
19
  session_file: string;
18
20
  context_entry_id: string | null;
19
21
  reply: string;
@@ -1 +1 @@
1
- {"version":3,"file":"session_turn.d.ts","sourceRoot":"","sources":["../src/session_turn.ts"],"names":[],"mappings":"AAcA,OAAO,EAAmB,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjG,MAAM,MAAM,kBAAkB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEL,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAIlD;AAoSD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CA+BA;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+F7B"}
1
+ {"version":3,"file":"session_turn.d.ts","sourceRoot":"","sources":["../src/session_turn.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjG,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;AACrD,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,MAAM,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,uBAAuB,GAAG,IAAI,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEL,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAIlD;AAsQD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAyCA;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+F7B"}
@@ -1,8 +1,8 @@
1
1
  import { getStorePaths } from "@femtomc/mu-core/node";
2
2
  import { readdir, readFile, stat } from "node:fs/promises";
3
3
  import { dirname, isAbsolute, join, resolve } from "node:path";
4
- import { DEFAULT_OPERATOR_SYSTEM_PROMPT, DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_REVIEWER_PROMPT, DEFAULT_WORKER_PROMPT, } from "./default_prompts.js";
5
- import { operatorExtensionPaths, orchestratorToolExtensionPaths, workerToolExtensionPaths, } from "./extensions/index.js";
4
+ import { DEFAULT_OPERATOR_SYSTEM_PROMPT } from "./default_prompts.js";
5
+ import { operatorExtensionPaths } from "./extensions/index.js";
6
6
  import { createMuSession } from "./session_factory.js";
7
7
  export class SessionTurnError extends Error {
8
8
  status;
@@ -29,21 +29,20 @@ function normalizeSessionKind(value) {
29
29
  return null;
30
30
  }
31
31
  const normalized = value.trim().toLowerCase().replaceAll("-", "_");
32
- if (normalized === "cpoperator" || normalized === "control_plane_operator") {
32
+ if (normalized === "cpoperator" || normalized === "control_plane_operator" || normalized === "cp_operator") {
33
33
  return "cp_operator";
34
34
  }
35
- return normalized;
35
+ if (normalized === "operator") {
36
+ return "operator";
37
+ }
38
+ return null;
36
39
  }
37
40
  function normalizeExtensionProfile(value) {
38
41
  if (!value) {
39
42
  return null;
40
43
  }
41
44
  const normalized = value.trim().toLowerCase();
42
- if (normalized === "operator" ||
43
- normalized === "worker" ||
44
- normalized === "orchestrator" ||
45
- normalized === "reviewer" ||
46
- normalized === "none") {
45
+ if (normalized === "operator" || normalized === "none") {
47
46
  return normalized;
48
47
  }
49
48
  return null;
@@ -62,13 +61,6 @@ function defaultSessionDirForKind(repoRoot, sessionKind) {
62
61
  case "operator":
63
62
  return join(storeDir, "operator", "sessions");
64
63
  case "cp_operator":
65
- return join(storeDir, "control-plane", "operator-sessions");
66
- case "orchestrator":
67
- return join(storeDir, "orchestrator", "sessions");
68
- case "worker":
69
- return join(storeDir, "worker", "sessions");
70
- case "reviewer":
71
- return join(storeDir, "reviewer", "sessions");
72
64
  default:
73
65
  return join(storeDir, "control-plane", "operator-sessions");
74
66
  }
@@ -152,38 +144,20 @@ function extensionPathsForTurn(opts) {
152
144
  if (opts.extensionProfile === "operator") {
153
145
  return [...operatorExtensionPaths];
154
146
  }
155
- if (opts.extensionProfile === "orchestrator") {
156
- return [...orchestratorToolExtensionPaths];
157
- }
158
- if (opts.extensionProfile === "worker" || opts.extensionProfile === "reviewer") {
159
- return [...workerToolExtensionPaths];
160
- }
161
147
  if (opts.sessionKind === "operator" || opts.sessionKind === "cp_operator") {
162
148
  return [...operatorExtensionPaths];
163
149
  }
164
- if (opts.sessionKind === "orchestrator") {
165
- return [...orchestratorToolExtensionPaths];
166
- }
167
- if (opts.sessionKind === "worker" || opts.sessionKind === "reviewer") {
168
- return [...workerToolExtensionPaths];
169
- }
170
150
  return [...operatorExtensionPaths];
171
151
  }
172
152
  function systemPromptForTurn(opts) {
173
- const role = opts.extensionProfile ?? opts.sessionKind;
174
- if (role === "operator" || role === "cp_operator") {
175
- return DEFAULT_OPERATOR_SYSTEM_PROMPT;
153
+ const profile = opts.extensionProfile ?? opts.sessionKind;
154
+ if (profile === "none") {
155
+ return undefined;
176
156
  }
177
- if (role === "orchestrator") {
178
- return DEFAULT_ORCHESTRATOR_PROMPT;
179
- }
180
- if (role === "reviewer") {
181
- return DEFAULT_REVIEWER_PROMPT;
182
- }
183
- if (role === "worker") {
184
- return DEFAULT_WORKER_PROMPT;
157
+ if (profile === "operator" || profile === "cp_operator") {
158
+ return DEFAULT_OPERATOR_SYSTEM_PROMPT;
185
159
  }
186
- return undefined;
160
+ return DEFAULT_OPERATOR_SYSTEM_PROMPT;
187
161
  }
188
162
  function extractAssistantText(message) {
189
163
  if (!message || typeof message !== "object") {
@@ -275,17 +249,26 @@ export function parseSessionTurnRequest(body) {
275
249
  if (!messageBody) {
276
250
  return { request: null, error: "body (or message/prompt) is required" };
277
251
  }
252
+ const sessionKindRaw = nonEmptyString(body.session_kind);
253
+ const normalizedSessionKind = normalizeSessionKind(sessionKindRaw);
254
+ if (sessionKindRaw && !normalizedSessionKind) {
255
+ return {
256
+ request: null,
257
+ error: "session_kind must be one of operator|cp_operator",
258
+ };
259
+ }
278
260
  const extensionProfileRaw = nonEmptyString(body.extension_profile);
279
- if (extensionProfileRaw && !normalizeExtensionProfile(extensionProfileRaw)) {
261
+ const normalizedExtensionProfile = normalizeExtensionProfile(extensionProfileRaw);
262
+ if (extensionProfileRaw && !normalizedExtensionProfile) {
280
263
  return {
281
264
  request: null,
282
- error: "extension_profile must be one of operator|worker|orchestrator|reviewer|none",
265
+ error: "extension_profile must be one of operator|none",
283
266
  };
284
267
  }
285
268
  return {
286
269
  request: {
287
270
  session_id: sessionId,
288
- session_kind: nonEmptyString(body.session_kind),
271
+ session_kind: normalizedSessionKind,
289
272
  body: messageBody,
290
273
  source: nonEmptyString(body.source),
291
274
  provider: nonEmptyString(body.provider),
@@ -293,7 +276,7 @@ export function parseSessionTurnRequest(body) {
293
276
  thinking: nonEmptyString(body.thinking),
294
277
  session_file: nonEmptyString(body.session_file),
295
278
  session_dir: nonEmptyString(body.session_dir),
296
- extension_profile: extensionProfileRaw,
279
+ extension_profile: normalizedExtensionProfile,
297
280
  },
298
281
  error: null,
299
282
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@femtomc/mu-agent",
3
- "version": "26.2.90",
4
- "description": "Shared agent runtime for mu assistant sessions, orchestration roles, and serve extensions.",
3
+ "version": "26.2.91",
4
+ "description": "Shared operator runtime for mu assistant sessions and serve extensions.",
5
5
  "keywords": [
6
6
  "mu",
7
7
  "agent",
@@ -24,7 +24,7 @@
24
24
  "themes/**"
25
25
  ],
26
26
  "dependencies": {
27
- "@femtomc/mu-core": "26.2.90",
27
+ "@femtomc/mu-core": "26.2.91",
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",
@@ -6,7 +6,7 @@ Available tools:
6
6
  - bash: Execute shell commands (primary path for `mu` CLI)
7
7
  - edit: Make surgical edits to files
8
8
  - write: Create or overwrite files
9
- - mu: Accessible via CLI through `bash`, and gives you access to contextual memory, workflow orchestration, and reactive operations.
9
+ - mu: Accessible via CLI through `bash`, and gives you access to contextual memory, workflow coordination, and reactive operations.
10
10
 
11
11
  Workflow:
12
12
  - Use bash for file operations like ls, grep, find, and to access the `mu` CLI.
@@ -109,11 +109,11 @@ Also inspect repo files directly (read/bash) for implementation constraints.
109
109
 
110
110
  ```bash
111
111
  # 1) Create root planning issue
112
- mu issues create "<Goal>" --body "<scope + success criteria>" --tag node:root --role orchestrator --pretty
112
+ mu issues create "<Goal>" --body "<scope + success criteria>" --tag node:root --pretty
113
113
 
114
114
  # 2) Create child work items
115
- mu issues create "<Subtask A>" --parent <root-id> --role worker --priority 2 --pretty
116
- mu issues create "<Subtask B>" --parent <root-id> --role worker --priority 2 --pretty
115
+ mu issues create "<Subtask A>" --parent <root-id> --priority 2 --pretty
116
+ mu issues create "<Subtask B>" --parent <root-id> --priority 2 --pretty
117
117
 
118
118
  # 3) Add dependency edges where needed
119
119
  mu issues dep <child-a-id> blocks <child-b-id>