|
20 | 20 | render_portfolio_report_markdown, |
21 | 21 | render_registry_markdown, |
22 | 22 | ) |
23 | | -from src.portfolio_truth_sources import _classify_context_quality, _extract_github_full_name |
| 23 | +from src.portfolio_truth_sources import ( |
| 24 | + _classify_context_quality, |
| 25 | + _extract_github_full_name, |
| 26 | + load_safe_notion_project_context, |
| 27 | +) |
24 | 28 | from src.portfolio_truth_validate import validate_portfolio_report_markdown |
25 | 29 | from src.registry_parser import parse_registry |
26 | 30 |
|
@@ -85,6 +89,37 @@ def test_extract_github_full_name_uses_exact_github_host() -> None: |
85 | 89 | assert _extract_github_full_name("https://evil.example/github.com/octo/repo.git") == "" |
86 | 90 |
|
87 | 91 |
|
| 92 | +def test_notion_context_uses_configured_title_aliases( |
| 93 | + tmp_path: Path, monkeypatch: pytest.MonkeyPatch |
| 94 | +) -> None: |
| 95 | + config_dir = tmp_path / "config" |
| 96 | + config_dir.mkdir() |
| 97 | + (config_dir / "project-registry-overrides.json").write_text( |
| 98 | + json.dumps( |
| 99 | + { |
| 100 | + "notion_title_aliases": { |
| 101 | + "Notion Operating System": "Notion", |
| 102 | + } |
| 103 | + } |
| 104 | + ) |
| 105 | + ) |
| 106 | + |
| 107 | + monkeypatch.setattr( |
| 108 | + "src.portfolio_truth_sources.load_notion_project_context", |
| 109 | + lambda _config_dir: { |
| 110 | + "Notion Operating System": { |
| 111 | + "portfolio_call": "Build Now", |
| 112 | + "momentum": "Post-Build Review Done", |
| 113 | + "current_state": "Shipped", |
| 114 | + } |
| 115 | + }, |
| 116 | + ) |
| 117 | + |
| 118 | + context = load_safe_notion_project_context(config_dir) |
| 119 | + |
| 120 | + assert context["notion"]["current_state"] == "Shipped" |
| 121 | + |
| 122 | + |
88 | 123 | @pytest.fixture |
89 | 124 | def portfolio_workspace(tmp_path: Path) -> Path: |
90 | 125 | workspace = tmp_path / "workspace" |
@@ -915,6 +950,45 @@ def _boom(_snapshot, _latest_json_path): |
915 | 950 | assert not list(output_dir.glob("*.tmp")) |
916 | 951 |
|
917 | 952 |
|
| 953 | +def test_publish_refuses_to_drop_existing_notion_context( |
| 954 | + portfolio_workspace: Path, |
| 955 | + portfolio_catalog: Path, |
| 956 | + legacy_registry: Path, |
| 957 | + tmp_path: Path, |
| 958 | + monkeypatch: pytest.MonkeyPatch, |
| 959 | +) -> None: |
| 960 | + output_dir = tmp_path / "output" |
| 961 | + output_dir.mkdir() |
| 962 | + latest_path = output_dir / "portfolio-truth-latest.json" |
| 963 | + latest_path.write_text( |
| 964 | + json.dumps({"source_summary": {"notion_context_rows": 137}}) + "\n" |
| 965 | + ) |
| 966 | + registry_output = portfolio_workspace / "project-registry.md" |
| 967 | + report_output = portfolio_workspace / "PORTFOLIO-AUDIT-REPORT.md" |
| 968 | + |
| 969 | + monkeypatch.setattr( |
| 970 | + "src.portfolio_truth_sources.load_notion_project_context", |
| 971 | + lambda _config_dir: None, |
| 972 | + ) |
| 973 | + monkeypatch.setattr( |
| 974 | + "src.portfolio_truth_publish._notion_project_context_configured", |
| 975 | + lambda: True, |
| 976 | + ) |
| 977 | + |
| 978 | + with pytest.raises(RuntimeError, match="0 Notion context rows"): |
| 979 | + publish_portfolio_truth( |
| 980 | + workspace_root=portfolio_workspace, |
| 981 | + output_dir=output_dir, |
| 982 | + registry_output=registry_output, |
| 983 | + portfolio_report_output=report_output, |
| 984 | + catalog_path=portfolio_catalog, |
| 985 | + legacy_registry_path=legacy_registry, |
| 986 | + include_notion=True, |
| 987 | + ) |
| 988 | + |
| 989 | + assert json.loads(latest_path.read_text())["source_summary"]["notion_context_rows"] == 137 |
| 990 | + |
| 991 | + |
918 | 992 | def test_context_recovery_plan_freezes_and_filters_targets( |
919 | 993 | portfolio_workspace: Path, |
920 | 994 | portfolio_catalog: Path, |
|
0 commit comments