From c87d506aecf4f4900565dc2b63630a45db1fb953 Mon Sep 17 00:00:00 2001 From: ProfRandom92 <159939812+ProfRandom92@users.noreply.github.com> Date: Mon, 11 May 2026 12:33:30 +0200 Subject: [PATCH] Add dashboard release health summary artifact --- .github/workflows/agent-checks.yml | 5 +- docs/AGENT_WORKFLOW.md | 17 +- docs/API_SURFACE.md | 35 ++- docs/reports/dashboard-health-summary.json | 116 ++++++++ docs/reports/dashboard-health-summary.md | 66 +++++ scripts/generate_dashboard_health_summary.py | 286 +++++++++++++++++++ 6 files changed, 517 insertions(+), 8 deletions(-) create mode 100644 docs/reports/dashboard-health-summary.json create mode 100644 docs/reports/dashboard-health-summary.md create mode 100644 scripts/generate_dashboard_health_summary.py diff --git a/.github/workflows/agent-checks.yml b/.github/workflows/agent-checks.yml index c75783c..9faea2e 100644 --- a/.github/workflows/agent-checks.yml +++ b/.github/workflows/agent-checks.yml @@ -17,7 +17,7 @@ jobs: python-version: '3.11' - name: Compile helper scripts - run: python -m py_compile scripts/repo_intake.py scripts/run_checks.py scripts/validate_contracts.py scripts/generate_contract_fixtures.py scripts/validate_api_exports.py scripts/generate_project_health_report.py + run: python -m py_compile scripts/repo_intake.py scripts/run_checks.py scripts/validate_contracts.py scripts/generate_contract_fixtures.py scripts/validate_api_exports.py scripts/generate_project_health_report.py scripts/generate_dashboard_health_summary.py - name: Generate repository intake report run: python scripts/repo_intake.py @@ -37,6 +37,9 @@ jobs: - name: Generate project health report run: python scripts/generate_project_health_report.py + - name: Generate dashboard health summary + run: python scripts/generate_dashboard_health_summary.py + - name: Upload agent reports if: always() uses: actions/upload-artifact@v4 diff --git a/docs/AGENT_WORKFLOW.md b/docs/AGENT_WORKFLOW.md index 9a536ea..f974ff7 100644 --- a/docs/AGENT_WORKFLOW.md +++ b/docs/AGENT_WORKFLOW.md @@ -68,16 +68,24 @@ changes: `docs/reports/project-health-report.md` as a deterministic snapshot of agent workflow readiness, contract/API validation surfaces, existing reports, and promotion checklist status without reading raw payload contents. -6. Let `.github/workflows/agent-checks.yml` provide the PR CI guardrail by +6. Run `python scripts/generate_dashboard_health_summary.py` after the local + reports are current. It writes `docs/reports/dashboard-health-summary.md` and + `docs/reports/dashboard-health-summary.json` as compact dashboard-facing + release-readiness artifacts from file-existence and simple metadata checks. +7. Let `.github/workflows/agent-checks.yml` provide the PR CI guardrail by compiling the helper scripts, regenerating intake evidence, generating contract fixtures, validating API/export payload shapes, generating the - project health report, and running the same safe checks on Python 3.11. + project health report, generating the dashboard health summary, and running + the same safe checks on Python 3.11. These checks complement benchmark, regression, sanitization, and forensic replay reports from `ProfRandom92/Comptext-Daimler-Experiment-`. They do not replace benchmark review and do not introduce runtime coupling between repositories. Use only sanitized summaries or synthetic examples when connecting those reports to -Comptextv7 PR evidence. +Comptextv7 PR evidence. Future dashboard/UI work should consume +`docs/reports/dashboard-health-summary.json` as a static status source for +release-readiness cards, missing-artifact lists, and safety notes instead of +requiring a live server, network access, or real Daimler data. ## Cross-repo promotion gate @@ -170,6 +178,9 @@ Before opening a Comptextv7 PR, agents should verify: issues. - [ ] Tests or validation steps are documented, or the PR states why no code execution was required. +- [ ] Release-readiness changes run `python scripts/generate_dashboard_health_summary.py` + and update `docs/reports/dashboard-health-summary.md` plus + `docs/reports/dashboard-health-summary.json` when generated. - [ ] API/dashboard/export changes run `python scripts/generate_contract_fixtures.py` and `python scripts/validate_api_exports.py`, with reports checked in under `docs/reports/contract-fixture-generation-report.md` and diff --git a/docs/API_SURFACE.md b/docs/API_SURFACE.md index abd67d8..f2da431 100644 --- a/docs/API_SURFACE.md +++ b/docs/API_SURFACE.md @@ -18,10 +18,11 @@ API, dashboard, and export contract changes should start with `python scripts/repo_intake.py` so reviewers can see the detected repository shape and likely API/dashboard/report areas before implementation. After making changes, run `python scripts/run_checks.py`, `python scripts/validate_contracts.py`, -`python scripts/generate_contract_fixtures.py`, and -`python scripts/validate_api_exports.py` to perform deterministic local validation -without installing dependencies, using real Daimler data, or requiring network -access. +`python scripts/generate_contract_fixtures.py`, +`python scripts/validate_api_exports.py`, and +`python scripts/generate_dashboard_health_summary.py` to perform deterministic +local validation without installing dependencies, using real Daimler data, or +requiring network access. The `.github/workflows/agent-checks.yml` workflow mirrors these steps for pull requests on Python 3.11 and uploads the generated `docs/reports/` artifacts when @@ -75,6 +76,15 @@ summaries include: Comptextv7. They should remain deterministic enough for review, small enough for PR artifacts, and explicit about any schema changes. +`docs/reports/dashboard-health-summary.json` is the dashboard-facing static +release-readiness artifact generated by +`python scripts/generate_dashboard_health_summary.py`. Future dashboard/UI work +can load that JSON directly from committed reports or CI artifacts to render +status badges, missing-artifact callouts, and next-action lists without starting +a live server or using real Daimler data. The companion Markdown report, +`docs/reports/dashboard-health-summary.md`, provides the human-readable review +summary. + Future report endpoints such as `/reports/benchmark-summary`, `/reports/regression-summary`, or `/reports/sanitization-summary` should not be added until a schema, security review, and issue scope approve them. If added, @@ -149,6 +159,23 @@ the generated example, checks required fields, simple field types, the standard library, require no live server, and must remain limited to synthetic values. +### Dashboard release health summary + +Run the dashboard health summary generator after local validation artifacts are +available: + +```bash +python scripts/generate_dashboard_health_summary.py +``` + +The generator inspects local report/check artifact existence under +`docs/reports/` and writes both `docs/reports/dashboard-health-summary.md` and +`docs/reports/dashboard-health-summary.json` with deterministic synthetic +metadata. The JSON includes `overall_status`, named validation `checks`, +`required_artifacts_present`, `missing_artifacts`, `next_recommended_actions`, +and `safety_notes`, so future UI work can consume one compact artifact instead +of reimplementing release-readiness logic. + ## Compatibility with benchmark/regression reports Benchmark summaries should map to Comptextv7 review surfaces this way: diff --git a/docs/reports/dashboard-health-summary.json b/docs/reports/dashboard-health-summary.json new file mode 100644 index 0000000..733961a --- /dev/null +++ b/docs/reports/dashboard-health-summary.json @@ -0,0 +1,116 @@ +{ + "checks": { + "api_export_validation_report": { + "description": "Synthetic API/export contract validation report.", + "key": "api_export_validation_report", + "path": "docs/reports/api-export-validation-report.md", + "present": true, + "required": true, + "size_bytes": 738, + "status": "present" + }, + "contract_fixture_generation_report": { + "description": "Synthetic API/dashboard fixture generation report.", + "key": "contract_fixture_generation_report", + "path": "docs/reports/contract-fixture-generation-report.md", + "present": true, + "required": true, + "size_bytes": 617, + "status": "present" + }, + "contract_validation_report": { + "description": "Contract schema validation report.", + "key": "contract_validation_report", + "path": "docs/reports/contract-validation-report.md", + "present": true, + "required": true, + "size_bytes": 1403, + "status": "present" + }, + "cross_repo_release_checklist": { + "description": "Cross-repo release checklist for sanitized promotion evidence.", + "key": "cross_repo_release_checklist", + "path": "docs/CROSS_REPO_RELEASE_CHECKLIST.md", + "present": true, + "required": true, + "size_bytes": 9343, + "status": "present" + }, + "project_health_report": { + "description": "Generated project health and release status report.", + "key": "project_health_report", + "path": "docs/reports/project-health-report.md", + "present": true, + "required": true, + "size_bytes": 4121, + "status": "present" + } + }, + "generated_at": "2026-01-01T00:00:00Z", + "missing_artifacts": { + "optional_cross_repo": [ + "benchmark-summary.json", + "regression-summary.json", + "sanitization-summary.json", + "report-contract-validation-report.md" + ], + "required_local": [] + }, + "next_recommended_actions": [ + "Render docs/reports/dashboard-health-summary.json in future dashboard/UI work as a static release-readiness widget.", + "Attach optional sanitized cross-repo benchmark, regression, sanitization, and report-contract summaries when promotion evidence is available.", + "Keep API/export contract validation and fixture generation in CI before release promotion." + ], + "optional_cross_repo_artifacts": [ + { + "description": "Optional sanitized benchmark promotion summary from the experiment repository.", + "key": "benchmark_summary", + "path": "benchmark-summary.json", + "present": false, + "required": false, + "status": "missing" + }, + { + "description": "Optional sanitized regression promotion summary from the experiment repository.", + "key": "regression_summary", + "path": "regression-summary.json", + "present": false, + "required": false, + "status": "missing" + }, + { + "description": "Optional sanitized data-handling summary from the experiment repository.", + "key": "sanitization_summary", + "path": "sanitization-summary.json", + "present": false, + "required": false, + "status": "missing" + }, + { + "description": "Optional report-contract validation evidence from the experiment repository.", + "key": "report_contract_validation_report", + "path": "report-contract-validation-report.md", + "present": false, + "required": false, + "status": "missing" + } + ], + "overall_status": "yellow", + "related_experiment_repo": "ProfRandom92/Comptext-Daimler-Experiment-", + "required_artifacts_present": [ + "docs/reports/project-health-report.md", + "docs/reports/contract-validation-report.md", + "docs/reports/api-export-validation-report.md", + "docs/reports/contract-fixture-generation-report.md", + "docs/CROSS_REPO_RELEASE_CHECKLIST.md" + ], + "safety_notes": [ + "Synthetic/static metadata only; generated_at is deterministic.", + "No real Daimler data, customer payloads, secrets, cookies, tokens, raw production logs, or proprietary documents are included.", + "No live server, network access, external dependencies, or experiment-repository checkout is required.", + "The generator uses file-existence and small filesystem metadata checks only and does not read report bodies." + ], + "summary_type": "dashboard_release_health", + "synthetic": true, + "target_repo": "ProfRandom92/Comptextv7" +} diff --git a/docs/reports/dashboard-health-summary.md b/docs/reports/dashboard-health-summary.md new file mode 100644 index 0000000..7f3c41b --- /dev/null +++ b/docs/reports/dashboard-health-summary.md @@ -0,0 +1,66 @@ +# Dashboard Release Health Summary + +This deterministic artifact converts local project health, contract validation, API/export validation, fixture generation, and cross-repo promotion signals into compact release-readiness metadata for future dashboard/UI rendering. + +## Repository overview + +- target_repo: `ProfRandom92/Comptextv7` +- related_experiment_repo: `ProfRandom92/Comptext-Daimler-Experiment-` +- summary_type: `dashboard_release_health` +- generated_at: `2026-01-01T00:00:00Z` +- synthetic: `true` +- live_server_required: `false` +- network_required: `false` +- real_daimler_data_required: `false` + +## Overall status + +- overall_status: `yellow` +- status_basis: Missing required local Comptextv7 validation artifacts are red; complete local validation with missing optional cross-repo promotion artifacts is yellow; complete local and optional promotion artifacts are green. + +## Local validation artifacts + +| Artifact | Status | Notes | +| --- | --- | --- | +| `docs/reports/project-health-report.md` | present | Generated project health and release status report. | +| `docs/reports/contract-validation-report.md` | present | Contract schema validation report. | +| `docs/reports/api-export-validation-report.md` | present | Synthetic API/export contract validation report. | +| `docs/reports/contract-fixture-generation-report.md` | present | Synthetic API/dashboard fixture generation report. | +| `docs/CROSS_REPO_RELEASE_CHECKLIST.md` | present | Cross-repo release checklist for sanitized promotion evidence. | + +## Optional cross-repo promotion artifacts + +These sanitized promotion summaries may be copied into `docs/reports/` when available from `ProfRandom92/Comptext-Daimler-Experiment-`, but they are not required for this local dashboard summary. + +| Artifact | Status | Notes | +| --- | --- | --- | +| `benchmark-summary.json` | missing | Optional sanitized benchmark promotion summary from the experiment repository. | +| `regression-summary.json` | missing | Optional sanitized regression promotion summary from the experiment repository. | +| `sanitization-summary.json` | missing | Optional sanitized data-handling summary from the experiment repository. | +| `report-contract-validation-report.md` | missing | Optional report-contract validation evidence from the experiment repository. | + +## Missing artifacts + +### Required local artifacts + +- None. + +### Optional cross-repo artifacts + +- `benchmark-summary.json` +- `regression-summary.json` +- `sanitization-summary.json` +- `report-contract-validation-report.md` + +## Next recommended actions + +- Render docs/reports/dashboard-health-summary.json in future dashboard/UI work as a static release-readiness widget. +- Attach optional sanitized cross-repo benchmark, regression, sanitization, and report-contract summaries when promotion evidence is available. +- Keep API/export contract validation and fixture generation in CI before release promotion. + +## Safety notes + +- Synthetic/static metadata only; generated_at is deterministic. +- No real Daimler data, customer payloads, secrets, cookies, tokens, raw production logs, or proprietary documents are included. +- No live server, network access, external dependencies, or experiment-repository checkout is required. +- The generator uses file-existence and small filesystem metadata checks only and does not read report bodies. diff --git a/scripts/generate_dashboard_health_summary.py b/scripts/generate_dashboard_health_summary.py new file mode 100644 index 0000000..0eab287 --- /dev/null +++ b/scripts/generate_dashboard_health_summary.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +"""Generate deterministic dashboard release health summary artifacts. + +The generator intentionally uses file-existence and small filesystem metadata +checks only. It does not read report bodies, contact network services, require a +live server, or inspect real experiment data. +""" + +from __future__ import annotations + +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable + +ROOT = Path(__file__).resolve().parents[1] +REPORT_DIR = ROOT / "docs" / "reports" +SUMMARY_MD_PATH = REPORT_DIR / "dashboard-health-summary.md" +SUMMARY_JSON_PATH = REPORT_DIR / "dashboard-health-summary.json" + +GENERATED_AT = "2026-01-01T00:00:00Z" +TARGET_REPO = "ProfRandom92/Comptextv7" +RELATED_EXPERIMENT_REPO = "ProfRandom92/Comptext-Daimler-Experiment-" +SUMMARY_TYPE = "dashboard_release_health" + + +@dataclass(frozen=True) +class Artifact: + """A small release-readiness artifact checked by path only.""" + + key: str + path: str + description: str + required: bool + + +LOCAL_ARTIFACTS = [ + Artifact( + "project_health_report", + "docs/reports/project-health-report.md", + "Generated project health and release status report.", + True, + ), + Artifact( + "contract_validation_report", + "docs/reports/contract-validation-report.md", + "Contract schema validation report.", + True, + ), + Artifact( + "api_export_validation_report", + "docs/reports/api-export-validation-report.md", + "Synthetic API/export contract validation report.", + True, + ), + Artifact( + "contract_fixture_generation_report", + "docs/reports/contract-fixture-generation-report.md", + "Synthetic API/dashboard fixture generation report.", + True, + ), + Artifact( + "cross_repo_release_checklist", + "docs/CROSS_REPO_RELEASE_CHECKLIST.md", + "Cross-repo release checklist for sanitized promotion evidence.", + True, + ), +] + +OPTIONAL_CROSS_REPO_ARTIFACTS = [ + Artifact( + "benchmark_summary", + "benchmark-summary.json", + "Optional sanitized benchmark promotion summary from the experiment repository.", + False, + ), + Artifact( + "regression_summary", + "regression-summary.json", + "Optional sanitized regression promotion summary from the experiment repository.", + False, + ), + Artifact( + "sanitization_summary", + "sanitization-summary.json", + "Optional sanitized data-handling summary from the experiment repository.", + False, + ), + Artifact( + "report_contract_validation_report", + "report-contract-validation-report.md", + "Optional report-contract validation evidence from the experiment repository.", + False, + ), +] + +SAFETY_NOTES = [ + "Synthetic/static metadata only; generated_at is deterministic.", + "No real Daimler data, customer payloads, secrets, cookies, tokens, raw production logs, or proprietary documents are included.", + "No live server, network access, external dependencies, or experiment-repository checkout is required.", + "The generator uses file-existence and small filesystem metadata checks only and does not read report bodies.", +] + +NEXT_ACTIONS_READY = [ + "Render docs/reports/dashboard-health-summary.json in future dashboard/UI work as a static release-readiness widget.", + "Attach optional sanitized cross-repo benchmark, regression, sanitization, and report-contract summaries when promotion evidence is available.", + "Keep API/export contract validation and fixture generation in CI before release promotion.", +] + +NEXT_ACTIONS_BLOCKED = [ + "Regenerate missing local validation artifacts before using this summary for release readiness.", + "Run the agent workflow checks and commit the updated docs/reports artifacts.", + *NEXT_ACTIONS_READY, +] + + +ArtifactRecord = dict[str, object] + + +def relative_path(path: Path) -> str: + """Return a repository-relative POSIX path.""" + return path.relative_to(ROOT).as_posix() + + +def artifact_record(artifact: Artifact, base_dir: Path | None = None) -> ArtifactRecord: + """Build a deterministic artifact status record without reading contents.""" + absolute_path = (base_dir / artifact.path) if base_dir else (ROOT / artifact.path) + present = absolute_path.exists() + record: ArtifactRecord = { + "key": artifact.key, + "path": artifact.path, + "required": artifact.required, + "present": present, + "status": "present" if present else "missing", + "description": artifact.description, + } + if present and absolute_path.is_file(): + record["size_bytes"] = absolute_path.stat().st_size + return record + + +def determine_overall_status(local_records: Iterable[ArtifactRecord], optional_records: Iterable[ArtifactRecord]) -> str: + """Return release-readiness status from local and optional artifacts.""" + local_records = list(local_records) + optional_records = list(optional_records) + required_missing = [record for record in local_records if record["required"] and not record["present"]] + if required_missing: + return "red" + + optional_missing = [record for record in optional_records if not record["present"]] + if optional_missing: + return "yellow" + + return "green" + + +def build_summary() -> dict[str, object]: + """Build a deterministic dashboard health summary payload.""" + local_records = [artifact_record(artifact) for artifact in LOCAL_ARTIFACTS] + optional_records = [artifact_record(artifact, REPORT_DIR) for artifact in OPTIONAL_CROSS_REPO_ARTIFACTS] + missing_required = [record["path"] for record in local_records if not record["present"]] + missing_optional = [record["path"] for record in optional_records if not record["present"]] + overall_status = determine_overall_status(local_records, optional_records) + + return { + "target_repo": TARGET_REPO, + "related_experiment_repo": RELATED_EXPERIMENT_REPO, + "summary_type": SUMMARY_TYPE, + "synthetic": True, + "generated_at": GENERATED_AT, + "overall_status": overall_status, + "checks": {record["key"]: record for record in local_records}, + "required_artifacts_present": [record["path"] for record in local_records if record["present"]], + "missing_artifacts": { + "required_local": missing_required, + "optional_cross_repo": missing_optional, + }, + "optional_cross_repo_artifacts": optional_records, + "next_recommended_actions": NEXT_ACTIONS_READY if overall_status != "red" else NEXT_ACTIONS_BLOCKED, + "safety_notes": SAFETY_NOTES, + } + + +def status_label(present: object) -> str: + """Return a compact Markdown status label.""" + return "present" if present else "missing" + + +def table_rows(records: Iterable[ArtifactRecord]) -> list[str]: + """Render artifact records as Markdown table rows.""" + rows = [] + for record in records: + rows.append( + f"| `{record['path']}` | {status_label(record['present'])} | {record['description']} |" + ) + return rows + + +def bullet_list(items: Iterable[object], empty: str) -> list[str]: + """Render a deterministic Markdown bullet list.""" + values = [str(item) for item in items] + if not values: + return [f"- {empty}"] + return [f"- `{value}`" for value in values] + + +def build_markdown(summary: dict[str, object]) -> str: + """Build the dashboard-facing Markdown summary.""" + local_records = list(summary["checks"].values()) # type: ignore[union-attr] + optional_records = list(summary["optional_cross_repo_artifacts"]) # type: ignore[arg-type] + missing = summary["missing_artifacts"] # type: ignore[assignment] + + lines = [ + "# Dashboard Release Health Summary", + "", + "This deterministic artifact converts local project health, contract validation, API/export validation, fixture generation, and cross-repo promotion signals into compact release-readiness metadata for future dashboard/UI rendering.", + "", + "## Repository overview", + "", + f"- target_repo: `{summary['target_repo']}`", + f"- related_experiment_repo: `{summary['related_experiment_repo']}`", + f"- summary_type: `{summary['summary_type']}`", + f"- generated_at: `{summary['generated_at']}`", + "- synthetic: `true`", + "- live_server_required: `false`", + "- network_required: `false`", + "- real_daimler_data_required: `false`", + "", + "## Overall status", + "", + f"- overall_status: `{summary['overall_status']}`", + "- status_basis: Missing required local Comptextv7 validation artifacts are red; complete local validation with missing optional cross-repo promotion artifacts is yellow; complete local and optional promotion artifacts are green.", + "", + "## Local validation artifacts", + "", + "| Artifact | Status | Notes |", + "| --- | --- | --- |", + *table_rows(local_records), + "", + "## Optional cross-repo promotion artifacts", + "", + "These sanitized promotion summaries may be copied into `docs/reports/` when available from `ProfRandom92/Comptext-Daimler-Experiment-`, but they are not required for this local dashboard summary.", + "", + "| Artifact | Status | Notes |", + "| --- | --- | --- |", + *table_rows(optional_records), + "", + "## Missing artifacts", + "", + "### Required local artifacts", + "", + *bullet_list(missing["required_local"], "None."), # type: ignore[index] + "", + "### Optional cross-repo artifacts", + "", + *bullet_list(missing["optional_cross_repo"], "None."), # type: ignore[index] + "", + "## Next recommended actions", + "", + *[f"- {item}" for item in summary["next_recommended_actions"]], # type: ignore[index] + "", + "## Safety notes", + "", + *[f"- {item}" for item in summary["safety_notes"]], # type: ignore[index] + "", + ] + return "\n".join(lines) + + +def write_summary(summary: dict[str, object]) -> None: + """Write Markdown and JSON summary artifacts.""" + REPORT_DIR.mkdir(parents=True, exist_ok=True) + SUMMARY_JSON_PATH.write_text(json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8") + SUMMARY_MD_PATH.write_text(build_markdown(summary), encoding="utf-8") + + +def main() -> int: + summary = build_summary() + write_summary(summary) + print(f"Wrote {relative_path(SUMMARY_MD_PATH)}") + print(f"Wrote {relative_path(SUMMARY_JSON_PATH)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())