@miller-tech/uap 1.99.0 → 1.101.0

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.
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Blackboard Task Orchestrator (P1) + Minimal Context Assembler (P2)
3
+ *
4
+ * The mechanism that lets a small-context model multi-step through a large
5
+ * build: instead of one convergence loop holding the WHOLE design in context,
6
+ * the orchestrator executes a task DAG where each leaf task runs in a FRESH,
7
+ * MINIMAL context assembled from externalized state — its own goal, its
8
+ * acceptance criteria, and ONLY the recorded outputs of its direct
9
+ * dependencies (not the full mission, not every prior summary).
10
+ *
11
+ * State lives on a "blackboard" (completed task outcomes), not in the prompt.
12
+ * A task that finishes writes a compact summary (P1) — and later its verified
13
+ * interface contract (P4) — back to the blackboard, so a dependent task loads
14
+ * a few hundred tokens of "what already exists" rather than re-reading source.
15
+ *
16
+ * This module is executor-agnostic: it takes a `runTask` callback that turns
17
+ * an assembled prompt into a pass/fail outcome (production wires the
18
+ * ConvergenceLoop; tests inject a deterministic stub). That keeps the graph
19
+ * logic unit-testable without a model.
20
+ */
21
+ import { topoOrder } from './decompose.js';
22
+ const DEFAULT_DEP_SUMMARY_CHARS = 240;
23
+ /** A short mission line — orientation, not the full spec. */
24
+ const MISSION_SNIPPET_CHARS = 300;
25
+ const DEFAULT_CONTEXT_BUDGET_CHARS = 6000;
26
+ const DEFAULT_MAX_TASKS = 40;
27
+ /**
28
+ * P6 — enforce the context budget: if the assembled prompt exceeds `budget`,
29
+ * drop whole dependency lines from the END (furthest/least-recent deps) until
30
+ * it fits, appending a note about what was elided. Pure + unit-tested; the
31
+ * governor turns "minimal context" into a hard invariant.
32
+ */
33
+ export function governContext(prompt, depLineCount, budget) {
34
+ if (prompt.length <= budget)
35
+ return { prompt, droppedDeps: 0 };
36
+ const lines = prompt.split('\n');
37
+ // dependency lines are the "- <id>: ..." entries under ALREADY BUILT.
38
+ let dropped = 0;
39
+ for (let i = lines.length - 1; i >= 0 && lines.join('\n').length > budget && dropped < depLineCount; i--) {
40
+ if (/^- [^:]+: /.test(lines[i])) {
41
+ lines.splice(i, 1);
42
+ dropped++;
43
+ }
44
+ }
45
+ let out = lines.join('\n');
46
+ if (dropped > 0)
47
+ out += `\n(context governor: elided ${dropped} lower-priority dependency summary(ies) to fit the ${budget}-char budget)`;
48
+ // Last resort: hard truncate if still over (e.g. a single huge goal).
49
+ if (out.length > budget)
50
+ out = out.slice(0, budget) + '\n…(truncated to context budget)…';
51
+ return { prompt: out, droppedDeps: dropped };
52
+ }
53
+ /**
54
+ * P2 — assemble one task's MINIMAL context: a short mission line, the task's
55
+ * own goal + criteria + declared files, and ONLY the summaries/contracts of
56
+ * its DIRECT dependencies (pulled from the blackboard). Pure and unit-tested;
57
+ * this is the function that keeps a small model's window optimal.
58
+ */
59
+ export function assembleTaskContext(task, mission, blackboard, maxDepSummaryChars = DEFAULT_DEP_SUMMARY_CHARS, opts = {}) {
60
+ const sections = [];
61
+ // Orientation only — a snippet, never the whole mission.
62
+ sections.push(`OBJECTIVE (context, one line): ${mission.slice(0, MISSION_SNIPPET_CHARS)}`);
63
+ sections.push('');
64
+ sections.push(`YOUR TASK — ${task.title}:`);
65
+ sections.push(task.goal);
66
+ if (task.files && task.files.length > 0) {
67
+ sections.push('');
68
+ sections.push(`Files for THIS task: ${task.files.join(', ')} (edit only these).`);
69
+ }
70
+ if (task.criteria && task.criteria.length > 0) {
71
+ sections.push('');
72
+ sections.push('This task is done when:');
73
+ task.criteria.forEach((c, i) => sections.push(` ${i + 1}. ${c}`));
74
+ }
75
+ // P3 — relevant persisted design decisions (objective/architecture): a
76
+ // small retrieval, not the full spec dump.
77
+ if (opts.designLines && opts.designLines.length > 0) {
78
+ sections.push('');
79
+ sections.push('DESIGN CONTEXT (established decisions — honor them):');
80
+ opts.designLines.slice(0, 6).forEach((d) => sections.push(`- ${d}`));
81
+ }
82
+ // ONLY direct dependencies' outputs — the crux of minimal context. A task
83
+ // that depends on 'store' loads store's contract/summary, not store's source
84
+ // and not the other 12 tasks. Dependents read the interface, not the tree.
85
+ const includedDeps = [];
86
+ const deps = (task.deps ?? []).filter((d) => blackboard.has(d));
87
+ if (deps.length > 0) {
88
+ sections.push('');
89
+ sections.push('ALREADY BUILT — build ON these, do not reimplement them:');
90
+ for (const depId of deps) {
91
+ const out = blackboard.get(depId);
92
+ includedDeps.push(depId);
93
+ const body = (out.contract ?? out.summary).slice(0, maxDepSummaryChars);
94
+ sections.push(`- ${depId}: ${body}`);
95
+ }
96
+ }
97
+ const raw = sections.join('\n');
98
+ const governed = governContext(raw, includedDeps.length, opts.budgetChars ?? DEFAULT_CONTEXT_BUDGET_CHARS);
99
+ return { taskId: task.id, prompt: governed.prompt, includedDeps };
100
+ }
101
+ /**
102
+ * P1 — execute the task DAG on a blackboard. Topologically ordered; a task
103
+ * runs only after every dependency has SUCCEEDED. A failed task blocks its
104
+ * dependents (their deps aren't all green) and they are reported as skipped/
105
+ * failed rather than run against incomplete state. Fail-soft on publish.
106
+ */
107
+ export async function orchestrate(config) {
108
+ const maxTasks = config.maxTasks ?? DEFAULT_MAX_TASKS;
109
+ const budget = config.contextBudgetChars;
110
+ // Mutable queue so P5 re-planning can append discovered subtasks; re-sorted
111
+ // topologically each time the set grows.
112
+ let queue = topoOrder(config.tasks);
113
+ const known = new Set(queue.map((t) => t.id));
114
+ const blackboard = new Map();
115
+ const done = new Set();
116
+ const failed = new Set();
117
+ const outcomes = [];
118
+ let turns = 0;
119
+ for (let qi = 0; qi < queue.length; qi++) {
120
+ const task = queue[qi];
121
+ const deps = task.deps ?? [];
122
+ // Skip a task whose dependency failed — never build against a broken base.
123
+ const blockedBy = deps.filter((d) => failed.has(d) || !done.has(d));
124
+ if (blockedBy.length > 0) {
125
+ const outcome = {
126
+ taskId: task.id,
127
+ success: false,
128
+ summary: `skipped — unmet dependency: ${blockedBy.join(', ')}`,
129
+ turns: 0,
130
+ };
131
+ failed.add(task.id);
132
+ outcomes.push(outcome);
133
+ config.onTask?.(task, outcome);
134
+ continue;
135
+ }
136
+ let designLines = [];
137
+ if (config.retrieveDesign) {
138
+ try {
139
+ designLines = await config.retrieveDesign(task);
140
+ }
141
+ catch {
142
+ designLines = [];
143
+ }
144
+ }
145
+ const ctx = assembleTaskContext(task, config.mission, blackboard, config.maxDepSummaryChars, {
146
+ designLines,
147
+ budgetChars: budget,
148
+ });
149
+ const outcome = await config.runTask(ctx, task);
150
+ turns += outcome.turns;
151
+ outcomes.push(outcome);
152
+ if (outcome.success) {
153
+ done.add(task.id);
154
+ blackboard.set(task.id, outcome);
155
+ try {
156
+ await config.publish?.(outcome, task);
157
+ }
158
+ catch {
159
+ // publishing to durable memory is best-effort
160
+ }
161
+ // P5 — adaptive re-planning: fold discovered subtasks into the queue.
162
+ const fresh = (outcome.newTasks ?? []).filter((t) => !known.has(t.id));
163
+ if (fresh.length > 0 && queue.length + fresh.length <= maxTasks) {
164
+ for (const t of fresh)
165
+ known.add(t.id);
166
+ // Re-topo-sort the not-yet-run remainder plus the new tasks so deps hold.
167
+ const remainder = queue.slice(qi + 1).concat(fresh);
168
+ const resorted = topoOrder(remainder);
169
+ queue = queue.slice(0, qi + 1).concat(resorted);
170
+ }
171
+ }
172
+ else {
173
+ failed.add(task.id);
174
+ }
175
+ config.onTask?.(task, outcome);
176
+ }
177
+ return {
178
+ success: failed.size === 0,
179
+ completed: [...done],
180
+ failed: [...failed],
181
+ turns,
182
+ outcomes,
183
+ };
184
+ }
185
+ //# sourceMappingURL=task-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-orchestrator.js","sourceRoot":"","sources":["../../src/delivery/task-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAmF3C,MAAM,yBAAyB,GAAG,GAAG,CAAC;AACtC,6DAA6D;AAC7D,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAC1C,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,YAAoB,EAAE,MAAc;IAChF,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,sEAAsE;IACtE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,OAAO,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACzG,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,IAAI,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,OAAO,GAAG,CAAC;QAAE,GAAG,IAAI,+BAA+B,OAAO,sDAAsD,MAAM,eAAe,CAAC;IAC1I,sEAAsE;IACtE,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,mCAAmC,CAAC;IAC1F,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAsB,EACtB,OAAe,EACf,UAAoC,EACpC,kBAAkB,GAAG,yBAAyB,EAC9C,OAAyD,EAAE;IAE3D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,kCAAkC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzB,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,uEAAuE;IACvE,2CAA2C;IAC3C,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACtE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,0EAA0E;IAC1E,6EAA6E;IAC7E,2EAA2E;IAC3E,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;YACnC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;YACxE,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,IAAI,4BAA4B,CAAC,CAAC;IAC3G,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC;AACpE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAA0B;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,kBAAkB,CAAC;IACzC,4EAA4E;IAC5E,yCAAyC;IACzC,IAAI,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,KAAwB,CAAuB,CAAC;IAC7E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC7B,2EAA2E;QAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,OAAO,GAAgB;gBAC3B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,+BAA+B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC9D,KAAK,EAAE,CAAC;aACT,CAAC;YACF,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,IAAI,WAAW,GAAa,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,WAAW,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,WAAW,GAAG,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,kBAAkB,EAAE;YAC3F,WAAW;YACX,WAAW,EAAE,MAAM;SACpB,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChD,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;YACD,sEAAsE;YACtE,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAChE,KAAK,MAAM,CAAC,IAAI,KAAK;oBAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACvC,0EAA0E;gBAC1E,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAA4B,CAAuB,CAAC;gBAC/E,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QACD,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC;QAC1B,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;QACnB,KAAK;QACL,QAAQ;KACT,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.99.0",
3
+ "version": "1.101.0",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",