diff --git a/README.md b/README.md index 262c2bf..7f4f0f0 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ https://polymarket-site-eta.vercel.app/personal.html The site fetches live Polymarket markets, generates agent suggestions, lets you run frequent paper cycles, and syncs the shared arena state through Neon or -Vercel Blob. Build 58 also installs an offline app shell and caches timestamped +Vercel Blob. Build 59 also installs an offline app shell and caches timestamped market snapshots. During an outage, cycles continue locally; cached entries are allowed for 90 minutes, older snapshots become mark-only, and all cached data expires after 24 hours. -Build 58 ranks the competition by each agent's return since Strategy 50 began. +Build 59 ranks the competition by each agent's return since Strategy 50 began. Historical replay equity remains visible for context, but it no longer makes an agent look like the current leader when the live adaptive strategy is losing. @@ -114,7 +114,7 @@ feature views before repeatable positive evidence can increase size or repeatabl negative evidence can block a new entry. Mixed evidence stays close to neutral instead of being mistaken for an edge. -Build 58 enforces the documented offline boundary end to end. Cached snapshots +Build 59 enforces the documented offline boundary end to end. Cached snapshots under 90 minutes old may continue paper execution. Older snapshots remain usable for valuation and chart snapshots for up to 24 hours, but cannot trigger entries, stop-losses, gain-stops, risk rebalances, settlements, or policy exits. Network @@ -127,12 +127,12 @@ adaptive baselines, pending signal grades, and trade evidence remain in one stra lineage until the actual entry, sizing, or exit logic changes. Legacy build 40 and 41 records are migrated into the same strategy lineage without losing evidence. -Build 58 independently refreshes markets for matured pending signals that have +Build 59 independently refreshes markets for matured pending signals that have left the current top-500 activity scan. Unavailable markets remain queued for a bounded retry window. This prevents activity-rank survivorship from deciding which wins and losses reach the adaptive calibration ledger. -Build 58 also allocates the 300 pending observation slots by evidence coverage. +Build 59 also allocates the 300 pending observation slots by evidence coverage. Under-sampled signal/side/category cohorts are observed first, followed by under-sampled independent events and market sides, with conviction used only as a later tie-breaker. This prevents the same popular contracts from monopolizing diff --git a/api/_db.js b/api/_db.js index 62ea69e..9d51fea 100644 --- a/api/_db.js +++ b/api/_db.js @@ -19,9 +19,8 @@ export function normalizeDatabaseUrl(raw) { export function databaseUrls() { const candidates = [process.env.DATABASE_URL, process.env.NEON_DATABASE_URL] .map(normalizeDatabaseUrl).filter(Boolean); - const ordered = [...candidates.filter(value => /^postgres(?:ql)?:\/\//i.test(value)), - ...candidates.filter(value => !/^postgres(?:ql)?:\/\//i.test(value))]; - return [...new Set(ordered)]; + const valid = candidates.filter(value => /^postgres(?:ql)?:\/\//i.test(value)); + return [...new Set(valid.length ? valid : candidates)]; } export function databaseUrl() { diff --git a/api/state.js b/api/state.js index 75e58db..d3eb0ea 100644 --- a/api/state.js +++ b/api/state.js @@ -19,7 +19,13 @@ function withBlobAuth(options = {}) { export function providerErrorCode(error) { if (!error) return "not_configured_or_not_attempted"; + const code = String(error.code || error.cause && error.cause.code || "").toUpperCase(); const message = String(error.message || error).toLowerCase(); + if (code === "28P01" || code === "28000") return "authorization_failed"; + if (code === "3D000") return "database_not_found"; + if (code.startsWith("08")) return "connection_failed"; + if (code === "ENOTFOUND" || code === "EAI_AGAIN") return "dns_failed"; + if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") return "timeout"; if (message.includes("invalid") && (message.includes("url") || message.includes("connection string"))) return "invalid_connection_string"; if (message.includes("password authentication") || message.includes("unauthorized") || /\b(?:401|403)\b/.test(message)) return "authorization_failed"; if (message.includes("enotfound") || message.includes("getaddrinfo") || message.includes("dns")) return "dns_failed"; diff --git a/index.html b/index.html index 143d12c..7aceaae 100644 --- a/index.html +++ b/index.html @@ -341,7 +341,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color