ado-git-repo-insights 3.3.0__tar.gz → 3.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.github/workflows/ci.yml +70 -2
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.gitignore +1 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/CHANGELOG.md +40 -0
- ado_git_repo_insights-3.6.0/CONTRIBUTING.md +156 -0
- {ado_git_repo_insights-3.3.0/src/ado_git_repo_insights.egg-info → ado_git_repo_insights-3.6.0}/PKG-INFO +1 -1
- ado_git_repo_insights-3.6.0/VERSION +1 -0
- ado_git_repo_insights-3.6.0/docs/DASHBOARD-HARDENING-PLAN.md +280 -0
- ado_git_repo_insights-3.6.0/docs/PHASE7.md +160 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tasks/extract-prs/task.json +1 -1
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/dashboard.test.js +418 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/dashboard.js +150 -4
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/vss-extension.json +1 -1
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/package-lock.json +2 -2
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/package.json +1 -1
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/pyproject.toml +3 -0
- ado_git_repo_insights-3.6.0/scripts/check-ui-bundle-sync.sh +80 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/cli.py +237 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/transform/aggregators.py +162 -10
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/VSS.SDK.min.js +2 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/artifact-client.js +580 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/dashboard.js +2223 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/dataset-loader.js +783 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/error-codes.js +172 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/error-types.js +187 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/index.html +282 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/settings.html +84 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/settings.js +554 -0
- ado_git_repo_insights-3.6.0/src/ado_git_repo_insights/ui_bundle/styles.css +1477 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0/src/ado_git_repo_insights.egg-info}/PKG-INFO +1 -1
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights.egg-info/SOURCES.txt +14 -3
- ado_git_repo_insights-3.6.0/tests/unit/test_aggregators.py +1244 -0
- ado_git_repo_insights-3.6.0/tests/unit/test_cli_args.py +99 -0
- ado_git_repo_insights-3.3.0/VERSION +0 -1
- ado_git_repo_insights-3.3.0/docs/PHASE5.md +0 -348
- ado_git_repo_insights-3.3.0/docs/PHASE6.md +0 -62
- ado_git_repo_insights-3.3.0/docs/phase5-contract-notes.md +0 -203
- ado_git_repo_insights-3.3.0/tests/unit/test_aggregators.py +0 -549
- ado_git_repo_insights-3.3.0/tests/unit/test_cli_args.py +0 -34
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.editorconfig +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.gitattributes +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.github/scripts/check-baseline-integrity.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.github/scripts/validate-test-results.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.github/workflows/release.yml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.gitleaks.toml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.husky/pre-commit +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.husky/pre-push +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.pre-commit-config.yaml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/.releaserc.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/LICENSE +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/MERMAID.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/README.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/agents/INVARIANTS.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/agents/definition-of-done.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/agents/victory-gates.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/config.example.yaml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/DEFAULT-DASHBOARD-ENHANCEMENT-PLAN.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/ENABLE-ML-FEATURES.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/EXTENSION.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/INSTALLATION.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/MANUAL_WALKTHROUGH.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/SESSION.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/SUMMARY.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/ado-pipeline-smoke-check.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/dataset-contract.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/rollout-plan.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/docs/runbook.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/images/README.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/images/icon.png +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/images/icon.png.placeholder +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/jest.config.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/overview.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/package-lock.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/package.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/scripts/copy-vss-sdk.sh +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/scripts/update-perf-baseline.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tasks/extract-prs/index.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tasks/extract-prs/index.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tasks/extract-prs/package-lock.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tasks/extract-prs/package.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/test-output.txt +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/test-results.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/ado-sdk.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/api-patterns.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/auth-pattern.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/chunked-loading.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/cross-project-settings.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/dataset-loader.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/date-range-warning.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/error-codes.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/aggregates/dimensions.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/aggregates/weekly_rollups/2026-W02.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/dataset-manifest.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/insights/summary.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/perf-baselines.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures/predictions/trends.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/fixtures.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/metrics.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/mocks/ado-sdk.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/performance.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/pipeline-artifact-url.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/production-issues.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/sdk-bundling.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/setup.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/tests/synthetic-fixtures.test.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/VSS.SDK.min.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/artifact-client.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/dataset-loader.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/error-codes.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/error-types.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/index.html +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/settings.html +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/settings.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension/ui/styles.css +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/extension-verification-test.yml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/insights-verification-test.yml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/pr-insights-pipeline.yml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/sample-pipeline.yml +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/schemas/dataset-manifest.schema.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/schemas/insights.schema.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/schemas/predictions.schema.json +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/scripts/check-version-unchanged.sh +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/scripts/csv_diff.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/scripts/generate-synthetic-dataset.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/scripts/stamp-extension-version.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/scripts/validate-task-inputs.js +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/setup.cfg +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/config.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/extractor/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/extractor/ado_client.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/extractor/pr_extractor.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/ml/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/ml/date_utils.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/ml/forecaster.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/ml/insights.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/persistence/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/persistence/database.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/persistence/models.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/persistence/repository.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/transform/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/transform/csv_generator.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/utils/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/utils/datetime_utils.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/utils/logging_config.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights/utils/run_summary.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights.egg-info/dependency_links.txt +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights.egg-info/entry_points.txt +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights.egg-info/requires.txt +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/src/ado_git_repo_insights.egg-info/top_level.txt +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/fixtures/README.md +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_backfill_convergence.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_db_open_failure.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_golden_outputs.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_incremental_run.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_multi_project_scoping.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/integration/test_phase5_ml_integration.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/test_redaction.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/__init__.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_ado_client_pagination.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_artifacts_dir.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_chunk_selection.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_cli_exit_code.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_comments_cli.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_comments_extraction.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_completed_only.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_config_validation.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_csv_contract.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_csv_determinism.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_date_range_defaults.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_datetime_utils.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_forecaster_contract.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_insights_contract.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_insights_id_stability.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_insights_schema.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_logging_config.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_ml_cli_flags.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_monday_alignment.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_operational_summary.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_predictions_schema.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_retry_policy.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_run_summary.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_secret_redaction.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_summary_drift_guard.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_synthetic_dataset.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_team_extraction.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_upsert_keys.py +0 -0
- {ado_git_repo_insights-3.3.0 → ado_git_repo_insights-3.6.0}/tests/unit/test_version_validation.py +0 -0
|
@@ -95,6 +95,18 @@ jobs:
|
|
|
95
95
|
|
|
96
96
|
echo "✓ No CRLF detected in Unix-executed files"
|
|
97
97
|
|
|
98
|
+
# Guard: Verify UI bundle is in sync with extension/ui
|
|
99
|
+
ui-bundle-sync:
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v4
|
|
103
|
+
|
|
104
|
+
- name: Check UI Bundle Synchronization
|
|
105
|
+
run: |
|
|
106
|
+
chmod +x scripts/check-ui-bundle-sync.sh
|
|
107
|
+
./scripts/check-ui-bundle-sync.sh
|
|
108
|
+
shell: bash
|
|
109
|
+
|
|
98
110
|
# Guard: Block task Major changes without explicit marker
|
|
99
111
|
task-major-guard:
|
|
100
112
|
runs-on: ubuntu-latest
|
|
@@ -218,7 +230,35 @@ jobs:
|
|
|
218
230
|
- name: Validate Test Results (Python)
|
|
219
231
|
if: always() && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
220
232
|
run: |
|
|
221
|
-
#
|
|
233
|
+
# Two-phase validation for robust CI diagnostics
|
|
234
|
+
# Phase 1: Check if pytest produced output at all
|
|
235
|
+
if [ ! -f test-results.xml ]; then
|
|
236
|
+
echo "::error::test-results.xml not found - pytest likely failed to start"
|
|
237
|
+
echo ""
|
|
238
|
+
echo "================================================================================"
|
|
239
|
+
echo "DIAGNOSTIC: pytest did not produce JUnit XML output"
|
|
240
|
+
echo "================================================================================"
|
|
241
|
+
echo ""
|
|
242
|
+
echo "Common causes:"
|
|
243
|
+
echo " 1. Import error in test file or source code"
|
|
244
|
+
echo " 2. Syntax error in Python files"
|
|
245
|
+
echo " 3. Missing dependency"
|
|
246
|
+
echo " 4. Test collection failed"
|
|
247
|
+
echo ""
|
|
248
|
+
echo "Check the 'Run Tests with Coverage' step above for the actual error."
|
|
249
|
+
echo ""
|
|
250
|
+
if [ -f pytest_output.txt ]; then
|
|
251
|
+
echo "================================================================================"
|
|
252
|
+
echo "Last 50 lines of pytest output:"
|
|
253
|
+
echo "================================================================================"
|
|
254
|
+
tail -50 pytest_output.txt
|
|
255
|
+
fi
|
|
256
|
+
echo ""
|
|
257
|
+
echo "================================================================================"
|
|
258
|
+
exit 1
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# Phase 2: Validate test results using JUnit XML parsing
|
|
222
262
|
# MIN_COLLECTED: Minimum expected tests (update when adding/removing tests)
|
|
223
263
|
# MAX_SKIPS: Maximum allowed skipped tests (0 = no skips allowed in CI)
|
|
224
264
|
python .github/scripts/validate-test-results.py \
|
|
@@ -384,7 +424,35 @@ jobs:
|
|
|
384
424
|
- name: Validate Test Results (Extension)
|
|
385
425
|
if: always()
|
|
386
426
|
run: |
|
|
387
|
-
#
|
|
427
|
+
# Two-phase validation for robust CI diagnostics
|
|
428
|
+
# Phase 1: Check if Jest produced output at all
|
|
429
|
+
if [ ! -f extension/test-results.xml ]; then
|
|
430
|
+
echo "::error::extension/test-results.xml not found - Jest likely failed to start"
|
|
431
|
+
echo ""
|
|
432
|
+
echo "================================================================================"
|
|
433
|
+
echo "DIAGNOSTIC: Jest did not produce JUnit XML output"
|
|
434
|
+
echo "================================================================================"
|
|
435
|
+
echo ""
|
|
436
|
+
echo "Common causes:"
|
|
437
|
+
echo " 1. Syntax error in test file or source code"
|
|
438
|
+
echo " 2. Missing npm dependency"
|
|
439
|
+
echo " 3. Jest configuration issue"
|
|
440
|
+
echo " 4. Test collection failed"
|
|
441
|
+
echo ""
|
|
442
|
+
echo "Check the 'Run Extension UI Tests' step above for the actual error."
|
|
443
|
+
echo ""
|
|
444
|
+
if [ -f extension/npm_test_output.txt ]; then
|
|
445
|
+
echo "================================================================================"
|
|
446
|
+
echo "Last 50 lines of Jest output:"
|
|
447
|
+
echo "================================================================================"
|
|
448
|
+
tail -50 extension/npm_test_output.txt
|
|
449
|
+
fi
|
|
450
|
+
echo ""
|
|
451
|
+
echo "================================================================================"
|
|
452
|
+
exit 1
|
|
453
|
+
fi
|
|
454
|
+
|
|
455
|
+
# Phase 2: Validate test results using JUnit XML parsing
|
|
388
456
|
# MIN_COLLECTED: Minimum expected tests (update when adding/removing tests)
|
|
389
457
|
# MAX_SKIPS: Maximum allowed skipped tests (0 = no skips allowed in CI)
|
|
390
458
|
python .github/scripts/validate-test-results.py \
|
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
# [3.6.0](https://github.com/oddessentials/ado-git-repo-insights/compare/v3.5.1...v3.6.0) (2026-01-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **ci:** add two-phase test validation for robust diagnostics ([ea1585a](https://github.com/oddessentials/ado-git-repo-insights/commit/ea1585ae173b8aa68640e6bc70036cf128e50b36))
|
|
7
|
+
* **tests:** add last_updated column to teams test fixtures ([f376e6f](https://github.com/oddessentials/ado-git-repo-insights/commit/f376e6f63fa2952f49bb45e6adacf0c483ebb792))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* **aggregators:** implement by_team dimension slices (Phase 7.2) ([02c0728](https://github.com/oddessentials/ado-git-repo-insights/commit/02c07284a50c150c99fb5591a03da25771c484fd))
|
|
13
|
+
* **ci:** add UI bundle sync verification (Phase 7.1) ([0309a5b](https://github.com/oddessentials/ado-git-repo-insights/commit/0309a5b9ac36435f4679892555e04d544b8a3fd2))
|
|
14
|
+
|
|
15
|
+
## [3.5.1](https://github.com/oddessentials/ado-git-repo-insights/compare/v3.5.0...v3.5.1) (2026-01-19)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* replace ui_bundle symlink with actual files for pip packaging ([6cb3504](https://github.com/oddessentials/ado-git-repo-insights/commit/6cb35048f21805e9cb28bbc47007faeb4eb0bc62))
|
|
21
|
+
|
|
22
|
+
# [3.5.0](https://github.com/oddessentials/ado-git-repo-insights/compare/v3.4.0...v3.5.0) (2026-01-19)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* use relative symlink for ui_bundle (CI compatibility) ([2d27fcd](https://github.com/oddessentials/ado-git-repo-insights/commit/2d27fcd832b45ffc2f74282a9da2453b05d35a76))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Features
|
|
31
|
+
|
|
32
|
+
* **phase6:** add local dashboard and build-aggregates commands ([3233dcd](https://github.com/oddessentials/ado-git-repo-insights/commit/3233dcde7447ec48f71fa7c19b903ca1501e58be))
|
|
33
|
+
|
|
34
|
+
# [3.4.0](https://github.com/oddessentials/ado-git-repo-insights/compare/v3.3.0...v3.4.0) (2026-01-19)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
* **dashboard:** fix reviewer count bug and implement client-side filtering ([4f0526e](https://github.com/oddessentials/ado-git-repo-insights/commit/4f0526e62ae6ea18372ff7a0adb58fb9cd6b8fd5))
|
|
40
|
+
|
|
1
41
|
# [3.3.0](https://github.com/oddessentials/ado-git-repo-insights/compare/v3.2.0...v3.3.0) (2026-01-18)
|
|
2
42
|
|
|
3
43
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Contributing to ADO Git Repo Insights
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This document covers the essential guidelines for contributing to this project.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Clone the repository
|
|
8
|
+
2. Install Python dependencies:
|
|
9
|
+
```bash
|
|
10
|
+
pip install -e .[dev]
|
|
11
|
+
```
|
|
12
|
+
3. Install Node.js dependencies for extension development:
|
|
13
|
+
```bash
|
|
14
|
+
cd extension && npm ci
|
|
15
|
+
```
|
|
16
|
+
4. Install pre-commit hooks:
|
|
17
|
+
```bash
|
|
18
|
+
pip install pre-commit
|
|
19
|
+
pre-commit install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Running Tests
|
|
23
|
+
|
|
24
|
+
### Python Tests
|
|
25
|
+
```bash
|
|
26
|
+
pytest
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Extension Tests
|
|
30
|
+
```bash
|
|
31
|
+
cd extension && npm test
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## UI Bundle Synchronization (IMPORTANT)
|
|
37
|
+
|
|
38
|
+
The dashboard UI files exist in **two locations** that must stay synchronized:
|
|
39
|
+
|
|
40
|
+
| Location | Purpose |
|
|
41
|
+
|----------|---------|
|
|
42
|
+
| `extension/ui/` | Source of truth for Azure DevOps extension |
|
|
43
|
+
| `src/ado_git_repo_insights/ui_bundle/` | Copy for Python pip package |
|
|
44
|
+
|
|
45
|
+
### Why Two Locations?
|
|
46
|
+
|
|
47
|
+
- **Symlinks don't work with pip packages**: When building Python wheels with setuptools, symlinks are not preserved. The wheel would contain broken symlinks instead of actual files.
|
|
48
|
+
- **The `ado-insights dashboard` command requires bundled UI files**: When users install via `pip install ado-git-repo-insights`, the UI files must be physically present in the package.
|
|
49
|
+
|
|
50
|
+
### Synchronization Process
|
|
51
|
+
|
|
52
|
+
**After modifying any files in `extension/ui/`**, you must sync to `ui_bundle/`:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cp -r extension/ui/* src/ado_git_repo_insights/ui_bundle/
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then commit both locations together.
|
|
59
|
+
|
|
60
|
+
### CI Enforcement
|
|
61
|
+
|
|
62
|
+
The `ui-bundle-sync` CI job automatically verifies synchronization on every PR. If the directories are out of sync, the job will fail and display:
|
|
63
|
+
- A patch-format diff showing the differences
|
|
64
|
+
- Instructions on how to fix the issue
|
|
65
|
+
|
|
66
|
+
### Files Ignored During Sync Check
|
|
67
|
+
|
|
68
|
+
The following file patterns are ignored during synchronization checks:
|
|
69
|
+
- `*.map` (source maps)
|
|
70
|
+
- `.DS_Store` (macOS metadata)
|
|
71
|
+
- `*.swp`, `*~`, `*.bak` (editor backup files)
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Commit Message Format
|
|
76
|
+
|
|
77
|
+
This project uses [Conventional Commits](https://www.conventionalcommits.org/) for semantic versioning:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
<type>(<scope>): <description>
|
|
81
|
+
|
|
82
|
+
[optional body]
|
|
83
|
+
|
|
84
|
+
[optional footer(s)]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Types
|
|
88
|
+
- `feat`: New feature (triggers minor version bump)
|
|
89
|
+
- `fix`: Bug fix (triggers patch version bump)
|
|
90
|
+
- `docs`: Documentation only
|
|
91
|
+
- `test`: Adding or updating tests
|
|
92
|
+
- `chore`: Maintenance tasks
|
|
93
|
+
- `refactor`: Code changes that neither fix bugs nor add features
|
|
94
|
+
- `perf`: Performance improvements
|
|
95
|
+
- `ci`: CI/CD changes
|
|
96
|
+
|
|
97
|
+
### Breaking Changes
|
|
98
|
+
|
|
99
|
+
For breaking changes, add `BREAKING CHANGE:` in the commit body or append `!` after the type:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
feat(api)!: change response format
|
|
103
|
+
|
|
104
|
+
BREAKING CHANGE: The API now returns dates in ISO 8601 format.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Task Version Changes
|
|
108
|
+
|
|
109
|
+
Changes to the Azure DevOps task Major version require special approval. Include `BREAKING TASK CHANGE:` in the PR title or commit message to acknowledge the breaking change.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Pull Request Guidelines
|
|
114
|
+
|
|
115
|
+
1. **Create a feature branch** from `main`
|
|
116
|
+
2. **Write tests** for new functionality
|
|
117
|
+
3. **Run the full test suite** before submitting
|
|
118
|
+
4. **Keep PRs focused** - one feature or fix per PR
|
|
119
|
+
5. **Update documentation** if behavior changes
|
|
120
|
+
|
|
121
|
+
### CI Checks
|
|
122
|
+
|
|
123
|
+
All PRs must pass:
|
|
124
|
+
- Secret scanning (gitleaks)
|
|
125
|
+
- Line ending checks (no CRLF in Unix-executed files)
|
|
126
|
+
- UI bundle synchronization check
|
|
127
|
+
- Python tests (matrix: 3 OSes × 3 Python versions)
|
|
128
|
+
- Extension tests
|
|
129
|
+
- Pre-commit hooks (ruff, formatting)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Architecture Notes
|
|
134
|
+
|
|
135
|
+
### Dataset Contract
|
|
136
|
+
|
|
137
|
+
The dataset format is documented in `docs/dataset-contract.md`. Changes to the dataset schema require:
|
|
138
|
+
1. Version bump in manifest
|
|
139
|
+
2. Update to schema documentation
|
|
140
|
+
3. Backward compatibility consideration
|
|
141
|
+
|
|
142
|
+
### ML Features
|
|
143
|
+
|
|
144
|
+
ML features are optional and gated behind the `[ml]` extra:
|
|
145
|
+
```bash
|
|
146
|
+
pip install ado-git-repo-insights[ml]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The base package must function without ML dependencies. See `tests/unit/test_ml_cli_flags.py` for isolation tests.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Questions?
|
|
154
|
+
|
|
155
|
+
- Check existing issues for similar questions
|
|
156
|
+
- Open a new issue with the `question` label
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.6.0
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Dashboard Hardening & Enhancement Plan
|
|
2
|
+
|
|
3
|
+
This document outlines the implementation plan for hardening existing dashboard features, fixing bugs, and preparing for future enhancements.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Executive Summary
|
|
8
|
+
|
|
9
|
+
### Critical Issues Identified
|
|
10
|
+
|
|
11
|
+
1. **Reviewer Activity Bug (P0)**: `reviewers_count` is hardcoded to `0` in `aggregators.py:501`
|
|
12
|
+
- Data exists in the `reviewers` table but is never counted
|
|
13
|
+
- UI correctly renders the value but always shows "0"
|
|
14
|
+
|
|
15
|
+
2. **Filters Not Working (P0)**: Dimension filters are populated but never applied
|
|
16
|
+
- Filter dropdowns work (populated from `dimensions.json`)
|
|
17
|
+
- Filter state is tracked (`currentFilters` object)
|
|
18
|
+
- **Missing**: Client-side filtering logic in `refreshMetrics()`
|
|
19
|
+
- **Missing**: Pre-computed dimension slices in weekly rollups
|
|
20
|
+
|
|
21
|
+
3. **Test Coverage Gaps (P1)**: No tests for filtering or reviewer aggregation
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Bug Analysis
|
|
26
|
+
|
|
27
|
+
### Bug #1: Reviewer Count Always Zero
|
|
28
|
+
|
|
29
|
+
**Location**: `src/ado_git_repo_insights/transform/aggregators.py:501`
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
reviewers_count=0, # TODO: Add reviewer counting
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Root Cause**: The weekly rollup generation never joins with the `reviewers` table.
|
|
36
|
+
|
|
37
|
+
**Fix Required**: Query unique reviewers per PR, then aggregate per week:
|
|
38
|
+
```sql
|
|
39
|
+
SELECT COUNT(DISTINCT r.user_id) as reviewers_count
|
|
40
|
+
FROM reviewers r
|
|
41
|
+
JOIN pull_requests pr ON r.pull_request_uid = pr.pull_request_uid
|
|
42
|
+
WHERE pr.closed_date >= ? AND pr.closed_date <= ?
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Test Data Verification**: The `reviewers` table schema exists and is validated:
|
|
46
|
+
- `database.py:117` validates `reviewers` table on connect
|
|
47
|
+
- Row counts are tracked in `_get_row_counts()` (line 665)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Bug #2: Filters Not Applied
|
|
52
|
+
|
|
53
|
+
**Location**: `extension/ui/dashboard.js`
|
|
54
|
+
|
|
55
|
+
**Current Behavior**:
|
|
56
|
+
1. `populateFilterDropdowns()` correctly loads dimensions (line 1522)
|
|
57
|
+
2. `handleFilterChange()` updates `currentFilters` state (line 1560)
|
|
58
|
+
3. `refreshMetrics()` loads data **ignoring filters** (line 809)
|
|
59
|
+
|
|
60
|
+
**Missing Logic**:
|
|
61
|
+
1. **Client-side filtering**: After loading rollups, filter by selected repos/teams
|
|
62
|
+
2. **Dimension-sliced data**: Aggregator should generate `by_repository` and `by_team` slices
|
|
63
|
+
|
|
64
|
+
**Test Fixture Shows Expected Format** (`2026-W02.json`):
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"by_repository": {
|
|
68
|
+
"main-repo": { "pr_count": 22, "cycle_time_p50": 200.0 },
|
|
69
|
+
"secondary-repo": { "pr_count": 8, "cycle_time_p50": 360.0 }
|
|
70
|
+
},
|
|
71
|
+
"by_team": {
|
|
72
|
+
"Backend Team": { "pr_count": 18, "cycle_time_p50": 180.0 },
|
|
73
|
+
"Frontend Team": { "pr_count": 12, "cycle_time_p50": 300.0 }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Implementation Plan
|
|
81
|
+
|
|
82
|
+
### Phase 1: Fix Reviewer Count Bug (P0)
|
|
83
|
+
|
|
84
|
+
**Tasks**:
|
|
85
|
+
1. Modify `_generate_weekly_rollups()` in `aggregators.py`
|
|
86
|
+
2. Add query to count distinct reviewers per week
|
|
87
|
+
3. Add unit test for reviewer aggregation
|
|
88
|
+
4. Verify in integration test
|
|
89
|
+
|
|
90
|
+
**SQL Query**:
|
|
91
|
+
```sql
|
|
92
|
+
SELECT
|
|
93
|
+
strftime('%G-W%W', pr.closed_date) as week,
|
|
94
|
+
COUNT(DISTINCT r.user_id) as reviewers_count
|
|
95
|
+
FROM reviewers r
|
|
96
|
+
JOIN pull_requests pr ON r.pull_request_uid = pr.pull_request_uid
|
|
97
|
+
WHERE pr.closed_date IS NOT NULL AND pr.status = 'completed'
|
|
98
|
+
GROUP BY week
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Estimated Effort**: 1-2 hours
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### Phase 2: Implement Client-Side Filtering (P0)
|
|
106
|
+
|
|
107
|
+
**Tasks**:
|
|
108
|
+
1. Add `filterRollups()` function to `dashboard.js`
|
|
109
|
+
2. Modify `refreshMetrics()` to apply filters after loading
|
|
110
|
+
3. Add dimension slicing to `aggregators.py` (optional for MVP)
|
|
111
|
+
4. Add filter tests
|
|
112
|
+
|
|
113
|
+
**Implementation Approach** (MVP - Client-Side):
|
|
114
|
+
```javascript
|
|
115
|
+
function filterRollups(rollups, filters) {
|
|
116
|
+
if (!filters.repos.length && !filters.teams.length) {
|
|
117
|
+
return rollups; // No filters, return all
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// If rollups have by_repository/by_team slices, use those
|
|
121
|
+
// Otherwise, filter at aggregate level (less granular)
|
|
122
|
+
return rollups.map(rollup => {
|
|
123
|
+
let filtered = { ...rollup };
|
|
124
|
+
// Apply repo filter
|
|
125
|
+
if (filters.repos.length && rollup.by_repository) {
|
|
126
|
+
const repoData = filters.repos.map(r => rollup.by_repository[r]).filter(Boolean);
|
|
127
|
+
filtered.pr_count = repoData.reduce((sum, d) => sum + d.pr_count, 0);
|
|
128
|
+
// ... aggregate other metrics
|
|
129
|
+
}
|
|
130
|
+
return filtered;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Estimated Effort**: 2-3 hours
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### Phase 3: Add Dimension-Sliced Data Generation (P1)
|
|
140
|
+
|
|
141
|
+
**Tasks**:
|
|
142
|
+
1. Modify `_generate_weekly_rollups()` to include `by_repository` slices
|
|
143
|
+
2. Add `by_team` slices (requires team membership join)
|
|
144
|
+
3. Update test fixtures
|
|
145
|
+
4. Add contract tests for new fields
|
|
146
|
+
|
|
147
|
+
**Query for Repository Slices**:
|
|
148
|
+
```sql
|
|
149
|
+
SELECT
|
|
150
|
+
strftime('%G-W%W', pr.closed_date) as week,
|
|
151
|
+
r.repository_name,
|
|
152
|
+
COUNT(*) as pr_count,
|
|
153
|
+
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY pr.cycle_time_minutes) as cycle_time_p50
|
|
154
|
+
FROM pull_requests pr
|
|
155
|
+
JOIN repositories r ON pr.repository_id = r.repository_id
|
|
156
|
+
WHERE pr.closed_date IS NOT NULL AND pr.status = 'completed'
|
|
157
|
+
GROUP BY week, r.repository_name
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Estimated Effort**: 3-4 hours
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### Phase 4: Enhanced Testing (P1)
|
|
165
|
+
|
|
166
|
+
**New Tests Required**:
|
|
167
|
+
|
|
168
|
+
1. **Unit Test**: `test_aggregator_reviewer_count.py`
|
|
169
|
+
- Verify reviewers are counted per week
|
|
170
|
+
- Verify unique counting (no duplicates)
|
|
171
|
+
|
|
172
|
+
2. **Unit Test**: `test_aggregator_dimension_slices.py`
|
|
173
|
+
- Verify `by_repository` slices generated
|
|
174
|
+
- Verify `by_team` slices generated
|
|
175
|
+
|
|
176
|
+
3. **Integration Test**: `test_dashboard_filtering.js`
|
|
177
|
+
- Verify filter state updates URL
|
|
178
|
+
- Verify metrics change when filters applied
|
|
179
|
+
- Verify filter chips display
|
|
180
|
+
|
|
181
|
+
4. **Contract Test**: `test_weekly_rollup_schema.py`
|
|
182
|
+
- Add schema validation for new fields
|
|
183
|
+
- Backward compatibility check
|
|
184
|
+
|
|
185
|
+
**Estimated Effort**: 2-3 hours
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Enhancement Ideas for Future Phases
|
|
190
|
+
|
|
191
|
+
### Visual Enhancements
|
|
192
|
+
|
|
193
|
+
1. **Interactive Chart Tooltips**: Already partially implemented, extend to all charts
|
|
194
|
+
2. **Responsive Sparklines**: Already implemented, ensure consistent rendering
|
|
195
|
+
3. **Loading States per Chart**: Show skeleton loaders during filter changes
|
|
196
|
+
|
|
197
|
+
### Performance Optimizations
|
|
198
|
+
|
|
199
|
+
1. **Lazy Loading Dimension Slices**: Only load repo/team data when filter selected
|
|
200
|
+
2. **Caching Strategy**: Cache filtered results by filter combination
|
|
201
|
+
3. **Virtual Scrolling**: For large dimension lists in filter dropdowns
|
|
202
|
+
|
|
203
|
+
### Future Features (Phase 6+ Integration)
|
|
204
|
+
|
|
205
|
+
1. **Local Dashboard Testing**:
|
|
206
|
+
- Download aggregates artifact from pipeline
|
|
207
|
+
- Serve locally for rapid iteration
|
|
208
|
+
- Validate compatibility between extension and local versions
|
|
209
|
+
|
|
210
|
+
2. **Schema Compatibility Layer**:
|
|
211
|
+
```javascript
|
|
212
|
+
// version-adapter.js
|
|
213
|
+
function adaptRollup(rollup, targetVersion) {
|
|
214
|
+
if (rollup.schema_version < targetVersion) {
|
|
215
|
+
// Add missing fields with defaults
|
|
216
|
+
return { ...rollup, by_repository: {}, by_team: {} };
|
|
217
|
+
}
|
|
218
|
+
return rollup;
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
3. **Dashboard Experimentation Framework**:
|
|
223
|
+
- A/B test new visualizations locally
|
|
224
|
+
- Validate with real data before deploying
|
|
225
|
+
- Share test configurations
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Success Criteria
|
|
230
|
+
|
|
231
|
+
After implementation:
|
|
232
|
+
|
|
233
|
+
- [ ] Reviewer Activity chart shows real data (not 0)
|
|
234
|
+
- [ ] Repository filter changes displayed metrics
|
|
235
|
+
- [ ] Team filter changes displayed metrics
|
|
236
|
+
- [ ] Filter combinations persist in URL
|
|
237
|
+
- [ ] All existing tests pass
|
|
238
|
+
- [ ] New tests cover filtering and reviewer aggregation
|
|
239
|
+
- [ ] No regressions in cycle time or throughput calculations
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Risk Assessment
|
|
244
|
+
|
|
245
|
+
| Risk | Impact | Mitigation |
|
|
246
|
+
|------|--------|------------|
|
|
247
|
+
| Breaking existing data contract | High | Add backward compat tests, version bump |
|
|
248
|
+
| Performance degradation with slices | Medium | Lazy load slices, cache aggressively |
|
|
249
|
+
| Filter state sync issues | Low | Use URL as source of truth |
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Appendix: Current Data Flow
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐
|
|
257
|
+
│ ADO API │ ──▶ │ SQLite Database │ ──▶ │ Aggregates │
|
|
258
|
+
│ (PRs, Reviewers)│ │ (pull_requests, │ │ (weekly_rollups│
|
|
259
|
+
│ │ │ reviewers) │ │ dimensions) │
|
|
260
|
+
└─────────────────┘ └──────────────────┘ └───────┬────────┘
|
|
261
|
+
│
|
|
262
|
+
┌───────────────────────────────▼────────┐
|
|
263
|
+
│ Dashboard UI │
|
|
264
|
+
│ ┌─────────────┐ ┌─────────────────┐ │
|
|
265
|
+
│ │ Filters │ │ Metrics Display │ │
|
|
266
|
+
│ │ (NOT WORKING)│ │ (reviewers=0) │ │
|
|
267
|
+
│ └─────────────┘ └─────────────────┘ │
|
|
268
|
+
└────────────────────────────────────────┘
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**After Fix**:
|
|
272
|
+
```
|
|
273
|
+
┌────────────────────────────────────────┐
|
|
274
|
+
│ Dashboard UI │
|
|
275
|
+
│ ┌─────────────┐ ┌─────────────────┐ │
|
|
276
|
+
│ │ Filters │──│ Metrics Display │ │
|
|
277
|
+
│ │ (WORKING) │ │ (reviewers=N) │ │
|
|
278
|
+
│ └─────────────┘ └─────────────────┘ │
|
|
279
|
+
└────────────────────────────────────────┘
|
|
280
|
+
```
|