@miller-tech/uap 2.16.6 → 2.19.5
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 +1 -1
- package/config/capacity-policy.json +33 -0
- package/config/model-profiles/qwen38.json +32 -33
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/capacity/policy.d.ts +32 -1
- package/dist/capacity/policy.d.ts.map +1 -1
- package/dist/capacity/policy.js +123 -4
- package/dist/capacity/policy.js.map +1 -1
- package/dist/capacity/probe.d.ts +26 -0
- package/dist/capacity/probe.d.ts.map +1 -1
- package/dist/capacity/probe.js +84 -3
- package/dist/capacity/probe.js.map +1 -1
- package/dist/cli/inference.d.ts +4 -0
- package/dist/cli/inference.d.ts.map +1 -1
- package/dist/cli/inference.js +74 -8
- package/dist/cli/inference.js.map +1 -1
- package/dist/cli/merge-gate.d.ts +59 -0
- package/dist/cli/merge-gate.d.ts.map +1 -0
- package/dist/cli/merge-gate.js +238 -0
- package/dist/cli/merge-gate.js.map +1 -0
- package/dist/cli/merge-queue.d.ts +13 -0
- package/dist/cli/merge-queue.d.ts.map +1 -1
- package/dist/cli/merge-queue.js +48 -2
- package/dist/cli/merge-queue.js.map +1 -1
- package/dist/cli/mission.d.ts +25 -0
- package/dist/cli/mission.d.ts.map +1 -0
- package/dist/cli/mission.js +225 -0
- package/dist/cli/mission.js.map +1 -0
- package/dist/cli/orch.d.ts +27 -0
- package/dist/cli/orch.d.ts.map +1 -0
- package/dist/cli/orch.js +70 -0
- package/dist/cli/orch.js.map +1 -0
- package/dist/cli/systemd-services.d.ts.map +1 -1
- package/dist/cli/systemd-services.js +44 -0
- package/dist/cli/systemd-services.js.map +1 -1
- package/dist/delivery/merge-gate.d.ts +168 -0
- package/dist/delivery/merge-gate.d.ts.map +1 -0
- package/dist/delivery/merge-gate.js +309 -0
- package/dist/delivery/merge-gate.js.map +1 -0
- package/dist/inference/analysis.d.ts +69 -3
- package/dist/inference/analysis.d.ts.map +1 -1
- package/dist/inference/analysis.js +123 -7
- package/dist/inference/analysis.js.map +1 -1
- package/dist/inference/probe.d.ts +38 -1
- package/dist/inference/probe.d.ts.map +1 -1
- package/dist/inference/probe.js +303 -30
- package/dist/inference/probe.js.map +1 -1
- package/dist/inference/strata.d.ts +95 -0
- package/dist/inference/strata.d.ts.map +1 -0
- package/dist/inference/strata.js +167 -0
- package/dist/inference/strata.js.map +1 -0
- package/dist/mission/database.d.ts +29 -0
- package/dist/mission/database.d.ts.map +1 -0
- package/dist/mission/database.js +131 -0
- package/dist/mission/database.js.map +1 -0
- package/dist/mission/ledger.d.ts +109 -0
- package/dist/mission/ledger.d.ts.map +1 -0
- package/dist/mission/ledger.js +294 -0
- package/dist/mission/ledger.js.map +1 -0
- package/dist/mission/poll-cycle.d.ts +73 -0
- package/dist/mission/poll-cycle.d.ts.map +1 -0
- package/dist/mission/poll-cycle.js +100 -0
- package/dist/mission/poll-cycle.js.map +1 -0
- package/dist/mission/poll-executor.d.ts +91 -0
- package/dist/mission/poll-executor.d.ts.map +1 -0
- package/dist/mission/poll-executor.js +328 -0
- package/dist/mission/poll-executor.js.map +1 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +33 -27
- package/dist/models/types.js.map +1 -1
- package/dist/self-tuning/profiles/qwen38.d.ts +13 -14
- package/dist/self-tuning/profiles/qwen38.d.ts.map +1 -1
- package/dist/self-tuning/profiles/qwen38.js +17 -18
- package/dist/self-tuning/profiles/qwen38.js.map +1 -1
- package/dist/types/mission.d.ts +80 -0
- package/dist/types/mission.d.ts.map +1 -0
- package/dist/types/mission.js +12 -0
- package/dist/types/mission.js.map +1 -0
- package/docs/architecture/adr/0003-mission-orchestrator.md +99 -0
- package/docs/architecture/adr/0004-deterministic-merge-gate.md +127 -0
- package/docs/guides/CAPACITY_POLICY.md +49 -0
- package/docs/guides/INFERENCE_HEALTH.md +65 -8
- package/docs/guides/MISSIONS.md +170 -0
- package/docs/guides/PROXY.md +2 -0
- package/docs/reports/2026-10-02-plane-admin-fail-closed.md +70 -0
- package/docs/reports/2026-10-02-plane-admin-protect-session.md +116 -0
- package/docs/visual/merge-gate.html +404 -0
- package/docs/visual/mission-orchestrator.html +472 -0
- package/package.json +2 -2
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
- package/src/policies/enforcers/plane_admin_protect.py +133 -0
- package/src/policies/schemas/policies/plane-admin-protect.md +55 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/templates/hooks/uap-policy-gate.sh +33 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +522 -45
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +171 -0
- package/tools/agents/tests/test_gate_failclosed_plane_admin.py +248 -0
- package/tools/agents/tests/test_plane_admin_protect.py +124 -0
- package/tools/agents/tests/test_repeat_call_guard.py +64 -0
- package/tools/agents/tests/test_stream_heartbeat.py +77 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mission ledger service — typed operations over the mission database.
|
|
3
|
+
*
|
|
4
|
+
* The ledger is the durable goal layer: a mission's acceptance criteria are
|
|
5
|
+
* FROZEN at creation (sha256) and only change through an explicit, recorded
|
|
6
|
+
* replan. Attempt history feeds the struggle metric; failed attempts seed
|
|
7
|
+
* approval-gated salvage proposals.
|
|
8
|
+
*/
|
|
9
|
+
import { createHash } from 'crypto';
|
|
10
|
+
import { MissionDatabase, getMissionDbPath } from './database.js';
|
|
11
|
+
/** sha256 of the trimmed acceptance text — the freeze-time hash. */
|
|
12
|
+
export function hashAcceptance(acceptance) {
|
|
13
|
+
return createHash('sha256').update(acceptance.trim()).digest('hex');
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Exponential relaunch backoff (minutes): 15, 30, 60, ... capped at one day.
|
|
17
|
+
* A crash-looping mission must not burn cycles every poll — the same lesson
|
|
18
|
+
* as the systemd start-rate limiter: back off, don't hammer.
|
|
19
|
+
*/
|
|
20
|
+
export function relaunchBackoffMinutes(relaunchCount) {
|
|
21
|
+
return Math.min(15 * 2 ** relaunchCount, 1440);
|
|
22
|
+
}
|
|
23
|
+
function rowToMission(r) {
|
|
24
|
+
return {
|
|
25
|
+
id: r.id,
|
|
26
|
+
goal: r.goal,
|
|
27
|
+
acceptance: r.acceptance,
|
|
28
|
+
acceptanceHash: r.acceptance_hash,
|
|
29
|
+
status: r.status,
|
|
30
|
+
...(r.preset_id !== null ? { presetId: r.preset_id } : {}),
|
|
31
|
+
...(r.latest_run_id !== null ? { latestRunId: r.latest_run_id } : {}),
|
|
32
|
+
launchCount: r.launch_count,
|
|
33
|
+
relaunchCount: r.relaunch_count,
|
|
34
|
+
...(r.last_launch_at !== null ? { lastLaunchAt: r.last_launch_at } : {}),
|
|
35
|
+
...(r.launch_pid !== null ? { launchPid: r.launch_pid } : {}),
|
|
36
|
+
createdAt: r.created_at,
|
|
37
|
+
updatedAt: r.updated_at,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function rowToAttempt(r) {
|
|
41
|
+
return {
|
|
42
|
+
id: r.id,
|
|
43
|
+
missionId: r.mission_id,
|
|
44
|
+
...(r.run_id !== null ? { runId: r.run_id } : {}),
|
|
45
|
+
...(r.task_ref !== null ? { taskRef: r.task_ref } : {}),
|
|
46
|
+
outcome: r.outcome,
|
|
47
|
+
...(r.summary !== null ? { summary: r.summary } : {}),
|
|
48
|
+
...(r.observed_at !== null ? { observedAt: r.observed_at } : {}),
|
|
49
|
+
createdAt: r.created_at,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function rowToSalvage(r) {
|
|
53
|
+
return {
|
|
54
|
+
id: r.id,
|
|
55
|
+
missionId: r.mission_id,
|
|
56
|
+
...(r.from_attempt_id !== null ? { fromAttemptId: r.from_attempt_id } : {}),
|
|
57
|
+
...(r.task_ref !== null ? { taskRef: r.task_ref } : {}),
|
|
58
|
+
proposal: r.proposal,
|
|
59
|
+
status: r.status,
|
|
60
|
+
createdAt: r.created_at,
|
|
61
|
+
...(r.decided_at !== null ? { decidedAt: r.decided_at } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function rowToRevision(r) {
|
|
65
|
+
return {
|
|
66
|
+
id: r.id,
|
|
67
|
+
missionId: r.mission_id,
|
|
68
|
+
priorAcceptance: r.prior_acceptance,
|
|
69
|
+
priorHash: r.prior_hash,
|
|
70
|
+
reason: r.reason,
|
|
71
|
+
createdAt: r.created_at,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Open (or reuse) the mission database for a project root. PURE-ish: no writes. */
|
|
75
|
+
export function openMissionDb(projectRoot) {
|
|
76
|
+
return MissionDatabase.getInstance(getMissionDbPath(projectRoot)).getDatabase();
|
|
77
|
+
}
|
|
78
|
+
/** Test seam: reset the singleton so a new path is honored. */
|
|
79
|
+
export function resetMissionDb() {
|
|
80
|
+
MissionDatabase.resetInstance();
|
|
81
|
+
}
|
|
82
|
+
/** Create a mission with frozen acceptance criteria. */
|
|
83
|
+
export function createMission(db, input) {
|
|
84
|
+
const now = new Date().toISOString();
|
|
85
|
+
const hash = hashAcceptance(input.acceptance);
|
|
86
|
+
const info = db
|
|
87
|
+
.prepare(`INSERT INTO missions (goal, acceptance, acceptance_hash, status, preset_id, created_at, updated_at)
|
|
88
|
+
VALUES (?, ?, ?, 'active', ?, ?, ?)`)
|
|
89
|
+
.run(input.goal, input.acceptance, hash, input.presetId ?? null, now, now);
|
|
90
|
+
return getMission(db, Number(info.lastInsertRowid));
|
|
91
|
+
}
|
|
92
|
+
export function getMission(db, id) {
|
|
93
|
+
const row = db
|
|
94
|
+
.prepare('SELECT * FROM missions WHERE id = ?')
|
|
95
|
+
.get(id);
|
|
96
|
+
if (!row)
|
|
97
|
+
throw new Error(`mission #${id} not found`);
|
|
98
|
+
return rowToMission(row);
|
|
99
|
+
}
|
|
100
|
+
export function listMissions(db, opts = {}) {
|
|
101
|
+
const rows = opts.status
|
|
102
|
+
? db
|
|
103
|
+
.prepare('SELECT * FROM missions WHERE status = ? ORDER BY id DESC LIMIT ?')
|
|
104
|
+
.all(opts.status, opts.limit ?? 100)
|
|
105
|
+
: db
|
|
106
|
+
.prepare('SELECT * FROM missions ORDER BY id DESC LIMIT ?')
|
|
107
|
+
.all(opts.limit ?? 100);
|
|
108
|
+
return rows.map(rowToMission);
|
|
109
|
+
}
|
|
110
|
+
export function setMissionStatus(db, id, status) {
|
|
111
|
+
const info = db
|
|
112
|
+
.prepare('UPDATE missions SET status = ?, updated_at = ? WHERE id = ?')
|
|
113
|
+
.run(status, new Date().toISOString(), id);
|
|
114
|
+
return info.changes > 0;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Explicit replan: supersede the frozen acceptance criteria. The prior text
|
|
118
|
+
* and hash move to the revisions history — never a silent change. The run
|
|
119
|
+
* link and backoff counters RESET: the prior run embeds the OLD criteria, so
|
|
120
|
+
* resuming it could deliver against superseded acceptance. The next poll
|
|
121
|
+
* launches a fresh run under the new criteria (new marker, new pid).
|
|
122
|
+
*/
|
|
123
|
+
export function replanAcceptance(db, id, newAcceptance, reason) {
|
|
124
|
+
const mission = getMission(db, id);
|
|
125
|
+
const now = new Date().toISOString();
|
|
126
|
+
const tx = db.transaction(() => {
|
|
127
|
+
db.prepare(`INSERT INTO acceptance_revisions (mission_id, prior_acceptance, prior_hash, reason, created_at)
|
|
128
|
+
VALUES (?, ?, ?, ?, ?)`).run(id, mission.acceptance, mission.acceptanceHash, reason, now);
|
|
129
|
+
db.prepare(`UPDATE missions
|
|
130
|
+
SET acceptance = ?, acceptance_hash = ?, latest_run_id = NULL, launch_pid = NULL,
|
|
131
|
+
relaunch_count = 0, updated_at = ?
|
|
132
|
+
WHERE id = ?`).run(newAcceptance, hashAcceptance(newAcceptance), now, id);
|
|
133
|
+
});
|
|
134
|
+
tx();
|
|
135
|
+
return getMission(db, id);
|
|
136
|
+
}
|
|
137
|
+
/** Does `acceptance` match the mission's frozen criteria? (merge-gate hook). */
|
|
138
|
+
export function verifyAcceptanceHash(db, id, acceptance) {
|
|
139
|
+
const row = db
|
|
140
|
+
.prepare('SELECT acceptance_hash FROM missions WHERE id = ?')
|
|
141
|
+
.get(id);
|
|
142
|
+
return row !== undefined && row.acceptance_hash === hashAcceptance(acceptance);
|
|
143
|
+
}
|
|
144
|
+
export function listAcceptanceRevisions(db, missionId) {
|
|
145
|
+
const rows = db
|
|
146
|
+
.prepare('SELECT * FROM acceptance_revisions WHERE mission_id = ? ORDER BY id DESC')
|
|
147
|
+
.all(missionId);
|
|
148
|
+
return rows.map(rowToRevision);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* How recent a claim blocks another: two concurrent cycles (daemon poll +
|
|
152
|
+
* `uap mission create --launch`) must not both spawn. The conditional UPDATE
|
|
153
|
+
* below makes the claim atomic; this window (not the 10-min decision grace)
|
|
154
|
+
* is the anti-race guard.
|
|
155
|
+
*/
|
|
156
|
+
export const LAUNCH_CLAIM_MS = 60_000;
|
|
157
|
+
/**
|
|
158
|
+
* Atomically claim the right to launch/resume. Returns the launch stamp when
|
|
159
|
+
* this cycle WON the claim, null when another cycle launched within the
|
|
160
|
+
* window (the caller must NOT spawn). Single-statement conditional update —
|
|
161
|
+
* no read-then-write race. `nowMs` is the poll cycle's clock (injected for
|
|
162
|
+
* tests; decisions and claims must share one timeline).
|
|
163
|
+
*/
|
|
164
|
+
export function claimLaunch(db, id, kind, nowMs = Date.now()) {
|
|
165
|
+
const now = new Date(nowMs).toISOString();
|
|
166
|
+
const cutoff = new Date(nowMs - LAUNCH_CLAIM_MS).toISOString();
|
|
167
|
+
const info = kind === 'fresh'
|
|
168
|
+
? db
|
|
169
|
+
.prepare(`UPDATE missions
|
|
170
|
+
SET launch_count = launch_count + 1, last_launch_at = ?, updated_at = ?
|
|
171
|
+
WHERE id = ? AND (last_launch_at IS NULL OR last_launch_at <= ?)`)
|
|
172
|
+
.run(now, now, id, cutoff)
|
|
173
|
+
: db
|
|
174
|
+
.prepare(`UPDATE missions
|
|
175
|
+
SET launch_count = launch_count + 1, relaunch_count = relaunch_count + 1,
|
|
176
|
+
last_launch_at = ?, updated_at = ?
|
|
177
|
+
WHERE id = ? AND (last_launch_at IS NULL OR last_launch_at <= ?)`)
|
|
178
|
+
.run(now, now, id, cutoff);
|
|
179
|
+
return info.changes > 0 ? now : null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Record the pid of the launch we spawned, guarded by OUR claim stamp so a
|
|
183
|
+
* concurrent winner's stamp is never overwritten.
|
|
184
|
+
*/
|
|
185
|
+
export function setLaunchPid(db, id, stamp, pid) {
|
|
186
|
+
db.prepare('UPDATE missions SET launch_pid = ?, updated_at = ? WHERE id = ? AND last_launch_at = ?').run(pid, new Date().toISOString(), id, stamp);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Link a discovered deliver run to the mission WITHOUT counting a launch:
|
|
190
|
+
* the poll cycle finds the run the mission's own launch created (by its
|
|
191
|
+
* embedded `mission:#<id>` marker) and records the linkage.
|
|
192
|
+
*/
|
|
193
|
+
export function linkRun(db, id, runId) {
|
|
194
|
+
const info = db
|
|
195
|
+
.prepare('UPDATE missions SET latest_run_id = ?, updated_at = ? WHERE id = ?')
|
|
196
|
+
.run(runId, new Date().toISOString(), id);
|
|
197
|
+
return info.changes > 0;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Record an attempt outcome.
|
|
201
|
+
*
|
|
202
|
+
* Rows tied to a RUN dedupe on (mission, run, outcome, taskRef, observedAt):
|
|
203
|
+
* a poll cycle that re-observes the SAME terminal run state (same
|
|
204
|
+
* updatedAt/exit time) cannot double-count it, while a genuinely NEW event
|
|
205
|
+
* for the same run (a resumed run failing again, a later exit) accumulates
|
|
206
|
+
* into the struggle metric. Without observedAt in the key, a crash-looping
|
|
207
|
+
* run could contribute at most one 'failed' row ever and never reach the
|
|
208
|
+
* struggle threshold (code review P1). Whole-mission notes (no runId) are
|
|
209
|
+
* never deduped: each occurrence is a distinct event.
|
|
210
|
+
*/
|
|
211
|
+
export function recordAttempt(db, input) {
|
|
212
|
+
if (input.runId) {
|
|
213
|
+
const dup = db
|
|
214
|
+
.prepare(`SELECT 1 FROM mission_attempts
|
|
215
|
+
WHERE mission_id = ? AND outcome = ? AND run_id = ?
|
|
216
|
+
AND ifnull(task_ref, '') = ifnull(?, '')
|
|
217
|
+
AND ifnull(observed_at, '') = ifnull(?, '')`)
|
|
218
|
+
.get(input.missionId, input.outcome, input.runId, input.taskRef ?? null, input.observedAt ?? null);
|
|
219
|
+
if (dup)
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
db.prepare(`INSERT INTO mission_attempts (mission_id, run_id, task_ref, outcome, summary, observed_at, created_at)
|
|
223
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`).run(input.missionId, input.runId ?? null, input.taskRef ?? null, input.outcome, input.summary ?? null, input.observedAt ?? null, new Date().toISOString());
|
|
224
|
+
}
|
|
225
|
+
export function listAttempts(db, missionId) {
|
|
226
|
+
const rows = db
|
|
227
|
+
.prepare('SELECT * FROM mission_attempts WHERE mission_id = ? ORDER BY id')
|
|
228
|
+
.all(missionId);
|
|
229
|
+
return rows.map(rowToAttempt);
|
|
230
|
+
}
|
|
231
|
+
/** Struggle metric: failed attempts, whole-mission (no taskRef) or per ref. */
|
|
232
|
+
export function failedAttemptCount(db, missionId, taskRef) {
|
|
233
|
+
const row = taskRef
|
|
234
|
+
? db
|
|
235
|
+
.prepare(`SELECT COUNT(*) AS n FROM mission_attempts
|
|
236
|
+
WHERE mission_id = ? AND outcome = 'failed' AND task_ref = ?`)
|
|
237
|
+
.get(missionId, taskRef)
|
|
238
|
+
: db
|
|
239
|
+
.prepare(`SELECT COUNT(*) AS n FROM mission_attempts
|
|
240
|
+
WHERE mission_id = ? AND outcome IN ('failed', 'interrupted')`)
|
|
241
|
+
.get(missionId);
|
|
242
|
+
return row.n;
|
|
243
|
+
}
|
|
244
|
+
export function proposeSalvage(db, input) {
|
|
245
|
+
const now = new Date().toISOString();
|
|
246
|
+
const info = db
|
|
247
|
+
.prepare(`INSERT INTO salvage_proposals (mission_id, from_attempt_id, task_ref, proposal, status, created_at)
|
|
248
|
+
VALUES (?, ?, ?, ?, 'proposed', ?)`)
|
|
249
|
+
.run(input.missionId, input.fromAttemptId ?? null, input.taskRef ?? null, input.proposal, now);
|
|
250
|
+
const row = db
|
|
251
|
+
.prepare('SELECT * FROM salvage_proposals WHERE id = ?')
|
|
252
|
+
.get(Number(info.lastInsertRowid));
|
|
253
|
+
return rowToSalvage(row);
|
|
254
|
+
}
|
|
255
|
+
/** True when an OPEN proposal already cites the same attempt (dedupe). */
|
|
256
|
+
export function hasOpenSalvageForAttempt(db, missionId, attemptId) {
|
|
257
|
+
if (attemptId === undefined)
|
|
258
|
+
return false;
|
|
259
|
+
const row = db
|
|
260
|
+
.prepare(`SELECT 1 FROM salvage_proposals
|
|
261
|
+
WHERE mission_id = ? AND from_attempt_id = ? AND status = 'proposed'`)
|
|
262
|
+
.get(missionId, attemptId);
|
|
263
|
+
return row !== undefined;
|
|
264
|
+
}
|
|
265
|
+
export function decideSalvage(db, id, status) {
|
|
266
|
+
const info = db
|
|
267
|
+
.prepare('UPDATE salvage_proposals SET status = ?, decided_at = ? WHERE id = ?')
|
|
268
|
+
.run(status, new Date().toISOString(), id);
|
|
269
|
+
if (info.changes === 0)
|
|
270
|
+
throw new Error(`salvage proposal #${id} not found`);
|
|
271
|
+
const row = db.prepare('SELECT * FROM salvage_proposals WHERE id = ?').get(id);
|
|
272
|
+
return rowToSalvage(row);
|
|
273
|
+
}
|
|
274
|
+
export function listSalvage(db, opts = {}) {
|
|
275
|
+
// One fixed, fully literal statement per filter combination — nothing is
|
|
276
|
+
// ever assembled at runtime, and all values are bound parameters.
|
|
277
|
+
const rows = opts.missionId !== undefined && opts.status !== undefined
|
|
278
|
+
? db
|
|
279
|
+
.prepare('SELECT * FROM salvage_proposals WHERE mission_id = ? AND status = ? ORDER BY id DESC LIMIT 200')
|
|
280
|
+
.all(opts.missionId, opts.status)
|
|
281
|
+
: opts.missionId !== undefined
|
|
282
|
+
? db
|
|
283
|
+
.prepare('SELECT * FROM salvage_proposals WHERE mission_id = ? ORDER BY id DESC LIMIT 200')
|
|
284
|
+
.all(opts.missionId)
|
|
285
|
+
: opts.status !== undefined
|
|
286
|
+
? db
|
|
287
|
+
.prepare('SELECT * FROM salvage_proposals WHERE status = ? ORDER BY id DESC LIMIT 200')
|
|
288
|
+
.all(opts.status)
|
|
289
|
+
: db
|
|
290
|
+
.prepare('SELECT * FROM salvage_proposals ORDER BY id DESC LIMIT 200')
|
|
291
|
+
.all();
|
|
292
|
+
return rows.map(rowToSalvage);
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/mission/ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll-cycle decision core (PURE — unit-tested, no I/O).
|
|
3
|
+
*
|
|
4
|
+
* One orchestrator poll asks, per active mission: given the mission's ledger
|
|
5
|
+
* state and its latest durable run, what should happen RIGHT NOW? The
|
|
6
|
+
* executor (poll-executor.ts) applies the returned actions through injected
|
|
7
|
+
* seams, so this module stays testable without models, daemons, or databases.
|
|
8
|
+
*
|
|
9
|
+
* The decision table (Choir's poll loop, UAP's primitives):
|
|
10
|
+
* no run → launch a fresh deliver run for the goal
|
|
11
|
+
* run running, pid alive → one supervisor cycle (watch, don't drive)
|
|
12
|
+
* run running, pid gone → the process died without marking the run:
|
|
13
|
+
* record interrupted, salvage, relaunch
|
|
14
|
+
* run interrupted/failed → record, salvage, relaunch (with backoff)
|
|
15
|
+
* run delivered → close the mission
|
|
16
|
+
* A relaunch only fires after the exponential backoff elapses, so a
|
|
17
|
+
* crash-looping mission waits instead of hammering the machine.
|
|
18
|
+
*/
|
|
19
|
+
import type { DeliverRunState } from '../delivery/run-state.js';
|
|
20
|
+
import type { Mission } from '../types/mission.js';
|
|
21
|
+
/** Failed/interrupted attempts before salvage proposes an escalation too. */
|
|
22
|
+
export declare const STRUGGLE_THRESHOLD = 3;
|
|
23
|
+
/**
|
|
24
|
+
* Grace window after a fresh launch: `uap deliver` needs time to register its
|
|
25
|
+
* durable run state. Within the window a mission with no run is "launch in
|
|
26
|
+
* flight", not "launch again" — without this the next poll double-launches.
|
|
27
|
+
*/
|
|
28
|
+
export declare const LAUNCH_GRACE_MS: number;
|
|
29
|
+
export type PollAction = {
|
|
30
|
+
kind: 'supervise';
|
|
31
|
+
runId: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'relaunch';
|
|
34
|
+
runId: string;
|
|
35
|
+
} | {
|
|
36
|
+
kind: 'launch';
|
|
37
|
+
} | {
|
|
38
|
+
kind: 'close-delivered';
|
|
39
|
+
runId: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'salvage-proposal';
|
|
42
|
+
summary: string;
|
|
43
|
+
escalate: boolean;
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'wait-backoff';
|
|
46
|
+
minutes: number;
|
|
47
|
+
reason: string;
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'none';
|
|
50
|
+
reason: string;
|
|
51
|
+
};
|
|
52
|
+
export interface PollView {
|
|
53
|
+
mission: Mission;
|
|
54
|
+
/** Latest durable run attached to the mission (null = never launched). */
|
|
55
|
+
run: DeliverRunState | null;
|
|
56
|
+
/** Is the run's owning pid still alive? (ignored when run is null). */
|
|
57
|
+
runPidAlive: boolean;
|
|
58
|
+
/** Struggle metric: failed/interrupted attempts recorded so far. */
|
|
59
|
+
failedAttempts: number;
|
|
60
|
+
/** ms since the mission's last launch (0 when never launched). */
|
|
61
|
+
sinceLastLaunchMs: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Backoff still owed for this mission right now (0 = free to relaunch).
|
|
65
|
+
*
|
|
66
|
+
* The FIRST relaunch is immediate — an interrupted run resuming cleanly is
|
|
67
|
+
* the common healthy case, not a crash loop. Backoff then doubles per
|
|
68
|
+
* relaunch: 15 min after one resume, 30 after two, and so on.
|
|
69
|
+
*/
|
|
70
|
+
export declare function backoffRemainingMs(view: PollView): number;
|
|
71
|
+
/** Decide what the orchestrator should do for one active mission. PURE. */
|
|
72
|
+
export declare function decideMissionActions(view: PollView): PollAction[];
|
|
73
|
+
//# sourceMappingURL=poll-cycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-cycle.d.ts","sourceRoot":"","sources":["../../src/mission/poll-cycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAc,CAAC;AAE3C,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5B,uEAAuE;IACvE,WAAW,EAAE,OAAO,CAAC;IACrB,oEAAoE;IACpE,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAIzD;AAUD,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,EAAE,CAgCjE"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll-cycle decision core (PURE — unit-tested, no I/O).
|
|
3
|
+
*
|
|
4
|
+
* One orchestrator poll asks, per active mission: given the mission's ledger
|
|
5
|
+
* state and its latest durable run, what should happen RIGHT NOW? The
|
|
6
|
+
* executor (poll-executor.ts) applies the returned actions through injected
|
|
7
|
+
* seams, so this module stays testable without models, daemons, or databases.
|
|
8
|
+
*
|
|
9
|
+
* The decision table (Choir's poll loop, UAP's primitives):
|
|
10
|
+
* no run → launch a fresh deliver run for the goal
|
|
11
|
+
* run running, pid alive → one supervisor cycle (watch, don't drive)
|
|
12
|
+
* run running, pid gone → the process died without marking the run:
|
|
13
|
+
* record interrupted, salvage, relaunch
|
|
14
|
+
* run interrupted/failed → record, salvage, relaunch (with backoff)
|
|
15
|
+
* run delivered → close the mission
|
|
16
|
+
* A relaunch only fires after the exponential backoff elapses, so a
|
|
17
|
+
* crash-looping mission waits instead of hammering the machine.
|
|
18
|
+
*/
|
|
19
|
+
import { relaunchBackoffMinutes } from './ledger.js';
|
|
20
|
+
/** Failed/interrupted attempts before salvage proposes an escalation too. */
|
|
21
|
+
export const STRUGGLE_THRESHOLD = 3;
|
|
22
|
+
/**
|
|
23
|
+
* Grace window after a fresh launch: `uap deliver` needs time to register its
|
|
24
|
+
* durable run state. Within the window a mission with no run is "launch in
|
|
25
|
+
* flight", not "launch again" — without this the next poll double-launches.
|
|
26
|
+
*/
|
|
27
|
+
export const LAUNCH_GRACE_MS = 10 * 60_000;
|
|
28
|
+
/**
|
|
29
|
+
* Backoff still owed for this mission right now (0 = free to relaunch).
|
|
30
|
+
*
|
|
31
|
+
* The FIRST relaunch is immediate — an interrupted run resuming cleanly is
|
|
32
|
+
* the common healthy case, not a crash loop. Backoff then doubles per
|
|
33
|
+
* relaunch: 15 min after one resume, 30 after two, and so on.
|
|
34
|
+
*/
|
|
35
|
+
export function backoffRemainingMs(view) {
|
|
36
|
+
if (view.mission.relaunchCount === 0)
|
|
37
|
+
return 0;
|
|
38
|
+
const owed = relaunchBackoffMinutes(view.mission.relaunchCount - 1) * 60_000;
|
|
39
|
+
return Math.max(0, owed - view.sinceLastLaunchMs);
|
|
40
|
+
}
|
|
41
|
+
function salvageSummary(view, outcome) {
|
|
42
|
+
return (`run ${view.run?.runId ?? '?'} ${outcome}` +
|
|
43
|
+
(view.run?.exit?.reason ? ` — ${view.run.exit.reason}` : '') +
|
|
44
|
+
`; ${view.failedAttempts} failed attempt(s) so far`);
|
|
45
|
+
}
|
|
46
|
+
/** Decide what the orchestrator should do for one active mission. PURE. */
|
|
47
|
+
export function decideMissionActions(view) {
|
|
48
|
+
if (view.mission.status !== 'active') {
|
|
49
|
+
return [{ kind: 'none', reason: `mission is ${view.mission.status}` }];
|
|
50
|
+
}
|
|
51
|
+
if (view.run === null) {
|
|
52
|
+
if (view.mission.lastLaunchAt && view.sinceLastLaunchMs < LAUNCH_GRACE_MS) {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
kind: 'wait-backoff',
|
|
56
|
+
minutes: Math.ceil((LAUNCH_GRACE_MS - view.sinceLastLaunchMs) / 60_000),
|
|
57
|
+
reason: 'fresh launch in flight — run state not yet registered',
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
return [{ kind: 'launch' }];
|
|
62
|
+
}
|
|
63
|
+
const escalate = view.failedAttempts >= STRUGGLE_THRESHOLD;
|
|
64
|
+
const backoff = backoffRemainingMs(view);
|
|
65
|
+
switch (view.run.status) {
|
|
66
|
+
case 'running':
|
|
67
|
+
if (view.runPidAlive) {
|
|
68
|
+
return [{ kind: 'supervise', runId: view.run.runId }];
|
|
69
|
+
}
|
|
70
|
+
// 'running' with a dead pid is a crash that never got to mark itself.
|
|
71
|
+
return terminal(view, 'interrupted', backoff, escalate, 'owner pid is gone');
|
|
72
|
+
case 'interrupted':
|
|
73
|
+
return terminal(view, 'interrupted', backoff, escalate, 'run interrupted');
|
|
74
|
+
case 'failed':
|
|
75
|
+
return terminal(view, 'failed', backoff, escalate, 'run failed');
|
|
76
|
+
case 'delivered':
|
|
77
|
+
return [{ kind: 'close-delivered', runId: view.run.runId }];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function terminal(view, outcome, backoffMs, escalate, reason) {
|
|
81
|
+
const actions = [
|
|
82
|
+
{
|
|
83
|
+
kind: 'salvage-proposal',
|
|
84
|
+
summary: salvageSummary(view, outcome),
|
|
85
|
+
escalate,
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
if (backoffMs > 0) {
|
|
89
|
+
actions.push({
|
|
90
|
+
kind: 'wait-backoff',
|
|
91
|
+
minutes: Math.ceil(backoffMs / 60_000),
|
|
92
|
+
reason: `${reason}; backoff after ${view.mission.relaunchCount} relaunch(es)`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
actions.push({ kind: 'relaunch', runId: view.run?.runId ?? '' });
|
|
97
|
+
}
|
|
98
|
+
return actions;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=poll-cycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-cycle.js","sourceRoot":"","sources":["../../src/mission/poll-cycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll-cycle executor — applies decideMissionActions through injectable seams.
|
|
3
|
+
*
|
|
4
|
+
* Production seams: ledger + run-state stores (real), runSupervisor (once
|
|
5
|
+
* mode), spawnDeliverRun (detached, deliver-detach's discipline: own session,
|
|
6
|
+
* stdio to a file, never a pipe). Tests inject stubs, so the orchestration
|
|
7
|
+
* logic runs without models or databases.
|
|
8
|
+
*
|
|
9
|
+
* Run linkage is PROVENANCE-CHECKED (security review P1): a discovered run
|
|
10
|
+
* only links to its mission when its instruction carries the mission's
|
|
11
|
+
* marker (which embeds the acceptance hash, so a replan cannot relink old
|
|
12
|
+
* runs) AND its pid matches the pid the orchestrator itself spawned. A
|
|
13
|
+
* planted run-state file cannot know the future child pid, so it can never
|
|
14
|
+
* steer the daemon. The launch claim (ledger.claimLaunch) makes concurrent
|
|
15
|
+
* cycles (daemon + `create --launch`) atomic: only one spawns.
|
|
16
|
+
*/
|
|
17
|
+
import { type DeliverRunState } from '../delivery/run-state.js';
|
|
18
|
+
import type { Mission } from '../types/mission.js';
|
|
19
|
+
/** signal-0 liveness probe; EPERM means alive but not ours. */
|
|
20
|
+
export declare function pidAlive(pid: number | undefined): boolean;
|
|
21
|
+
/** A launch the executor performed. */
|
|
22
|
+
export interface SpawnResult {
|
|
23
|
+
pid: number;
|
|
24
|
+
}
|
|
25
|
+
export interface PollSeams {
|
|
26
|
+
/** Launch a fresh deliver run for a mission goal. */
|
|
27
|
+
launchDeliver: (input: {
|
|
28
|
+
projectRoot: string;
|
|
29
|
+
instruction: string;
|
|
30
|
+
presetId?: string;
|
|
31
|
+
}) => SpawnResult | null;
|
|
32
|
+
/** Resume an interrupted/failed durable run. */
|
|
33
|
+
resumeDeliver: (input: {
|
|
34
|
+
projectRoot: string;
|
|
35
|
+
runId: string;
|
|
36
|
+
}) => SpawnResult | null;
|
|
37
|
+
/** One supervisor cycle over a live run; returns the action taken (or error note). */
|
|
38
|
+
superviseOnce: (input: {
|
|
39
|
+
projectRoot: string;
|
|
40
|
+
runId: string;
|
|
41
|
+
}) => Promise<string | null>;
|
|
42
|
+
/** Post a note to the collaboration board (best-effort, never throws). */
|
|
43
|
+
postBoardNote: (text: string) => void;
|
|
44
|
+
}
|
|
45
|
+
/** Where detached orch-launched runs stream their output. */
|
|
46
|
+
export declare function orchLogPath(projectRoot: string, stamp: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Spawn a detached `uap deliver …` process (own session, stdio to a file) so
|
|
49
|
+
* the mission outlives the poll cycle and any daemon restart. Returns null
|
|
50
|
+
* when the CLI entrypoint cannot be resolved — the caller records nothing.
|
|
51
|
+
*/
|
|
52
|
+
export declare function spawnDeliverRun(args: {
|
|
53
|
+
projectRoot: string;
|
|
54
|
+
deliverArgs: string[];
|
|
55
|
+
stamp: string;
|
|
56
|
+
}): SpawnResult | null;
|
|
57
|
+
/**
|
|
58
|
+
* The mission marker links a deliver run back to its owning mission. The
|
|
59
|
+
* acceptance-hash slice makes it replan-scoped: after a replan the hash
|
|
60
|
+
* changes, so discovery can never relink a run that embeds the OLD criteria
|
|
61
|
+
* — and goal text that merely mentions another mission's marker cannot
|
|
62
|
+
* collide (code review P2).
|
|
63
|
+
*/
|
|
64
|
+
export declare function missionMarker(mission: Mission): string;
|
|
65
|
+
/**
|
|
66
|
+
* The mission's acceptance criteria travel inside the instruction text. The
|
|
67
|
+
* marker prefix also guarantees the argv token can never start with `-`, so
|
|
68
|
+
* commander cannot misread it as a flag.
|
|
69
|
+
*/
|
|
70
|
+
export declare function missionInstruction(mission: Mission): string;
|
|
71
|
+
export declare function defaultSeams(): PollSeams;
|
|
72
|
+
/** One line summarizing a poll cycle for logs and the --json output. */
|
|
73
|
+
export interface PollMissionReport {
|
|
74
|
+
missionId: number;
|
|
75
|
+
actions: string[];
|
|
76
|
+
notes: string[];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Find the durable run a fresh launch created. PROVENANCE-CHECKED (security
|
|
80
|
+
* review P1): the run must carry this mission's marker (replan-scoped via
|
|
81
|
+
* the acceptance-hash slice), its pid must match the pid the orchestrator
|
|
82
|
+
* spawned (a planted state file cannot know a future child pid), and it must
|
|
83
|
+
* have been created at/after the launch. Status is not filtered — a short
|
|
84
|
+
* mission can deliver inside one poll interval and must still be linked.
|
|
85
|
+
*/
|
|
86
|
+
export declare function discoverRunForMission(projectRoot: string, mission: Mission): DeliverRunState | null;
|
|
87
|
+
/** Run ONE poll cycle over active missions. Returns per-mission reports. */
|
|
88
|
+
export declare function runPollCycle(projectRoot: string, seams?: PollSeams, nowMs?: number, opts?: {
|
|
89
|
+
missionIds?: number[];
|
|
90
|
+
}): Promise<PollMissionReport[]>;
|
|
91
|
+
//# sourceMappingURL=poll-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-executor.d.ts","sourceRoot":"","sources":["../../src/mission/poll-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAmBxF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAQzD;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACxB,qDAAqD;IACrD,aAAa,EAAE,CAAC,KAAK,EAAE;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,KAAK,WAAW,GAAG,IAAI,CAAC;IACzB,gDAAgD;IAChD,aAAa,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,WAAW,GAAG,IAAI,CAAC;IACrF,sFAAsF;IACtF,aAAa,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzF,0EAA0E;IAC1E,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,WAAW,GAAG,IAAI,CAyBrB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE3D;AAED,wBAAgB,YAAY,IAAI,SAAS,CA0CxC;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAmBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,GACf,eAAe,GAAG,IAAI,CAaxB;AA8ID,4EAA4E;AAC5E,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,SAA0B,EACjC,KAAK,GAAE,MAAmB,EAC1B,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACnC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA4B9B"}
|