Skip to content

Commit 6c65e2e

Browse files
authored
Merge pull request #8 from HanSun103/agent/live-forward-readme
Audit README evidence and dashboard links
2 parents 17ad8f3 + 5d1800a commit 6c65e2e

7 files changed

Lines changed: 153 additions & 107 deletions

File tree

README.md

Lines changed: 127 additions & 96 deletions
Large diffs are not rendered by default.

docs/design/DASHBOARD_TWO_PAGE_MERGE.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Two-page dashboard merge design
22

3-
Status: local proposal awaiting approval. Do not merge or deploy yet.
3+
Status: implemented. The GitHub Pages workflow publishes production updates
4+
only from `main`.
45

56
## Decision
67

@@ -80,9 +81,9 @@ The daily pipeline should:
8081
Publishing must be atomic: a cycle should never expose one page with a newer data
8182
contract than the other.
8283

83-
## Approval boundary
84+
## Implementation status
8485

85-
The current local Horizon Comparison preview demonstrates the second page. After
86-
approval, the merge work will add the page switcher and v2 arm support to the
87-
original dashboard, generate the final `horizons.html`, update the refresh and
88-
deployment workflows, and then request approval before pushing.
86+
The shared page switcher, v2 arm support, partial-outcome display, collapsed
87+
SHAP panels, final `horizons.html`, daily refresh integration, public payload
88+
validation, and GitHub Pages packaging are implemented. The deployment job
89+
runs only for `main`.

site/data/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema_version": 3,
3-
"generated_at_utc": "2026-07-29T22:29:54.012984+00:00",
3+
"generated_at_utc": "2026-07-29T23:59:49.062830+00:00",
44
"latest_decision_date": "2026-07-28",
55
"snapshot_count": 17,
66
"evaluation_count": 14,

site/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
33
<title>Live Forward Research Monitor</title>
44
<link rel="stylesheet" href="./assets/dashboard.css"></head><body>
5-
<header><div class="hero-row"><div><div class="eyebrow">AI Portfolio Research</div><h1>Live Forward Monitor</h1><p>Out-of-sample model portfolios tracked against SPY. Every session uses the portfolio frozen before its evaluation window.</p><nav class="page-switcher" aria-label="Monitor pages"><a class="page-link active" href="dashboard.html" aria-current="page"><strong>Live Forward Monitor</strong><small>Default · daily evidence and stock-level view</small></a><a class="page-link" href="./horizons.html"><strong>Horizon Comparison</strong><small>5 / 10 / 20-session experiment</small></a></nav></div><div class="hero-badge"><span>Default view</span><strong>Daily evidence</strong><span>Frozen-cohort monitor</span></div></div></header>
5+
<header><div class="hero-row"><div><div class="eyebrow">AI Portfolio Research</div><h1>Live Forward Monitor</h1><p>Out-of-sample model portfolios tracked against SPY. Every session uses the portfolio frozen before its evaluation window.</p><nav class="page-switcher" aria-label="Monitor pages"><a class="page-link active" href="./index.html" aria-current="page"><strong>Live Forward Monitor</strong><small>Default · daily evidence and stock-level view</small></a><a class="page-link" href="./horizons.html"><strong>Horizon Comparison</strong><small>5 / 10 / 20-session experiment</small></a></nav></div><div class="hero-badge"><span>Default view</span><strong>Daily evidence</strong><span>Frozen-cohort monitor</span></div></div></header>
66
<main>
77
<div class="toolbar panel"><div class="toolbar-group"><label>Start date<input id="startDate" type="date"></label><label>End date<input id="endDate" type="date"></label><div class="segmented"><button data-range="latest">Latest session</button><button data-range="5">5 sessions</button><button data-range="all" class="active">All available</button></div></div><div class="toolbar-group"><button id="refreshData" title="Reload deployed dashboard data">Refresh data</button><div class="status" id="dataStatus">Frozen evidence loaded</div></div></div>
88
<section class="pending-panel panel" id="nextSession"></section>

src/experiments/live_dashboard_publish.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,16 @@ def publish_live_dashboard(
333333

334334
latest_decision = max(item["decision_date"] for item in snapshots)
335335
assets = dashboard_site_assets()
336-
assets["index.html"] = assets["index.html"].replace(
337-
'href="../live_forward_horizon_matched_v2/dashboard.html"',
338-
'href="./horizons.html"',
336+
assets["index.html"] = (
337+
assets["index.html"]
338+
.replace(
339+
'class="page-link active" href="dashboard.html"',
340+
'class="page-link active" href="./index.html"',
341+
)
342+
.replace(
343+
'href="../live_forward_horizon_matched_v2/dashboard.html"',
344+
'href="./horizons.html"',
345+
)
339346
)
340347
for relative, contents in assets.items():
341348
target = destination / relative

src/experiments/public_dashboard_validation.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ def validate_public_dashboard_bundle(output_dir: str | Path) -> dict[str, Any]:
5050
exposed = [token for token in forbidden if token in public_text]
5151
if exposed:
5252
raise ValueError(f"Public dashboard contains forbidden private fields: {exposed}")
53+
index_html = (root / "index.html").read_text(encoding="utf-8")
54+
if 'href="dashboard.html"' in index_html:
55+
raise ValueError(
56+
"Public dashboard must link its default page through index.html"
57+
)
5358

5459
payload = json.loads(dashboard_text)
5560
snapshots = payload.get("snapshots", []) if isinstance(payload, dict) else payload

tests/test_live_dashboard_publish.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ def test_publish_site_splits_assets_and_passes_validation(
153153
horizons = (site / "horizons.html").read_text(encoding="utf-8")
154154
assert '<link rel="stylesheet" href="./assets/dashboard.css">' in index
155155
assert '<script src="./assets/loader.js" defer></script>' in index
156+
assert 'href="./index.html" aria-current="page"' in index
157+
assert 'href="dashboard.html"' not in index
156158
assert 'href="./horizons.html"' in index
157159
assert 'href="./index.html"' in horizons
158160
assert "Horizon Comparison" in horizons

0 commit comments

Comments
 (0)