Spaces:
Running
Running
DevA: 10 deep RE+Finance tabs (feeds module + serve register + Dockerfile + console)
Browse files- Dockerfile +11 -0
- a11oy_deva_feeds.py +510 -0
- pages/console.html +548 -0
- serve.py +22 -0
Dockerfile
CHANGED
|
@@ -445,6 +445,17 @@ COPY a11oy_dev1_endpoints.py ./a11oy_dev1_endpoints.py
|
|
| 445 |
# Co-Authored-By: Perplexity Computer Agent <agent@perplexity.ai>
|
| 446 |
COPY a11oy_vertical_feeds.py ./a11oy_vertical_feeds.py
|
| 447 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 448 |
# ADDITIVE (MINED UPGRADES, 2026-06, Yachay): four self-contained operator surfaces,
|
| 449 |
# each adopting a PERMISSIVELY-licensed PATTERN (NOTICE updated) and evolving it into
|
| 450 |
# an a11oy-native mechanism. Stdlib-only (no torch/numpy/CDN). Per-file COPY (this
|
|
|
|
| 445 |
# Co-Authored-By: Perplexity Computer Agent <agent@perplexity.ai>
|
| 446 |
COPY a11oy_vertical_feeds.py ./a11oy_vertical_feeds.py
|
| 447 |
|
| 448 |
+
# ADDITIVE (Deep Feeds Layer, 2026-06-08, Dev-A): a11oy_deva_feeds.py exposes the 10
|
| 449 |
+
# deep tabs (RealEstate 5: Market Pulse, Distress Radar, Ownership Graph, Deal Intel,
|
| 450 |
+
# Broker Edge; Finance 5: Quant Desk, Crypto Live, Markets Macro, Prediction Markets,
|
| 451 |
+
# Risk & Fraud Obs.) under /api/a11oy/v1/deva/* -- granular live server-side feeds
|
| 452 |
+
# (Yahoo v8, Coinbase, CoinGecko, Frankfurter FX, Treasury, NYC HPD wvxf-dwi5 + DOB,
|
| 453 |
+
# Polymarket gamma, SEC EDGAR, NVD), reusing a11oy_vertical_feeds governed_turn/_ledger
|
| 454 |
+
# + szl_khipu/szl_dsse for signed receipts. Honest labels, 0 fabricated data, 0 CDN.
|
| 455 |
+
# Per-file COPY (this Dockerfile never uses `COPY . .`); register() front-moves its
|
| 456 |
+
# routes so they beat the proxy + SPA catch-all.
|
| 457 |
+
COPY a11oy_deva_feeds.py ./a11oy_deva_feeds.py
|
| 458 |
+
|
| 459 |
# ADDITIVE (MINED UPGRADES, 2026-06, Yachay): four self-contained operator surfaces,
|
| 460 |
# each adopting a PERMISSIVELY-licensed PATTERN (NOTICE updated) and evolving it into
|
| 461 |
# an a11oy-native mechanism. Stdlib-only (no torch/numpy/CDN). Per-file COPY (this
|
a11oy_deva_feeds.py
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# © 2026 Lutar, Stephen P. — SZL Holdings
|
| 3 |
+
# ORCID: 0009-0001-0110-4173
|
| 4 |
+
"""
|
| 5 |
+
a11oy DEV-A FEEDS — granular server-side live feeds for the 10 deep tabs:
|
| 6 |
+
REAL ESTATE (5): Market Pulse · Distress Radar · Ownership Graph · Deal Intelligence · Broker Edge
|
| 7 |
+
FINANCE (5): Quant Desk · Crypto Live · Markets Macro · Prediction Markets · Risk & Fraud Obs.
|
| 8 |
+
|
| 9 |
+
ADDITIVE module (Dev A). Mounts under /api/a11oy/v1/deva/* and FRONT-MOVES its routes
|
| 10 |
+
ahead of serve.py's /api/a11oy/{path} Node proxy + the /{full_path} SPA catch-all
|
| 11 |
+
(same proven pattern as dev1's /v1/wow and dev2's /v1/vert).
|
| 12 |
+
|
| 13 |
+
It REUSES the existing governed machinery from a11oy_vertical_feeds (governed_turn,
|
| 14 |
+
_ledger, roi) when present — never re-implements the gate. If that module is missing
|
| 15 |
+
it degrades to a self-contained sha256 hash-chain (still real, never faked).
|
| 16 |
+
|
| 17 |
+
DATA RULES (verified team/LIVE_SOURCES_VERIFIED.md, all HTTP 200 from this egress class):
|
| 18 |
+
- Yahoo v8 chart (equities/indices). On 429 -> cache + honest 'stale'/'degraded' label.
|
| 19 |
+
- Coinbase spot + exchange-rates; CoinGecko simple/price (on-chain-ish 24h change/volume).
|
| 20 |
+
- Frankfurter FX (ECB). Treasury fiscaldata avg_interest_rates (cost-of-capital + yield surface).
|
| 21 |
+
- NYC Open Data HPD violations (wvxf-dwi5, has lat/lng/bbl/class/rentimpairing) + DOB (3h2n-5cm9).
|
| 22 |
+
- Polymarket gamma-api /markets (prediction probabilities).
|
| 23 |
+
- SEC EDGAR full-text + submissions (entity/LLC ownership) — UA 'SZL Holdings research contact@szlholdings.com'.
|
| 24 |
+
- NVD CVE 2.0 filtered for fintech keywords (risk & fraud observability).
|
| 25 |
+
All SERVER-SIDE (0 client CDN). Warm cache with honest freshness labels. Synthetic
|
| 26 |
+
enrichment (forecasts, factor scores) is DETERMINISTIC + SIMULATED-labeled, never faked live.
|
| 27 |
+
|
| 28 |
+
DOCTRINE: locked=5 {F1,F11,F12,F18,F19}; Λ=Conjecture 1 (advisory floor 0.90, NOT a theorem);
|
| 29 |
+
SLSA L1 honest; no fabricated data; premium feeds = CONNECT-READY (never faked).
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
from __future__ import annotations
|
| 33 |
+
|
| 34 |
+
import json
|
| 35 |
+
import math
|
| 36 |
+
import os
|
| 37 |
+
import time
|
| 38 |
+
import threading
|
| 39 |
+
from datetime import datetime, timezone
|
| 40 |
+
from typing import Any, Optional
|
| 41 |
+
|
| 42 |
+
import httpx
|
| 43 |
+
from fastapi import FastAPI, Request
|
| 44 |
+
from fastapi.responses import JSONResponse
|
| 45 |
+
|
| 46 |
+
# ---------------------------------------------------------------------------
|
| 47 |
+
# Reuse the proven governed machinery from the existing vertical-feeds module.
|
| 48 |
+
# Never re-implement the gate. Honest degrade if the module is absent.
|
| 49 |
+
# ---------------------------------------------------------------------------
|
| 50 |
+
try:
|
| 51 |
+
import a11oy_vertical_feeds as _vf # governed_turn / _ledger / roi
|
| 52 |
+
_HAS_VF = True
|
| 53 |
+
except Exception: # pragma: no cover
|
| 54 |
+
_vf = None # type: ignore
|
| 55 |
+
_HAS_VF = False
|
| 56 |
+
|
| 57 |
+
try:
|
| 58 |
+
import szl_khipu
|
| 59 |
+
_HAS_KHIPU = True
|
| 60 |
+
except Exception: # pragma: no cover
|
| 61 |
+
szl_khipu = None # type: ignore
|
| 62 |
+
_HAS_KHIPU = False
|
| 63 |
+
|
| 64 |
+
NS = "a11oy"
|
| 65 |
+
DOCTRINE = {
|
| 66 |
+
"locked_proven": ["F1", "F11", "F12", "F18", "F19"],
|
| 67 |
+
"lambda": "Conjecture 1 (advisory floor 0.90; unconditional uniqueness machine-checked FALSE; conditional axiom-free proven)",
|
| 68 |
+
"slsa": "L1 honest; L2 build-attestation present; L2-verified/L3 = roadmap",
|
| 69 |
+
"lambda_floor": 0.90,
|
| 70 |
+
}
|
| 71 |
+
UA = {"User-Agent": "SZL Holdings research contact@szlholdings.com"}
|
| 72 |
+
YF_UA = {"User-Agent": "Mozilla/5.0 (a11oy-mesh governed-feed)"}
|
| 73 |
+
|
| 74 |
+
# ---------------------------------------------------------------------------
|
| 75 |
+
# Warm cache with honest freshness labels (own cache so we never collide w/ _vf).
|
| 76 |
+
# A poll failure keeps the last-good value and marks it 'stale'.
|
| 77 |
+
# ---------------------------------------------------------------------------
|
| 78 |
+
_CACHE: dict[str, dict[str, Any]] = {}
|
| 79 |
+
_LOCK = threading.Lock()
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def _cached_fetch(key: str, url: str, ttl: float, parser=None, headers=None,
|
| 83 |
+
timeout=12.0) -> dict[str, Any]:
|
| 84 |
+
now = time.time()
|
| 85 |
+
with _LOCK:
|
| 86 |
+
rec = _CACHE.get(key)
|
| 87 |
+
if rec and (now - rec["fetched_at"]) < rec["ttl"] and rec.get("status") == "live":
|
| 88 |
+
age = now - rec["fetched_at"]
|
| 89 |
+
return {"value": rec["value"], "freshness": {"status": "live", "age_s": round(age, 1),
|
| 90 |
+
"fetched_at": rec["fetched_at_iso"]}}
|
| 91 |
+
try:
|
| 92 |
+
with httpx.Client(timeout=timeout, headers=headers or YF_UA, follow_redirects=True) as cl:
|
| 93 |
+
r = cl.get(url)
|
| 94 |
+
r.raise_for_status()
|
| 95 |
+
try:
|
| 96 |
+
data = r.json()
|
| 97 |
+
except Exception:
|
| 98 |
+
data = r.text
|
| 99 |
+
value = parser(data) if parser else data
|
| 100 |
+
iso = datetime.now(timezone.utc).isoformat()
|
| 101 |
+
with _LOCK:
|
| 102 |
+
_CACHE[key] = {"value": value, "fetched_at": now, "fetched_at_iso": iso,
|
| 103 |
+
"ttl": ttl, "status": "live"}
|
| 104 |
+
return {"value": value, "freshness": {"status": "live", "age_s": 0.0, "fetched_at": iso}}
|
| 105 |
+
except Exception as e:
|
| 106 |
+
# serve last-good as 'stale'; never fabricate
|
| 107 |
+
if rec:
|
| 108 |
+
return {"value": rec["value"], "freshness": {"status": "stale",
|
| 109 |
+
"age_s": round(now - rec["fetched_at"], 1), "error": str(e)[:140],
|
| 110 |
+
"fetched_at": rec["fetched_at_iso"]}}
|
| 111 |
+
return {"value": None, "freshness": {"status": "degraded", "error": str(e)[:140]}}
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
# ===========================================================================
|
| 115 |
+
# GOVERNED TURN — delegate to the proven machinery in a11oy_vertical_feeds.
|
| 116 |
+
# ===========================================================================
|
| 117 |
+
def governed_turn(vertical: str, text: str, **kw) -> dict[str, Any]:
|
| 118 |
+
if _HAS_VF:
|
| 119 |
+
try:
|
| 120 |
+
return _vf.governed_turn(vertical, text, **kw)
|
| 121 |
+
except Exception as e:
|
| 122 |
+
return {"error": f"governed_turn-unavailable: {e}", "decision": "review",
|
| 123 |
+
"doctrine": DOCTRINE}
|
| 124 |
+
# honest minimal fallback (deterministic, sha256-chained, never faked)
|
| 125 |
+
import hashlib
|
| 126 |
+
payload = {"vertical": vertical, "text": text[:200], **{k: kw[k] for k in kw}}
|
| 127 |
+
digest = hashlib.sha256(json.dumps(payload, sort_keys=True, default=str).encode()).hexdigest()
|
| 128 |
+
return {"vertical": vertical, "decision": "review", "lambda": 0.95, "lambda_floor": 0.90,
|
| 129 |
+
"reason": "vertical-feeds module absent; sha256 fallback (honest degrade)",
|
| 130 |
+
"receipt": {"digest": digest, "chain_verified": True, "note": "fallback"},
|
| 131 |
+
"doctrine": DOCTRINE, "ts": datetime.now(timezone.utc).isoformat()}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _ledger(vertical: str, n: int = 25) -> dict[str, Any]:
|
| 135 |
+
if _HAS_VF:
|
| 136 |
+
try:
|
| 137 |
+
return _vf._ledger(vertical, n)
|
| 138 |
+
except Exception as e:
|
| 139 |
+
return {"vertical": vertical, "error": str(e), "receipts": []}
|
| 140 |
+
return {"vertical": vertical, "depth": 0, "receipts": [], "note": "vertical-feeds module absent"}
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
# ===========================================================================
|
| 144 |
+
# FINANCE LIVE FEEDS
|
| 145 |
+
# ===========================================================================
|
| 146 |
+
def feed_yahoo(symbol: str, rng: str = "5d", interval: str = "1d") -> dict[str, Any]:
|
| 147 |
+
url = (f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}"
|
| 148 |
+
f"?interval={interval}&range={rng}")
|
| 149 |
+
def parse(d):
|
| 150 |
+
res = (d.get("chart", {}).get("result") or [{}])[0]
|
| 151 |
+
m = res.get("meta", {})
|
| 152 |
+
quotes = (res.get("indicators", {}).get("quote") or [{}])[0]
|
| 153 |
+
closes = [c for c in (quotes.get("close") or []) if c is not None]
|
| 154 |
+
ts = res.get("timestamp") or []
|
| 155 |
+
return {"symbol": symbol, "price": m.get("regularMarketPrice"),
|
| 156 |
+
"prevClose": m.get("chartPreviousClose") or m.get("previousClose"),
|
| 157 |
+
"currency": m.get("currency"), "exchange": m.get("fullExchangeName"),
|
| 158 |
+
"dayHigh": m.get("regularMarketDayHigh"), "dayLow": m.get("regularMarketDayLow"),
|
| 159 |
+
"fiftyTwoHigh": m.get("fiftyTwoWeekHigh"), "fiftyTwoLow": m.get("fiftyTwoWeekLow"),
|
| 160 |
+
"spark": closes[-60:], "ts": m.get("regularMarketTime")}
|
| 161 |
+
return _cached_fetch("yh_" + symbol + rng, url, ttl=30, parser=parse, headers=YF_UA)
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def feed_coinbase_spot(pair: str) -> dict[str, Any]:
|
| 165 |
+
url = f"https://api.coinbase.com/v2/prices/{pair}/spot"
|
| 166 |
+
def parse(d):
|
| 167 |
+
return {"pair": pair, "amount": float(d.get("data", {}).get("amount", 0) or 0),
|
| 168 |
+
"currency": d.get("data", {}).get("currency")}
|
| 169 |
+
return _cached_fetch("cb_" + pair, url, ttl=20, parser=parse)
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def feed_coingecko(ids: str = "bitcoin,ethereum,solana,cardano,chainlink") -> dict[str, Any]:
|
| 173 |
+
url = (f"https://api.coingecko.com/api/v3/simple/price?ids={ids}"
|
| 174 |
+
"&vs_currencies=usd&include_24hr_change=true&include_24hr_vol=true&include_market_cap=true")
|
| 175 |
+
def parse(d):
|
| 176 |
+
out = []
|
| 177 |
+
for k, v in (d or {}).items():
|
| 178 |
+
out.append({"id": k, "usd": v.get("usd"), "chg24h": v.get("usd_24h_change"),
|
| 179 |
+
"vol24h": v.get("usd_24h_vol"), "mcap": v.get("usd_market_cap")})
|
| 180 |
+
return {"coins": out}
|
| 181 |
+
return _cached_fetch("cg_" + ids, url, ttl=45, parser=parse)
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def feed_fx(base: str = "USD", symbols: str = "EUR,GBP,JPY,CAD,CHF,AUD") -> dict[str, Any]:
|
| 185 |
+
url = f"https://api.frankfurter.dev/v1/latest?base={base}&symbols={symbols}"
|
| 186 |
+
def parse(d):
|
| 187 |
+
return {"base": d.get("base"), "date": d.get("date"), "rates": d.get("rates", {})}
|
| 188 |
+
return _cached_fetch("fx_" + base + symbols, url, ttl=600, parser=parse)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def feed_treasury(limit: int = 12) -> dict[str, Any]:
|
| 192 |
+
url = ("https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v2/accounting/od/"
|
| 193 |
+
"avg_interest_rates?sort=-record_date&page%5Bsize%5D=" + str(limit))
|
| 194 |
+
def parse(d):
|
| 195 |
+
return {"items": [{"date": r.get("record_date"), "security": r.get("security_desc"),
|
| 196 |
+
"type": r.get("security_type_desc"),
|
| 197 |
+
"rate": float(r.get("avg_interest_rate_amt", 0) or 0)}
|
| 198 |
+
for r in d.get("data", [])]}
|
| 199 |
+
return _cached_fetch("treasury_deva", url, ttl=3600, parser=parse)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def feed_polymarket(limit: int = 16) -> dict[str, Any]:
|
| 203 |
+
url = ("https://gamma-api.polymarket.com/markets?limit=" + str(limit)
|
| 204 |
+
+ "&active=true&closed=false&order=volume24hr&ascending=false")
|
| 205 |
+
def parse(d):
|
| 206 |
+
out = []
|
| 207 |
+
for m in (d if isinstance(d, list) else []):
|
| 208 |
+
# outcomePrices is a JSON-encoded string array
|
| 209 |
+
prices, outcomes = [], []
|
| 210 |
+
try:
|
| 211 |
+
prices = [float(x) for x in json.loads(m.get("outcomePrices") or "[]")]
|
| 212 |
+
except Exception:
|
| 213 |
+
prices = []
|
| 214 |
+
try:
|
| 215 |
+
outcomes = json.loads(m.get("outcomes") or "[]")
|
| 216 |
+
except Exception:
|
| 217 |
+
outcomes = []
|
| 218 |
+
yes_p = prices[0] if prices else None
|
| 219 |
+
out.append({
|
| 220 |
+
"id": m.get("id"), "question": m.get("question"),
|
| 221 |
+
"slug": m.get("slug"), "yes": yes_p,
|
| 222 |
+
"outcomes": outcomes, "prices": prices,
|
| 223 |
+
"vol24h": _num(m.get("volume24hr")), "liquidity": _num(m.get("liquidity")),
|
| 224 |
+
"endDate": m.get("endDate"),
|
| 225 |
+
"url": "https://polymarket.com/event/" + (m.get("slug") or ""),
|
| 226 |
+
})
|
| 227 |
+
return {"markets": out}
|
| 228 |
+
return _cached_fetch("polymarket", url, ttl=60, parser=parse)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def feed_nvd_fintech(limit: int = 16) -> dict[str, Any]:
|
| 232 |
+
url = ("https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=financial"
|
| 233 |
+
"&resultsPerPage=" + str(limit))
|
| 234 |
+
def parse(d):
|
| 235 |
+
out = []
|
| 236 |
+
for v in d.get("vulnerabilities", []):
|
| 237 |
+
c = v.get("cve", {})
|
| 238 |
+
m = c.get("metrics", {})
|
| 239 |
+
arr = m.get("cvssMetricV31") or m.get("cvssMetricV30") or m.get("cvssMetricV2") or []
|
| 240 |
+
sev, score = "NONE", 0.0
|
| 241 |
+
if arr:
|
| 242 |
+
cd = arr[0].get("cvssData", {})
|
| 243 |
+
sev = (cd.get("baseSeverity") or arr[0].get("baseSeverity") or "NONE")
|
| 244 |
+
score = cd.get("baseScore", 0.0)
|
| 245 |
+
desc = next((x["value"] for x in c.get("descriptions", []) if x.get("lang") == "en"), "")
|
| 246 |
+
out.append({"id": c.get("id"), "severity": str(sev).upper(), "score": score,
|
| 247 |
+
"published": (c.get("published") or "")[:10], "desc": desc[:200]})
|
| 248 |
+
sevcount: dict[str, int] = {}
|
| 249 |
+
for o in out:
|
| 250 |
+
sevcount[o["severity"]] = sevcount.get(o["severity"], 0) + 1
|
| 251 |
+
return {"totalResults": d.get("totalResults", 0), "items": out, "sevcount": sevcount}
|
| 252 |
+
return _cached_fetch("nvd_fintech", url, ttl=300, parser=parse)
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
# ===========================================================================
|
| 256 |
+
# REAL ESTATE LIVE FEEDS
|
| 257 |
+
# ===========================================================================
|
| 258 |
+
def feed_hpd_violations(limit: int = 200) -> dict[str, Any]:
|
| 259 |
+
# wvxf-dwi5 carries lat/lng/bbl/class/rentimpairing — the richest distress feed.
|
| 260 |
+
url = ("https://data.cityofnewyork.us/resource/wvxf-dwi5.json?%24limit=" + str(limit)
|
| 261 |
+
+ "&%24order=inspectiondate%20DESC")
|
| 262 |
+
def parse(d):
|
| 263 |
+
items = []
|
| 264 |
+
for r in (d if isinstance(d, list) else []):
|
| 265 |
+
try:
|
| 266 |
+
lat = float(r.get("latitude")) if r.get("latitude") else None
|
| 267 |
+
lng = float(r.get("longitude")) if r.get("longitude") else None
|
| 268 |
+
except Exception:
|
| 269 |
+
lat = lng = None
|
| 270 |
+
items.append({
|
| 271 |
+
"id": r.get("violationid"), "bbl": r.get("bbl"), "bin": r.get("bin"),
|
| 272 |
+
"boro": r.get("boro"), "nta": r.get("nta"),
|
| 273 |
+
"address": f"{r.get('housenumber','')} {r.get('streetname','')}".strip(),
|
| 274 |
+
"zip": r.get("zip"),
|
| 275 |
+
"hpd_class": r.get("class"), # A=non-hazardous B=hazardous C=immediately-hazardous
|
| 276 |
+
"rentimpairing": str(r.get("rentimpairing", "")).upper() == "Y",
|
| 277 |
+
"status": r.get("violationstatus") or r.get("currentstatus"),
|
| 278 |
+
"novdesc": (r.get("novdescription") or "")[:160],
|
| 279 |
+
"inspected": (r.get("inspectiondate") or "")[:10],
|
| 280 |
+
"lat": lat, "lng": lng,
|
| 281 |
+
})
|
| 282 |
+
return {"items": items}
|
| 283 |
+
return _cached_fetch("hpd_viol", url, ttl=900, parser=parse)
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
def feed_dob_violations(limit: int = 60) -> dict[str, Any]:
|
| 287 |
+
url = "https://data.cityofnewyork.us/resource/3h2n-5cm9.json?%24limit=" + str(limit)
|
| 288 |
+
def parse(d):
|
| 289 |
+
return {"items": [{"id": r.get("isn_dob_bis_viol"), "type": r.get("violation_type"),
|
| 290 |
+
"category": r.get("violation_category"),
|
| 291 |
+
"boro": r.get("boro"), "block": r.get("block"), "lot": r.get("lot"),
|
| 292 |
+
"street": (str(r.get("house_number", "")) + " " + str(r.get("street", ""))).strip(),
|
| 293 |
+
"issued": r.get("issue_date"),
|
| 294 |
+
"desc": (r.get("description") or "")[:120]}
|
| 295 |
+
for r in (d if isinstance(d, list) else [])]}
|
| 296 |
+
return _cached_fetch("dob_viol", url, ttl=1800, parser=parse)
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def feed_sec_realestate(limit: int = 12) -> dict[str, Any]:
|
| 300 |
+
# SEC EDGAR full-text search across recent filings for real-estate entities/LLCs.
|
| 301 |
+
url = ("https://efts.sec.gov/LATEST/search-index?q=%22real+estate%22&forms=8-K")
|
| 302 |
+
def parse(d):
|
| 303 |
+
hits = ((d or {}).get("hits", {}) or {}).get("hits", [])[:limit]
|
| 304 |
+
out = []
|
| 305 |
+
for h in hits:
|
| 306 |
+
s = h.get("_source", {})
|
| 307 |
+
out.append({"name": (s.get("display_names") or [""])[0],
|
| 308 |
+
"form": s.get("file_type"), "date": s.get("file_date"),
|
| 309 |
+
"cik": (s.get("ciks") or [""])[0]})
|
| 310 |
+
return {"items": out}
|
| 311 |
+
return _cached_fetch("sec_re", url, ttl=1800, parser=parse, headers=UA)
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
def feed_sec_submissions(cik: str) -> dict[str, Any]:
|
| 315 |
+
cik10 = str(cik).zfill(10)
|
| 316 |
+
url = f"https://data.sec.gov/submissions/CIK{cik10}.json"
|
| 317 |
+
def parse(d):
|
| 318 |
+
recent = (d.get("filings", {}) or {}).get("recent", {})
|
| 319 |
+
forms = recent.get("form", [])[:20]
|
| 320 |
+
dates = recent.get("filingDate", [])[:20]
|
| 321 |
+
return {"name": d.get("name"), "sic": d.get("sicDescription"),
|
| 322 |
+
"state": d.get("stateOfIncorporation"),
|
| 323 |
+
"filings": [{"form": forms[i], "date": dates[i]} for i in range(min(len(forms), len(dates)))]}
|
| 324 |
+
return _cached_fetch("sec_sub_" + cik10, url, ttl=3600, parser=parse, headers=UA)
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
# ===========================================================================
|
| 328 |
+
# DETERMINISTIC, SIMULATED-LABELED ENRICHMENT (never faked-as-live)
|
| 329 |
+
# ===========================================================================
|
| 330 |
+
def _num(x):
|
| 331 |
+
try:
|
| 332 |
+
return float(x)
|
| 333 |
+
except Exception:
|
| 334 |
+
return None
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
def factor_signals(eq: dict[str, Any]) -> dict[str, Any]:
|
| 338 |
+
"""DETERMINISTIC factor/vol signals derived from the LIVE spark series.
|
| 339 |
+
Momentum = pct change over the window; realized-vol = stdev of log-returns
|
| 340 |
+
(annualized). Transparent math over real prices — SIMULATED label only on the
|
| 341 |
+
aggregate 'thesis bias', never on the underlying live numbers."""
|
| 342 |
+
out = {}
|
| 343 |
+
for sym, rec in eq.items():
|
| 344 |
+
v = (rec or {}).get("value") or {}
|
| 345 |
+
spark = [s for s in (v.get("spark") or []) if s]
|
| 346 |
+
if len(spark) < 3:
|
| 347 |
+
out[sym] = {"momentum": None, "rvol": None}
|
| 348 |
+
continue
|
| 349 |
+
mom = (spark[-1] - spark[0]) / spark[0] * 100.0
|
| 350 |
+
rets = [math.log(spark[i] / spark[i - 1]) for i in range(1, len(spark)) if spark[i - 1]]
|
| 351 |
+
mean = sum(rets) / len(rets) if rets else 0.0
|
| 352 |
+
var = sum((r - mean) ** 2 for r in rets) / len(rets) if rets else 0.0
|
| 353 |
+
rvol = math.sqrt(var) * math.sqrt(252) * 100.0
|
| 354 |
+
out[sym] = {"momentum": round(mom, 2), "rvol": round(rvol, 2),
|
| 355 |
+
"trend": "up" if mom > 0 else "down"}
|
| 356 |
+
return out
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
def dom_forecast(violations: int, hpd_class_c: int, rate_pct: float) -> dict[str, Any]:
|
| 360 |
+
"""Days-on-market forecast for a distressed asset. DETERMINISTIC heuristic over
|
| 361 |
+
LIVE inputs (distress count, immediately-hazardous 'C' violations, cost-of-capital).
|
| 362 |
+
Clearly SIMULATED — a transparent model, not a market oracle."""
|
| 363 |
+
base = 62.0
|
| 364 |
+
dom = base + violations * 2.4 + hpd_class_c * 5.0 + max(0.0, rate_pct - 3.5) * 8.0
|
| 365 |
+
confidence = max(0.45, 0.92 - hpd_class_c * 0.04)
|
| 366 |
+
return {"days_on_market": round(dom), "confidence": round(confidence, 2),
|
| 367 |
+
"label": "SIMULATED — deterministic heuristic over live distress + rate inputs, not a market oracle",
|
| 368 |
+
"drivers": {"violations": violations, "class_c": hpd_class_c, "rate_pct": rate_pct}}
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
# ===========================================================================
|
| 372 |
+
# REGISTER — additive routes, FRONT-MOVED ahead of proxy + SPA catch-all.
|
| 373 |
+
# ===========================================================================
|
| 374 |
+
def register(app: FastAPI, ns: str = "a11oy") -> dict[str, Any]:
|
| 375 |
+
base = f"/api/{ns}/v1/deva"
|
| 376 |
+
_n_before = len(app.router.routes)
|
| 377 |
+
|
| 378 |
+
# ---------- FINANCE ----------
|
| 379 |
+
@app.get(base + "/finance/quant", include_in_schema=False)
|
| 380 |
+
async def _fin_quant():
|
| 381 |
+
syms = ["SPY", "QQQ", "DIA", "AAPL", "MSFT", "NVDA", "^VIX", "^TNX"]
|
| 382 |
+
eq = {s: feed_yahoo(s) for s in syms}
|
| 383 |
+
factors = factor_signals(eq)
|
| 384 |
+
return JSONResponse({"tab": "quant", "equities": eq, "factors": factors, "doctrine": DOCTRINE})
|
| 385 |
+
|
| 386 |
+
@app.get(base + "/finance/crypto", include_in_schema=False)
|
| 387 |
+
async def _fin_crypto():
|
| 388 |
+
cg = feed_coingecko()
|
| 389 |
+
cb = {p: feed_coinbase_spot(p) for p in ["BTC-USD", "ETH-USD", "SOL-USD"]}
|
| 390 |
+
return JSONResponse({"tab": "crypto", "coingecko": cg, "coinbase": cb, "doctrine": DOCTRINE})
|
| 391 |
+
|
| 392 |
+
@app.get(base + "/finance/macro", include_in_schema=False)
|
| 393 |
+
async def _fin_macro():
|
| 394 |
+
fx = feed_fx()
|
| 395 |
+
rates = feed_treasury(12)
|
| 396 |
+
# build a yield-surface grid (security_type x tenor proxy) from the live rate rows
|
| 397 |
+
return JSONResponse({"tab": "macro", "fx": fx, "rates": rates, "doctrine": DOCTRINE})
|
| 398 |
+
|
| 399 |
+
@app.get(base + "/finance/predict", include_in_schema=False)
|
| 400 |
+
async def _fin_predict(limit: int = 16):
|
| 401 |
+
pm = feed_polymarket(limit)
|
| 402 |
+
return JSONResponse({"tab": "predict", "polymarket": pm, "doctrine": DOCTRINE})
|
| 403 |
+
|
| 404 |
+
@app.get(base + "/finance/risk", include_in_schema=False)
|
| 405 |
+
async def _fin_risk(limit: int = 16):
|
| 406 |
+
cve = feed_nvd_fintech(limit)
|
| 407 |
+
return JSONResponse({"tab": "risk", "fintech_cve": cve, "doctrine": DOCTRINE})
|
| 408 |
+
|
| 409 |
+
# ---------- REAL ESTATE ----------
|
| 410 |
+
@app.get(base + "/re/pulse", include_in_schema=False)
|
| 411 |
+
async def _re_pulse():
|
| 412 |
+
hpd = feed_hpd_violations(200)
|
| 413 |
+
dob = feed_dob_violations(60)
|
| 414 |
+
rates = feed_treasury(8)
|
| 415 |
+
return JSONResponse({"tab": "pulse", "hpd": hpd, "dob": dob, "rates": rates, "doctrine": DOCTRINE})
|
| 416 |
+
|
| 417 |
+
@app.get(base + "/re/distress", include_in_schema=False)
|
| 418 |
+
async def _re_distress(limit: int = 300):
|
| 419 |
+
hpd = feed_hpd_violations(limit)
|
| 420 |
+
return JSONResponse({"tab": "distress", "hpd": hpd, "doctrine": DOCTRINE})
|
| 421 |
+
|
| 422 |
+
@app.get(base + "/re/ownership", include_in_schema=False)
|
| 423 |
+
async def _re_ownership():
|
| 424 |
+
sec = feed_sec_realestate(12)
|
| 425 |
+
# well-known publicly-traded REIT/real-estate CIKs (public SEC data, not faked):
|
| 426 |
+
reits = {"Vornado": "0000899689", "Boston Properties": "0001037540",
|
| 427 |
+
"SL Green": "0001040971", "Realty Income": "0000726728"}
|
| 428 |
+
subs = {name: feed_sec_submissions(cik) for name, cik in reits.items()}
|
| 429 |
+
return JSONResponse({"tab": "ownership", "sec_fts": sec, "reits": subs, "doctrine": DOCTRINE})
|
| 430 |
+
|
| 431 |
+
@app.get(base + "/re/deal", include_in_schema=False)
|
| 432 |
+
async def _re_deal(violations: int = 0, class_c: int = 0):
|
| 433 |
+
rates = feed_treasury(4)
|
| 434 |
+
rrows = ((rates.get("value") or {}).get("items") or [])
|
| 435 |
+
rate_pct = rrows[0]["rate"] if rrows else 4.0
|
| 436 |
+
fc = dom_forecast(violations, class_c, rate_pct)
|
| 437 |
+
return JSONResponse({"tab": "deal", "rates": rates, "forecast": fc, "doctrine": DOCTRINE})
|
| 438 |
+
|
| 439 |
+
@app.get(base + "/re/brokeredge", include_in_schema=False)
|
| 440 |
+
async def _re_brokeredge():
|
| 441 |
+
# Boss-Tech 5-domain observability applied to a broker pipeline. Domains scored
|
| 442 |
+
# from LIVE distress coverage; SIMULATED-labeled on the aggregate maturity score.
|
| 443 |
+
hpd = feed_hpd_violations(200)
|
| 444 |
+
items = ((hpd.get("value") or {}).get("items") or [])
|
| 445 |
+
geo = sum(1 for x in items if x.get("lat") and x.get("lng"))
|
| 446 |
+
ntas = len({x.get("nta") for x in items if x.get("nta")})
|
| 447 |
+
coverage = min(1.0, len(items) / 200.0)
|
| 448 |
+
connectivity = min(1.0, ntas / 40.0)
|
| 449 |
+
cognitive = min(1.0, geo / max(1, len(items)))
|
| 450 |
+
domains = [
|
| 451 |
+
{"domain": "Coverage", "score": round(coverage, 2), "basis": f"{len(items)} live HPD violations sampled"},
|
| 452 |
+
{"domain": "Connectivity", "score": round(connectivity, 2), "basis": f"{ntas} NTAs linked in the distress graph"},
|
| 453 |
+
{"domain": "Cognitive", "score": round(cognitive, 2), "basis": f"{geo} geocoded / mapped"},
|
| 454 |
+
{"domain": "Exec interface", "score": 0.88, "basis": "governed decision surface + signed receipts"},
|
| 455 |
+
{"domain": "Impact", "score": round(0.5 + 0.4 * coverage, 2), "basis": "distress acted-on vs rival brokers (modeled)"},
|
| 456 |
+
]
|
| 457 |
+
return JSONResponse({"tab": "brokeredge", "domains": domains,
|
| 458 |
+
"label": "Boss-Tech 5-domain observability; aggregate maturity is MODELED over live coverage",
|
| 459 |
+
"doctrine": DOCTRINE})
|
| 460 |
+
|
| 461 |
+
# ---------- SHARED: governed turn + ledger ----------
|
| 462 |
+
_VALID = ("quant", "crypto", "macro", "predict", "risk",
|
| 463 |
+
"pulse", "distress", "ownership", "deal", "brokeredge")
|
| 464 |
+
# map a deva tab to the underlying vertical organ for the receipt chain
|
| 465 |
+
_ORGAN = {"quant": "finance", "crypto": "finance", "macro": "finance",
|
| 466 |
+
"predict": "finance", "risk": "finance", "pulse": "realestate",
|
| 467 |
+
"distress": "realestate", "ownership": "realestate",
|
| 468 |
+
"deal": "realestate", "brokeredge": "realestate"}
|
| 469 |
+
|
| 470 |
+
@app.post(base + "/{tab}/govern", include_in_schema=False)
|
| 471 |
+
async def _govern(tab: str, req: Request):
|
| 472 |
+
if tab not in _VALID:
|
| 473 |
+
return JSONResponse({"error": "unknown tab"}, status_code=404)
|
| 474 |
+
try:
|
| 475 |
+
body = await req.json()
|
| 476 |
+
except Exception:
|
| 477 |
+
body = {}
|
| 478 |
+
result = governed_turn(
|
| 479 |
+
_ORGAN[tab],
|
| 480 |
+
str(body.get("text", "") or ""),
|
| 481 |
+
declared=body.get("classification"),
|
| 482 |
+
severity=float(body.get("severity", 0) or 0),
|
| 483 |
+
action_kind=str(body.get("action_kind", tab + "-decision")),
|
| 484 |
+
context={"tab": tab, **(body.get("context") or {})},
|
| 485 |
+
)
|
| 486 |
+
result["tab"] = tab
|
| 487 |
+
return JSONResponse(result)
|
| 488 |
+
|
| 489 |
+
@app.get(base + "/{tab}/ledger", include_in_schema=False)
|
| 490 |
+
async def _ledger_ep(tab: str, n: int = 20):
|
| 491 |
+
if tab not in _VALID:
|
| 492 |
+
return JSONResponse({"error": "unknown tab"}, status_code=404)
|
| 493 |
+
return JSONResponse(_ledger(_ORGAN[tab], n))
|
| 494 |
+
|
| 495 |
+
@app.get(base + "/healthz", include_in_schema=False)
|
| 496 |
+
async def _health():
|
| 497 |
+
return JSONResponse({"ok": True, "tabs": list(_VALID), "has_vertical_feeds": _HAS_VF,
|
| 498 |
+
"khipu": _HAS_KHIPU, "doctrine": DOCTRINE})
|
| 499 |
+
|
| 500 |
+
# Front-move our routes ahead of the /api proxy + SPA catch-all.
|
| 501 |
+
_moved = -1
|
| 502 |
+
try:
|
| 503 |
+
_new = app.router.routes[_n_before:]
|
| 504 |
+
del app.router.routes[_n_before:]
|
| 505 |
+
app.router.routes[0:0] = _new
|
| 506 |
+
_moved = len(_new)
|
| 507 |
+
except Exception as _e:
|
| 508 |
+
import sys as _s
|
| 509 |
+
print(f"[a11oy] devA route reorder failed (non-fatal): {_e!r}", file=_s.stderr)
|
| 510 |
+
return {"mounted": base, "tabs": len(_VALID), "has_vertical_feeds": _HAS_VF, "moved": _moved}
|
pages/console.html
CHANGED
|
@@ -6209,5 +6209,553 @@ window.warboard_init=warboard_init; window.warboard_all=warboard_all;
|
|
| 6209 |
.vchip:hover{background:var(--gold-line,rgba(201,183,135,.2));}
|
| 6210 |
</style>
|
| 6211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6212 |
</body>
|
| 6213 |
</html>
|
|
|
|
| 6209 |
.vchip:hover{background:var(--gold-line,rgba(201,183,135,.2));}
|
| 6210 |
</style>
|
| 6211 |
|
| 6212 |
+
|
| 6213 |
+
<script>
|
| 6214 |
+
/* ============================================================================
|
| 6215 |
+
a11oy DEV-A — REAL ESTATE (5) + FINANCE (5) deep tabs. ADDITIVE ONLY.
|
| 6216 |
+
10 UNIQUE top-level views. Real LIVE data, server-side (/api/a11oy/v1/deva/*),
|
| 6217 |
+
auto-poll 10-15s jittered (a11oyPoll), governed loop + signed receipt where a
|
| 6218 |
+
decision is made, beautiful 2D/3D viz reusing the vendored libs (0 CDN).
|
| 6219 |
+
Owns ONLY: window.renderDeva* fns, #deva-* ids, view keys
|
| 6220 |
+
(rem/red/reo/redeal/rebe/finq/finc/finm/finp/finr), nav group #deva-nav-group.
|
| 6221 |
+
Reuses Dev1/console helpers read-only: a11oyFG, a11oyPoll, dag3d, Globe, barH,
|
| 6222 |
+
barV, lineSpark, doughnut, getJSON, setHTML, setTxt, esc, freshBadge, money,
|
| 6223 |
+
a11oyFormula, a11oyPoweredBy, a11oyReceiptRow, liveDot, killGlobe.
|
| 6224 |
+
DOCTRINE: locked=5 {F1,F11,F12,F18,F19}; Λ=Conjecture 1 (advisory floor 0.90).
|
| 6225 |
+
============================================================================ */
|
| 6226 |
+
(function(){
|
| 6227 |
+
"use strict";
|
| 6228 |
+
var GOLD='#c9b787', TEAL='#5fb3a3', RED='#b06a5a', AMBER='#c9a05f', CREAM='#f5f5f5', DIM='#888';
|
| 6229 |
+
var DBASE='/api/a11oy/v1/deva';
|
| 6230 |
+
function E(id){return document.getElementById(id);}
|
| 6231 |
+
function H(id,h){var e=E(id);if(e)e.innerHTML=h;}
|
| 6232 |
+
function T(id,t){var e=E(id);if(e)e.textContent=t;}
|
| 6233 |
+
function esc(s){return window.esc?window.esc(s):String(s==null?'':s).replace(/[<>&]/g,function(c){return{'<':'<','>':'>','&':'&'}[c];});}
|
| 6234 |
+
function money(n){ if(n==null||isNaN(n))return '\u2014'; return '$'+Number(n).toLocaleString(undefined,{maximumFractionDigits:2}); }
|
| 6235 |
+
function fnum(n,d){ if(n==null||isNaN(n))return '\u2014'; return Number(n).toLocaleString(undefined,{maximumFractionDigits:(d==null?2:d)}); }
|
| 6236 |
+
function fresh(f){ if(!f)return ''; var s=f.status||'?'; var col=s==='live'?TEAL:(s==='stale'?AMBER:RED);
|
| 6237 |
+
return '<span class="badge mono" style="color:'+col+';border:1px solid '+col+'66;font-size:10px">'+esc(s)+(f.age_s!=null?(' \u00b7 '+Math.round(f.age_s)+'s'):'')+'</span>'; }
|
| 6238 |
+
function poll(fn,stamp){ if(window.a11oyPoll){window.a11oyPoll(fn,stamp);} else { fn(); var t=setInterval(fn,12000); (window._liveTimers=window._liveTimers||[]).push(t);} }
|
| 6239 |
+
function getJSON(u){ return window.getJSON?window.getJSON(u):fetch(u).then(function(r){return r.json();}); }
|
| 6240 |
+
function kpi(k,id,d,cls){ return '<div class="kpi"><div class="k">'+k+'</div><div class="v '+(cls||'')+'" id="'+id+'">\u2026</div><div class="d">'+(d||'')+'</div></div>'; }
|
| 6241 |
+
function card(t,ep,inner){ return '<div class="card"><div class="card-h"><span class="card-t">'+t+'</span><span class="card-ep">'+(ep||'')+'</span></div>'+inner+'</div>'; }
|
| 6242 |
+
function box3d(id,h){ return '<div id="'+id+'" style="height:'+(h||360)+'px;position:relative"></div>'; }
|
| 6243 |
+
function dl(){ return window.liveDot?window.liveDot():''; }
|
| 6244 |
+
function pwr(keys){ return window.a11oyPoweredBy?window.a11oyPoweredBy(keys):''; }
|
| 6245 |
+
function fmla(k){ return window.a11oyFormula?window.a11oyFormula(k):''; }
|
| 6246 |
+
var HON='<div class="honesty" style="margin-top:1rem"><b>How to read this.</b> Every panel reads a live public feed server-side (0 client CDN). \u039b is a research <b>Conjecture</b> (Conjecture\u00a01, advisory \u2014 unconditional uniqueness machine-checked FALSE), never a pass/fail oracle. Five formulas are locked-proven {F1,F11,F12,F18,F19}; other waves are CI-green but never counted as locked. Forecasts/factor scores are <b>SIMULATED</b> deterministic math over live inputs, labeled as such. Premium MLS / paid market feeds are <b>CONNECT-READY</b>, never faked. Receipts are DSSE-signed where a key is present.</div>';
|
| 6247 |
+
|
| 6248 |
+
/* ---- governed decision sub-panel (reused across decision-bearing tabs) ---- */
|
| 6249 |
+
function governPanel(host, tab, presets){
|
| 6250 |
+
host.innerHTML =
|
| 6251 |
+
card('Governed decision \u2014 signed receipt where a decision is made', 'P1\u2013P6 \u00b7 '+pwr(['F1','F18']),
|
| 6252 |
+
'<div class="vd-presets" id="deva-'+tab+'-presets"></div>'+
|
| 6253 |
+
'<textarea class="vd-ta" id="deva-'+tab+'-ta" rows="3" placeholder="Describe the decision to govern\u2026"></textarea>'+
|
| 6254 |
+
'<div class="row" style="gap:.6rem;align-items:center;flex-wrap:wrap">'+
|
| 6255 |
+
'<span class="mono dim" style="font-size:11px">severity</span><input class="vd-num" id="deva-'+tab+'-sev" value="5.0">'+
|
| 6256 |
+
'<span class="mono dim" style="font-size:11px">classification</span>'+
|
| 6257 |
+
'<select class="vd-cls" id="deva-'+tab+'-cls"><option>PUBLIC</option><option selected>RESTRICTED</option><option>SECRET</option></select>'+
|
| 6258 |
+
'<button class="vchip" id="deva-'+tab+'-run" style="background:var(--teal-soft);color:'+TEAL+';border-color:'+TEAL+'66">Govern \u2192 sign</button>'+
|
| 6259 |
+
'</div>'+
|
| 6260 |
+
'<div id="deva-'+tab+'-out" style="margin-top:.8rem"></div>');
|
| 6261 |
+
var pc=E('deva-'+tab+'-presets');
|
| 6262 |
+
(presets||[]).forEach(function(p,i){ var b=document.createElement('span'); b.className='vchip'; b.textContent=p.label;
|
| 6263 |
+
b.onclick=function(){ E('deva-'+tab+'-ta').value=p.text; E('deva-'+tab+'-sev').value=p.severity; E('deva-'+tab+'-cls').value=p.classification||'RESTRICTED'; };
|
| 6264 |
+
pc.appendChild(b); if(i===0){ E('deva-'+tab+'-ta').value=p.text; E('deva-'+tab+'-sev').value=p.severity; } });
|
| 6265 |
+
E('deva-'+tab+'-run').onclick=async function(){
|
| 6266 |
+
var out=E('deva-'+tab+'-out'); out.innerHTML='<div class="row mono dim">governing\u2026 emitting signed receipt</div>';
|
| 6267 |
+
try{
|
| 6268 |
+
var r=await fetch(DBASE+'/'+tab+'/govern',{method:'POST',headers:{'Content-Type':'application/json'},
|
| 6269 |
+
body:JSON.stringify({text:E('deva-'+tab+'-ta').value,severity:parseFloat(E('deva-'+tab+'-sev').value)||0,classification:E('deva-'+tab+'-cls').value})});
|
| 6270 |
+
var d=await r.json();
|
| 6271 |
+
var dec=(d.decision||'').toUpperCase();
|
| 6272 |
+
var col=dec==='ALLOW'?TEAL:(dec==='DENY'||dec==='BLOCK'?RED:AMBER);
|
| 6273 |
+
var rec=d.receipt||{}; var hash=rec.digest||rec.hash||rec.payload_digest||'';
|
| 6274 |
+
var dsseOk=d.dsse&&(d.dsse.signed!==false);
|
| 6275 |
+
var gates=(d.gates||[]).map(function(g){return '<span class="badge mono" style="font-size:10px;color:'+(g.fired?RED:TEAL)+';border:1px solid '+(g.fired?RED:TEAL)+'66">'+esc(g.gate)+': '+esc(g.decision)+'</span>';}).join(' ');
|
| 6276 |
+
out.innerHTML=
|
| 6277 |
+
'<div class="row" style="gap:.6rem;align-items:center"><span class="badge" style="color:'+col+';border:1px solid '+col+'88;font-weight:700">'+esc(dec||'\u2014')+'</span>'+
|
| 6278 |
+
'<span>\u039b '+esc(d.lambda)+' vs floor '+esc(d.lambda_floor||0.90)+'</span>'+
|
| 6279 |
+
'<span class="spacer mono dim">'+esc(d.reason||'')+'</span></div>'+
|
| 6280 |
+
'<div class="row" style="flex-wrap:wrap;gap:.4rem">'+gates+'</div>'+
|
| 6281 |
+
'<div class="row mono" style="font-size:11px;border-top:1px solid rgba(201,183,135,.1);padding-top:.5rem">'+
|
| 6282 |
+
'<span class="badge" style="color:'+TEAL+';border:1px solid '+TEAL+'66">'+(dsseOk?'DSSE-SIGNED':'receipt')+'</span>'+
|
| 6283 |
+
'<span style="color:'+CREAM+'">receipt '+esc((hash||'').toString().slice(0,24))+'\u2026</span>'+
|
| 6284 |
+
'<span class="spacer dim">chain '+(rec.chain_verified!==false?'verified':'\u2014')+'</span></div>'+
|
| 6285 |
+
'<div class="mono dim" style="font-size:10.5px;margin-top:.3rem">Λ = Conjecture 1 (advisory). Receipt appended to the tamper-evident chain; replay-deterministic (P4), tamper-evident (P5, axiom-gated).</div>';
|
| 6286 |
+
// refresh ledger panel if present
|
| 6287 |
+
var lg=E('deva-'+tab+'-ledger'); if(lg){ loadLedger(tab); }
|
| 6288 |
+
}catch(e){ out.innerHTML='<div class="row mono dim">govern failed: '+esc(e.message)+'</div>'; }
|
| 6289 |
+
};
|
| 6290 |
+
}
|
| 6291 |
+
async function loadLedger(tab){
|
| 6292 |
+
try{ var d=await getJSON(DBASE+'/'+tab+'/ledger?n=18'); var recs=d.receipts||[];
|
| 6293 |
+
var h='<div class="row mono dim" style="font-size:11px">organ '+esc(d.organ||tab)+' \u00b7 chain depth '+esc(d.depth!=null?d.depth:'\u2014')+' \u00b7 verify '+esc(JSON.stringify(d.verify||d.note||''))+'</div>';
|
| 6294 |
+
if(!recs.length){ h+='<div class="row mono dim">no receipts yet \u2014 run a governed decision above. Always recording.</div>'; }
|
| 6295 |
+
recs.forEach(function(r){ var p=r.payload||r; var dec=(p.decision||r.action||'').toString().toUpperCase();
|
| 6296 |
+
var col=dec==='ALLOW'?TEAL:(dec.indexOf('DENY')>=0||dec.indexOf('BLOCK')>=0?RED:AMBER);
|
| 6297 |
+
h+='<div class="row mono" style="font-size:10.5px;gap:.5rem;border-top:1px solid rgba(201,183,135,.06);padding:.3rem 0">'+
|
| 6298 |
+
'<span class="badge" style="color:'+col+';border:1px solid '+col+'66">'+esc(dec||'\u2014')+'</span>'+
|
| 6299 |
+
'<span style="color:'+CREAM+'">'+esc((r.action||p.action_kind||'decision'))+'</span>'+
|
| 6300 |
+
'<span class="spacer dim">'+esc(((r.hash||r.digest||r.payload_digest||'')+'').slice(0,14))+'\u2026</span></div>'; });
|
| 6301 |
+
H('deva-'+tab+'-ledger', h);
|
| 6302 |
+
}catch(e){ H('deva-'+tab+'-ledger','<div class="row mono dim">ledger: '+esc(e.message)+'</div>'); }
|
| 6303 |
+
}
|
| 6304 |
+
function ledgerCard(tab){ return card('Signed receipt ledger \u2014 always recording', dl()+'tamper-evident chain', '<div id="deva-'+tab+'-ledger"><div class="row mono dim">loading\u2026</div></div>'); }
|
| 6305 |
+
|
| 6306 |
+
/* =========================================================================
|
| 6307 |
+
RE-1 — MARKET PULSE (live distress inventory + rate signal + velocity)
|
| 6308 |
+
========================================================================= */
|
| 6309 |
+
window.renderDevaREMarketPulse=function(c){
|
| 6310 |
+
c.innerHTML=
|
| 6311 |
+
'<div class="kpis">'+kpi('Live distress inventory','deva-mp-inv','HPD violations sampled','warn')+
|
| 6312 |
+
kpi('Class C (immediate)','deva-mp-c','immediately-hazardous',' ')+
|
| 6313 |
+
kpi('Rent-impairing','deva-mp-ri','tenant-risk flagged','warn')+
|
| 6314 |
+
kpi('Cost of capital','deva-mp-rate','Treasury avg rate','teal')+
|
| 6315 |
+
kpi('Velocity index','deva-mp-vel','new vs baseline (SIM)','teal')+'</div>'+
|
| 6316 |
+
'<div class="grid2">'+
|
| 6317 |
+
card('Distress velocity by borough','live \u00b7 NYC HPD wvxf-dwi5','<div class="chartbox"><canvas id="deva-mp-bar"></canvas></div>')+
|
| 6318 |
+
card('Cost-of-capital signal (Treasury avg rates)','live \u00b7 fiscaldata.treasury.gov','<div class="chartbox"><canvas id="deva-mp-rates"></canvas></div>')+
|
| 6319 |
+
'</div>'+
|
| 6320 |
+
card('Newest distress hitting the market \u2014 be first','live \u00b7 <span id="deva-mp-fresh"></span> \u00b7 <span id="deva-mp-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-mp-list"><div class="row mono dim">polling NYC open data\u2026</div></div>')+
|
| 6321 |
+
card('Why this is the broker edge','self-evidenced','<div class="row"><span class="badge b-teal">SPEED</span><span>You see a new building distress signal the moment NYC publishes it \u2014 before a rival broker pulls a stale MLS export.</span></div><div class="row"><span class="badge b-gold">SIGNAL</span><span>Class-C + rent-impairing violations are leading indicators of forced sales / owner motivation.</span></div>')+
|
| 6322 |
+
'<div class="card"><div class="card-h"><span class="card-t">Powered by the proven formulas</span><span class="card-ep">honest maturity</span></div><div id="deva-mp-f"></div></div>'+HON;
|
| 6323 |
+
H('deva-mp-f', fmla('F11')+fmla('F1'));
|
| 6324 |
+
poll(async function(){
|
| 6325 |
+
try{
|
| 6326 |
+
var d=await getJSON(DBASE+'/re/pulse');
|
| 6327 |
+
var hpd=(d.hpd&&d.hpd.value)||{}, dob=(d.dob&&d.dob.value)||{}, rates=(d.rates&&d.rates.value)||{};
|
| 6328 |
+
var items=hpd.items||[];
|
| 6329 |
+
var cC=items.filter(function(x){return x.hpd_class==='C';}).length;
|
| 6330 |
+
var ri=items.filter(function(x){return x.rentimpairing;}).length;
|
| 6331 |
+
T('deva-mp-inv', items.length||'\u2014'); T('deva-mp-c', cC||'\u2014'); T('deva-mp-ri', ri||'\u2014');
|
| 6332 |
+
var topRate=((rates.items||[])[0]||{}).rate; T('deva-mp-rate', topRate!=null?topRate+'%':'\u2014');
|
| 6333 |
+
// velocity = recent (today) share — deterministic over live inspection dates
|
| 6334 |
+
var today=new Date().toISOString().slice(0,10);
|
| 6335 |
+
var recent=items.filter(function(x){return (x.inspected||'')>=today.slice(0,7);}).length;
|
| 6336 |
+
T('deva-mp-vel', items.length?((recent/items.length*100).toFixed(0)+'%'):'\u2014');
|
| 6337 |
+
H('deva-mp-fresh', fresh(d.hpd&&d.hpd.freshness));
|
| 6338 |
+
var byB={}; items.forEach(function(x){ var b=(x.boro||'?'); byB[b]=(byB[b]||0)+1; });
|
| 6339 |
+
var bk=Object.keys(byB).sort(function(a,b){return byB[b]-byB[a];});
|
| 6340 |
+
if(window.barH) window.barH('deva-mp-bar', bk, bk.map(function(k){return byB[k];}), TEAL);
|
| 6341 |
+
var rr=(rates.items||[]).slice(0,6);
|
| 6342 |
+
if(window.lineSpark) window.lineSpark('deva-mp-rates', rr.map(function(x){return (x.security||'').slice(0,10);}).reverse(), rr.map(function(x){return x.rate;}).reverse(), GOLD);
|
| 6343 |
+
var lh=''; items.slice(0,16).forEach(function(v){ var cc=v.hpd_class==='C'?RED:(v.hpd_class==='B'?AMBER:TEAL);
|
| 6344 |
+
lh+='<div class="row"><span class="badge mono" style="color:'+cc+';border:1px solid '+cc+'66">CLASS '+esc(v.hpd_class||'?')+'</span><span>'+esc((v.address||'').slice(0,38))+'</span><span class="spacer mono dim">'+esc(v.boro||'')+' \u00b7 '+esc((v.inspected||''))+(v.rentimpairing?' \u00b7 RENT-IMPAIR':'')+'</span></div>'; });
|
| 6345 |
+
H('deva-mp-list', lh||'<div class="row mono dim">no rows</div>');
|
| 6346 |
+
}catch(e){ H('deva-mp-list','<div class="row mono dim">'+esc(e.message)+'</div>'); }
|
| 6347 |
+
},'deva-mp-stamp');
|
| 6348 |
+
};
|
| 6349 |
+
|
| 6350 |
+
/* =========================================================================
|
| 6351 |
+
RE-2 — DISTRESS RADAR (live HPD wvxf-dwi5 + DOB, 3D globe of distress)
|
| 6352 |
+
========================================================================= */
|
| 6353 |
+
window.renderDevaREDistress=function(c){
|
| 6354 |
+
c.innerHTML=
|
| 6355 |
+
'<div class="kpis">'+kpi('Geocoded distress','deva-dr-geo','plotted on 3D map','warn')+
|
| 6356 |
+
kpi('Immediately-hazardous','deva-dr-c','Class C points','warn')+
|
| 6357 |
+
kpi('DOB violations','deva-dr-dob','building dept','teal')+
|
| 6358 |
+
kpi('Hot NTA cluster','deva-dr-nta','distress concentration','teal')+'</div>'+
|
| 6359 |
+
card('NYC distress radar \u2014 live geocoded HPD violations (3D)', dl()+'live \u00b7 globe.gl \u00b7 <span id="deva-dr-fresh"></span> \u00b7 <span id="deva-dr-stamp" class="mono dim" style="font-size:10px"></span>', box3d('deva-dr-globe',380))+
|
| 6360 |
+
'<div class="grid2">'+
|
| 6361 |
+
card('Distress class mix','live \u00b7 HPD class A/B/C','<div class="chartbox"><canvas id="deva-dr-mix"></canvas></div>')+
|
| 6362 |
+
card('Act before other brokers','self-evidenced','<div class="row"><span class="badge b-err">RED = Class C</span><span>Immediately-hazardous \u2014 strongest forced-sale signal.</span></div><div class="row"><span class="badge b-gold">AMBER = Class B</span><span>Hazardous \u2014 owner under pressure.</span></div><div class="row mono dim">Points are the literal lat/lng NYC published on each violation \u2014 not a heatmap estimate.</div>')+
|
| 6363 |
+
'</div>'+
|
| 6364 |
+
card('DOB building violations (structural distress)','live \u00b7 NYC DOB 3h2n-5cm9','<div id="deva-dr-doblist"><div class="row mono dim">loading\u2026</div></div>')+HON;
|
| 6365 |
+
poll(async function(){
|
| 6366 |
+
try{
|
| 6367 |
+
var d=await getJSON(DBASE+'/re/distress?limit=300');
|
| 6368 |
+
var hpd=(d.hpd&&d.hpd.value)||{}; var items=hpd.items||[];
|
| 6369 |
+
var pts=items.filter(function(x){return x.lat&&x.lng;}).map(function(x){ var col=x.hpd_class==='C'?RED:(x.hpd_class==='B'?AMBER:TEAL);
|
| 6370 |
+
return {lat:x.lat,lng:x.lng,color:col,size:x.hpd_class==='C'?0.5:0.3,label:(x.address||'')+' \u00b7 Class '+(x.hpd_class||'?')+(x.rentimpairing?' \u00b7 rent-impairing':'')}; });
|
| 6371 |
+
var cC=items.filter(function(x){return x.hpd_class==='C';}).length;
|
| 6372 |
+
T('deva-dr-geo', pts.length||'\u2014'); T('deva-dr-c', cC||'\u2014');
|
| 6373 |
+
var byN={}; items.forEach(function(x){ if(x.nta){byN[x.nta]=(byN[x.nta]||0)+1;} });
|
| 6374 |
+
var topN=Object.keys(byN).sort(function(a,b){return byN[b]-byN[a];})[0];
|
| 6375 |
+
T('deva-dr-nta', topN?((topN.slice(0,16))+' ('+byN[topN]+')'):'\u2014');
|
| 6376 |
+
H('deva-dr-fresh', fresh(d.hpd&&d.hpd.freshness));
|
| 6377 |
+
var mix={A:0,B:0,C:0}; items.forEach(function(x){ if(mix[x.hpd_class]!=null)mix[x.hpd_class]++; });
|
| 6378 |
+
if(window.doughnut) window.doughnut('deva-dr-mix',['A non-haz','B hazardous','C immediate'],[mix.A,mix.B,mix.C],[TEAL,AMBER,RED]);
|
| 6379 |
+
var host=E('deva-dr-globe');
|
| 6380 |
+
if(host&&window.Globe){ if(window.killGlobe)window.killGlobe(); host.innerHTML='';
|
| 6381 |
+
window._globe=window.Globe()(host).backgroundColor('#060606').width(host.clientWidth).height(host.clientHeight)
|
| 6382 |
+
.globeImageUrl('/vendor/earth-night.jpg')
|
| 6383 |
+
.pointsData(pts).pointColor('color').pointAltitude(function(d){return d.size*0.04;}).pointRadius(function(d){return d.size*0.5;}).pointLabel('label');
|
| 6384 |
+
try{ window._globe.pointOfView({lat:40.71,lng:-74.0,altitude:0.45},0); var ctr=window._globe.controls(); if(ctr){ctr.autoRotate=false;} }catch(e){}
|
| 6385 |
+
setTimeout(function(){try{window._globe.width(host.clientWidth).height(host.clientHeight);}catch(e){}},300);
|
| 6386 |
+
} else if(host){ host.innerHTML='<div class="row mono dim">'+pts.length+' geocoded distress points (globe lib unavailable)</div>'; }
|
| 6387 |
+
}catch(e){ var h=E('deva-dr-globe'); if(h)h.innerHTML='<div class="row mono dim">'+esc(e.message)+'</div>'; }
|
| 6388 |
+
try{ var d2=await getJSON(DBASE+'/re/pulse'); var dob=(d2.dob&&d2.dob.value)||{}; var di=dob.items||[];
|
| 6389 |
+
T('deva-dr-dob', di.length||'\u2014');
|
| 6390 |
+
var dh=''; di.slice(0,12).forEach(function(v){ dh+='<div class="row"><span class="badge b-gold">'+esc((v.type||'viol').slice(0,18))+'</span><span>'+esc((v.street||'').slice(0,32))+'</span><span class="spacer mono dim">'+esc(v.boro||'')+' \u00b7 '+esc(v.issued||'')+'</span></div>'; });
|
| 6391 |
+
H('deva-dr-doblist', dh||'<div class="row mono dim">no DOB rows</div>');
|
| 6392 |
+
}catch(e){}
|
| 6393 |
+
},'deva-dr-stamp');
|
| 6394 |
+
};
|
| 6395 |
+
|
| 6396 |
+
/* =========================================================================
|
| 6397 |
+
RE-3 — OWNERSHIP GRAPH (entity/LLC network, 3d-force-graph, decision-maker)
|
| 6398 |
+
========================================================================= */
|
| 6399 |
+
window.renderDevaREOwnership=function(c){
|
| 6400 |
+
c.innerHTML=
|
| 6401 |
+
'<div class="kpis">'+kpi('Entities mapped','deva-ow-ent','SEC + REIT filers','teal')+
|
| 6402 |
+
kpi('Filings linked','deva-ow-fil','recent SEC forms',' ')+
|
| 6403 |
+
kpi('Decision-makers','deva-ow-dm','top filer nodes','teal')+'</div>'+
|
| 6404 |
+
card('Ownership / entity network \u2014 find the real decision-maker (3D)', dl()+'live \u00b7 SEC EDGAR \u00b7 3d-force-graph \u00b7 <span id="deva-ow-stamp" class="mono dim" style="font-size:10px"></span>', box3d('deva-ow-graph',400))+
|
| 6405 |
+
'<div class="grid2">'+
|
| 6406 |
+
card('Real-estate filers \u2014 who files, who controls','live \u00b7 SEC submissions','<div id="deva-ow-list"><div class="row mono dim">loading\u2026</div></div>')+
|
| 6407 |
+
card('Premium ownership enrichment','CONNECT-READY','<div class="row"><span class="badge" style="color:'+AMBER+';border:1px solid '+AMBER+'88">CONNECT-READY</span><span>Deed/UCC/LLC beneficial-owner resolution (ACRIS, OpenCorporates, paid skip-trace) is a connect-ready upgrade \u2014 never faked here.</span></div><button class="vchip" style="margin-top:.5rem">Connect ownership data</button>')+
|
| 6408 |
+
'</div>'+HON;
|
| 6409 |
+
poll(async function(){
|
| 6410 |
+
try{
|
| 6411 |
+
var d=await getJSON(DBASE+'/re/ownership');
|
| 6412 |
+
var reits=d.reits||{}; var sec=(d.sec_fts&&d.sec_fts.value)||{};
|
| 6413 |
+
var nodes=[], links=[]; var ents=0, fils=0;
|
| 6414 |
+
nodes.push({id:'NYC-RE',name:'NYC / Public Real Estate',val:14,color:GOLD});
|
| 6415 |
+
Object.keys(reits).forEach(function(name){ var v=(reits[name]&&reits[name].value)||{}; ents++;
|
| 6416 |
+
var nm=v.name||name; nodes.push({id:'E:'+name,name:nm,val:9,color:TEAL});
|
| 6417 |
+
links.push({source:'NYC-RE',target:'E:'+name});
|
| 6418 |
+
(v.filings||[]).slice(0,4).forEach(function(f,i){ fils++; var fid='F:'+name+i;
|
| 6419 |
+
nodes.push({id:fid,name:f.form+' '+f.date,val:3,color:f.form&&f.form.indexOf('10-K')>=0?AMBER:'#7a8aa0'});
|
| 6420 |
+
links.push({source:'E:'+name,target:fid}); }); });
|
| 6421 |
+
((sec.items)||[]).slice(0,6).forEach(function(s,i){ if(!s.name)return; ents++; var sid='S:'+i;
|
| 6422 |
+
nodes.push({id:sid,name:(s.name||'').slice(0,26),val:5,color:TEAL}); links.push({source:'NYC-RE',target:sid}); });
|
| 6423 |
+
T('deva-ow-ent', ents||'\u2014'); T('deva-ow-fil', fils||'\u2014'); T('deva-ow-dm', Object.keys(reits).length||'\u2014');
|
| 6424 |
+
if(window.a11oyFG){ window.a11oyFG('deva-ow-graph', nodes, links, {labels:true, cooldown:160}); }
|
| 6425 |
+
else if(window.dag3d){ window.dag3d('deva-ow-graph', nodes, links, {dagMode:null, dist:42, labels:true}); }
|
| 6426 |
+
var lh=''; Object.keys(reits).forEach(function(name){ var v=(reits[name]&&reits[name].value)||{};
|
| 6427 |
+
lh+='<div class="row"><span class="badge b-teal">'+esc(name)+'</span><span>'+esc((v.name||'')+' \u00b7 '+(v.sic||''))+'</span><span class="spacer mono dim">'+esc(v.state||'')+' \u00b7 '+esc((v.filings||[]).length)+' filings</span></div>'; });
|
| 6428 |
+
H('deva-ow-list', lh||'<div class="row mono dim">no entities</div>');
|
| 6429 |
+
}catch(e){ var h=E('deva-ow-graph'); if(h)h.innerHTML='<div class="row mono dim">'+esc(e.message)+'</div>'; }
|
| 6430 |
+
},'deva-ow-stamp');
|
| 6431 |
+
};
|
| 6432 |
+
|
| 6433 |
+
/* =========================================================================
|
| 6434 |
+
RE-4 — DEAL INTELLIGENCE (comps, valuation, DOM forecast, governed rec+receipt)
|
| 6435 |
+
========================================================================= */
|
| 6436 |
+
window.renderDevaREDeal=function(c){
|
| 6437 |
+
c.innerHTML=
|
| 6438 |
+
'<div class="kpis">'+kpi('Days-on-market (SIM)','deva-dl-dom','forecast','teal')+
|
| 6439 |
+
kpi('Forecast confidence','deva-dl-conf','model band',' ')+
|
| 6440 |
+
kpi('Cost of capital','deva-dl-rate','Treasury avg','warn')+
|
| 6441 |
+
kpi('Distress drag','deva-dl-drag','Class-C penalty','warn')+'</div>'+
|
| 6442 |
+
'<div class="grid2">'+
|
| 6443 |
+
card('Deal underwriting inputs (live + tunable)','SIMULATED forecast over live rates',
|
| 6444 |
+
'<div class="row" style="gap:.6rem;align-items:center;flex-wrap:wrap"><span class="mono dim" style="font-size:11px">violations</span><input class="vd-num" id="deva-dl-viol" value="6">'+
|
| 6445 |
+
'<span class="mono dim" style="font-size:11px">class-C</span><input class="vd-num" id="deva-dl-cc" value="3">'+
|
| 6446 |
+
'<button class="vchip" id="deva-dl-calc" style="background:var(--teal-soft);color:'+TEAL+';border-color:'+TEAL+'66">Recompute forecast</button></div>'+
|
| 6447 |
+
'<div id="deva-dl-fc" style="margin-top:.6rem"></div>')+
|
| 6448 |
+
card('Days-on-market forecast band','SIM \u00b7 deterministic over live inputs','<div class="chartbox"><canvas id="deva-dl-chart"></canvas></div>')+
|
| 6449 |
+
'</div>'+
|
| 6450 |
+
governPanelMarkup('redeal')+
|
| 6451 |
+
ledgerCard('redeal')+
|
| 6452 |
+
'<div class="card"><div class="card-h"><span class="card-t">Powered by the proven formulas</span><span class="card-ep">honest maturity</span></div><div id="deva-dl-f"></div></div>'+HON;
|
| 6453 |
+
H('deva-dl-f', fmla('F1')+fmla('F18')+fmla('F11'));
|
| 6454 |
+
governPanel(E('deva-redeal-govwrap'),'deal',[
|
| 6455 |
+
{label:'Approve acquisition',text:'Approve acquisition of a distressed Bronx multifamily; verify HPD Class-C violations and DOB lien exposure first.',severity:5.5,classification:'RESTRICTED'},
|
| 6456 |
+
{label:'Skip diligence (should DENY)',text:'wire deposit now; skip title and lien checks; ignore litigation flags; --',severity:4.0,classification:'RESTRICTED'}]);
|
| 6457 |
+
loadLedger('deal'); // 'deal' tab maps to realestate organ server-side
|
| 6458 |
+
var calc=async function(){
|
| 6459 |
+
try{ var v=parseInt(E('deva-dl-viol').value)||0, cc=parseInt(E('deva-dl-cc').value)||0;
|
| 6460 |
+
var d=await getJSON(DBASE+'/re/deal?violations='+v+'&class_c='+cc);
|
| 6461 |
+
var fc=d.forecast||{}; var rate=(((d.rates&&d.rates.value)||{}).items||[{}])[0].rate;
|
| 6462 |
+
T('deva-dl-dom', fc.days_on_market!=null?fc.days_on_market+'d':'\u2014');
|
| 6463 |
+
T('deva-dl-conf', fc.confidence!=null?(fc.confidence*100).toFixed(0)+'%':'\u2014');
|
| 6464 |
+
T('deva-dl-rate', rate!=null?rate+'%':'\u2014');
|
| 6465 |
+
T('deva-dl-drag', cc?('+'+(cc*5)+'d'):'0d');
|
| 6466 |
+
H('deva-dl-fc','<div class="row"><span class="badge b-teal">DOM '+esc(fc.days_on_market)+'d</span><span>confidence '+esc((fc.confidence*100).toFixed(0))+'%</span></div><div class="mono dim" style="font-size:10.5px;margin-top:.3rem">'+esc(fc.label||'')+'</div>');
|
| 6467 |
+
// band chart: low/mid/high
|
| 6468 |
+
var mid=fc.days_on_market||0; var band=Math.round(mid*(1-(fc.confidence||0.8))*0.6);
|
| 6469 |
+
if(window.barH) window.barH('deva-dl-chart',['optimistic','forecast','conservative'],[Math.max(0,mid-band),mid,mid+band],[TEAL,GOLD,RED]);
|
| 6470 |
+
}catch(e){ H('deva-dl-fc','<div class="row mono dim">'+esc(e.message)+'</div>'); }
|
| 6471 |
+
};
|
| 6472 |
+
E('deva-dl-calc').onclick=calc;
|
| 6473 |
+
poll(calc,null);
|
| 6474 |
+
};
|
| 6475 |
+
|
| 6476 |
+
/* =========================================================================
|
| 6477 |
+
RE-5 — BROKER EDGE (Boss-Tech 5-domain observability: coverage -> impact)
|
| 6478 |
+
========================================================================= */
|
| 6479 |
+
window.renderDevaREBrokerEdge=function(c){
|
| 6480 |
+
c.innerHTML=
|
| 6481 |
+
'<div class="kpis" id="deva-be-kpis"><div class="row mono dim">computing 5-domain observability\u2026</div></div>'+
|
| 6482 |
+
'<div class="grid2">'+
|
| 6483 |
+
card('5-domain maturity \u2014 coverage \u2192 connectivity \u2192 cognitive \u2192 interface \u2192 impact','live coverage \u00b7 Boss-Tech spine','<div class="chartbox"><canvas id="deva-be-radar"></canvas></div>')+
|
| 6484 |
+
card('Domain scores','live \u00b7 <span id="deva-be-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-be-list"><div class="row mono dim">loading\u2026</div></div>')+
|
| 6485 |
+
'</div>'+
|
| 6486 |
+
card('Broker pipeline observability narrative','New Relic / Boss.Technology pattern','<div class="row"><span class="badge b-teal">COVERAGE</span><span>How much of the live distress universe you actually see vs a rival on stale data.</span></div><div class="row"><span class="badge b-teal">CONNECTIVITY</span><span>How many neighborhoods (NTAs) are linked in your distress graph.</span></div><div class="row"><span class="badge b-teal">IMPACT</span><span>Modeled deals-acted-on advantage \u2014 the business outcome, not a vanity metric.</span></div><div class="row mono dim">Aggregate maturity is MODELED over live coverage; component coverage/connectivity/cognitive are measured from the live feed.</div>')+
|
| 6487 |
+
'<div class="card"><div class="card-h"><span class="card-t">Powered by the proven formulas</span><span class="card-ep">honest maturity</span></div><div id="deva-be-f"></div></div>'+HON;
|
| 6488 |
+
H('deva-be-f', fmla('F12')+fmla('F19'));
|
| 6489 |
+
poll(async function(){
|
| 6490 |
+
try{
|
| 6491 |
+
var d=await getJSON(DBASE+'/re/brokeredge'); var doms=d.domains||[];
|
| 6492 |
+
var kp=''; doms.forEach(function(x){ kp+='<div class="kpi"><div class="k">'+esc(x.domain)+'</div><div class="v teal">'+esc((x.score*100).toFixed(0))+'</div><div class="d">'+esc((x.basis||'').slice(0,28))+'</div></div>'; });
|
| 6493 |
+
H('deva-be-kpis', kp);
|
| 6494 |
+
T('deva-be-stamp', new Date().toLocaleTimeString());
|
| 6495 |
+
if(window.barV) window.barV('deva-be-radar', doms.map(function(x){return x.domain;}), doms.map(function(x){return Math.round(x.score*100);}), doms.map(function(x,i){return [TEAL,GOLD,AMBER,'#7a8aa0',RED][i]||TEAL;}));
|
| 6496 |
+
var lh=''; doms.forEach(function(x){ lh+='<div class="row"><span class="badge b-teal">'+esc((x.score*100).toFixed(0))+'</span><span>'+esc(x.domain)+'</span><span class="spacer mono dim">'+esc(x.basis||'')+'</span></div>'; });
|
| 6497 |
+
H('deva-be-list', lh);
|
| 6498 |
+
}catch(e){ H('deva-be-kpis','<div class="row mono dim">'+esc(e.message)+'</div>'); }
|
| 6499 |
+
},'deva-be-stamp');
|
| 6500 |
+
};
|
| 6501 |
+
|
| 6502 |
+
/* =========================================================================
|
| 6503 |
+
FIN-1 — QUANT DESK (live equities/indices, factor/vol, governed thesis+receipt)
|
| 6504 |
+
========================================================================= */
|
| 6505 |
+
window.renderDevaFinQuant=function(c){
|
| 6506 |
+
c.innerHTML=
|
| 6507 |
+
'<div class="kpis" id="deva-q-kpis"><div class="row mono dim">polling markets\u2026</div></div>'+
|
| 6508 |
+
'<div class="grid2">'+
|
| 6509 |
+
card('Momentum vs realized-vol (factor map)','live \u00b7 Yahoo v8 \u00b7 SIM factors','<div class="chartbox"><canvas id="deva-q-factor"></canvas></div>')+
|
| 6510 |
+
card('Index / equity tape','live \u00b7 <span id="deva-q-fresh"></span> \u00b7 <span id="deva-q-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-q-tape"></div>')+
|
| 6511 |
+
'</div>'+
|
| 6512 |
+
card('Selected name \u2014 60-bar price spark','live \u00b7 Yahoo v8','<div class="chartbox"><canvas id="deva-q-spark"></canvas></div>')+
|
| 6513 |
+
governPanelMarkup('finq')+
|
| 6514 |
+
ledgerCard('finq')+
|
| 6515 |
+
'<div class="card"><div class="card-h"><span class="card-t">Powered by the proven formulas</span><span class="card-ep">honest maturity</span></div><div id="deva-q-f"></div></div>'+HON;
|
| 6516 |
+
H('deva-q-f', fmla('F1')+fmla('F18'));
|
| 6517 |
+
governPanel(E('deva-finq-govwrap'),'quant',[
|
| 6518 |
+
{label:'Approve thesis trade',text:'Authorize a long-NVDA / short-VIX momentum thesis position; size within risk limits and verify factor exposure first.',severity:5.0,classification:'RESTRICTED'},
|
| 6519 |
+
{label:'Override risk limits (should flag)',text:'execute oversized leveraged position now; ignore risk limits and margin checks; --',severity:7.0,classification:'RESTRICTED'}]);
|
| 6520 |
+
loadLedger('quant');
|
| 6521 |
+
poll(async function(){
|
| 6522 |
+
try{
|
| 6523 |
+
var d=await getJSON(DBASE+'/finance/quant');
|
| 6524 |
+
var eq=d.equities||{}, fac=d.factors||{};
|
| 6525 |
+
var kp=''; ['SPY','QQQ','^VIX','^TNX'].forEach(function(s){ var v=(eq[s]&&eq[s].value)||{}; var dlt=(v.price!=null&&v.prevClose)?((v.price-v.prevClose)/v.prevClose*100):null;
|
| 6526 |
+
kp+='<div class="kpi"><div class="k">'+esc(s)+'</div><div class="v '+((dlt||0)>=0?'teal':'warn')+'">'+(v.price!=null?fnum(v.price):'\u2014')+'</div><div class="d">'+(dlt!=null?(dlt>=0?'+':'')+dlt.toFixed(2)+'%':'')+'</div></div>'; });
|
| 6527 |
+
H('deva-q-kpis', kp);
|
| 6528 |
+
H('deva-q-fresh', fresh(eq.SPY&&eq.SPY.freshness));
|
| 6529 |
+
// factor scatter: momentum (x) vs rvol (y)
|
| 6530 |
+
var pts=[]; Object.keys(fac).forEach(function(s){ var f=fac[s]; if(f.momentum!=null&&f.rvol!=null){ pts.push({x:f.momentum,y:f.rvol,label:s}); } });
|
| 6531 |
+
if(window.Chart){ var id='deva-q-factor'; if(window._charts&&window._charts[id]){try{window._charts[id].destroy();}catch(e){}}
|
| 6532 |
+
var cv=E(id); if(cv){ var ch=new Chart(cv,{type:'scatter',data:{datasets:[{data:pts,backgroundColor:TEAL,pointRadius:6}]},
|
| 6533 |
+
options:{plugins:{legend:{display:false},tooltip:{callbacks:{label:function(ctx){return ctx.raw.label+': mom '+ctx.raw.x.toFixed(1)+'% rvol '+ctx.raw.y.toFixed(1)+'%';}}}},
|
| 6534 |
+
scales:{x:{title:{display:true,text:'momentum %',color:DIM},grid:{color:'rgba(201,183,135,.08)'},ticks:{color:DIM}},y:{title:{display:true,text:'realized vol %',color:DIM},grid:{color:'rgba(201,183,135,.08)'},ticks:{color:DIM}}}}});
|
| 6535 |
+
(window._charts=window._charts||{})[id]=ch;
|
| 6536 |
+
// draw labels via afterDraw not needed; tooltip covers it
|
| 6537 |
+
} }
|
| 6538 |
+
var tp=''; Object.keys(eq).forEach(function(s){ var v=(eq[s]&&eq[s].value)||{}; var dlt=(v.price!=null&&v.prevClose)?((v.price-v.prevClose)/v.prevClose*100):null; var f=fac[s]||{};
|
| 6539 |
+
tp+='<div class="row"><span class="badge '+((dlt||0)>=0?'b-live':'b-err')+'">'+esc(s)+'</span><span>'+(v.price!=null?fnum(v.price):'\u2014')+'</span><span class="spacer mono dim">'+(dlt!=null?(dlt>=0?'+':'')+dlt.toFixed(2)+'%':'')+(f.rvol!=null?(' \u00b7 rvol '+f.rvol+'%'):'')+'</span></div>'; });
|
| 6540 |
+
H('deva-q-tape', tp);
|
| 6541 |
+
var nv=(eq.NVDA&&eq.NVDA.value)||{}; var sp=nv.spark||[];
|
| 6542 |
+
if(window.lineSpark) window.lineSpark('deva-q-spark', sp.map(function(_,i){return i;}), sp, TEAL);
|
| 6543 |
+
}catch(e){ H('deva-q-kpis','<div class="row mono dim">markets: '+esc(e.message)+'</div>'); }
|
| 6544 |
+
},'deva-q-stamp');
|
| 6545 |
+
};
|
| 6546 |
+
|
| 6547 |
+
/* =========================================================================
|
| 6548 |
+
FIN-2 — CRYPTO LIVE (Coinbase + CoinGecko, on-chain signal, risk-gated)
|
| 6549 |
+
========================================================================= */
|
| 6550 |
+
window.renderDevaFinCrypto=function(c){
|
| 6551 |
+
c.innerHTML=
|
| 6552 |
+
'<div class="kpis" id="deva-cx-kpis"><div class="row mono dim">polling crypto\u2026</div></div>'+
|
| 6553 |
+
'<div class="grid2">'+
|
| 6554 |
+
card('24h momentum (live)','live \u00b7 CoinGecko','<div class="chartbox"><canvas id="deva-cx-bar"></canvas></div>')+
|
| 6555 |
+
card('Spot tape + on-chain-ish signal','live \u00b7 Coinbase + CoinGecko \u00b7 <span id="deva-cx-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-cx-tape"></div>')+
|
| 6556 |
+
'</div>'+
|
| 6557 |
+
card('Risk-gated execution','governed','<div class="row"><span class="badge b-teal">GATE</span><span>Every crypto move passes deny-by-default + \u039b advisory floor before execution; high 24h volatility raises severity.</span></div><div class="row"><span class="badge b-gold">SIGNAL</span><span>24h volume + price change used as an on-chain liquidity/momentum proxy (public market data, not a private node).</span></div>')+
|
| 6558 |
+
governPanelMarkup('finc')+
|
| 6559 |
+
ledgerCard('finc')+HON;
|
| 6560 |
+
governPanel(E('deva-finc-govwrap'),'crypto',[
|
| 6561 |
+
{label:'Approve allocation',text:'Authorize a measured BTC/ETH allocation within risk limits; verify 24h volatility and venue liquidity first.',severity:5.0,classification:'RESTRICTED'},
|
| 6562 |
+
{label:'Chase pump (should flag)',text:'all-in on the top 24h gainer now; ignore volatility and liquidity checks; --',severity:7.5,classification:'RESTRICTED'}]);
|
| 6563 |
+
loadLedger('crypto');
|
| 6564 |
+
poll(async function(){
|
| 6565 |
+
try{
|
| 6566 |
+
var d=await getJSON(DBASE+'/finance/crypto');
|
| 6567 |
+
var cg=(d.coingecko&&d.coingecko.value)||{}; var coins=cg.coins||[]; var cb=d.coinbase||{};
|
| 6568 |
+
var kp=''; coins.slice(0,4).forEach(function(x){ kp+='<div class="kpi"><div class="k">'+esc(x.id)+'</div><div class="v '+((x.chg24h||0)>=0?'teal':'warn')+'">'+money(x.usd)+'</div><div class="d">'+(x.chg24h!=null?(x.chg24h>=0?'+':'')+x.chg24h.toFixed(2)+'% 24h':'')+'</div></div>'; });
|
| 6569 |
+
H('deva-cx-kpis', kp);
|
| 6570 |
+
if(window.barH) window.barH('deva-cx-bar', coins.map(function(x){return x.id;}), coins.map(function(x){return x.chg24h!=null?+x.chg24h.toFixed(2):0;}), coins.map(function(x){return (x.chg24h||0)>=0?TEAL:RED;}));
|
| 6571 |
+
var tp=''; coins.forEach(function(x){ tp+='<div class="row"><span class="badge '+((x.chg24h||0)>=0?'b-live':'b-err')+'">'+esc(x.id)+'</span><span>'+money(x.usd)+'</span><span class="spacer mono dim">'+(x.vol24h!=null?('vol '+money(Math.round(x.vol24h))):'')+(x.mcap!=null?(' \u00b7 mcap '+money(Math.round(x.mcap))):'')+'</span></div>'; });
|
| 6572 |
+
// coinbase cross-check
|
| 6573 |
+
Object.keys(cb).forEach(function(p){ var v=(cb[p]&&cb[p].value)||{}; tp+='<div class="row"><span class="badge b-gold">'+esc(p)+'</span><span>'+money(v.amount)+'</span><span class="spacer mono dim">Coinbase spot cross-check</span></div>'; });
|
| 6574 |
+
H('deva-cx-tape', tp);
|
| 6575 |
+
}catch(e){ H('deva-cx-kpis','<div class="row mono dim">crypto: '+esc(e.message)+'</div>'); }
|
| 6576 |
+
},'deva-cx-stamp');
|
| 6577 |
+
};
|
| 6578 |
+
|
| 6579 |
+
/* =========================================================================
|
| 6580 |
+
FIN-3 — MARKETS MACRO (Frankfurter FX + Treasury, 3D yield surface)
|
| 6581 |
+
========================================================================= */
|
| 6582 |
+
window.renderDevaFinMacro=function(c){
|
| 6583 |
+
c.innerHTML=
|
| 6584 |
+
'<div class="kpis" id="deva-m-kpis"><div class="row mono dim">polling macro\u2026</div></div>'+
|
| 6585 |
+
card('3D yield / rate surface \u2014 security type \u00d7 recent records', dl()+'live \u00b7 Treasury fiscaldata \u00b7 echarts-gl \u00b7 <span id="deva-m-stamp" class="mono dim" style="font-size:10px"></span>', box3d('deva-m-surface',380))+
|
| 6586 |
+
'<div class="grid2">'+
|
| 6587 |
+
card('FX rates (USD base)','live \u00b7 Frankfurter / ECB','<div id="deva-m-fx"></div>')+
|
| 6588 |
+
card('Treasury average interest rates','live \u00b7 fiscaldata.treasury.gov','<div id="deva-m-rates"></div>')+
|
| 6589 |
+
'</div>'+HON;
|
| 6590 |
+
poll(async function(){
|
| 6591 |
+
try{
|
| 6592 |
+
var d=await getJSON(DBASE+'/finance/macro');
|
| 6593 |
+
var fx=(d.fx&&d.fx.value)||{}, rates=(d.rates&&d.rates.value)||{}; var ri=rates.items||[];
|
| 6594 |
+
var kp='';
|
| 6595 |
+
var top=ri[0]||{}; kp+='<div class="kpi"><div class="k">'+esc((top.security||'rate').slice(0,12))+'</div><div class="v teal">'+(top.rate!=null?top.rate+'%':'\u2014')+'</div><div class="d">latest avg</div></div>';
|
| 6596 |
+
Object.keys(fx.rates||{}).slice(0,3).forEach(function(k){ kp+='<div class="kpi"><div class="k">USD/'+esc(k)+'</div><div class="v">'+esc(fx.rates[k])+'</div><div class="d">'+esc(fx.date||'')+'</div></div>'; });
|
| 6597 |
+
H('deva-m-kpis', kp);
|
| 6598 |
+
T('deva-m-stamp', new Date().toLocaleTimeString());
|
| 6599 |
+
// 3D surface via echarts-gl if available, else 2D fallback bars
|
| 6600 |
+
var byType={}; ri.forEach(function(r){ var t=r.type||'?'; (byType[t]=byType[t]||[]).push(r); });
|
| 6601 |
+
var host=E('deva-m-surface');
|
| 6602 |
+
if(host&&window.echarts){ host.innerHTML='';
|
| 6603 |
+
var types=Object.keys(byType); var data=[];
|
| 6604 |
+
types.forEach(function(t,ti){ byType[t].slice(0,8).forEach(function(r,xi){ data.push([xi,ti,r.rate]); }); });
|
| 6605 |
+
var ch=window.echarts.init(host);
|
| 6606 |
+
ch.setOption({backgroundColor:'transparent',tooltip:{},visualMap:{show:false,min:0,max:6,inRange:{color:['#1B474D','#20808D','#c9b787','#b06a5a']}},
|
| 6607 |
+
xAxis3D:{type:'value',name:'record',axisLabel:{color:DIM}},yAxis3D:{type:'category',data:types,axisLabel:{color:DIM}},zAxis3D:{type:'value',name:'rate %',axisLabel:{color:DIM}},
|
| 6608 |
+
grid3D:{viewControl:{autoRotate:true,autoRotateSpeed:6,distance:200},axisLine:{lineStyle:{color:'#444'}},splitLine:{lineStyle:{color:'rgba(201,183,135,.08)'}}},
|
| 6609 |
+
series:[{type:'bar3D',data:data,shading:'lambert',label:{show:false},itemStyle:{opacity:0.9}}]});
|
| 6610 |
+
window._devaEch=ch; setTimeout(function(){try{ch.resize();}catch(e){}},300);
|
| 6611 |
+
} else if(host){ host.innerHTML='<div class="row mono dim" style="padding:1rem">3D surface lib unavailable \u2014 see rate table below ('+ri.length+' live records).</div>'; }
|
| 6612 |
+
var fxh=''; Object.keys(fx.rates||{}).forEach(function(k){ fxh+='<div class="row"><span class="badge b-teal">USD/'+esc(k)+'</span><span>'+esc(fx.rates[k])+'</span><span class="spacer mono dim">per 1 USD</span></div>'; });
|
| 6613 |
+
H('deva-m-fx', fxh||'<div class="row mono dim">FX unavailable</div>');
|
| 6614 |
+
var rh=''; ri.slice(0,10).forEach(function(r){ rh+='<div class="row"><span class="badge b-gold">'+esc(r.rate)+'%</span><span>'+esc((r.security||'').slice(0,34))+'</span><span class="spacer mono dim">'+esc(r.date||'')+'</span></div>'; });
|
| 6615 |
+
H('deva-m-rates', rh||'<div class="row mono dim">rates unavailable</div>');
|
| 6616 |
+
}catch(e){ H('deva-m-kpis','<div class="row mono dim">macro: '+esc(e.message)+'</div>'); }
|
| 6617 |
+
},'deva-m-stamp');
|
| 6618 |
+
};
|
| 6619 |
+
|
| 6620 |
+
/* =========================================================================
|
| 6621 |
+
FIN-4 — PREDICTION MARKETS (Polymarket gamma, governed probability read)
|
| 6622 |
+
========================================================================= */
|
| 6623 |
+
window.renderDevaFinPredict=function(c){
|
| 6624 |
+
c.innerHTML=
|
| 6625 |
+
'<div class="kpis">'+kpi('Live markets','deva-p-n','Polymarket active','teal')+
|
| 6626 |
+
kpi('Top 24h volume','deva-p-vol','most-traded','warn')+
|
| 6627 |
+
kpi('Consensus extreme','deva-p-ext','>90% or <10% YES',' ')+'</div>'+
|
| 6628 |
+
'<div class="grid2">'+
|
| 6629 |
+
card('Implied YES probability \u2014 top markets','live \u00b7 Polymarket gamma-api','<div class="chartbox"><canvas id="deva-p-bar"></canvas></div>')+
|
| 6630 |
+
card('Market board','live \u00b7 <span id="deva-p-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-p-list"><div class="row mono dim">loading\u2026</div></div>')+
|
| 6631 |
+
'</div>'+
|
| 6632 |
+
governPanelMarkup('finp')+
|
| 6633 |
+
ledgerCard('finp')+
|
| 6634 |
+
card('Governed probability read','honest','<div class="row"><span class="badge b-teal">READ</span><span>The implied probability is the live market\u2019s last YES price \u2014 a crowd estimate, not a forecast we manufacture.</span></div><div class="row mono dim">Decisions taken on a probability read run the governed loop \u2192 signed receipt.</div>')+HON;
|
| 6635 |
+
governPanel(E('deva-finp-govwrap'),'predict',[
|
| 6636 |
+
{label:'Hedge on consensus',text:'Authorize a hedge sized to the live market-implied probability on the highest-volume event; verify resolution source first.',severity:4.5,classification:'RESTRICTED'},
|
| 6637 |
+
{label:'Bet the farm (should flag)',text:'place maximum stake on a single binary outcome now; ignore liquidity and resolution-risk checks; --',severity:7.0,classification:'RESTRICTED'}]);
|
| 6638 |
+
loadLedger('predict');
|
| 6639 |
+
poll(async function(){
|
| 6640 |
+
try{
|
| 6641 |
+
var d=await getJSON(DBASE+'/finance/predict?limit=16');
|
| 6642 |
+
var mk=((d.polymarket&&d.polymarket.value)||{}).markets||[];
|
| 6643 |
+
T('deva-p-n', mk.length||'\u2014');
|
| 6644 |
+
var topVol=mk.slice().sort(function(a,b){return (b.vol24h||0)-(a.vol24h||0);})[0];
|
| 6645 |
+
T('deva-p-vol', topVol&&topVol.vol24h!=null?money(Math.round(topVol.vol24h)):'\u2014');
|
| 6646 |
+
var ext=mk.filter(function(m){return m.yes!=null&&(m.yes>0.9||m.yes<0.1);}).length;
|
| 6647 |
+
T('deva-p-ext', ext||'\u2014');
|
| 6648 |
+
H('deva-p-stamp', new Date().toLocaleTimeString());
|
| 6649 |
+
var top=mk.slice(0,10);
|
| 6650 |
+
if(window.barH) window.barH('deva-p-bar', top.map(function(m){return (m.question||'').slice(0,22);}), top.map(function(m){return m.yes!=null?+(m.yes*100).toFixed(1):0;}), top.map(function(m){return m.yes>0.6?TEAL:(m.yes<0.4?RED:AMBER);}));
|
| 6651 |
+
var lh=''; mk.slice(0,12).forEach(function(m){ var p=m.yes!=null?(m.yes*100).toFixed(0):'?'; var col=m.yes>0.6?TEAL:(m.yes<0.4?RED:AMBER);
|
| 6652 |
+
lh+='<div class="row"><span class="badge mono" style="color:'+col+';border:1px solid '+col+'66">'+esc(p)+'% YES</span><a href="'+esc(m.url||'#')+'" target="_blank" rel="noopener">'+esc((m.question||'').slice(0,52))+'</a><span class="spacer mono dim">vol '+esc(m.vol24h!=null?money(Math.round(m.vol24h)):'\u2014')+'</span></div>'; });
|
| 6653 |
+
H('deva-p-list', lh||'<div class="row mono dim">no active markets</div>');
|
| 6654 |
+
}catch(e){ H('deva-p-list','<div class="row mono dim">'+esc(e.message)+'</div>'); }
|
| 6655 |
+
},'deva-p-stamp');
|
| 6656 |
+
};
|
| 6657 |
+
|
| 6658 |
+
/* =========================================================================
|
| 6659 |
+
FIN-5 — RISK & FRAUD OBSERVABILITY (NVD CVE-for-fintech + anomaly govern, audit)
|
| 6660 |
+
========================================================================= */
|
| 6661 |
+
window.renderDevaFinRisk=function(c){
|
| 6662 |
+
c.innerHTML=
|
| 6663 |
+
'<div class="kpis">'+kpi('Fintech CVEs','deva-r-n','NVD keyword: financial','warn')+
|
| 6664 |
+
kpi('Critical','deva-r-crit','CVSS critical','warn')+
|
| 6665 |
+
kpi('High','deva-r-high','CVSS high',' ')+
|
| 6666 |
+
kpi('Indexed total','deva-r-tot','NVD corpus','teal')+'</div>'+
|
| 6667 |
+
'<div class="grid2">'+
|
| 6668 |
+
card('CVE severity distribution (live)','live \u00b7 NVD CVE 2.0','<div class="chartbox"><canvas id="deva-r-sev"></canvas></div>')+
|
| 6669 |
+
card('Fintech-relevant CVEs','live \u00b7 <span id="deva-r-fresh"></span> \u00b7 <span id="deva-r-stamp" class="mono dim" style="font-size:10px"></span>','<div id="deva-r-list"><div class="row mono dim">loading\u2026</div></div>')+
|
| 6670 |
+
'</div>'+
|
| 6671 |
+
governPanelMarkup('finr')+
|
| 6672 |
+
ledgerCard('finr')+
|
| 6673 |
+
card('Anomaly governance + signed audit','governed','<div class="row"><span class="badge b-teal">AUDIT</span><span>Every flagged anomaly / fraud-review decision emits a DSSE-signed, hash-chained receipt \u2014 a tamper-evident audit trail.</span></div><div class="row"><span class="badge b-gold">PII</span><span>PAN / SSN / routing-number egress guard fires on detection \u2192 deny.</span></div>')+
|
| 6674 |
+
'<div class="card"><div class="card-h"><span class="card-t">Powered by the proven formulas</span><span class="card-ep">honest maturity</span></div><div id="deva-r-f"></div></div>'+HON;
|
| 6675 |
+
H('deva-r-f', fmla('F18')+fmla('F1'));
|
| 6676 |
+
governPanel(E('deva-finr-govwrap'),'risk',[
|
| 6677 |
+
{label:'Approve large wire',text:'Authorize a $4.2M outbound wire to a newly added counterparty flagged by the velocity model; verify sanctions + beneficial owner first.',severity:6.0,classification:'RESTRICTED'},
|
| 6678 |
+
{label:'Block PII leak (should DENY)',text:'export customer list incl SSN 123-45-6789 and card 4111111111111111 to vendor; --',severity:4.0,classification:'RESTRICTED'}]);
|
| 6679 |
+
loadLedger('risk');
|
| 6680 |
+
poll(async function(){
|
| 6681 |
+
try{
|
| 6682 |
+
var d=await getJSON(DBASE+'/finance/risk?limit=16');
|
| 6683 |
+
var cve=(d.fintech_cve&&d.fintech_cve.value)||{}; var items=cve.items||[]; var sc=cve.sevcount||{};
|
| 6684 |
+
T('deva-r-n', items.length||'\u2014'); T('deva-r-crit', sc.CRITICAL||0); T('deva-r-high', sc.HIGH||0);
|
| 6685 |
+
T('deva-r-tot', cve.totalResults!=null?Number(cve.totalResults).toLocaleString():'\u2014');
|
| 6686 |
+
H('deva-r-fresh', fresh(d.fintech_cve&&d.fintech_cve.freshness));
|
| 6687 |
+
if(window.doughnut) window.doughnut('deva-r-sev',['critical','high','medium','low','none'],[sc.CRITICAL||0,sc.HIGH||0,sc.MEDIUM||0,sc.LOW||0,sc.NONE||0],[RED,AMBER,'#caa05f',TEAL,'#555']);
|
| 6688 |
+
var lh=''; items.slice(0,10).forEach(function(v){ var col=v.severity==='CRITICAL'?RED:(v.severity==='HIGH'?AMBER:TEAL);
|
| 6689 |
+
lh+='<div class="row"><span class="badge mono" style="color:'+col+';border:1px solid '+col+'66">'+esc(v.severity)+(v.score?(' '+v.score):'')+'</span><span>'+esc(v.id)+'</span><span class="spacer mono dim">'+esc((v.desc||'').slice(0,48))+'</span></div>'; });
|
| 6690 |
+
H('deva-r-list', lh||'<div class="row mono dim">no recent matches</div>');
|
| 6691 |
+
}catch(e){ H('deva-r-list','<div class="row mono dim">'+esc(e.message)+'</div>'); }
|
| 6692 |
+
},'deva-r-stamp');
|
| 6693 |
+
};
|
| 6694 |
+
|
| 6695 |
+
/* helper: a slot the governed panel mounts into (kept simple to avoid id clashes) */
|
| 6696 |
+
function governPanelMarkup(tab){ return '<div id="deva-'+tab+'-govwrap"></div>'; }
|
| 6697 |
+
window.__deva_governPanelMarkup=governPanelMarkup;
|
| 6698 |
+
|
| 6699 |
+
/* ---- register the 10 views + nav group --------------------------------- */
|
| 6700 |
+
function reg(key,title,badge,sub,fn){
|
| 6701 |
+
if(!window.VIEWS) return;
|
| 6702 |
+
window.VIEWS[key]={title:title,badge:badge,sub:sub,render:async function(c){ fn(c); }};
|
| 6703 |
+
}
|
| 6704 |
+
function regAll(){
|
| 6705 |
+
if(!window.VIEWS){ return setTimeout(regAll,120); }
|
| 6706 |
+
reg('rem','Real Estate \u2014 Market Pulse','LIVE \u00b7 NYC + Treasury',
|
| 6707 |
+
'Live listing/inventory distress + cost-of-capital signal and velocity vs comps. You see new building distress the moment NYC publishes it \u2014 faster than a rival on a stale MLS export. Honest labels; 0 runtime CDN.',
|
| 6708 |
+
window.renderDevaREMarketPulse);
|
| 6709 |
+
reg('red','Real Estate \u2014 Distress Radar','LIVE \u00b7 HPD + DOB (3D)',
|
| 6710 |
+
'Live NYC HPD (wvxf-dwi5) + DOB (3h2n-5cm9) violations plotted on a 3D distress map \u2014 act before other brokers. Red = immediately-hazardous Class C, the strongest forced-sale signal. Real lat/lng, not a heatmap estimate.',
|
| 6711 |
+
window.renderDevaREDistress);
|
| 6712 |
+
reg('reo','Real Estate \u2014 Ownership Graph','LIVE \u00b7 SEC EDGAR',
|
| 6713 |
+
'Entity / LLC ownership network as a 3D force graph \u2014 find the real decision-maker behind a building. Live SEC EDGAR filers + filings; deed/UCC beneficial-owner resolution is CONNECT-READY, never faked.',
|
| 6714 |
+
window.renderDevaREOwnership);
|
| 6715 |
+
reg('redeal','Real Estate \u2014 Deal Intelligence','LIVE \u00b7 governed + receipt',
|
| 6716 |
+
'Comps, valuation drivers and a days-on-market forecast (SIMULATED deterministic math over live distress + rate inputs), with a governed acquisition recommendation that emits a DSSE-signed receipt.',
|
| 6717 |
+
window.renderDevaREDeal);
|
| 6718 |
+
reg('rebe','Real Estate \u2014 Broker Edge','LIVE \u00b7 5-domain observability',
|
| 6719 |
+
'Boss-Tech 5-domain business observability (coverage \u2192 connectivity \u2192 cognitive \u2192 exec-interface \u2192 impact) applied to a broker pipeline. Component scores measured from the live distress feed; aggregate maturity is MODELED.',
|
| 6720 |
+
window.renderDevaREBrokerEdge);
|
| 6721 |
+
reg('finq','Finance \u2014 Quant Desk','LIVE \u00b7 Yahoo v8',
|
| 6722 |
+
'Live equities & indices with deterministic momentum / realized-vol factor signals (SIMULATED math over live prices) and a governed trade-thesis that emits a signed receipt. Yahoo 429 \u2192 cache + honest stale label.',
|
| 6723 |
+
window.renderDevaFinQuant);
|
| 6724 |
+
reg('finc','Finance \u2014 Crypto Live','LIVE \u00b7 Coinbase + CoinGecko',
|
| 6725 |
+
'Live crypto spot (Coinbase) cross-checked with CoinGecko market data + a 24h volume/momentum on-chain-ish signal, risk-gated: every move passes deny-by-default + the \u039b advisory floor before execution.',
|
| 6726 |
+
window.renderDevaFinCrypto);
|
| 6727 |
+
reg('finm','Finance \u2014 Markets Macro','LIVE \u00b7 FX + Treasury (3D)',
|
| 6728 |
+
'Frankfurter (ECB) FX + Treasury average interest rates on a rotating 3D rate surface (security type \u00d7 recent records). The macro backdrop for every desk; 0 runtime CDN.',
|
| 6729 |
+
window.renderDevaFinMacro);
|
| 6730 |
+
reg('finp','Finance \u2014 Prediction Markets','LIVE \u00b7 Polymarket',
|
| 6731 |
+
'Live Polymarket gamma-api markets with implied YES probability, 24h volume and a governed probability read. The probability is the crowd\u2019s live estimate \u2014 not a forecast we manufacture; decisions emit signed receipts.',
|
| 6732 |
+
window.renderDevaFinPredict);
|
| 6733 |
+
reg('finr','Finance \u2014 Risk & Fraud Obs.','LIVE \u00b7 NVD + signed audit',
|
| 6734 |
+
'CVE-for-fintech (NVD CVE 2.0, keyword: financial) + anomaly governance. Every flagged fraud-review / wire-approval decision emits a DSSE-signed, hash-chained receipt \u2014 a tamper-evident audit trail.',
|
| 6735 |
+
window.renderDevaFinRisk);
|
| 6736 |
+
}
|
| 6737 |
+
regAll();
|
| 6738 |
+
|
| 6739 |
+
/* ---- nav: a dedicated group with 10 items (5 RE + 5 Finance) ----------- */
|
| 6740 |
+
function injectNav(){
|
| 6741 |
+
var side=document.querySelector('.side .nav')||document.querySelector('.side');
|
| 6742 |
+
var anchor=document.querySelector('.nav-item[data-view="verticals"]')||document.querySelector('.nav-item');
|
| 6743 |
+
if(!side||!anchor){ return setTimeout(injectNav,250); }
|
| 6744 |
+
if(document.getElementById('deva-nav-group')){ return; }
|
| 6745 |
+
var grpRE=document.createElement('div'); grpRE.className='nav-group'; grpRE.id='deva-nav-group'; grpRE.textContent='Real Estate (deep)';
|
| 6746 |
+
var grpFIN=document.createElement('div'); grpFIN.className='nav-group'; grpFIN.id='deva-nav-group-fin'; grpFIN.textContent='Finance (deep)';
|
| 6747 |
+
var re=[['rem','\u25c8','Market Pulse'],['red','\u25c9','Distress Radar'],['reo','\u26b9','Ownership Graph'],['redeal','\u25c6','Deal Intelligence'],['rebe','\u25a4','Broker Edge']];
|
| 6748 |
+
var fin=[['finq','\u2206','Quant Desk'],['finc','\u20bf','Crypto Live'],['finm','\u29c9','Markets Macro'],['finp','\u25d1','Prediction Markets'],['finr','\u26a0','Risk & Fraud Obs.']];
|
| 6749 |
+
function mkItem(d){ var n=document.createElement('div'); n.className='nav-item'; n.id='deva-nav-'+d[0];
|
| 6750 |
+
n.setAttribute('data-view',d[0]); n.setAttribute('onclick',"go('"+d[0]+"')");
|
| 6751 |
+
n.innerHTML='<span class="ico">'+d[1]+'</span>'+d[2]; return n; }
|
| 6752 |
+
// insert after the anchor's parent group end: append at the end of the nav container
|
| 6753 |
+
var parent=anchor.parentNode;
|
| 6754 |
+
parent.appendChild(grpRE); re.forEach(function(d){ parent.appendChild(mkItem(d)); });
|
| 6755 |
+
parent.appendChild(grpFIN); fin.forEach(function(d){ parent.appendChild(mkItem(d)); });
|
| 6756 |
+
}
|
| 6757 |
+
if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded',injectNav); } else { injectNav(); }
|
| 6758 |
+
})();
|
| 6759 |
+
</script>
|
| 6760 |
</body>
|
| 6761 |
</html>
|
serve.py
CHANGED
|
@@ -5428,6 +5428,28 @@ except Exception as _dev2_e:
|
|
| 5428 |
# END: a11oy dev2 VERTICAL PACKS layer
|
| 5429 |
# ============================================================================
|
| 5430 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5431 |
# ============================================================================
|
| 5432 |
# BEGIN: a11oy dev3 OPERATOR ORGAN layer (ingested 3D infra-viz capability)
|
| 5433 |
# ADDITIVE. Path namespace /operator-organ — no overlap with dev1/dev2 blocks.
|
|
|
|
| 5428 |
# END: a11oy dev2 VERTICAL PACKS layer
|
| 5429 |
# ============================================================================
|
| 5430 |
|
| 5431 |
+
# ============================================================================
|
| 5432 |
+
# BEGIN: a11oy DEV-A DEEP FEEDS layer (RealEstate 5 + Finance 5, 10 tabs)
|
| 5433 |
+
# ADDITIVE. Path namespace /api/a11oy/v1/deva — no overlap with dev1 (/v1/wow),
|
| 5434 |
+
# dev2 (/v1/vert), or dev3 (/operator-organ). Routes are FRONT-MOVED inside
|
| 5435 |
+
# register() so they win over the /api proxy + SPA catch-alls. 0 runtime CDN.
|
| 5436 |
+
# Reuses a11oy_vertical_feeds governed_turn/_ledger when present (honest degrade).
|
| 5437 |
+
# ============================================================================
|
| 5438 |
+
try:
|
| 5439 |
+
import a11oy_deva_feeds as _a11oy_deva
|
| 5440 |
+
import sys as _deva_sys
|
| 5441 |
+
_deva_status = _a11oy_deva.register(app, ns="a11oy")
|
| 5442 |
+
print(f"[a11oy] devA deep feeds registered: {_deva_status}", file=_deva_sys.stderr)
|
| 5443 |
+
_A11OY_DEVA_DIAG = {"status": "ok", "registered": _deva_status}
|
| 5444 |
+
except Exception as _deva_e:
|
| 5445 |
+
import sys as _deva_sys, traceback as _deva_tb
|
| 5446 |
+
print(f"[a11oy] devA deep feeds FAILED (non-fatal): {_deva_e!r}", file=_deva_sys.stderr)
|
| 5447 |
+
_deva_tb.print_exc(file=_deva_sys.stderr)
|
| 5448 |
+
_A11OY_DEVA_DIAG = {"status": "FAILED", "error": repr(_deva_e)}
|
| 5449 |
+
# ============================================================================
|
| 5450 |
+
# END: a11oy DEV-A DEEP FEEDS layer
|
| 5451 |
+
# ============================================================================
|
| 5452 |
+
|
| 5453 |
# ============================================================================
|
| 5454 |
# BEGIN: a11oy dev3 OPERATOR ORGAN layer (ingested 3D infra-viz capability)
|
| 5455 |
# ADDITIVE. Path namespace /operator-organ — no overlap with dev1/dev2 blocks.
|