Skip to content

feat(dashboard): Active Observations surface — page 27 + System Health KPI strip#135

Merged
cipher813 merged 1 commit into
mainfrom
feat/active-observations-surface
May 28, 2026
Merged

feat(dashboard): Active Observations surface — page 27 + System Health KPI strip#135
cipher813 merged 1 commit into
mainfrom
feat/active-observations-surface

Conversation

@cipher813
Copy link
Copy Markdown
Owner

Summary

Phase 2 of the observation-registry arc (Phase 1: alpha-engine-config #349 seed + #351 validator). Companion surface to /Artifact_Freshness (page 26).

  • New loaders/observation_registry_loader.py reads OBSERVATION_REGISTRY.yaml directly from local disk.
  • New pages/27_Active_Observations.py — deep-dive surface with filters, table, and per-entry expanders.
  • pages/4_System_Health.py — adds Section 0.5 KPI strip below the existing Section 0 freshness strip.

Why

Per feedback_observe_mode_unconditional_gates_govern_cutover (2026-05-28): observe-mode producer code runs unconditionally; activation flags gate ONLY the consumer-cutover transition. This surface makes the gates visible so a soak that passes its acceptance criterion isn't silently forgotten.

Sibling axis to page 26: freshness asks "does the artifact land on time?"; observation asks "is the consumer plumbed to read it yet?"

Architecture

The registry IS the data — no Lambda or S3 hop. The dashboard EC2 instance already pulls alpha-engine-config via infrastructure/boot-pull.sh (sibling repo at /home/ec2-user/alpha-engine-config). The loader walks four candidate paths: env override → EC2 console path → local-dev path → sibling-directory fallback.

If the file isn't resolvable, both the page and the System Health KPI strip degrade gracefully (page shows an error panel, KPI strip is skipped — same pattern the existing freshness KPI strip uses when the heartbeat S3 key is absent).

Page 27 layout

  • KPI strip (7 metrics: Total / always-on / gated-on / gated-off / substrate / cutover / promoted)
  • Filters (state, phase, producer_repo multiselects + sort selector)
  • Table view (collapsed columns: id, state, phase, producer_repo, flag, earliest_flip_date, cutover_gate, verified, roadmap_ref)
  • Per-entry expanders (full cutover_gate, producer_artifact, composes_with, evidence list)
  • About section (vocabulary reference: state, phase, verification_status)

Test plan

  • Loader smoke: resolves the live YAML, 13 observations loaded, defaults merge confirmed
  • All 13 entries carry the keys the page reads (no KeyErrors)
  • summarize_by_state / summarize_by_phase return correct counts (2 always-on / 4 gated-on / 7 gated-off; 1 substrate / 10 observe / 1 cutover / 1 promoted)
  • Both files parse cleanly (ast.parse)
  • Streamlit server starts clean, HTTP 200 on the page route, no tracebacks in the server log

Deploy after merge

Per CLAUDE.md, code-only PRs need explicit restart on both the console + public services:

```
ae-dashboard "sudo systemctl start boot-pull && \
sudo systemctl restart dashboard && \
sudo systemctl restart nous-ergon-public"
```

boot-pull.sh refreshes both the dashboard repo AND the alpha-engine-config clone the loader reads.

Composes with

  • alpha-engine-config #349 (seed registry, 2026-05-28)
  • alpha-engine-config #351 (validator + GHA chokepoint, 2026-05-28)
  • alpha-engine-data #338 (CheckEnableStandaloneScanner removal, 2026-05-28)
  • feedback_observe_mode_unconditional_gates_govern_cutover (2026-05-28)

🤖 Generated with Claude Code

…h KPI strip

Phase 2 of the observation-registry arc. Companion to the
/Artifact_Freshness surface (page 26) — that page covers the freshness
axis ("does the artifact land on time?"); this one covers the
observation axis ("is the consumer plumbed to read it yet, and what's
the cutover gate?").

Per feedback_observe_mode_unconditional_gates_govern_cutover: observe-
mode producer code runs unconditionally; activation flags gate ONLY
the consumer-cutover transition. This surface makes the gates visible
so a soak that passes its acceptance criterion isn't silently forgotten.

Changes:

- `loaders/observation_registry_loader.py` — direct-from-disk YAML
  loader. No S3 hop / no Lambda dependency (the registry IS the data).
  Path resolution: env override → EC2 console path
  (/home/ec2-user/alpha-engine-config/...) → local-dev path
  (~/Development/alpha-engine-config/...) → sibling-directory fallback.
  Applies the YAML's `defaults` block to each entry (so
  `verification_status: audit-found-needs-curation` survives without
  per-row repetition). Returns None if no path resolves; caller
  renders a "registry not found" panel rather than crashing.

- `pages/27_Active_Observations.py` — deep-dive surface mirroring
  page 26's structure: KPI strip (counts by state + phase), filters
  (state / phase / producer_repo / sort), table view, per-entry
  expanders showing the full cutover_gate / evidence / composes_with
  detail.

- `pages/4_System_Health.py` — adds Section 0.5 "Active Observations"
  KPI strip directly below the existing Section 0 freshness strip.
  Same 7-column layout: total / always-on / gated-on / gated-off /
  substrate / cutover / promoted. Links to /Active_Observations for
  the deep dive.

Live smoke (local):
  - Loader resolves to ~/Development/alpha-engine-config/private-docs/...
  - 13 observations loaded, defaults merge confirmed
  - All 13 entries carry the keys the page reads
  - Streamlit server starts clean, HTTP 200 on the page route, no
    tracebacks in the server log

Deploy: per CLAUDE.md, code-only PRs need explicit restart on both
console + public services. After merge:
  ae-dashboard "sudo systemctl start boot-pull && \
                sudo systemctl restart dashboard && \
                sudo systemctl restart nous-ergon-public"

boot-pull.sh will refresh both the dashboard repo AND the
alpha-engine-config clone the loader reads.

Composes with:
  - alpha-engine-config #349 (seed registry, 2026-05-28)
  - alpha-engine-config #351 (validator + GHA chokepoint)
  - alpha-engine-data #338 (CheckEnableStandaloneScanner removal)
  - feedback_observe_mode_unconditional_gates_govern_cutover (2026-05-28)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying nousergon-marketing with  Cloudflare Pages  Cloudflare Pages

Latest commit: e763cdd
Status: ✅  Deploy successful!
Preview URL: https://2616b5b9.nousergon-marketing.pages.dev
Branch Preview URL: https://feat-active-observations-sur.nousergon-marketing.pages.dev

View logs

@cipher813 cipher813 merged commit 6cba81f into main May 28, 2026
2 checks passed
@cipher813 cipher813 deleted the feat/active-observations-surface branch May 28, 2026 13:53
cipher813 added a commit that referenced this pull request May 28, 2026
…on artifacts

Closes the cross-registry-visibility gap surfaced by the operator
question "are the observation-only artifacts marked as such in the
artifact freshness page?" Severity (warning/critical) was overloaded
and there was no way to tell which warning entries were observe-mode
rollouts vs which were secondary observability for production runs.

Derivation rule (single SoT, no new data — uses cross-link in
OBSERVATION_REGISTRY.yaml + severity in ARTIFACT_REGISTRY.yaml):

  - production: severity == critical OR no active observation entry's
    composes_with references this artifact
  - observation: severity == warning AND at least one active
    (state in {always-on, gated-on}) observation references this id

Live verification: 51 entries → 3 observation + 48 production.
- observation: scanner_candidates_json, factor_profiles_latest,
  research_scorecard_latest
- production: includes critical entries (signals.json,
  predictor_predictions, weekly_collector_manifest) AND warning-
  severity secondary-observability (macro_snapshot,
  research_consolidated_morning)
- Boundary case: signals.json is severity=critical AND observed by
  attractiveness_pillars_phase_4 → classified production (critical
  wins; cross-link doesn't override load-bearing status)

Changes:
- Imports observation_registry_loader (shipped in #135)
- New _load_active_observation_artifact_refs helper (TTL 60s cache)
- _derive_type applies the rule per-row
- df.apply builds a type column
- New "Type" filter (5th multiselect)
- New "Type" column inserted between State and Artifact in display table

Deploy after merge:
  ae-dashboard "sudo systemctl start boot-pull && sudo systemctl restart dashboard"

Composes with alpha-engine-config #349/#351/#352/#355 (registry arc)
+ alpha-engine-dashboard #135 (page 27) + #136 (format_age fix) +
[[feedback_observe_mode_unconditional_gates_govern_cutover]].

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cipher813 added a commit that referenced this pull request May 28, 2026
…on artifacts (#137)

Closes the cross-registry-visibility gap surfaced by the operator
question "are the observation-only artifacts marked as such in the
artifact freshness page?" Severity (warning/critical) was overloaded
and there was no way to tell which warning entries were observe-mode
rollouts vs which were secondary observability for production runs.

Derivation rule (single SoT, no new data — uses cross-link in
OBSERVATION_REGISTRY.yaml + severity in ARTIFACT_REGISTRY.yaml):

  - production: severity == critical OR no active observation entry's
    composes_with references this artifact
  - observation: severity == warning AND at least one active
    (state in {always-on, gated-on}) observation references this id

Live verification: 51 entries → 3 observation + 48 production.
- observation: scanner_candidates_json, factor_profiles_latest,
  research_scorecard_latest
- production: includes critical entries (signals.json,
  predictor_predictions, weekly_collector_manifest) AND warning-
  severity secondary-observability (macro_snapshot,
  research_consolidated_morning)
- Boundary case: signals.json is severity=critical AND observed by
  attractiveness_pillars_phase_4 → classified production (critical
  wins; cross-link doesn't override load-bearing status)

Changes:
- Imports observation_registry_loader (shipped in #135)
- New _load_active_observation_artifact_refs helper (TTL 60s cache)
- _derive_type applies the rule per-row
- df.apply builds a type column
- New "Type" filter (5th multiselect)
- New "Type" column inserted between State and Artifact in display table

Deploy after merge:
  ae-dashboard "sudo systemctl start boot-pull && sudo systemctl restart dashboard"

Composes with alpha-engine-config #349/#351/#352/#355 (registry arc)
+ alpha-engine-dashboard #135 (page 27) + #136 (format_age fix) +
[[feedback_observe_mode_unconditional_gates_govern_cutover]].

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cipher813 added a commit that referenced this pull request May 28, 2026
Surfaces the per-cycle history for each artifact, reading the new
_freshness_monitor/history.json written daily at 04:00 UTC by the
freshness-monitor Lambda's historical mode (alpha-engine-data PR #339).

Closes the gap surfaced 2026-05-28: 'are there gaps in the producer's
history?' — operators want to know not just current-cycle state but
whether last weekend / last month had silent absences.

Changes:

- _load_history loader (TTL 300s — refreshes once/day, not 15min)
- New History (12wk) column on the main table:
    ✅ N/N continuous   — clean history
    ⚠️ G/N gaps        — gappy producer
    ✅ exists (latest)  — latest-pointer present
    ❌ absent (latest)  — latest-pointer missing
    —                   — historical probe hasn't covered this id yet
      (continuous-cadence artifacts skip historical mode)
- New 'Per-artifact history drill-down' section below the main
  table. Each artifact in the filtered view gets an expander
  showing the per-cycle sequence (date / present / size /
  last_modified / error_code). Sort: gappy first, continuous last;
  latest-pointer absent at top, latest-pointer present at bottom.
  First 3 worst-offender entries auto-expand.
- Graceful-degrade: if history.json doesn't exist yet, page shows
  a single info box explaining the daily cron + manual-invoke
  instructions.

Operator caveat: calendar-naive. NYSE holidays may render as
false-positive ❌ absent cells. Calendar-aware probe is a future
enhancement (P3 in the Lambda PR).

Composes with alpha-engine-data PR #339 (historical-mode Lambda)
+ the prior page 26/27 work in #134/#135/#136/#137.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant