pandora-cli-skills 1.1.57 → 1.1.59
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/SKILL.md +1 -1
- package/cli/lib/mirror_service.cjs +41 -17
- package/cli/lib/mirror_verify_service.cjs +88 -65
- package/cli/lib/quant/abm_market.cjs +61 -2
- package/cli/lib/scan_command_service.cjs +1 -0
- package/cli/pandora.cjs +157 -160
- package/package.json +2 -8
- package/cli/lib/model_store.cjs +0 -292
- package/cli/lib/quant/copula.cjs +0 -399
- package/cli/lib/quant/importance_sampling.cjs +0 -223
- package/cli/lib/quant/mc_stats.cjs +0 -179
- package/cli/lib/quant/particle_filter.cjs +0 -311
- package/cli/lib/quant/rng.cjs +0 -206
- package/cli/lib/quant/variance_reduction.cjs +0 -148
- package/tests/cli/agent_workflow.integration.test.cjs +0 -301
- package/tests/cli/cli.integration.test.cjs +0 -6230
- package/tests/cli/mcp.integration.test.cjs +0 -427
- package/tests/cli/sports.integration.test.cjs +0 -445
- package/tests/cli/stream.integration.test.cjs +0 -218
- package/tests/helpers/cli_runner.cjs +0 -189
- package/tests/smoke/consumer-json-smoke.cjs +0 -217
- package/tests/smoke/pack-install-smoke.cjs +0 -302
- package/tests/unit/abm_market.test.cjs +0 -272
- package/tests/unit/brier_scoring.test.cjs +0 -74
- package/tests/unit/brier_watch_command.test.cjs +0 -121
- package/tests/unit/combinatorial_arb.test.cjs +0 -252
- package/tests/unit/core_command_flags.test.cjs +0 -113
- package/tests/unit/export_service.test.cjs +0 -87
- package/tests/unit/fork_preview_service.test.cjs +0 -249
- package/tests/unit/lp_command_service.test.cjs +0 -125
- package/tests/unit/lp_flags.test.cjs +0 -116
- package/tests/unit/market_admin_resolution_state.test.cjs +0 -71
- package/tests/unit/mirror_close_service.test.cjs +0 -56
- package/tests/unit/mirror_go_regressions.test.cjs +0 -479
- package/tests/unit/mirror_simulate_mc.test.cjs +0 -152
- package/tests/unit/model_calibrate.test.cjs +0 -142
- package/tests/unit/model_correlation.test.cjs +0 -147
- package/tests/unit/model_diagnose.test.cjs +0 -83
- package/tests/unit/new-features.test.cjs +0 -2756
- package/tests/unit/odds_history_service.test.cjs +0 -132
- package/tests/unit/polymarket_adapter.test.cjs +0 -81
- package/tests/unit/quant_core.test.cjs +0 -104
- package/tests/unit/quant_models.test.cjs +0 -85
- package/tests/unit/quant_stores.test.cjs +0 -134
- package/tests/unit/risk_guard_service.test.cjs +0 -175
- package/tests/unit/risk_state_store.test.cjs +0 -166
- package/tests/unit/sanity.test.cjs +0 -15
- package/tests/unit/scan_command_service.test.cjs +0 -68
- package/tests/unit/simulate_command_service.test.cjs +0 -91
- package/tests/unit/simulate_flags.test.cjs +0 -185
- package/tests/unit/simulate_handlers.test.cjs +0 -103
- package/tests/unit/sports_consensus.test.cjs +0 -103
- package/tests/unit/sports_creation.test.cjs +0 -102
- package/tests/unit/sports_resolve_plan.test.cjs +0 -103
- package/tests/unit/sports_sync.test.cjs +0 -92
- package/tests/unit/sports_timing.test.cjs +0 -127
- package/tests/unit/trade_market_type_service.test.cjs +0 -109
- package/tests/unit/venue_connector_factory.test.cjs +0 -67
package/SKILL.md
CHANGED
|
@@ -3,7 +3,13 @@ const path = require('path');
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const { computeLiquidityRecommendation, computeDistributionHint, normalizeProbability } = require('./mirror_sizing_service.cjs');
|
|
5
5
|
const { resolvePolymarketMarket, fetchDepthForMarket, browsePolymarketMarkets } = require('./polymarket_trade_adapter.cjs');
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
findBestPandoraMatch,
|
|
8
|
+
fetchPandoraMarketContext,
|
|
9
|
+
verifyMirrorPair,
|
|
10
|
+
hashRules,
|
|
11
|
+
preloadPandoraMatchCandidates,
|
|
12
|
+
} = require('./mirror_verify_service.cjs');
|
|
7
13
|
const { deployPandoraAmmMarket } = require('./pandora_deploy_service.cjs');
|
|
8
14
|
const { defaultManifestFile, upsertPair } = require('./mirror_manifest_store.cjs');
|
|
9
15
|
const { round } = require('./shared/utils.cjs');
|
|
@@ -421,27 +427,45 @@ async function browseMirrorMarkets(options = {}) {
|
|
|
421
427
|
limit: options.limit,
|
|
422
428
|
});
|
|
423
429
|
|
|
430
|
+
let preloadedPandoraCandidates = null;
|
|
431
|
+
let preloadDuplicateCheckError = null;
|
|
432
|
+
if (options.indexerUrl) {
|
|
433
|
+
try {
|
|
434
|
+
preloadedPandoraCandidates = await preloadPandoraMatchCandidates({
|
|
435
|
+
indexerUrl: options.indexerUrl,
|
|
436
|
+
timeoutMs: options.timeoutMs,
|
|
437
|
+
chainId: options.chainId,
|
|
438
|
+
limit: 100,
|
|
439
|
+
});
|
|
440
|
+
} catch (err) {
|
|
441
|
+
preloadDuplicateCheckError = err;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
424
445
|
const items = [];
|
|
425
446
|
for (const entry of polymarket.items || []) {
|
|
426
447
|
let existingMirror = null;
|
|
427
448
|
if (options.indexerUrl) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
449
|
+
if (preloadDuplicateCheckError) {
|
|
450
|
+
diagnostics.push(
|
|
451
|
+
`Duplicate-check skipped for "${entry.slug || entry.marketId || entry.question || 'market'}": ${preloadDuplicateCheckError && preloadDuplicateCheckError.message ? preloadDuplicateCheckError.message : String(preloadDuplicateCheckError)}`,
|
|
452
|
+
);
|
|
453
|
+
} else {
|
|
454
|
+
try {
|
|
455
|
+
const match = await findBestPandoraMatch({
|
|
456
|
+
sourceQuestion: entry.question,
|
|
457
|
+
candidateSet: preloadedPandoraCandidates,
|
|
458
|
+
});
|
|
459
|
+
if (match.best && match.best.similarity && Number(match.best.similarity.score) >= 0.86) {
|
|
460
|
+
existingMirror = {
|
|
461
|
+
marketAddress: match.best.marketAddress,
|
|
462
|
+
similarity: match.best.similarity.score,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
diagnostics.push(...(match.diagnostics || []));
|
|
466
|
+
} catch (err) {
|
|
467
|
+
diagnostics.push(`Duplicate-check skipped for "${entry.slug || entry.marketId || entry.question || 'market'}": ${err && err.message ? err.message : String(err)}`);
|
|
441
468
|
}
|
|
442
|
-
diagnostics.push(...(match.diagnostics || []));
|
|
443
|
-
} catch (err) {
|
|
444
|
-
diagnostics.push(`Duplicate-check skipped for "${entry.slug || entry.marketId || entry.question || 'market'}": ${err && err.message ? err.message : String(err)}`);
|
|
445
469
|
}
|
|
446
470
|
}
|
|
447
471
|
|
|
@@ -161,6 +161,91 @@ async function fetchPandoraMarketContext(options = {}) {
|
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
function buildPandoraMatchCandidates(markets, pollsMap) {
|
|
165
|
+
const rows = [];
|
|
166
|
+
|
|
167
|
+
for (const market of Array.isArray(markets) ? markets : []) {
|
|
168
|
+
const pollAddress = String(market && market.pollAddress ? market.pollAddress : '').trim();
|
|
169
|
+
const poll = pollsMap.get(pollAddress.toLowerCase()) || pollsMap.get(pollAddress);
|
|
170
|
+
const question = poll && poll.question ? String(poll.question) : null;
|
|
171
|
+
if (!question) continue;
|
|
172
|
+
|
|
173
|
+
rows.push({
|
|
174
|
+
marketAddress: market.id,
|
|
175
|
+
pollAddress: market.pollAddress,
|
|
176
|
+
question,
|
|
177
|
+
status: toOptionalNumber(poll && poll.status),
|
|
178
|
+
rules: poll && poll.rules ? String(poll.rules) : null,
|
|
179
|
+
yesPct: derivePandoraYesPct(market),
|
|
180
|
+
closeTimestamp: toOptionalNumber(market.marketCloseTimestamp),
|
|
181
|
+
chainId: toOptionalNumber(market.chainId),
|
|
182
|
+
marketType: market.marketType || null,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return rows;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function scorePandoraMatchCandidates(sourceQuestion, candidates) {
|
|
190
|
+
const rows = (Array.isArray(candidates) ? candidates : []).map((candidate) => ({
|
|
191
|
+
...candidate,
|
|
192
|
+
similarity: questionSimilarityBreakdown(sourceQuestion, candidate.question),
|
|
193
|
+
}));
|
|
194
|
+
|
|
195
|
+
rows.sort((a, b) => (b.similarity.score || 0) - (a.similarity.score || 0));
|
|
196
|
+
|
|
197
|
+
const diagnostics = [];
|
|
198
|
+
const best = rows[0] || null;
|
|
199
|
+
if (!best) diagnostics.push('No Pandora candidate markets with poll questions were found.');
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
generatedAt: new Date().toISOString(),
|
|
203
|
+
best,
|
|
204
|
+
candidateCount: rows.length,
|
|
205
|
+
diagnostics,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function preloadPandoraMatchCandidates(options = {}) {
|
|
210
|
+
const client = createIndexerClient(options.indexerUrl, options.timeoutMs);
|
|
211
|
+
|
|
212
|
+
const page = await client.list({
|
|
213
|
+
queryName: 'marketss',
|
|
214
|
+
filterType: 'marketsFilter',
|
|
215
|
+
fields: ['id', 'chainId', 'marketType', 'pollAddress', 'marketCloseTimestamp', 'yesChance', 'reserveYes', 'reserveNo'],
|
|
216
|
+
variables: {
|
|
217
|
+
where: {
|
|
218
|
+
...(options.chainId !== null && options.chainId !== undefined ? { chainId: options.chainId } : {}),
|
|
219
|
+
},
|
|
220
|
+
orderBy: 'createdAt',
|
|
221
|
+
orderDirection: 'desc',
|
|
222
|
+
before: null,
|
|
223
|
+
after: null,
|
|
224
|
+
limit: Math.max(25, Math.min(Number(options.limit) || 150, 500)),
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const markets = Array.isArray(page.items) ? page.items : [];
|
|
229
|
+
const pollIds = Array.from(
|
|
230
|
+
new Set(
|
|
231
|
+
markets
|
|
232
|
+
.map((market) => String(market && market.pollAddress ? market.pollAddress : '').trim())
|
|
233
|
+
.filter(Boolean),
|
|
234
|
+
),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const pollsMap = await client.getManyByIds({
|
|
238
|
+
queryName: 'polls',
|
|
239
|
+
fields: ['id', 'question', 'status', 'deadlineEpoch', 'rules'],
|
|
240
|
+
ids: pollIds,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
generatedAt: new Date().toISOString(),
|
|
245
|
+
candidates: buildPandoraMatchCandidates(markets, pollsMap),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
164
249
|
function buildGateChecks({
|
|
165
250
|
similarity,
|
|
166
251
|
confidenceThreshold,
|
|
@@ -325,71 +410,8 @@ async function verifyMirrorPair(options = {}) {
|
|
|
325
410
|
}
|
|
326
411
|
|
|
327
412
|
async function findBestPandoraMatch(options = {}) {
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const page = await client.list({
|
|
332
|
-
queryName: 'marketss',
|
|
333
|
-
filterType: 'marketsFilter',
|
|
334
|
-
fields: ['id', 'chainId', 'marketType', 'pollAddress', 'marketCloseTimestamp', 'yesChance', 'reserveYes', 'reserveNo'],
|
|
335
|
-
variables: {
|
|
336
|
-
where: {
|
|
337
|
-
...(options.chainId !== null && options.chainId !== undefined ? { chainId: options.chainId } : {}),
|
|
338
|
-
},
|
|
339
|
-
orderBy: 'createdAt',
|
|
340
|
-
orderDirection: 'desc',
|
|
341
|
-
before: null,
|
|
342
|
-
after: null,
|
|
343
|
-
limit: Math.max(25, Math.min(Number(options.limit) || 150, 500)),
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
const markets = Array.isArray(page.items) ? page.items : [];
|
|
348
|
-
const pollIds = Array.from(
|
|
349
|
-
new Set(
|
|
350
|
-
markets
|
|
351
|
-
.map((market) => String(market && market.pollAddress ? market.pollAddress : '').trim())
|
|
352
|
-
.filter(Boolean),
|
|
353
|
-
),
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
const pollsMap = await client.getManyByIds({
|
|
357
|
-
queryName: 'polls',
|
|
358
|
-
fields: ['id', 'question', 'status', 'deadlineEpoch', 'rules'],
|
|
359
|
-
ids: pollIds,
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
const rows = [];
|
|
363
|
-
for (const market of markets) {
|
|
364
|
-
const poll = pollsMap.get(String(market.pollAddress || '').toLowerCase()) || pollsMap.get(String(market.pollAddress || ''));
|
|
365
|
-
const question = poll && poll.question ? String(poll.question) : null;
|
|
366
|
-
if (!question) continue;
|
|
367
|
-
|
|
368
|
-
const similarity = questionSimilarityBreakdown(options.sourceQuestion, question);
|
|
369
|
-
rows.push({
|
|
370
|
-
marketAddress: market.id,
|
|
371
|
-
pollAddress: market.pollAddress,
|
|
372
|
-
question,
|
|
373
|
-
similarity,
|
|
374
|
-
status: toOptionalNumber(poll && poll.status),
|
|
375
|
-
rules: poll && poll.rules ? String(poll.rules) : null,
|
|
376
|
-
yesPct: derivePandoraYesPct(market),
|
|
377
|
-
closeTimestamp: toOptionalNumber(market.marketCloseTimestamp),
|
|
378
|
-
chainId: toOptionalNumber(market.chainId),
|
|
379
|
-
marketType: market.marketType || null,
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
rows.sort((a, b) => (b.similarity.score || 0) - (a.similarity.score || 0));
|
|
384
|
-
const best = rows[0] || null;
|
|
385
|
-
if (!best) diagnostics.push('No Pandora candidate markets with poll questions were found.');
|
|
386
|
-
|
|
387
|
-
return {
|
|
388
|
-
generatedAt: new Date().toISOString(),
|
|
389
|
-
best,
|
|
390
|
-
candidateCount: rows.length,
|
|
391
|
-
diagnostics,
|
|
392
|
-
};
|
|
413
|
+
const candidateSet = options.candidateSet || (await preloadPandoraMatchCandidates(options));
|
|
414
|
+
return scorePandoraMatchCandidates(options.sourceQuestion, candidateSet && candidateSet.candidates);
|
|
393
415
|
}
|
|
394
416
|
|
|
395
417
|
module.exports = {
|
|
@@ -400,5 +422,6 @@ module.exports = {
|
|
|
400
422
|
questionSimilarityBreakdown,
|
|
401
423
|
fetchPandoraMarketContext,
|
|
402
424
|
verifyMirrorPair,
|
|
425
|
+
preloadPandoraMatchCandidates,
|
|
403
426
|
findBestPandoraMatch,
|
|
404
427
|
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const { createRng } = require('./rng.cjs');
|
|
2
|
-
const { mean, standardDeviation } = require('./mc_stats.cjs');
|
|
3
1
|
const { createQuantError } = require('./errors.cjs');
|
|
4
2
|
|
|
5
3
|
const ABM_SCHEMA_VERSION = '1.0.0';
|
|
@@ -10,6 +8,67 @@ function clamp(value, min, max) {
|
|
|
10
8
|
return Math.min(max, Math.max(min, value));
|
|
11
9
|
}
|
|
12
10
|
|
|
11
|
+
function createRng(seed) {
|
|
12
|
+
let state = Number.isInteger(seed) ? seed >>> 0 : 1;
|
|
13
|
+
|
|
14
|
+
function next() {
|
|
15
|
+
state += 0x6d2b79f5;
|
|
16
|
+
let t = Math.imul(state ^ (state >>> 15), 1 | state);
|
|
17
|
+
t ^= t + Math.imul(t ^ (t >>> 7), 61 | t);
|
|
18
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let spare = null;
|
|
22
|
+
function nextNormal(meanValue = 0, stdDev = 1) {
|
|
23
|
+
if (spare !== null) {
|
|
24
|
+
const value = spare;
|
|
25
|
+
spare = null;
|
|
26
|
+
return meanValue + value * stdDev;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let u1 = next();
|
|
30
|
+
let u2 = next();
|
|
31
|
+
if (u1 <= Number.EPSILON) u1 = Number.EPSILON;
|
|
32
|
+
if (u2 <= Number.EPSILON) u2 = Number.EPSILON;
|
|
33
|
+
|
|
34
|
+
const radius = Math.sqrt(-2 * Math.log(u1));
|
|
35
|
+
const theta = 2 * Math.PI * u2;
|
|
36
|
+
const z0 = radius * Math.cos(theta);
|
|
37
|
+
const z1 = radius * Math.sin(theta);
|
|
38
|
+
spare = z1;
|
|
39
|
+
return meanValue + z0 * stdDev;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
next,
|
|
44
|
+
nextNormal,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function mean(values) {
|
|
49
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
let total = 0;
|
|
53
|
+
for (const value of values) {
|
|
54
|
+
total += value;
|
|
55
|
+
}
|
|
56
|
+
return total / values.length;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function standardDeviation(values) {
|
|
60
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
const average = mean(values);
|
|
64
|
+
let variance = 0;
|
|
65
|
+
for (const value of values) {
|
|
66
|
+
const delta = value - average;
|
|
67
|
+
variance += delta * delta;
|
|
68
|
+
}
|
|
69
|
+
return Math.sqrt(variance / values.length);
|
|
70
|
+
}
|
|
71
|
+
|
|
13
72
|
function validatePositiveInteger(value, name) {
|
|
14
73
|
const numeric = Number(value);
|
|
15
74
|
if (!Number.isInteger(numeric) || numeric <= 0) {
|
|
@@ -7,6 +7,7 @@ const SCAN_USAGE =
|
|
|
7
7
|
'pandora [--output table|json] scan [--limit <n>] [--after <cursor>] [--before <cursor>] [--order-by <field>] [--order-direction asc|desc] [--chain-id <id>] [--creator <address>] [--poll-address <address>] [--market-type <type>|--type <type>] [--where-json <json>] [--active|--resolved|--expiring-soon] [--expiring-hours <n>] [--min-tvl <usdc>] [--hedgeable] [--expand] [--with-odds]';
|
|
8
8
|
|
|
9
9
|
const SCAN_NOTES = [
|
|
10
|
+
'scan is a top-level alias for `markets scan`; prefer `markets scan` in docs and scripts.',
|
|
10
11
|
'scan always returns expanded market payloads with odds included.',
|
|
11
12
|
'--with-odds is accepted for backward compatibility and is effectively a no-op.',
|
|
12
13
|
'--min-tvl applies a client-side filter against current TVL in USDC units.',
|