Verified defects fixed (each reproduced against live data before and after):
viz-fees.js, viz-send.js, viz-research.js, generate_viz_data.js and data-engine.js divided block fees by 4,000,000 (the consensus WEIGHT limit) instead of 1,000,000 vBYTES. Block 967352 read 0.37 sat/vB instead of the true 1.486. All fee-rate conversions now use vBYTES; the weight-limit uses of 4,000,000 are unchanged and correct.quantities.N was re-based to 26,586 while L_net still held the N=32,000 value (5627.808) and bw_cost_per_year_net held 126230.4 — a consumer trusting them computed SCCR ~17% low. Both are now DERIVED from quantities.N (L_net = 4675.653, bw_net = 104873.8) and the SCCR descriptive value no longer hardcodes a point.integrity_audit.py: recomputes every N-derived value from quantities.N and FAILs on drift (demonstrated firing).d.N || 32000 in the SCCR calculator -> 26,586.getaddrinfo ENOTFOUND) during a network switch, not broken endpoints — it is self-clearing (30% / 24h -> 10% / 12h -> 0% / last 2h). The separate orchestrator-heartbeat alert refers to the engagement orchestrator, which is not launchd-scheduled (dormant, not stalled).research-data.yml) had not published since 2026-09-17 11:12 and the local tracker is disabled by design, so the headline sat at a manual run's value. Added tools/research/sccr_fallback.py: if the committed data/sccr.json is older than 2 h, it re-derives from the local capture DB; otherwise it is inert (never a second writer). Wired into com.bsahi.collectors. Refreshed 0.36238/139 -> 0.321889/140, with fee_allocation and sccr_sensitivity following.research/cgnat-containment-finding.md): both available networks are CGNAT (mobile: symmetric, multi-egress; JioFiber: four stacked private hops). Every alternative path was tested and closed (port-forward, UPnP, NAT-PMP, IPv6, Tor identity, STUN/hole-punch, free sandboxes, Play-with-Docker, ngrok, zrok).tools/net/census.py — unified, environment-adaptive census emitting DISTINCT / CONCURRENCY / CONTAINED with the strongest honest bound.tools/net/deploy_sentinel_remote.sh — one-command deploy of the seeding sentinel to any public-IP host, for the moment one exists.Dated changes to BSAHI's measurements, grades, and methods. Corrections are recorded here with their cause. Newest first.
research-data.yml, every 30 min): the public 24h fee endpoint → the live capture → sccr_live.py --frozen → data/sccr*.json. It is Mac-independent by design — the research tier stays fresh when this machine is off.com.bsahi.sccr-tracker launchd job (daily, live-DB mode) is Disabled by design, not broken. It would be a second writer of sccr.json and race the cloud. Do not re-enable it without retiring the cloud writer first. Earlier "runs daily locally" references were misleading and are corrected here and in sccr_live_runner.js.research-data.yml now stages everything the chain writes — sccr_sensitivity.json, fee_allocation.json, datasets.json, the baked static HTML, and the tokenised research/.html pages — and its rebase-conflict path covers the HTML. Previously it staged sccr.json only, so the cloud wrote those artifacts and then discarded them.com.bsahi.collectors (see the same-day persistent-collector entry).nohup loops under /tmp: macOS clears /tmp on reboot, the loops died on logout, and nothing restarted them — so capture stopped silently while the site kept serving the last values. node_census_capture.py (the canonical N source) and mining_concentration.py had no scheduler at all.tools/agents/29-local-collectors.js (launchd com.bsahi.collectors, every 15 min) runs each instrument on its own cadence from a ~/.bsahi state file. Legacy /tmp/supervise_*.sh loops retired.20-site-health-agent.js now also checks dataset freshness against a tolerable-age table and raises the normal alert path — a dead collector can no longer present as HEALTHY. Exposed in /data/site-health.json.node_census_capture.py: json.load(path) passed a string where a file object is required, crashing on every cached Wayback file.data/mining_concentration.json: pool_concentration.py (schema v2, MEASURED) is canonical; the legacy mining_concentration.py (v1 stub) now refuses to overwrite a v2 file.tools/research/population_snapshot.py -> data/population_snapshot.json: a dated, SHA-256-hashed pin of the population-observability workstream (N and its provenance, the three quantities, the observed activity partition, and every contributing dataset). Drift in any slow-moving input is now detectable; the three re-sampled instruments are flagged as expected to move.census block in research/model-spec.json still carried the superseded N=32000, so the C leg of research/reproduce/cross_check.sh read 32,000 while JS/Python read quantities.N = 26586: the published three-way reproduction failed (0.2406 vs 0.2896). Root cause, not symptom — the stale duplicate was removed so N has exactly one surface (quantities.N), and sccr_live.py reads the N provenance from there (falling back to the reachable-node series, then the legacy addrman mirror). Cross-check now returns ALL THREE IMPLEMENTATIONS AGREE.data/reproduction_verification.json: frozen-capture average 0.240641 -> 0.289645 (= x32000/26586), 155/155 heights matched, max per-block diff 5e-7, spec v2.1.1. research/replicate.md expected-value corrected and extended with the population-replication method.L_net 5,627.80 -> 4,675.65 USD/block.sccr.json, sccr_latest.json, sccr_history.json (37 points, exact rescale), sccr_historical_series.json, sccr_sensitivity.json, fee_allocation.json. Re-based the working paper's headline figures and labelled §5.4 as the pre-re-base record.sccr_historical_reconstruct.py, sccr_dynamics.py and sccr_sensitivity.py now read N from model-spec.json instead of hardcoding 32,000 — single source of truth.tools/research/fee_allocation.py -> data/fee_allocation.json: the three claims on fee revenue, per block, and the subsidy crossover. 2026: security/production claim $198,549/block (fees cover 0.7%, subsidy 107%), storage externality $5,628/block (fees cover 28.8% = the SCCR), fee revenue $1,415/block. At the current price the subsidy alone stops covering the network energy cost of production around 2028./research/fee-allocation; added to the dataset index, the hub, the dashboard and the sitemap.N remains the validating set.getnodeaddresses returning 32,000 as a lower bound on reachable nodes. It is not: getnodeaddresses 32000 returns addresses from the node's address manager (learned via addr gossip) and 32,000 was the requested ceiling, returned in full. It is a lower bound on gossiped addresses — a set including stale/unreachable entries, sized by peer count and uptime — not a node count and not a bound on reachable nodes. Corrected in model-spec.json, node_census.json, the census agent, and the working paper (§5.4 and all dependent rows).getnodeaddresses 0 (returns all known addresses, per Core docs) so the addrman size is exact rather than truncated at the request ceiling.N = 32,000 marked provisional / deprecated as a node count; the SCCR value is unchanged pending Phase C (re-basing N on the observability model). N 32K -> 26.6K would move the headline ~+20%; the direction is unchanged.data/verification_population.json and /research/verification-population.tools/research/integrity_audit.py): heights/dates monotonicity, anchor consistency, unit agreement, provenance, layer classification. Runs as a gate.production_cost_ratio.py stored the hash-rate series (unit TH/s) under the field hashrate_ehs — a 10⁶ mislabel. The power calculation was correct; the label was not. Now stores hashrate_ths and a derived hashrate_ehs, and the audit asserts the relation./research/evidence-matrix): 27 headline numbers classified Observed / Reconstructed / Modelled with source, date and grade.utxo_state_measure.py) and a first Observed gettxoutsetinfo row captured (h671,462 · 72,234,156 UTXOs · 4.39 GB). The 2013-2026 UTXO table remains Reconstructed (grade D)./research/sccr-sensitivity.data/reproduction_verification.json./research/methodology); versioned dataset index (/data/datasets.json) and replication invite (/research/replicate) added.data/datasets.json — deterministic, frozen-input instrument; re-runnable offline.