@femtomc/mu-core 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/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export * from "./dag.js";
2
1
  export * from "./events.js";
3
2
  export * from "./ids.js";
4
3
  export * from "./persistence.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from "./dag.js";
2
1
  export * from "./events.js";
3
2
  export * from "./ids.js";
4
3
  export * from "./persistence.js";
@@ -6,7 +6,6 @@ export { findRepoRoot, getMuHomeDir, getStorePaths, workspaceIdForRepoRoot } fro
6
6
  import { EventLog } from "../events.js";
7
7
  export declare function fsEventLog(path: string): EventLog;
8
8
  export declare function fsEventLogFromRepoRoot(repoRoot: string): EventLog;
9
- export * from "../dag.js";
10
9
  export { EVENT_VERSION, type EventEnvelope, EventLog, type EventSink, JsonlEventSink, NullEventSink, type RunIdProvider, } from "../events.js";
11
10
  export { newRunId, nowTs, nowTsMs, randomHex, shortId } from "../ids.js";
12
11
  export { InMemoryJsonlStore, type JsonlStore } from "../persistence.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,WAAW,EACX,YAAY,EACZ,eAAe,EACf,yBAAyB,EACzB,SAAS,EACT,WAAW,EACX,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC5D,cAAc,qBAAqB,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,EAAE,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAKxD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAEjD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAEjE;AAED,cAAc,WAAW,CAAC;AAE1B,OAAO,EACN,aAAa,EACb,KAAK,aAAa,EAClB,QAAQ,EACR,KAAK,SAAS,EACd,cAAc,EACd,aAAa,EACb,KAAK,aAAa,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACxE,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,WAAW,EACX,YAAY,EACZ,eAAe,EACf,yBAAyB,EACzB,SAAS,EACT,WAAW,EACX,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC5D,cAAc,qBAAqB,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,EAAE,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAKxD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAEjD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAEjE;AAGD,OAAO,EACN,aAAa,EACb,KAAK,aAAa,EAClB,QAAQ,EACR,KAAK,SAAS,EACd,cAAc,EACd,aAAa,EACb,KAAK,aAAa,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACxE,cAAc,YAAY,CAAC"}
@@ -12,7 +12,6 @@ export function fsEventLog(path) {
12
12
  export function fsEventLogFromRepoRoot(repoRoot) {
13
13
  return fsEventLog(getStorePaths(repoRoot).eventsPath);
14
14
  }
15
- export * from "../dag.js";
16
15
  // Re-export the node-free surface so node code can import from a single place.
17
16
  export { EVENT_VERSION, EventLog, JsonlEventSink, NullEventSink, } from "../events.js";
18
17
  export { newRunId, nowTs, nowTsMs, randomHex, shortId } from "../ids.js";
@@ -623,7 +623,7 @@ async function collectCommandJournal(repoRoot, path) {
623
623
  const channelTenantId = command ? nonEmptyString(command.channel_tenant_id) : null;
624
624
  const channelConversationId = command ? nonEmptyString(command.channel_conversation_id) : null;
625
625
  const actorBindingId = command ? nonEmptyString(command.actor_binding_id) : null;
626
- const runId = command ? nonEmptyString(command.run_root_id) : null;
626
+ const runId = null;
627
627
  const sessionId = command
628
628
  ? nonEmptyString(command.operator_session_id) ?? nonEmptyString(command.meta_session_id)
629
629
  : null;
@@ -674,7 +674,7 @@ async function collectCommandJournal(repoRoot, path) {
674
674
  const channelTenantId = correlation ? nonEmptyString(correlation.channel_tenant_id) : null;
675
675
  const channelConversationId = correlation ? nonEmptyString(correlation.channel_conversation_id) : null;
676
676
  const actorBindingId = correlation ? nonEmptyString(correlation.actor_binding_id) : null;
677
- const runId = correlation ? nonEmptyString(correlation.run_root_id) : null;
677
+ const runId = null;
678
678
  const sessionId = correlation
679
679
  ? nonEmptyString(correlation.operator_session_id) ?? nonEmptyString(correlation.meta_session_id)
680
680
  : null;
@@ -735,7 +735,7 @@ async function collectOutbox(repoRoot, path) {
735
735
  conversationId: channelConversationId,
736
736
  bindingId: actorBindingId,
737
737
  });
738
- const runId = correlation ? nonEmptyString(correlation.run_root_id) : null;
738
+ const runId = null;
739
739
  const sessionId = correlation
740
740
  ? nonEmptyString(correlation.operator_session_id) ?? nonEmptyString(correlation.meta_session_id)
741
741
  : null;
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@femtomc/mu-core",
3
- "version": "26.2.90",
4
- "description": "Core primitives for mu: IDs, events, DAG helpers, and persistence interfaces.",
3
+ "version": "26.2.91",
4
+ "description": "Core primitives for mu: IDs, events, schemas, and persistence interfaces.",
5
5
  "keywords": [
6
6
  "mu",
7
7
  "agent",
8
8
  "core",
9
- "events",
10
- "dag"
9
+ "events"
11
10
  ],
12
11
  "type": "module",
13
12
  "main": "./dist/index.js",
package/dist/dag.d.ts DELETED
@@ -1,46 +0,0 @@
1
- import type { Issue } from "./spec.js";
2
- export type ValidationResult = {
3
- is_final: boolean;
4
- reason: string;
5
- };
6
- export type RetryableDagCandidate = {
7
- issue: Issue;
8
- reason: string;
9
- };
10
- /**
11
- * Deterministic DAG reconcile primitives used by orchestrator reconciliation.
12
- *
13
- * Contract: these helpers are pure functions over the provided issue snapshot and must remain
14
- * side-effect free so reconcile passes are replayable/idempotent.
15
- */
16
- export declare const DAG_RECONCILE_PRIMITIVE_INVARIANTS: readonly ["DAG-RECON-001: `readyLeaves` only returns open, unblocked, leaf issues within the requested subtree scope.", "DAG-RECON-002: `readyLeaves` ordering is deterministic for a fixed input snapshot (priority-ordered candidate set).", "DAG-RECON-003: `validateDag(...).is_final=true` implies no remaining non-expanded open work in the subtree.", "DAG-RECON-004: closed(failure|needs_work) and expanded-without-children are non-final and require reconcile action.", "DAG-RECON-005: `retryableDagCandidates` selection is deterministic and side-effect free for a fixed snapshot + attempts map."];
17
- export declare function subtreeIds(issues: readonly Issue[], rootId: string): string[];
18
- /**
19
- * Reconcile selection primitive: the orchestrator must only dispatch from this ready set (or an
20
- * equivalent deterministic adapter) to preserve replayability.
21
- */
22
- export declare function readyLeaves(issues: readonly Issue[], opts?: {
23
- root_id?: string;
24
- tags?: readonly string[];
25
- }): Issue[];
26
- /**
27
- * Reconcile retry primitive.
28
- *
29
- * Produces a deterministic list of closed nodes that are eligible to be reopened for orchestration.
30
- * The orchestrator decides whether/when to apply the reopen side effect.
31
- */
32
- export declare function retryableDagCandidates(issues: readonly Issue[], opts: {
33
- root_id: string;
34
- retry_outcomes?: readonly string[];
35
- attempts_by_issue_id?: ReadonlyMap<string, number>;
36
- max_attempts?: number;
37
- }): RetryableDagCandidate[];
38
- export declare function collapsible(issues: readonly Issue[], rootId: string): Issue[];
39
- /**
40
- * Reconcile termination primitive.
41
- *
42
- * `is_final=false` is a hard signal that orchestrator must continue reconciling (or repair invalid
43
- * expanded state) before the root run can be considered terminal.
44
- */
45
- export declare function validateDag(issues: readonly Issue[], rootId: string): ValidationResult;
46
- //# sourceMappingURL=dag.d.ts.map
package/dist/dag.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,slBAMrC,CAAC;AA0BX,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB7E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAO,GACvD,KAAK,EAAE,CAuCT;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,IAAI,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,GACC,qBAAqB,EAAE,CAsCzB;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CA6B7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAqDtF"}
package/dist/dag.js DELETED
@@ -1,212 +0,0 @@
1
- /**
2
- * Deterministic DAG reconcile primitives used by orchestrator reconciliation.
3
- *
4
- * Contract: these helpers are pure functions over the provided issue snapshot and must remain
5
- * side-effect free so reconcile passes are replayable/idempotent.
6
- */
7
- export const DAG_RECONCILE_PRIMITIVE_INVARIANTS = [
8
- "DAG-RECON-001: `readyLeaves` only returns open, unblocked, leaf issues within the requested subtree scope.",
9
- "DAG-RECON-002: `readyLeaves` ordering is deterministic for a fixed input snapshot (priority-ordered candidate set).",
10
- "DAG-RECON-003: `validateDag(...).is_final=true` implies no remaining non-expanded open work in the subtree.",
11
- "DAG-RECON-004: closed(failure|needs_work) and expanded-without-children are non-final and require reconcile action.",
12
- "DAG-RECON-005: `retryableDagCandidates` selection is deterministic and side-effect free for a fixed snapshot + attempts map.",
13
- ];
14
- function childrenByParent(issues) {
15
- const byParent = new Map();
16
- for (const issue of issues) {
17
- for (const dep of issue.deps) {
18
- if (dep.type !== "parent") {
19
- continue;
20
- }
21
- const list = byParent.get(dep.target) ?? [];
22
- list.push(issue);
23
- byParent.set(dep.target, list);
24
- }
25
- }
26
- return byParent;
27
- }
28
- function compareByPriorityThenId(a, b) {
29
- const pa = a.priority ?? 3;
30
- const pb = b.priority ?? 3;
31
- if (pa !== pb) {
32
- return pa - pb;
33
- }
34
- return a.id.localeCompare(b.id);
35
- }
36
- export function subtreeIds(issues, rootId) {
37
- const children = childrenByParent(issues);
38
- const result = [];
39
- const q = [rootId];
40
- const seen = new Set();
41
- while (q.length > 0) {
42
- const nodeId = q.shift();
43
- if (!nodeId) {
44
- continue;
45
- }
46
- if (seen.has(nodeId)) {
47
- continue;
48
- }
49
- seen.add(nodeId);
50
- result.push(nodeId);
51
- for (const child of children.get(nodeId) ?? []) {
52
- q.push(child.id);
53
- }
54
- }
55
- return result;
56
- }
57
- /**
58
- * Reconcile selection primitive: the orchestrator must only dispatch from this ready set (or an
59
- * equivalent deterministic adapter) to preserve replayability.
60
- */
61
- export function readyLeaves(issues, opts = {}) {
62
- const byId = new Map(issues.map((i) => [i.id, i]));
63
- const idsInScope = new Set(opts.root_id ? subtreeIds(issues, opts.root_id) : byId.keys());
64
- const blocked = new Set();
65
- for (const issue of issues) {
66
- for (const dep of issue.deps) {
67
- if (dep.type !== "blocks") {
68
- continue;
69
- }
70
- if (issue.status !== "closed" || issue.outcome === "expanded") {
71
- blocked.add(dep.target);
72
- }
73
- }
74
- }
75
- const children = childrenByParent(issues);
76
- const result = [];
77
- for (const issueId of idsInScope) {
78
- const issue = byId.get(issueId);
79
- if (!issue || issue.status !== "open") {
80
- continue;
81
- }
82
- if (blocked.has(issueId)) {
83
- continue;
84
- }
85
- const kids = children.get(issueId) ?? [];
86
- if (kids.some((kid) => kid.status !== "closed")) {
87
- continue;
88
- }
89
- if (opts.tags && !opts.tags.every((tag) => issue.tags.includes(tag))) {
90
- continue;
91
- }
92
- result.push(issue);
93
- }
94
- result.sort(compareByPriorityThenId);
95
- return result;
96
- }
97
- /**
98
- * Reconcile retry primitive.
99
- *
100
- * Produces a deterministic list of closed nodes that are eligible to be reopened for orchestration.
101
- * The orchestrator decides whether/when to apply the reopen side effect.
102
- */
103
- export function retryableDagCandidates(issues, opts) {
104
- const idsInScope = new Set(subtreeIds(issues, opts.root_id));
105
- const children = childrenByParent(issues);
106
- const retryOutcomes = new Set(opts.retry_outcomes ?? ["failure", "needs_work"]);
107
- const maxAttempts = typeof opts.max_attempts === "number" && Number.isFinite(opts.max_attempts)
108
- ? Math.max(1, Math.trunc(opts.max_attempts))
109
- : Number.POSITIVE_INFINITY;
110
- const out = [];
111
- for (const issue of issues) {
112
- if (!idsInScope.has(issue.id)) {
113
- continue;
114
- }
115
- if (issue.status !== "closed") {
116
- continue;
117
- }
118
- const attempts = opts.attempts_by_issue_id?.get(issue.id) ?? 0;
119
- if (attempts >= maxAttempts) {
120
- continue;
121
- }
122
- if (issue.outcome && retryOutcomes.has(issue.outcome)) {
123
- const hasOpenChildren = (children.get(issue.id) ?? []).some((child) => child.status !== "closed");
124
- if (!hasOpenChildren) {
125
- out.push({ issue, reason: `outcome=${issue.outcome}` });
126
- }
127
- continue;
128
- }
129
- if (issue.outcome === "expanded" && (children.get(issue.id)?.length ?? 0) === 0) {
130
- out.push({ issue, reason: "outcome=expanded_without_children" });
131
- }
132
- }
133
- out.sort((a, b) => compareByPriorityThenId(a.issue, b.issue));
134
- return out;
135
- }
136
- export function collapsible(issues, rootId) {
137
- const byId = new Map(issues.map((i) => [i.id, i]));
138
- const idsInScope = new Set(subtreeIds(issues, rootId));
139
- const children = childrenByParent(issues);
140
- // `refine` is terminal for a closed reviewer node; refinement itself is
141
- // orchestrated by root-phase reconcile transitions.
142
- const terminalOutcomes = new Set(["success", "skipped", "refine"]);
143
- const result = [];
144
- for (const issueId of idsInScope) {
145
- const node = byId.get(issueId);
146
- if (!node) {
147
- continue;
148
- }
149
- if (node.status !== "closed" || node.outcome !== "expanded") {
150
- continue;
151
- }
152
- const kids = children.get(issueId) ?? [];
153
- if (kids.length === 0) {
154
- continue;
155
- }
156
- if (kids.every((kid) => kid.status === "closed" && kid.outcome != null && terminalOutcomes.has(kid.outcome))) {
157
- result.push(node);
158
- }
159
- }
160
- result.sort((a, b) => a.id.localeCompare(b.id));
161
- return result;
162
- }
163
- /**
164
- * Reconcile termination primitive.
165
- *
166
- * `is_final=false` is a hard signal that orchestrator must continue reconciling (or repair invalid
167
- * expanded state) before the root run can be considered terminal.
168
- */
169
- export function validateDag(issues, rootId) {
170
- const byId = new Map(issues.map((i) => [i.id, i]));
171
- const ids = new Set(subtreeIds(issues, rootId));
172
- const root = byId.get(rootId);
173
- if (!root) {
174
- return { is_final: true, reason: "root not found" };
175
- }
176
- const children = childrenByParent(issues);
177
- const needsReorch = [...ids]
178
- .filter((issueId) => {
179
- const issue = byId.get(issueId);
180
- return issue?.status === "closed" && (issue.outcome === "failure" || issue.outcome === "needs_work");
181
- })
182
- .sort();
183
- if (needsReorch.length > 0) {
184
- return { is_final: false, reason: `needs work: ${needsReorch.join(",")}` };
185
- }
186
- const badExpanded = [...ids]
187
- .filter((issueId) => {
188
- const issue = byId.get(issueId);
189
- return (issue?.status === "closed" && issue.outcome === "expanded" && (children.get(issueId)?.length ?? 0) === 0);
190
- })
191
- .sort();
192
- if (badExpanded.length > 0) {
193
- return { is_final: false, reason: `expanded without children: ${badExpanded.join(",")}` };
194
- }
195
- const pending = [...ids].filter((issueId) => {
196
- const issue = byId.get(issueId);
197
- if (!issue) {
198
- return false;
199
- }
200
- if (issue.status === "closed" && issue.outcome === "expanded") {
201
- return false;
202
- }
203
- return issue.status !== "closed";
204
- });
205
- if (pending.length === 0) {
206
- return { is_final: true, reason: "all work completed" };
207
- }
208
- if (pending.length === 1 && pending[0] === rootId && ids.size > 1) {
209
- return { is_final: false, reason: "all children closed, root still open" };
210
- }
211
- return { is_final: false, reason: "in progress" };
212
- }