@neuroverseos/governance 0.1.5 → 0.2.1

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.
Files changed (82) hide show
  1. package/README.md +279 -423
  2. package/dist/adapters/express.cjs +242 -2
  3. package/dist/adapters/express.d.cts +1 -1
  4. package/dist/adapters/express.d.ts +1 -1
  5. package/dist/adapters/express.js +5 -3
  6. package/dist/adapters/index.cjs +301 -5
  7. package/dist/adapters/index.d.cts +1 -1
  8. package/dist/adapters/index.d.ts +1 -1
  9. package/dist/adapters/index.js +8 -6
  10. package/dist/adapters/langchain.cjs +267 -3
  11. package/dist/adapters/langchain.d.cts +8 -1
  12. package/dist/adapters/langchain.d.ts +8 -1
  13. package/dist/adapters/langchain.js +5 -3
  14. package/dist/adapters/openai.cjs +267 -3
  15. package/dist/adapters/openai.d.cts +8 -1
  16. package/dist/adapters/openai.d.ts +8 -1
  17. package/dist/adapters/openai.js +5 -3
  18. package/dist/adapters/openclaw.cjs +267 -3
  19. package/dist/adapters/openclaw.d.cts +8 -1
  20. package/dist/adapters/openclaw.d.ts +8 -1
  21. package/dist/adapters/openclaw.js +5 -3
  22. package/dist/{bootstrap-H4HHKQ5G.js → bootstrap-GXVDZNF7.js} +2 -1
  23. package/dist/{build-73KAVHEY.js → build-P42YFKQV.js} +34 -3
  24. package/dist/{chunk-FYPYZFV5.js → chunk-2JQJ5U5X.js} +1 -1
  25. package/dist/chunk-37JG24WH.js +161 -0
  26. package/dist/chunk-5EDDNJU6.js +321 -0
  27. package/dist/{chunk-O5OMJMIE.js → chunk-7P3S7MAY.js} +502 -2
  28. package/dist/chunk-A5W4GNQO.js +130 -0
  29. package/dist/{chunk-ITJ3LCPG.js → chunk-ADV7Q2LJ.js} +1 -1
  30. package/dist/chunk-AKW5YVCE.js +96 -0
  31. package/dist/{chunk-EIUHJXBB.js → chunk-GR6DGCZ2.js} +1 -1
  32. package/dist/{chunk-EQXFOKH2.js → chunk-IVPKFJX3.js} +24 -3
  33. package/dist/{chunk-D7BGWV2J.js → chunk-NF5POFCI.js} +5 -3
  34. package/dist/chunk-OT6PXH54.js +61 -0
  35. package/dist/chunk-P74Y66ZV.js +205 -0
  36. package/dist/chunk-PAX2P6ZP.js +601 -0
  37. package/dist/{chunk-B4NF3OLW.js → chunk-PQBJBVSW.js} +56 -2
  38. package/dist/{chunk-T4X42QXC.js → chunk-Q6O7ZLO2.js} +0 -59
  39. package/dist/{chunk-FZQCRGUU.js → chunk-TINSRYXQ.js} +24 -3
  40. package/dist/{chunk-CROPZ75A.js → chunk-UPJNTSVM.js} +24 -3
  41. package/dist/chunk-YZFATT7X.js +9 -0
  42. package/dist/{chunk-Z2S2HIV5.js → chunk-ZL4AHY4X.js} +2 -2
  43. package/dist/cli/neuroverse.cjs +5287 -740
  44. package/dist/cli/neuroverse.js +69 -13
  45. package/dist/cli/plan.cjs +1554 -0
  46. package/dist/cli/plan.d.cts +20 -0
  47. package/dist/cli/plan.d.ts +20 -0
  48. package/dist/cli/plan.js +346 -0
  49. package/dist/cli/run.cjs +1716 -0
  50. package/dist/cli/run.d.cts +20 -0
  51. package/dist/cli/run.d.ts +20 -0
  52. package/dist/cli/run.js +143 -0
  53. package/dist/{configure-ai-46JVG56I.js → configure-ai-TK67ZWZL.js} +5 -2
  54. package/dist/{derive-6NAEWLM5.js → derive-TLIV4OOU.js} +6 -4
  55. package/dist/doctor-V72UM2TC.js +170 -0
  56. package/dist/{explain-3B3VB6TL.js → explain-IDCRWMPX.js} +2 -1
  57. package/dist/{guard-67Y66P3I.js → guard-WA3FCCIO.js} +20 -6
  58. package/dist/{guard-contract-D_RQz9kt.d.ts → guard-contract-D-2LQInm.d.cts} +144 -2
  59. package/dist/{guard-contract-D_RQz9kt.d.cts → guard-contract-D-2LQInm.d.ts} +144 -2
  60. package/dist/guard-engine-D7X4CVAE.js +10 -0
  61. package/dist/{impact-CHERK3O6.js → impact-BWULZ5RP.js} +5 -3
  62. package/dist/{improve-YG6I6ERG.js → improve-GPUBKTEA.js} +4 -3
  63. package/dist/index.cjs +2095 -89
  64. package/dist/index.d.cts +466 -12
  65. package/dist/index.d.ts +466 -12
  66. package/dist/index.js +70 -20
  67. package/dist/{init-Z66T6TDI.js → init-PKPIYHYE.js} +2 -0
  68. package/dist/mcp-server-YUOQP4M5.js +13 -0
  69. package/dist/model-adapter-BB7G4MFI.js +11 -0
  70. package/dist/playground-CBXMAW2B.js +550 -0
  71. package/dist/redteam-SSNABQ7W.js +357 -0
  72. package/dist/session-MWRBTCYX.js +14 -0
  73. package/dist/{simulate-ETHHINZ4.js → simulate-VDOYQFRO.js} +2 -1
  74. package/dist/test-3GZSG5FR.js +217 -0
  75. package/dist/{trace-3YODSSIP.js → trace-TM4Z7G73.js} +4 -2
  76. package/dist/{validate-UVE6GKQU.js → validate-LLBWVPGV.js} +15 -6
  77. package/dist/validate-engine-UIABSIHD.js +7 -0
  78. package/dist/{world-WLNHL5XC.js → world-LAXO6DOX.js} +87 -7
  79. package/dist/world-loader-HMPTOEA2.js +9 -0
  80. package/package.json +19 -5
  81. package/dist/validate-engine-657D75OG.js +0 -6
  82. /package/dist/{chunk-M3TZFGHO.js → chunk-JZPQGIKR.js} +0 -0
@@ -0,0 +1,96 @@
1
+ // src/loader/world-resolver.ts
2
+ import { existsSync, readFileSync, writeFileSync, readdirSync, mkdirSync } from "fs";
3
+ import { join, resolve, isAbsolute } from "path";
4
+ var WORLDS_DIR = ".neuroverse/worlds";
5
+ var ACTIVE_WORLD_FILE = ".neuroverse/active_world";
6
+ function listWorlds(cwd = process.cwd()) {
7
+ const worldsDir = join(cwd, WORLDS_DIR);
8
+ if (!existsSync(worldsDir)) return [];
9
+ const activeName = getActiveWorldName(cwd);
10
+ const entries = readdirSync(worldsDir);
11
+ return entries.filter((name) => {
12
+ const worldJson = join(worldsDir, name, "world.json");
13
+ return existsSync(worldJson);
14
+ }).map((name) => ({
15
+ name,
16
+ path: join(worldsDir, name),
17
+ active: name === activeName
18
+ })).sort((a, b) => a.name.localeCompare(b.name));
19
+ }
20
+ function getActiveWorldName(cwd = process.cwd()) {
21
+ const filePath = join(cwd, ACTIVE_WORLD_FILE);
22
+ try {
23
+ return readFileSync(filePath, "utf-8").trim() || void 0;
24
+ } catch {
25
+ return void 0;
26
+ }
27
+ }
28
+ function setActiveWorld(name, cwd = process.cwd()) {
29
+ const worldsDir = join(cwd, WORLDS_DIR);
30
+ const worldPath = join(worldsDir, name, "world.json");
31
+ if (!existsSync(worldPath)) {
32
+ const available = listWorlds(cwd);
33
+ const names = available.map((w) => w.name).join(", ");
34
+ throw new Error(
35
+ `World "${name}" not found in ${WORLDS_DIR}/
36
+ ` + (names ? `Available: ${names}` : "No worlds found. Run `neuroverse build` first.")
37
+ );
38
+ }
39
+ const dir = join(cwd, ".neuroverse");
40
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
41
+ writeFileSync(join(cwd, ACTIVE_WORLD_FILE), name + "\n", "utf-8");
42
+ }
43
+ function resolveWorldPath(explicit, cwd = process.cwd()) {
44
+ if (explicit) {
45
+ return resolveNameOrPath(explicit, cwd);
46
+ }
47
+ const envWorld = process.env.NEUROVERSE_WORLD;
48
+ if (envWorld) {
49
+ return resolveNameOrPath(envWorld, cwd);
50
+ }
51
+ const activeName = getActiveWorldName(cwd);
52
+ if (activeName) {
53
+ return resolveNameOrPath(activeName, cwd);
54
+ }
55
+ const worlds = listWorlds(cwd);
56
+ if (worlds.length === 1) {
57
+ return resolve(worlds[0].path);
58
+ }
59
+ return void 0;
60
+ }
61
+ function describeActiveWorld(explicit, cwd = process.cwd()) {
62
+ if (explicit) {
63
+ return { name: explicit, source: "--world flag" };
64
+ }
65
+ const envWorld = process.env.NEUROVERSE_WORLD;
66
+ if (envWorld) {
67
+ return { name: envWorld, source: "NEUROVERSE_WORLD env var" };
68
+ }
69
+ const activeName = getActiveWorldName(cwd);
70
+ if (activeName) {
71
+ return { name: activeName, source: ".neuroverse/active_world" };
72
+ }
73
+ const worlds = listWorlds(cwd);
74
+ if (worlds.length === 1) {
75
+ return { name: worlds[0].name, source: "auto-detected (only world)" };
76
+ }
77
+ return void 0;
78
+ }
79
+ function resolveNameOrPath(ref, cwd) {
80
+ if (ref.includes("/") || ref.includes("\\") || ref.startsWith(".") || isAbsolute(ref)) {
81
+ return resolve(cwd, ref);
82
+ }
83
+ const namedPath = join(cwd, WORLDS_DIR, ref);
84
+ if (existsSync(join(namedPath, "world.json"))) {
85
+ return resolve(namedPath);
86
+ }
87
+ return resolve(cwd, ref);
88
+ }
89
+
90
+ export {
91
+ listWorlds,
92
+ getActiveWorldName,
93
+ setActiveWorld,
94
+ resolveWorldPath,
95
+ describeActiveWorld
96
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FYS2CBUW.js";
4
4
  import {
5
5
  validateWorld
6
- } from "./chunk-O5OMJMIE.js";
6
+ } from "./chunk-7P3S7MAY.js";
7
7
 
8
8
  // src/engine/improve-engine.ts
9
9
  function improveWorld(world) {
@@ -1,9 +1,14 @@
1
1
  import {
2
2
  evaluateGuard
3
- } from "./chunk-B4NF3OLW.js";
3
+ } from "./chunk-PQBJBVSW.js";
4
4
  import {
5
5
  loadWorld
6
- } from "./chunk-M3TZFGHO.js";
6
+ } from "./chunk-JZPQGIKR.js";
7
+ import {
8
+ advancePlan,
9
+ evaluatePlan,
10
+ getPlanProgress
11
+ } from "./chunk-P74Y66ZV.js";
7
12
 
8
13
  // src/adapters/langchain.ts
9
14
  var GovernanceBlockedError = class extends Error {
@@ -31,12 +36,15 @@ var NeuroVerseCallbackHandler = class {
31
36
  options;
32
37
  engineOptions;
33
38
  mapToolCall;
39
+ activePlan;
34
40
  constructor(world, options = {}) {
35
41
  this.world = world;
36
42
  this.options = options;
43
+ this.activePlan = options.plan;
37
44
  this.engineOptions = {
38
45
  trace: options.trace ?? false,
39
- level: options.level
46
+ level: options.level,
47
+ plan: this.activePlan
40
48
  };
41
49
  this.mapToolCall = options.mapToolCall ?? defaultMapToolCall;
42
50
  }
@@ -55,6 +63,7 @@ var NeuroVerseCallbackHandler = class {
55
63
  parsedInput = { raw: input };
56
64
  }
57
65
  const event = this.mapToolCall(tool.name, parsedInput);
66
+ this.engineOptions.plan = this.activePlan;
58
67
  const verdict = evaluateGuard(event, this.world, this.engineOptions);
59
68
  this.options.onEvaluate?.(verdict, event);
60
69
  if (verdict.status === "BLOCK") {
@@ -67,6 +76,18 @@ var NeuroVerseCallbackHandler = class {
67
76
  throw new GovernanceBlockedError(verdict, event);
68
77
  }
69
78
  }
79
+ if (verdict.status === "ALLOW" && this.activePlan) {
80
+ const planVerdict = evaluatePlan(event, this.activePlan);
81
+ if (planVerdict.matchedStep) {
82
+ this.activePlan = advancePlan(this.activePlan, planVerdict.matchedStep);
83
+ this.engineOptions.plan = this.activePlan;
84
+ const progress = getPlanProgress(this.activePlan);
85
+ this.options.onPlanProgress?.(progress);
86
+ if (progress.completed === progress.total) {
87
+ this.options.onPlanComplete?.();
88
+ }
89
+ }
90
+ }
70
91
  }
71
92
  };
72
93
  async function createNeuroVerseCallbackHandler(worldPath, options) {
@@ -1,14 +1,16 @@
1
1
  import {
2
- createProvider,
2
+ createProvider
3
+ } from "./chunk-Q6O7ZLO2.js";
4
+ import {
3
5
  loadConfig
4
- } from "./chunk-T4X42QXC.js";
6
+ } from "./chunk-OT6PXH54.js";
5
7
  import {
6
8
  emitWorldDefinition,
7
9
  parseWorldMarkdown
8
10
  } from "./chunk-XPDMYECO.js";
9
11
  import {
10
12
  validateWorld
11
- } from "./chunk-O5OMJMIE.js";
13
+ } from "./chunk-7P3S7MAY.js";
12
14
 
13
15
  // src/engine/derive-normalizer.ts
14
16
  function findSections(lines) {
@@ -0,0 +1,61 @@
1
+ // src/providers/config-manager.ts
2
+ import { readFile, writeFile, mkdir, chmod } from "fs/promises";
3
+ import { join } from "path";
4
+ import { homedir } from "os";
5
+ function getConfigDir() {
6
+ const xdg = process.env.XDG_CONFIG_HOME;
7
+ if (xdg) return join(xdg, "neuroverse");
8
+ return join(homedir(), ".neuroverse");
9
+ }
10
+ function getConfigPath() {
11
+ return join(getConfigDir(), "config.json");
12
+ }
13
+ async function loadConfig() {
14
+ try {
15
+ const raw = await readFile(getConfigPath(), "utf-8");
16
+ const parsed = JSON.parse(raw);
17
+ if (!parsed.provider || !parsed.model || !parsed.apiKey) {
18
+ return null;
19
+ }
20
+ return {
21
+ provider: parsed.provider,
22
+ model: parsed.model,
23
+ apiKey: parsed.apiKey,
24
+ endpoint: parsed.endpoint ?? null
25
+ };
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+ async function saveConfig(config) {
31
+ const dir = getConfigDir();
32
+ await mkdir(dir, { recursive: true });
33
+ const configPath = getConfigPath();
34
+ const content = JSON.stringify(
35
+ {
36
+ provider: config.provider,
37
+ model: config.model,
38
+ apiKey: config.apiKey,
39
+ endpoint: config.endpoint
40
+ },
41
+ null,
42
+ 2
43
+ );
44
+ await writeFile(configPath, content, { mode: 384 });
45
+ await chmod(configPath, 384);
46
+ }
47
+ function redactConfig(config) {
48
+ return {
49
+ provider: config.provider,
50
+ model: config.model,
51
+ apiKey: config.apiKey ? `${config.apiKey.slice(0, 4)}...${config.apiKey.slice(-4)}` : "(not set)",
52
+ endpoint: config.endpoint
53
+ };
54
+ }
55
+
56
+ export {
57
+ getConfigPath,
58
+ loadConfig,
59
+ saveConfig,
60
+ redactConfig
61
+ };
@@ -0,0 +1,205 @@
1
+ // src/engine/plan-engine.ts
2
+ function keywordMatch(eventText, step) {
3
+ const stepText = [
4
+ step.label,
5
+ step.description ?? "",
6
+ ...step.tags ?? []
7
+ ].join(" ").toLowerCase();
8
+ const keywords = stepText.split(/\s+/).filter((w) => w.length > 3);
9
+ if (keywords.length === 0) return false;
10
+ const matched = keywords.filter((kw) => eventText.includes(kw));
11
+ return matched.length >= Math.ceil(keywords.length * 0.5);
12
+ }
13
+ function tokenSimilarity(a, b) {
14
+ const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
15
+ const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
16
+ if (tokensA.size === 0 || tokensB.size === 0) return 0;
17
+ let intersection = 0;
18
+ for (const t of tokensA) {
19
+ if (tokensB.has(t)) intersection++;
20
+ }
21
+ const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
22
+ return union > 0 ? intersection / union : 0;
23
+ }
24
+ function findMatchingStep(eventText, event, steps) {
25
+ const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
26
+ if (pendingOrActive.length === 0) {
27
+ return { matched: null, closest: null, closestScore: 0 };
28
+ }
29
+ for (const step of pendingOrActive) {
30
+ if (keywordMatch(eventText, step)) {
31
+ if (step.tools && event.tool && !step.tools.includes(event.tool)) {
32
+ continue;
33
+ }
34
+ return { matched: step, closest: step, closestScore: 1 };
35
+ }
36
+ }
37
+ const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
38
+ let bestStep = null;
39
+ let bestScore = 0;
40
+ for (const step of pendingOrActive) {
41
+ const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
42
+ const score = tokenSimilarity(intentText, stepText);
43
+ if (score > bestScore) {
44
+ bestScore = score;
45
+ bestStep = step;
46
+ }
47
+ }
48
+ const SIMILARITY_THRESHOLD = 0.35;
49
+ if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
50
+ if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
51
+ return { matched: null, closest: bestStep, closestScore: bestScore };
52
+ }
53
+ return { matched: bestStep, closest: bestStep, closestScore: bestScore };
54
+ }
55
+ return { matched: null, closest: bestStep, closestScore: bestScore };
56
+ }
57
+ function isSequenceValid(step, plan) {
58
+ if (!plan.sequential) return true;
59
+ if (!step.requires || step.requires.length === 0) return true;
60
+ return step.requires.every((reqId) => {
61
+ const reqStep = plan.steps.find((s) => s.id === reqId);
62
+ return reqStep?.status === "completed";
63
+ });
64
+ }
65
+ function checkConstraints(event, eventText, constraints) {
66
+ const checks = [];
67
+ for (const constraint of constraints) {
68
+ if (constraint.type === "approval") {
69
+ if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
70
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
71
+ return { violated: constraint, checks };
72
+ }
73
+ const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
74
+ const relevant = keywords.some((kw) => eventText.includes(kw));
75
+ if (relevant) {
76
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
77
+ return { violated: constraint, checks };
78
+ }
79
+ checks.push({ constraintId: constraint.id, passed: true });
80
+ continue;
81
+ }
82
+ if (constraint.type === "scope" && constraint.trigger) {
83
+ const keywords = constraint.trigger.split(/\s+/).filter((w) => w.length > 3);
84
+ const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
85
+ checks.push({
86
+ constraintId: constraint.id,
87
+ passed: !violated,
88
+ reason: violated ? constraint.description : void 0
89
+ });
90
+ if (violated) {
91
+ return { violated: constraint, checks };
92
+ }
93
+ continue;
94
+ }
95
+ checks.push({ constraintId: constraint.id, passed: true });
96
+ }
97
+ return { violated: null, checks };
98
+ }
99
+ function getPlanProgress(plan) {
100
+ const completed = plan.steps.filter((s) => s.status === "completed").length;
101
+ const total = plan.steps.length;
102
+ return {
103
+ completed,
104
+ total,
105
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0
106
+ };
107
+ }
108
+ function advancePlan(plan, stepId) {
109
+ return {
110
+ ...plan,
111
+ steps: plan.steps.map(
112
+ (s) => s.id === stepId ? { ...s, status: "completed" } : s
113
+ )
114
+ };
115
+ }
116
+ function evaluatePlan(event, plan) {
117
+ const progress = getPlanProgress(plan);
118
+ if (plan.expires_at) {
119
+ const expiresAt = new Date(plan.expires_at).getTime();
120
+ if (Date.now() > expiresAt) {
121
+ return {
122
+ allowed: true,
123
+ status: "PLAN_COMPLETE",
124
+ reason: "Plan has expired.",
125
+ progress
126
+ };
127
+ }
128
+ }
129
+ if (progress.completed === progress.total) {
130
+ return {
131
+ allowed: true,
132
+ status: "PLAN_COMPLETE",
133
+ reason: "All plan steps are completed.",
134
+ progress
135
+ };
136
+ }
137
+ const eventText = [
138
+ event.intent,
139
+ event.tool ?? "",
140
+ event.scope ?? ""
141
+ ].join(" ").toLowerCase();
142
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
143
+ if (!matched) {
144
+ return {
145
+ allowed: false,
146
+ status: "OFF_PLAN",
147
+ reason: "Action does not match any plan step.",
148
+ closestStep: closest?.label,
149
+ similarityScore: closestScore,
150
+ progress
151
+ };
152
+ }
153
+ if (!isSequenceValid(matched, plan)) {
154
+ const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
155
+ return {
156
+ allowed: false,
157
+ status: "OFF_PLAN",
158
+ reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
159
+ matchedStep: matched.id,
160
+ progress
161
+ };
162
+ }
163
+ const { violated } = checkConstraints(event, eventText, plan.constraints);
164
+ if (violated) {
165
+ return {
166
+ allowed: false,
167
+ status: "CONSTRAINT_VIOLATED",
168
+ reason: violated.description,
169
+ matchedStep: matched.id,
170
+ progress
171
+ };
172
+ }
173
+ return {
174
+ allowed: true,
175
+ status: "ON_PLAN",
176
+ reason: `Matches step: ${matched.label}`,
177
+ matchedStep: matched.id,
178
+ progress
179
+ };
180
+ }
181
+ function buildPlanCheck(event, plan, verdict) {
182
+ const eventText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ").toLowerCase();
183
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
184
+ const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
185
+ const progress = getPlanProgress(plan);
186
+ return {
187
+ planId: plan.plan_id,
188
+ matched: !!matched,
189
+ matchedStepId: matched?.id,
190
+ matchedStepLabel: matched?.label,
191
+ closestStepId: !matched ? closest?.id : void 0,
192
+ closestStepLabel: !matched ? closest?.label : void 0,
193
+ similarityScore: !matched ? closestScore : void 0,
194
+ sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
195
+ constraintsChecked: constraintChecks,
196
+ progress: { completed: progress.completed, total: progress.total }
197
+ };
198
+ }
199
+
200
+ export {
201
+ getPlanProgress,
202
+ advancePlan,
203
+ evaluatePlan,
204
+ buildPlanCheck
205
+ };