diff --git a/.github/workflows/agent-checks.yml b/.github/workflows/agent-checks.yml index ffbd1ff..c75783c 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 + 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 - name: Generate repository intake report run: python scripts/repo_intake.py @@ -34,6 +34,9 @@ jobs: - name: Validate API export contract fixtures run: python scripts/validate_api_exports.py + - name: Generate project health report + run: python scripts/generate_project_health_report.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 45f389f..9a536ea 100644 --- a/docs/AGENT_WORKFLOW.md +++ b/docs/AGENT_WORKFLOW.md @@ -63,10 +63,15 @@ changes: API/dashboard/export fixture against `contracts/api-dashboard.schema.json`. It writes `docs/reports/api-export-validation-report.md` and requires no live server. -5. Let `.github/workflows/agent-checks.yml` provide the PR CI guardrail by +5. Run `python scripts/generate_project_health_report.py` before release-readiness + review or cross-repo promotion review. It writes + `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 compiling the helper scripts, regenerating intake evidence, generating - contract fixtures, validating API/export payload shapes, and running the same - safe checks on Python 3.11. + contract fixtures, validating API/export payload shapes, generating the + project health report, 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 diff --git a/docs/CROSS_REPO_RELEASE_CHECKLIST.md b/docs/CROSS_REPO_RELEASE_CHECKLIST.md index 907dfd6..c05b0ce 100644 --- a/docs/CROSS_REPO_RELEASE_CHECKLIST.md +++ b/docs/CROSS_REPO_RELEASE_CHECKLIST.md @@ -68,6 +68,7 @@ python scripts/run_checks.py python scripts/validate_contracts.py python scripts/generate_contract_fixtures.py python scripts/validate_api_exports.py +python scripts/generate_project_health_report.py ``` If a command cannot run because of an environment limitation, document the exact @@ -83,6 +84,9 @@ Promotion may proceed only when all of these statements are true: - The report contract validation passes in the experiment repository. - Comptextv7 local checks pass. - API/export contract validation passes. +- The generated project health report exists at + `docs/reports/project-health-report.md` and reflects the current validation + and promotion-readiness snapshot. - The PR is small and reversible. - The change has clear ownership in Comptextv7. - The PR uses synthetic examples only and avoids runtime coupling to the @@ -101,6 +105,8 @@ PR, when any of these conditions apply: - Report contract validation fails. - Comptextv7 checks fail. - API/export contract validation fails. +- Project health report generation fails or records missing required local + validation evidence without an accepted explanation. - Ownership between the experiment repository and runtime repository is unclear. - The proposed PR requires runtime coupling to the experiment repository without a separate approved issue. @@ -116,6 +122,8 @@ conditions appear after merge: - New sanitizer findings. - Unexpected runtime failures. - Missing report artifacts. +- Stale or missing project health report after validation, promotion, or release + readiness changes. - Evidence that sensitive material entered the repository, dashboard, exports, or documentation. @@ -140,6 +148,8 @@ conditions appear after merge: - [ ] Required experiment artifacts are listed and reviewed. - [ ] Required Comptextv7 validation commands are run or explicitly documented as not required because of a safe environment limitation. +- [ ] `python scripts/generate_project_health_report.py` has refreshed + `docs/reports/project-health-report.md` for the current PR. - [ ] Go/no-go decision is documented. - [ ] Rollback criteria are understood and noted when relevant. - [ ] PR scope is small, reviewable, and reversible. @@ -157,9 +167,12 @@ before creating a Comptextv7 implementation PR. Agents should: 3. Create a Comptextv7 issue when ownership, safety, or release impact is unclear. 4. Keep promotion PRs narrow and avoid unrelated refactors. 5. Run the required Comptextv7 validation commands for implementation PRs. -6. Use documentation-only updates when the finding only changes review policy or +6. Generate and review `docs/reports/project-health-report.md` when release + readiness, validation evidence, API/export contracts, or cross-repo promotion + status changes. +7. Use documentation-only updates when the finding only changes review policy or release criteria. -7. Never introduce imports, generated vendor folders, submodules, or CI coupling +8. Never introduce imports, generated vendor folders, submodules, or CI coupling to the experiment repository as part of this checklist. ## Example synthetic promotion record @@ -184,6 +197,7 @@ required_comptextv7_commands: - python scripts/validate_contracts.py - python scripts/generate_contract_fixtures.py - python scripts/validate_api_exports.py + - python scripts/generate_project_health_report.py security_review: synthetic_only: true real_daimler_data_present: false diff --git a/docs/reports/project-health-report.md b/docs/reports/project-health-report.md new file mode 100644 index 0000000..8fc5f92 --- /dev/null +++ b/docs/reports/project-health-report.md @@ -0,0 +1,106 @@ +# Project Health and Release Status Report + +This deterministic report summarizes local agent workflow readiness, contract validation surfaces, API/export validation, and cross-repo promotion readiness for review. + +## Repository overview + +- target_repo: `ProfRandom92/Comptextv7` +- related_experiment_repo: `ProfRandom92/Comptext-Daimler-Experiment-` +- generated_at: `2026-01-01T00:00:00Z` +- synthetic: `true` +- live_server_required: `false` +- network_required: `false` +- real_daimler_data_required: `false` + +## Detected workflow files + +- `.github/workflows/agent-checks.yml` +- `.github/workflows/ci.yml` + +## Detected scripts + +- `scripts/generate_contract_fixtures.py` +- `scripts/generate_project_health_report.py` +- `scripts/repo_intake.py` +- `scripts/run_checks.py` +- `scripts/validate.py` +- `scripts/validate_api_exports.py` +- `scripts/validate_contracts.py` + +## Contract files + +- `contracts/api-dashboard.schema.json` +- `contracts/benchmark-summary.schema.json` +- `contracts/regression-summary.schema.json` +- `contracts/sanitization-summary.schema.json` + +## Contract examples + +- `contracts/examples/api-dashboard.example.json` +- `contracts/examples/benchmark-summary.example.json` +- `contracts/examples/regression-summary.example.json` +- `contracts/examples/sanitization-summary.example.json` + +## Existing report files + +- `docs/reports/api-export-validation-report.md` +- `docs/reports/check-report.md` +- `docs/reports/contract-fixture-generation-report.md` +- `docs/reports/contract-validation-report.md` +- `docs/reports/project-health-report.md` +- `docs/reports/repo-intake-report.md` + +## Required validation commands + +- `python scripts/repo_intake.py` +- `python scripts/run_checks.py` +- `python scripts/validate_contracts.py` +- `python scripts/generate_contract_fixtures.py` +- `python scripts/validate_api_exports.py` +- `python scripts/generate_project_health_report.py` + +## Release readiness checklist + +| Item | Status | Notes | +| --- | --- | --- | +| repo intake report exists | present | Generated by `python scripts/repo_intake.py`. | +| check report exists | present | Generated by `python scripts/run_checks.py`. | +| contract validation report exists | present | Generated by `python scripts/validate_contracts.py`. | +| API/export validation report exists | present | Generated by `python scripts/validate_api_exports.py`. | +| project health report exists | present | Generated by `python scripts/generate_project_health_report.py`. | +| no real Daimler data included | policy-required | This report uses path and existence metadata only. | +| no secrets included | policy-required | This report does not print file contents, tokens, cookies, or credentials. | +| PR is small and reversible | reviewer-confirmed | Keep changes limited to generator, generated report, CI, and docs. | + +## Cross-repo promotion readiness checklist + +### Required experiment artifacts + +- `benchmark-summary.json` +- `regression-summary.json` +- `sanitization-summary.json` +- `report-contract-validation-report.md` + +### Required Comptextv7 artifacts + +| Artifact | Status | Notes | +| --- | --- | --- | +| contract schemas | present | Detected under `contracts/`. | +| contract examples | present | Detected under `contracts/examples/`. | +| API/export validation report | present | Local synthetic validation evidence. | +| cross-repo release checklist | present | Promotion gate documentation. | + +## Next recommended PRs + +- `dashboard rendering of sanitized benchmark summary` +- `optional JSON artifact importer` +- `release readiness badge/report` +- `stricter schema validation only if needed` + +## Safety notes + +- The generator uses only the Python standard library and repository metadata. +- The generator does not require network access, a live server, external dependencies, or real Daimler data. +- The generated report is deterministic and safe to commit because `generated_at` is static/synthetic. +- Do not copy secrets, tokens, cookies, customer data, raw production logs, proprietary documents, or real Daimler data into this report. +- Cross-repo findings should be summarized from sanitized artifacts rather than copied as raw payloads. diff --git a/scripts/generate_project_health_report.py b/scripts/generate_project_health_report.py new file mode 100644 index 0000000..4f535e6 --- /dev/null +++ b/scripts/generate_project_health_report.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +"""Generate a deterministic project health and release status report. + +The report intentionally uses repository path and file-existence metadata only. +It does not read fixture payloads, contact a network service, require a live +server, or inspect real experiment data. +""" + +from __future__ import annotations + +from pathlib import Path +from typing import Iterable + +ROOT = Path(__file__).resolve().parents[1] +REPORT_PATH = ROOT / "docs" / "reports" / "project-health-report.md" +GENERATED_AT = "2026-01-01T00:00:00Z" +TARGET_REPO = "ProfRandom92/Comptextv7" +RELATED_EXPERIMENT_REPO = "ProfRandom92/Comptext-Daimler-Experiment-" + +SKIP_DIRS = { + ".git", + ".hg", + ".mypy_cache", + ".pytest_cache", + ".ruff_cache", + ".tox", + ".venv", + "__pycache__", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +} + +REQUIRED_COMMANDS = [ + "python scripts/repo_intake.py", + "python scripts/run_checks.py", + "python scripts/validate_contracts.py", + "python scripts/generate_contract_fixtures.py", + "python scripts/validate_api_exports.py", + "python scripts/generate_project_health_report.py", +] + +REQUIRED_EXPERIMENT_ARTIFACTS = [ + "benchmark-summary.json", + "regression-summary.json", + "sanitization-summary.json", + "report-contract-validation-report.md", +] + + +NEXT_RECOMMENDED_PRS = [ + "dashboard rendering of sanitized benchmark summary", + "optional JSON artifact importer", + "release readiness badge/report", + "stricter schema validation only if needed", +] + + +def iter_repo_files(root: Path) -> list[Path]: + """Return repository files in stable order while skipping bulky trees.""" + files: list[Path] = [] + for path in root.rglob("*"): + rel = path.relative_to(root) + if any(part in SKIP_DIRS for part in rel.parts): + continue + if path.is_file(): + files.append(rel) + return sorted(files, key=lambda item: item.as_posix()) + + +def bullet_list(items: Iterable[Path | str], empty: str = "None detected.") -> list[str]: + values = [item.as_posix() if isinstance(item, Path) else item for item in items] + if not values: + return [f"- {empty}"] + return [f"- `{value}`" for value in values] + + +def status_row(label: str, present: bool, note: str) -> str: + status = "present" if present else "missing" + return f"| {label} | {status} | {note} |" + + +def path_exists(path: str) -> bool: + return (ROOT / path).exists() + + +def build_report(files: list[Path]) -> str: + workflows = [path for path in files if path.parts[:2] == (".github", "workflows") and path.suffix in {".yml", ".yaml"}] + scripts = [path for path in files if path.parts[:1] == ("scripts",) and path.suffix == ".py"] + contract_files = [path for path in files if path.parts[:1] == ("contracts",) and path.suffix == ".json" and "examples" not in path.parts] + contract_examples = [path for path in files if path.parts[:2] == ("contracts", "examples") and path.suffix == ".json"] + report_files = [path for path in files if path.parts[:2] == ("docs", "reports")] + + contract_schema_present = any(path.parts[:1] == ("contracts",) and path.name.endswith(".schema.json") for path in files) + contract_examples_present = bool(contract_examples) + + lines: list[str] = [ + "# Project Health and Release Status Report", + "", + "This deterministic report summarizes local agent workflow readiness, contract validation surfaces, API/export validation, and cross-repo promotion readiness for review.", + "", + "## Repository overview", + "", + f"- target_repo: `{TARGET_REPO}`", + f"- related_experiment_repo: `{RELATED_EXPERIMENT_REPO}`", + f"- generated_at: `{GENERATED_AT}`", + "- synthetic: `true`", + "- live_server_required: `false`", + "- network_required: `false`", + "- real_daimler_data_required: `false`", + "", + "## Detected workflow files", + "", + *bullet_list(workflows), + "", + "## Detected scripts", + "", + *bullet_list(scripts), + "", + "## Contract files", + "", + *bullet_list(contract_files), + "", + "## Contract examples", + "", + *bullet_list(contract_examples), + "", + "## Existing report files", + "", + *bullet_list(report_files), + "", + "## Required validation commands", + "", + *bullet_list(REQUIRED_COMMANDS), + "", + "## Release readiness checklist", + "", + "| Item | Status | Notes |", + "| --- | --- | --- |", + status_row("repo intake report exists", path_exists("docs/reports/repo-intake-report.md"), "Generated by `python scripts/repo_intake.py`."), + status_row("check report exists", path_exists("docs/reports/check-report.md"), "Generated by `python scripts/run_checks.py`."), + status_row("contract validation report exists", path_exists("docs/reports/contract-validation-report.md"), "Generated by `python scripts/validate_contracts.py`."), + status_row("API/export validation report exists", path_exists("docs/reports/api-export-validation-report.md"), "Generated by `python scripts/validate_api_exports.py`."), + status_row("project health report exists", True, "Generated by `python scripts/generate_project_health_report.py`."), + "| no real Daimler data included | policy-required | This report uses path and existence metadata only. |", + "| no secrets included | policy-required | This report does not print file contents, tokens, cookies, or credentials. |", + "| PR is small and reversible | reviewer-confirmed | Keep changes limited to generator, generated report, CI, and docs. |", + "", + "## Cross-repo promotion readiness checklist", + "", + "### Required experiment artifacts", + "", + *bullet_list(REQUIRED_EXPERIMENT_ARTIFACTS), + "", + "### Required Comptextv7 artifacts", + "", + "| Artifact | Status | Notes |", + "| --- | --- | --- |", + status_row("contract schemas", contract_schema_present, "Detected under `contracts/`."), + status_row("contract examples", contract_examples_present, "Detected under `contracts/examples/`."), + status_row("API/export validation report", path_exists("docs/reports/api-export-validation-report.md"), "Local synthetic validation evidence."), + status_row("cross-repo release checklist", path_exists("docs/CROSS_REPO_RELEASE_CHECKLIST.md"), "Promotion gate documentation."), + "", + "## Next recommended PRs", + "", + *bullet_list(NEXT_RECOMMENDED_PRS), + "", + "## Safety notes", + "", + "- The generator uses only the Python standard library and repository metadata.", + "- The generator does not require network access, a live server, external dependencies, or real Daimler data.", + "- The generated report is deterministic and safe to commit because `generated_at` is static/synthetic.", + "- Do not copy secrets, tokens, cookies, customer data, raw production logs, proprietary documents, or real Daimler data into this report.", + "- Cross-repo findings should be summarized from sanitized artifacts rather than copied as raw payloads.", + "", + ] + return "\n".join(lines) + + +def main() -> int: + files = iter_repo_files(ROOT) + REPORT_PATH.parent.mkdir(parents=True, exist_ok=True) + REPORT_PATH.write_text(build_report(files), encoding="utf-8") + print(f"Wrote {REPORT_PATH.relative_to(ROOT).as_posix()}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())