test: delete 9 dead tests (2 chronology + 7 scavenge) + add test_directive_structure.py
The 2 tests/test_*chronology* files imported from scripts.audit.* modules that were deleted 2026-07-05 (Tier 1 manual-chronology maintenance); both were ImportError on collection. The 7 test_scavenge_*.py files were one-shot verifications of the 2026-07-02/03 directive-lift (specific names exist) — permanently green tautologies with zero ongoing value. test_directive_structure.py enforces the general invariant every directive in conductor/directives has v1.md + meta.md + matching heading.
This commit is contained in:
@@ -1,76 +0,0 @@
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
from scripts.audit.chronology_quality_gate import run_quality_gate, QualityGateResult
|
||||
|
||||
|
||||
def _make_row(status: str, confidence: str, reason: str, summary: str) -> dict:
|
||||
return {
|
||||
"status": status,
|
||||
"confidence": confidence,
|
||||
"reason": reason,
|
||||
"summary": summary,
|
||||
"track_id": "test_track",
|
||||
"date": "2026-07-01",
|
||||
"folder_link": "conductor/tracks/test_track",
|
||||
"init_sha": "abc1234",
|
||||
"end_sha": "def5678",
|
||||
"commit_count": 1,
|
||||
}
|
||||
|
||||
|
||||
def test_quality_gate_passes_on_good_rows() -> None:
|
||||
rows = [
|
||||
_make_row("Completed", "high", "completion report found", "A real summary."),
|
||||
_make_row("Completed", "medium", "3 work commits", "Another real summary."),
|
||||
_make_row("Active", "medium", "0 work commits in tracks/", "Spec-only track."),
|
||||
]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is True
|
||||
assert result.violations == []
|
||||
|
||||
|
||||
def test_quality_gate_fails_on_too_many_needs_review() -> None:
|
||||
rows = [
|
||||
_make_row("Needs Review", "none", "inconclusive", "Summary 1."),
|
||||
_make_row("Needs Review", "none", "inconclusive", "Summary 2."),
|
||||
_make_row("Completed", "high", "completion report", "Summary 3."),
|
||||
]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is False
|
||||
assert any("Needs Review" in v for v in result.violations)
|
||||
|
||||
|
||||
def test_quality_gate_fails_on_zero_completed() -> None:
|
||||
rows = [
|
||||
_make_row("Active", "medium", "0 work commits", "Summary 1."),
|
||||
_make_row("Active", "medium", "0 work commits", "Summary 2."),
|
||||
]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is False
|
||||
assert any("0 rows are Completed" in v for v in result.violations)
|
||||
|
||||
|
||||
def test_quality_gate_fails_on_metadata_field_summaries() -> None:
|
||||
rows = [
|
||||
_make_row("Completed", "high", "completion report", "Real summary."),
|
||||
_make_row("Completed", "high", "completion report", "**Priority:** A (foundational)"),
|
||||
]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is False
|
||||
assert any("metadata-field" in v for v in result.violations)
|
||||
|
||||
|
||||
def test_quality_gate_fails_on_empty_reason() -> None:
|
||||
rows = [
|
||||
_make_row("Completed", "high", "", "Real summary."),
|
||||
]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is False
|
||||
assert any("empty reason" in v for v in result.violations)
|
||||
|
||||
|
||||
def test_quality_gate_strict_mode_exits_nonzero() -> None:
|
||||
rows = [_make_row("Active", "medium", "0 work commits", "Summary.")]
|
||||
result = run_quality_gate(rows)
|
||||
assert result.passed is False
|
||||
assert result.exit_code == 1
|
||||
@@ -1,246 +0,0 @@
|
||||
from pathlib import Path
|
||||
import json
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from scripts.audit.generate_chronology import (
|
||||
extract_slug_date,
|
||||
extract_summary,
|
||||
classify_status,
|
||||
walk_track_folders,
|
||||
format_markdown,
|
||||
)
|
||||
from scripts.audit.chronology_quality_gate import run_quality_gate
|
||||
|
||||
|
||||
def test_slug_date_extraction() -> None:
|
||||
result: str = extract_slug_date("gencpp_python_bindings_20260308")
|
||||
assert result == "2026-03-08"
|
||||
|
||||
|
||||
def test_slug_date_extraction_handles_missing_date() -> None:
|
||||
result = extract_slug_date("my_folder")
|
||||
assert result is None
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_priority_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Priority:** A (foundational)\n\nReal description of the work.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description of the work."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_date_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Date:** 2026-06-20\n\nReal description.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_initialized_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Initialized:** 2026-06-13\n\nReal description.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_track_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Track:** Some track\n\nReal description.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_parent_umbrella_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Parent umbrella:** result_migration_20260616\n\nReal description.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_confidence_line(tmp_path: Path) -> None:
|
||||
spec_content: str = "# Title\n\n**Confidence:** high\n\nReal description.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description."
|
||||
|
||||
|
||||
def test_summary_extraction_prefers_metadata_description_prose(tmp_path: Path) -> None:
|
||||
metadata: dict = {"description": "A real prose description of the track."}
|
||||
(tmp_path / "metadata.json").write_text(json.dumps(metadata), encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "A real prose description of the track."
|
||||
|
||||
|
||||
def test_summary_extraction_rejects_metadata_description_field_text(tmp_path: Path) -> None:
|
||||
metadata: dict = {"description": "**Priority:** A (foundational)"}
|
||||
(tmp_path / "metadata.json").write_text(json.dumps(metadata), encoding="utf-8")
|
||||
spec_content: str = "# Title\n\nReal description from spec.\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
assert result == "Real description from spec."
|
||||
|
||||
|
||||
def test_summary_extraction_truncates_to_25_words(tmp_path: Path) -> None:
|
||||
long_line: str = " ".join(["word"] * 50)
|
||||
spec_content: str = f"# Title\n\n{long_line}\n"
|
||||
(tmp_path / "spec.md").write_text(spec_content, encoding="utf-8")
|
||||
result: str = extract_summary(tmp_path)
|
||||
expected: str = " ".join(["word"] * 25) + "\u2026"
|
||||
assert result == expected
|
||||
|
||||
|
||||
# --- Classifier tests (the new git-history classifier) ---
|
||||
|
||||
def test_classify_status_completion_report_override(tmp_path: Path) -> None:
|
||||
"""TRACK_COMPLETION report in docs/reports/ overrides everything."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
(reports_dir / "TRACK_COMPLETION_my_track_20260701.md").write_text("report", encoding="utf-8")
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert result[0] == "Completed"
|
||||
assert result[1] == "high"
|
||||
assert "completion report" in result[2]
|
||||
|
||||
|
||||
def test_classify_status_abort_report_override(tmp_path: Path) -> None:
|
||||
"""TRACK_ABORTED report -> Abandoned."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
(reports_dir / "TRACK_ABORTED_my_track_20260701.md").write_text("report", encoding="utf-8")
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
has_abort_report=True,
|
||||
)
|
||||
assert result[0] == "Abandoned"
|
||||
assert result[1] == "high"
|
||||
assert "abort report" in result[2]
|
||||
|
||||
|
||||
def test_classify_status_superseded_state_toml_overrides_abort(tmp_path: Path) -> None:
|
||||
"""state.toml status=superseded wins over abort report."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
(reports_dir / "TRACK_ABORTED_my_track_20260701.md").write_text("report", encoding="utf-8")
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
has_abort_report=True,
|
||||
state_status="superseded",
|
||||
)
|
||||
assert result[0] == "Superseded"
|
||||
assert result[1] == "high"
|
||||
|
||||
|
||||
def test_classify_status_work_commits_completed(tmp_path: Path) -> None:
|
||||
""">=3 work commits -> Completed."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = "abc1234 feat: add thing\ndef5678 fix: fix thing\nghi9012 refactor: refactor thing\n"
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert result[0] == "Completed"
|
||||
assert result[1] == "medium"
|
||||
assert "work commits" in result[2]
|
||||
|
||||
|
||||
def test_classify_status_metadata_commits_not_countd_as_work(tmp_path: Path) -> None:
|
||||
"""conductor(plan): commits don't count as work commits."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = "abc1234 conductor(plan): mark task\ndef5678 conductor(state): update\nghi9012 conductor(track): init\n"
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert result[0] == "Active"
|
||||
|
||||
|
||||
def test_classify_status_1_2_work_commits_in_progress(tmp_path: Path) -> None:
|
||||
"""1-2 work commits + in tracks/ -> In Progress."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = "abc1234 feat: add thing\ndef5678 fix: fix thing\n"
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert result[0] == "In Progress"
|
||||
|
||||
|
||||
def test_classify_status_archive_no_override_completed_low(tmp_path: Path) -> None:
|
||||
"""archive/ + no completion report -> Completed (low confidence)."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = "abc1234 feat: thing\ndef5678 fix: thing\nghi9012 refactor: thing\n"
|
||||
result = classify_status(
|
||||
folder_link="conductor/archive/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
# >=3 work commits -> Completed (medium), even in archive
|
||||
assert result[0] == "Completed"
|
||||
|
||||
|
||||
def test_classify_status_fallback_needs_review(tmp_path: Path) -> None:
|
||||
"""Inconclusive -> Needs Review (path is neither tracks/ nor archive/)."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = ""
|
||||
result = classify_status(
|
||||
folder_link="some/other/path/my_track",
|
||||
current="",
|
||||
track_id="my_track",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert result[0] == "Needs Review"
|
||||
|
||||
|
||||
def test_classify_status_returns_3_tuple(tmp_path: Path) -> None:
|
||||
"""Classifier must return (status, confidence, reason)."""
|
||||
reports_dir = tmp_path / "docs/reports"
|
||||
reports_dir.mkdir(parents=True)
|
||||
with patch("scripts.audit.generate_chronology._git_log") as mock_log:
|
||||
mock_log.return_value = ""
|
||||
result = classify_status(
|
||||
folder_link="conductor/tracks/my_track_20260701",
|
||||
current="active",
|
||||
track_id="my_track_20260701",
|
||||
repo_root=tmp_path,
|
||||
reports_dir=reports_dir,
|
||||
)
|
||||
assert len(result) == 3
|
||||
assert isinstance(result[0], str)
|
||||
assert isinstance(result[1], str)
|
||||
assert isinstance(result[2], str)
|
||||
@@ -1,106 +0,0 @@
|
||||
"""Tests for the 2026-07-03 scavenge sweep (batch 1/5: docs/reports/2026-03-02 through docs/reports/2026-06-08).
|
||||
|
||||
Lifted 9 new directives from historical docs/reports/ markdown. Each one
|
||||
encodes a post-mortem or process rule. These tests pin the structural contract:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count grew from 81 to 90
|
||||
|
||||
Additive to tests/test_aggregate_directives.py and tests/test_scavenge_directives_lift.py
|
||||
(the existing scavenge-pass tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_BATCH_1_DIRECTIVES: list[str] = [
|
||||
"pathlib_read_write_no_newline_kwarg",
|
||||
"profile_first_optimize_second",
|
||||
"surface_gaps_at_discovery_not_checkpoint",
|
||||
"test_instantiation_not_mock_away",
|
||||
"preserve_prior_versions_of_review_docs",
|
||||
"neutral_language_for_doc_drift",
|
||||
"preserve_before_compact_archive",
|
||||
"user_corrections_log_in_state_toml",
|
||||
"surface_dirty_state_in_test_runner",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_batch_1_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_BATCH_1_DIRECTIVES) == 9, "scavenge batch 1 lifted 9 directives; list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_1_DIRECTIVES)
|
||||
def test_scavenge_batch_1_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-batch-1 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_1_DIRECTIVES)
|
||||
def test_scavenge_batch_1_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-batch-1 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_1_DIRECTIVES)
|
||||
def test_scavenge_batch_1_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_1_DIRECTIVES)
|
||||
def test_scavenge_batch_1_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_batch_1_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_BATCH_1_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-batch-1 directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_total_directive_count_at_least_90_after_scavenge_batch_1() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 90, (
|
||||
"expected >= 90 directives after scavenge batch 1 (81 baseline + 9 batch-1); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew_after_scavenge_batch_1() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 90, (
|
||||
"current_baseline.md should have >= 90 directive lines after scavenge batch 1"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_1_DIRECTIVES)
|
||||
def test_scavenge_batch_1_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
@@ -1,107 +0,0 @@
|
||||
"""Tests for the 2026-07-03 scavenge sweep (batch 2/5: docs/superpowers/specs/).
|
||||
|
||||
Lifted 16 new directives from 22 design specs in docs/superpowers/specs/.
|
||||
These tests pin the structural contract:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count grew by 16 from this batch
|
||||
|
||||
Additive to tests/test_scavenge_batch_1.py and tests/test_scavenge_directives_lift.py
|
||||
(the prior scavenge-pass tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_BATCH_2_DIRECTIVES: list[str] = [
|
||||
"defer_heavy_sdk_imports_to_subprocess",
|
||||
"graceful_optional_dependency_degradation",
|
||||
"interceptor_activates_only_on_matching_shape",
|
||||
"missing_data_renders_as_em_dash_not_crash",
|
||||
"float_only_math_for_visual_transforms",
|
||||
"view_composes_does_not_leak_into_theme_get_color",
|
||||
"surface_upstream_api_limits_honestly_in_spec",
|
||||
"use_git_history_as_classification_source_of_truth",
|
||||
"classifier_must_emit_per_row_evidence",
|
||||
"chronology_must_regenerate_after_every_track_ship",
|
||||
"quality_gate_catches_broken_classifier_before_ship",
|
||||
"generation_script_walks_filesystem_fresh_each_run",
|
||||
"quarantine_flag_the_engine_not_shared_types",
|
||||
"test_classification_via_import_presence",
|
||||
"three_tier_test_strategy_for_fragile_subsystems",
|
||||
"runtime_config_flag_vs_test_env_var_gate",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_batch_2_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_BATCH_2_DIRECTIVES) == 16, "scavenge batch 2 lifted 16 directives; list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_2_DIRECTIVES)
|
||||
def test_scavenge_batch_2_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-batch-2 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_2_DIRECTIVES)
|
||||
def test_scavenge_batch_2_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-batch-2 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_2_DIRECTIVES)
|
||||
def test_scavenge_batch_2_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_2_DIRECTIVES)
|
||||
def test_scavenge_batch_2_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_batch_2_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_BATCH_2_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-batch-2 directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_scavenge_batch_2_meta_source_cites_docs_superpowers_specs() -> None:
|
||||
for name in SCAVENGE_BATCH_2_DIRECTIVES:
|
||||
meta_path = DIRECTIVES_DIR / name / "meta.md"
|
||||
body = _read(meta_path)
|
||||
assert "docs/superpowers/specs/" in body, (
|
||||
name + " meta.md Source line must cite docs/superpowers/specs/"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_2_DIRECTIVES)
|
||||
def test_scavenge_batch_2_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
@@ -1,121 +0,0 @@
|
||||
"""Tests for the 2026-07-03 scavenge sweep (batch 3/5: docs/superpowers/plans/).
|
||||
|
||||
Lifted 12 new directives from implementation plans in `docs/superpowers/plans/`.
|
||||
Each one encodes a constraint or "don't do X" rule that surfaced from past
|
||||
regressions or design docs during implementation of the corresponding track.
|
||||
|
||||
These tests pin the structural contract:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count in baseline grew from 90 to 102
|
||||
|
||||
Additive to tests/test_aggregate_directives.py,
|
||||
tests/test_scavenge_directives_lift.py, and tests/test_scavenge_batch_1.py.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_BATCH_3_DIRECTIVES: list[str] = [
|
||||
"adapt_test_mocks_to_production_api_change",
|
||||
"cheap_fix_first_investigation_phases",
|
||||
"controller_property_delegation_no_dual_state",
|
||||
"docs_philosophy_then_boundaries_then_logic_then_verify",
|
||||
"enforce_no_real_toml_in_tests",
|
||||
"imgui_scope_entered_flag_for_no_op_return",
|
||||
"imscope_tuple_return_per_scope_override",
|
||||
"log_pruner_backoff_for_locked_files",
|
||||
"modal_explicit_opened_list_for_lifecycle",
|
||||
"no_content_duplication_across_agent_docs",
|
||||
"opt_in_integration_test_via_env_var_marker",
|
||||
"toml_loader_global_then_project_merge",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_batch_3_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_BATCH_3_DIRECTIVES) == 12, "scavenge batch 3 lifted 12 directives; list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-batch-3 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-batch-3 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_batch_3_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_BATCH_3_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-batch-3 directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_total_directive_count_at_least_102_after_scavenge_batch_3() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 102, (
|
||||
"expected >= 102 directives after scavenge batch 3 (90 baseline + 12 batch-3); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew_after_scavenge_batch_3() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 102, (
|
||||
"current_baseline.md should have >= 102 directive lines after scavenge batch 3"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_3_DIRECTIVES)
|
||||
def test_scavenge_batch_3_meta_references_docs_superpowers_plans_source(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "docs/superpowers/plans/" in body, (
|
||||
directive_name + " meta.md must cite docs/superpowers/plans/ as the source"
|
||||
)
|
||||
@@ -1,119 +0,0 @@
|
||||
"""Tests for the 2026-07-03 scavenge sweep (batch 4/5: tracks + commands + styleguides + todos).
|
||||
|
||||
Lifted 18 new directives from the remaining unread markdown: conductor/tier2/agents/,
|
||||
conductor/tier2/commands/, the dispatch_tier3_phase1.md directive file,
|
||||
conductor/code_styleguides/type_aliases.md §2.5, the remaining nagent_review v3.1
|
||||
docs (decisions.md, comparison_table.md, etc.), the intent_dsl_survey research
|
||||
clusters not yet lifted, and the 3 conductor/todos/ files.
|
||||
|
||||
These tests pin the structural contract:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
|
||||
Additive to tests/test_scavenge_directives_lift.py and tests/test_scavenge_batch_1.py
|
||||
(the existing scavenge-pass tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_BATCH_4_DIRECTIVES: list[str] = [
|
||||
"acknowledgment_in_first_commit",
|
||||
"ban_appdata_paths",
|
||||
"deterministic_signal_endpoint_pattern",
|
||||
"end_of_track_report_required",
|
||||
"failure_message_actionable_not_vague",
|
||||
"fragile_test_in_batch_is_failing_test",
|
||||
"master_branch_default",
|
||||
"no_conductor_yaml_for_artifacts",
|
||||
"per_aggregate_dataclass_promotion",
|
||||
"per_conversation_scratch_dir",
|
||||
"per_dimension_pick_dim_not_tool",
|
||||
"per_phase_metric_regression_fix",
|
||||
"submit_io_lazy_pool_recreation",
|
||||
"throwaway_scripts_isolated_subdir",
|
||||
"timeline_is_immutable",
|
||||
"use_batched_test_runner",
|
||||
"verbatim_lift_not_rewrite",
|
||||
"warm_md_duplicates_not_in_place",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_batch_4_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_BATCH_4_DIRECTIVES) == 18, "scavenge batch 4 lifted 18 directives; list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_4_DIRECTIVES)
|
||||
def test_scavenge_batch_4_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-batch-4 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_4_DIRECTIVES)
|
||||
def test_scavenge_batch_4_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-batch-4 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_4_DIRECTIVES)
|
||||
def test_scavenge_batch_4_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_4_DIRECTIVES)
|
||||
def test_scavenge_batch_4_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_batch_4_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_BATCH_4_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-batch-4 directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_total_directive_count_grew_after_scavenge_batch_4() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 108, (
|
||||
"expected >= 108 directives after scavenge batch 4 (90 baseline + 18 batch-4); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew_after_scavenge_batch_4() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 108, (
|
||||
"current_baseline.md should have >= 108 directive lines after scavenge batch 4"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_4_DIRECTIVES)
|
||||
def test_scavenge_batch_4_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
@@ -1,190 +0,0 @@
|
||||
"""Tests for the 2026-07-03 scavenge sweep (batch 5/5: guides + role prompts + transcripts).
|
||||
|
||||
Lifted 11 new directives from guides, role prompts, and transcripts. Each one
|
||||
encodes a process rule or architectural invariant. These tests pin the structural
|
||||
contract:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count grew from the prior baseline (124) to 135
|
||||
|
||||
Additive to tests/test_aggregate_directives.py, tests/test_scavenge_directives_lift.py,
|
||||
and tests/test_scavenge_batch_1.py (the existing scavenge-pass tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_BATCH_5_DIRECTIVES: list[str] = [
|
||||
"anti_entropy_state_audit_before_adding",
|
||||
"audit_before_claiming_current_state",
|
||||
"manual_compaction_only_no_auto_summarize",
|
||||
"meta_tooling_app_boundary_check",
|
||||
"spec_template_required_6_sections",
|
||||
"system_reminder_redact_don_act",
|
||||
"tier1_first_commit_6file_acknowledgment",
|
||||
"tier2_post_track_ruff_mypy_audit",
|
||||
"tier2_pre_commit_deletion_and_diff_check",
|
||||
"tier2_pre_flight_audit_gates",
|
||||
"worker_three_point_abort_check",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_batch_5_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_BATCH_5_DIRECTIVES) == 11, "scavenge batch 5 lifted 11 directives; list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_5_DIRECTIVES)
|
||||
def test_scavenge_batch_5_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-batch-5 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_5_DIRECTIVES)
|
||||
def test_scavenge_batch_5_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-batch-5 directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_5_DIRECTIVES)
|
||||
def test_scavenge_batch_5_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_5_DIRECTIVES)
|
||||
def test_scavenge_batch_5_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_batch_5_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_BATCH_5_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-batch-5 directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_total_directive_count_at_least_135_after_scavenge_batch_5() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 135, (
|
||||
"expected >= 135 directives after scavenge batch 5 (124 baseline + 11 batch-5); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew_after_scavenge_batch_5() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 135, (
|
||||
"current_baseline.md should have >= 135 directive lines after scavenge batch 5"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_BATCH_5_DIRECTIVES)
|
||||
def test_scavenge_batch_5_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
|
||||
|
||||
def test_scavenge_batch_5_directives_do_not_collide_with_existing() -> None:
|
||||
"""Each batch-5 directive name must be unique vs the batch-1 (9 directives) and
|
||||
batch-3 scavenge sets; the 11 new names do not overlap with the prior 124."""
|
||||
prior_batches = {
|
||||
"adapt_test_mocks_to_production_api_change", "acknowledgment_in_first_commit",
|
||||
"ast_parse_insufficient", "ast_verify_class_methods_after_edit",
|
||||
"atomic_per_task_commits", "ban_any_type", "ban_appdata_paths",
|
||||
"ban_arbitrary_core_mocking", "ban_day_estimates", "ban_dict_any",
|
||||
"ban_dict_get_on_known_fields", "ban_getattr_dispatch",
|
||||
"ban_hasattr_dispatch", "ban_local_imports", "ban_optional_returns",
|
||||
"ban_prefix_aliasing", "ban_repeated_from_from",
|
||||
"batch_verification_not_isolation", "boundary_layer_exception",
|
||||
"cache_stable_to_volatile", "cheap_fix_first_investigation_phases",
|
||||
"chroma_cache_path", "chronology_must_regenerate_after_every_track_ship",
|
||||
"classifier_must_emit_per_row_evidence", "comprehensive_logging",
|
||||
"config_state_owner", "contract_change_audit",
|
||||
"controller_property_delegation_no_dual_state",
|
||||
"convention_enforcement_4_mechanisms", "core_value_read_first",
|
||||
"decompose_or_isolate_never_offload", "decorator_orphan_pitfall",
|
||||
"defer_heavy_sdk_imports_to_subprocess", "defer_not_catch_for_native_crashes",
|
||||
"deduction_loop_limit", "deterministic_signal_endpoint_pattern",
|
||||
"docs_philosophy_then_boundaries_then_logic_then_verify",
|
||||
"dsl_uses_first_class_spans_for_errors", "edit_small_incremental",
|
||||
"end_of_track_report_required", "enforce_no_real_toml_in_tests",
|
||||
"failure_message_actionable_not_vague", "feature_flag_delete_to_turn_off",
|
||||
"file_id_stable_across_rename", "file_naming_convention",
|
||||
"float_only_math_for_visual_transforms", "fragile_test_in_batch_is_failing_test",
|
||||
"generation_script_walks_filesystem_fresh_each_run", "git_hard_bans",
|
||||
"graceful_optional_dependency_degradation",
|
||||
"imgui_scope_entered_flag_for_no_op_return", "imgui_scope_verification",
|
||||
"imscope_tuple_return_per_scope_override", "inherited_cruft_ask_first",
|
||||
"intent_signal_postfix_not_xml", "interceptor_activates_only_on_matching_shape",
|
||||
"knowledge_harvest_pattern", "large_files_are_fine", "master_branch_default",
|
||||
"live_gui_poll_not_sleep", "live_gui_session_scoped_no_restart",
|
||||
"log_pruner_backoff_for_locked_files", "mandatory_research_first",
|
||||
"metadata_boundary_type", "missing_data_renders_as_em_dash_not_crash",
|
||||
"modal_explicit_opened_list_for_lifecycle", "modular_controller_pattern",
|
||||
"neutral_language_for_doc_drift", "nil_sentinel_pattern",
|
||||
"no_comments_in_body", "no_conductor_yaml_for_artifacts",
|
||||
"no_content_duplication_across_agent_docs", "no_diagnostic_noise",
|
||||
"no_new_src_files_without_permission", "no_output_filtering",
|
||||
"no_real_io_during_tests", "no_skip_markers_as_avoidance",
|
||||
"one_space_indent", "opt_in_integration_test_via_env_var_marker",
|
||||
"parse_failure_visible_to_conversation", "pathlib_read_write_no_newline_kwarg",
|
||||
"per_aggregate_dataclass_promotion", "per_conversation_scratch_dir",
|
||||
"per_dimension_pick_dim_not_tool", "per_phase_metric_regression_fix",
|
||||
"pipeline_immediate_mode_no_object", "prefer_targeted_tier_runs",
|
||||
"preserve_before_compact_archive", "preserve_line_endings",
|
||||
"preserve_prior_versions_of_review_docs", "profile_first_optimize_second",
|
||||
"quality_gate_catches_broken_classifier_before_ship",
|
||||
"quarantine_flag_the_engine_not_shared_types", "rag_six_rules",
|
||||
"report_instead_of_fix_ban", "reset_session_preserves_project_path",
|
||||
"result_error_pattern", "run_full_tier_after_phase_refactor",
|
||||
"runtime_config_flag_vs_test_env_var_gate", "scope_creep_track_doc_ban",
|
||||
"sdm_dependency_tags", "search_all_call_sites_after_signature_change",
|
||||
"state_visible_at_the_right_layer", "strict_state_management",
|
||||
"stub_before_implement", "subagent_returns_artifact_not_transcript",
|
||||
"submit_io_lazy_pool_recreation", "surface_dirty_state_in_test_runner",
|
||||
"surface_gaps_at_discovery_not_checkpoint",
|
||||
"surface_upstream_api_limits_honestly_in_spec",
|
||||
"throwaway_scripts_isolated_subdir", "tdd_red_green_required",
|
||||
"test_classification_via_import_presence", "test_instantiation_not_mock_away",
|
||||
"test_narrow_not_kitchen_sink", "test_sandbox",
|
||||
"three_tier_test_strategy_for_fragile_subsystems",
|
||||
"tier1_orchestrator_no_implementation", "tier3_worker_amnesia",
|
||||
"tier4_qa_compressed_fix", "timeline_is_immutable",
|
||||
"token_firewall_prevents_bloat", "toml_loader_global_then_project_merge",
|
||||
"type_hints_required", "typed_dataclass_fields", "ui_delegation_for_hot_reload",
|
||||
"undo_redo_100_snapshot_capacity", "use_batched_test_runner",
|
||||
"use_git_history_as_classification_source_of_truth",
|
||||
"user_corrections_log_in_state_toml", "verbatim_lift_not_rewrite",
|
||||
"view_composes_does_not_leak_into_theme_get_color",
|
||||
"verify_before_editing", "verbose_commit_message_ban",
|
||||
"warm_md_duplicates_not_in_place", "workspace_paths",
|
||||
}
|
||||
for name in SCAVENGE_BATCH_5_DIRECTIVES:
|
||||
assert name not in prior_batches, (
|
||||
"scavenge batch 5 directive name collides with an existing directive: " + name
|
||||
)
|
||||
@@ -1,118 +0,0 @@
|
||||
"""Tests for the 2026-07-02 directive scavenge lift.
|
||||
|
||||
The scavenge pass lifted 15 new directives from previously-unscanned markdown
|
||||
(MMA_Support, nagent_review, intent_dsl_survey, docs/handoffs). These tests
|
||||
encode the structural contract for those new directives:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count grew from 66 to 81
|
||||
|
||||
These tests are additive to tests/test_aggregate_directives.py (the existing
|
||||
contract tests for the aggregator script). The new tests here pin the
|
||||
scavenge-pass output so a future agent can verify the lift was complete.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_DIRECTIVES: list[str] = [
|
||||
"tier1_orchestrator_no_implementation",
|
||||
"tier3_worker_amnesia",
|
||||
"tier4_qa_compressed_fix",
|
||||
"token_firewall_prevents_bloat",
|
||||
"stub_before_implement",
|
||||
"subagent_returns_artifact_not_transcript",
|
||||
"parse_failure_visible_to_conversation",
|
||||
"state_visible_at_the_right_layer",
|
||||
"file_id_stable_across_rename",
|
||||
"decompose_or_isolate_never_offload",
|
||||
"intent_signal_postfix_not_xml",
|
||||
"pipeline_immediate_mode_no_object",
|
||||
"dsl_uses_first_class_spans_for_errors",
|
||||
"search_all_call_sites_after_signature_change",
|
||||
"run_full_tier_after_phase_refactor",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_DIRECTIVES) == 15, "scavenge pass lifted 15 directives; SCAVENGE_DIRECTIVES list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_DIRECTIVES)
|
||||
def test_scavenge_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-lifted directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_DIRECTIVES)
|
||||
def test_scavenge_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-lifted directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_DIRECTIVES)
|
||||
def test_scavenge_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), (
|
||||
directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_DIRECTIVES)
|
||||
def test_scavenge_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
def test_scavenge_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_DIRECTIVES:
|
||||
assert name in preset_body, (
|
||||
"current_baseline.md does not reference scavenge-lifted directive: " + name
|
||||
)
|
||||
|
||||
|
||||
def test_total_directive_count_at_least_81() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 81, (
|
||||
"expected >= 81 directives after scavenge pass (66 baseline + 15 scavenge); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 81, (
|
||||
"current_baseline.md should have >= 81 directive lines after scavenge pass"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_DIRECTIVES)
|
||||
def test_scavenge_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, (
|
||||
directive_name + " v1.md first-line statement is too short to be a complete imperative: "
|
||||
+ first_line
|
||||
)
|
||||
assert first_line[0].isupper() or first_line.startswith(("Tier", "Sub-", "Parse", "State", "File", "Decompose", "Intent", "DSL", "Search", "Run")), (
|
||||
directive_name + " v1.md first-line statement should start with a capitalized verb/noun: "
|
||||
+ first_line
|
||||
)
|
||||
@@ -1,174 +0,0 @@
|
||||
"""Tests for the 2026-07-04 superpowers plugin scavenge lift.
|
||||
|
||||
The scavenge pass lifted 25 new directives from the global OpenCode superpowers
|
||||
plugin (obra/superpowers) — 14 SKILL.md files harvested, 13 produced actionable
|
||||
directives, writing-skills was skipped (meta about authoring skills, not
|
||||
generally applicable to manual_slop consumers). These tests encode the
|
||||
structural contract for the new directives:
|
||||
|
||||
- every new directive has both a v1.md and a meta.md file
|
||||
- every new directive's v1.md body starts with a '# ' imperative heading
|
||||
- every new directive's meta.md has the ## v1 section + Source/Lifted lines
|
||||
- every new directive is referenced in conductor/directives/presets/current_baseline.md
|
||||
- the total directive count grew from the prior baseline (147) to 172
|
||||
- the 25 new names do NOT collide with any of the prior 147 directives
|
||||
- the directive bodies preserve the user's pollution-fix conventions
|
||||
(1 newline between top-level defs, no editor headers stripping, line
|
||||
endings preserved as LF on edit)
|
||||
|
||||
Additive to tests/test_aggregate_directives.py (the existing contract tests for
|
||||
the aggregator script) and tests/test_scavenge_{directives_lift,batch_1..5}.py
|
||||
(the existing scavenge-pass tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DIRECTIVES_DIR = REPO_ROOT / "conductor" / "directives"
|
||||
PRESET = REPO_ROOT / "conductor" / "directives" / "presets" / "current_baseline.md"
|
||||
|
||||
SCAVENGE_SUPERPOWERS_DIRECTIVES: list[str] = [
|
||||
"skill_check_before_clarifying",
|
||||
"brainstorm_even_for_simple_projects",
|
||||
"design_leads_with_recommendation",
|
||||
"spec_self_review_four_checks",
|
||||
"agent_prompt_one_independent_domain",
|
||||
"review_plan_critically_before_executing",
|
||||
"test_must_fail_for_believed_reason",
|
||||
"delete_means_delete_no_reference",
|
||||
"test_passing_immediately_proves_nothing",
|
||||
"three_fix_failures_question_architecture",
|
||||
"single_hypothesis_minimal_test",
|
||||
"reproduction_before_fix",
|
||||
"no_performative_agreement_in_review",
|
||||
"verify_critique_before_implementing",
|
||||
"clarify_unclear_review_before_partial_impl",
|
||||
"review_after_each_task_not_end",
|
||||
"spec_review_before_quality_review",
|
||||
"never_inherit_session_history_to_subagent",
|
||||
"detect_existing_isolation_before_creating",
|
||||
"verify_clean_baseline_before_starting",
|
||||
"verify_tests_before_offering_completion_options",
|
||||
"exactly_four_completion_options",
|
||||
"evidence_before_completion_claims",
|
||||
"plan_steps_2_to_5_minutes_each",
|
||||
"plans_no_placeholders_or_tbds",
|
||||
]
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_scavenge_superpowers_lift_count_matches_expected() -> None:
|
||||
assert len(SCAVENGE_SUPERPOWERS_DIRECTIVES) == 25, "scavenge superpowers pass lifted 25 directives; SCAVENGE_SUPERPOWERS_DIRECTIVES list must stay in sync"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_directive_has_v1_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
assert path.is_file(), "missing v1.md for scavenge-superpowers directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_directive_has_meta_file(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
assert path.is_file(), "missing meta.md for scavenge-superpowers directive: " + directive_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_v1_starts_with_imperative_heading(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0]
|
||||
assert first_line.startswith("# "), directive_name + " v1.md first line is not a '# ' imperative heading: " + first_line
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_meta_has_required_sections(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "## v1" in body, directive_name + " meta.md missing '## v1' section"
|
||||
assert "**Source:**" in body, directive_name + " meta.md missing **Source:** line"
|
||||
assert "**Lifted:**" in body, directive_name + " meta.md missing **Lifted:** line"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_meta_references_superpowers_source(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "meta.md"
|
||||
body = _read(path)
|
||||
assert "superpowers plugin" in body, directive_name + " meta.md does not reference superpowers plugin source"
|
||||
|
||||
|
||||
def test_scavenge_superpowers_directives_listed_in_current_baseline_preset() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
for name in SCAVENGE_SUPERPOWERS_DIRECTIVES:
|
||||
assert name in preset_body, "current_baseline.md does not reference scavenge-superpowers directive: " + name
|
||||
|
||||
|
||||
def test_total_directive_count_at_least_172_after_scavenge_superpowers() -> None:
|
||||
v1_files = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
assert len(v1_files) >= 172, (
|
||||
"expected >= 172 directives after scavenge-superpowers (147 baseline + 25 new); found "
|
||||
+ str(len(v1_files))
|
||||
)
|
||||
|
||||
|
||||
def test_baseline_preset_size_grew_after_scavenge_superpowers() -> None:
|
||||
preset_body = _read(PRESET)
|
||||
assert preset_body.count("\n- ") >= 172, (
|
||||
"current_baseline.md should have >= 172 directive lines after scavenge-superpowers"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directive_name", SCAVENGE_SUPERPOWERS_DIRECTIVES)
|
||||
def test_scavenge_superpowers_v1_first_line_is_complete_sentence(directive_name: str) -> None:
|
||||
path = DIRECTIVES_DIR / directive_name / "v1.md"
|
||||
first_line = _read(path).splitlines()[0].lstrip("# ").strip()
|
||||
assert len(first_line) > 20, directive_name + " v1.md first-line statement is too short to be a complete imperative: " + first_line
|
||||
|
||||
|
||||
def test_scavenge_superpowers_directives_do_not_collide_with_existing() -> None:
|
||||
"""Each scavenge-superpowers directive name must be unique vs the existing 147 directives; the 25 new names do not overlap with the prior libraries."""
|
||||
existing_v1 = sorted(DIRECTIVES_DIR.glob("*/v1.md"))
|
||||
existing_names = {p.parent.name for p in existing_v1}
|
||||
for name in SCAVENGE_SUPERPOWERS_DIRECTIVES:
|
||||
assert name in existing_names, "scavenge-superpowers directive missing on disk: " + name
|
||||
collisions = {n for n in SCAVENGE_SUPERPOWERS_DIRECTIVES if sum(1 for _ in existing_names if _.startswith(n)) > 1}
|
||||
assert not collisions, "scavenge-superpowers directive names collide (prefix collision): " + ", ".join(sorted(collisions))
|
||||
|
||||
|
||||
def test_scavenge_superpowers_distribution_skips_writing_skills_skill() -> None:
|
||||
"""The 25 lifted directives are distributed across 13 of the 14 superpowers skills; writing-skills was intentionally skipped (its content is about authoring skills, not generally applicable to manual_slop consumers)."""
|
||||
source_skills_referenced = {
|
||||
"skill_check_before_clarifying",
|
||||
"brainstorm_even_for_simple_projects",
|
||||
"design_leads_with_recommendation",
|
||||
"spec_self_review_four_checks",
|
||||
"agent_prompt_one_independent_domain",
|
||||
"review_plan_critically_before_executing",
|
||||
"test_must_fail_for_believed_reason",
|
||||
"delete_means_delete_no_reference",
|
||||
"test_passing_immediately_proves_nothing",
|
||||
"three_fix_failures_question_architecture",
|
||||
"single_hypothesis_minimal_test",
|
||||
"reproduction_before_fix",
|
||||
"no_performative_agreement_in_review",
|
||||
"verify_critique_before_implementing",
|
||||
"clarify_unclear_review_before_partial_impl",
|
||||
"review_after_each_task_not_end",
|
||||
"spec_review_before_quality_review",
|
||||
"never_inherit_session_history_to_subagent",
|
||||
"detect_existing_isolation_before_creating",
|
||||
"verify_clean_baseline_before_starting",
|
||||
"verify_tests_before_offering_completion_options",
|
||||
"exactly_four_completion_options",
|
||||
"evidence_before_completion_claims",
|
||||
"plan_steps_2_to_5_minutes_each",
|
||||
"plans_no_placeholders_or_tbds",
|
||||
}
|
||||
assert source_skills_referenced == set(SCAVENGE_SUPERPOWERS_DIRECTIVES), (
|
||||
"scavenge-superpowers coverage mismatch: writing-skills should be skipped; set differs from lifted"
|
||||
)
|
||||
Reference in New Issue
Block a user