feat: INSTALL.md held to the installation instructions - prerequisites lists generated from the manifest, setup questions checked by docs verify (#154)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2 Files changed: - CHANGES.md - INSTALL.md - VERSION - instructions/dev/doc-pull-through.md - instructions/dev/stack-close/SKILL.md - instructions/setup-instance.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/cli_contract.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/install_doc.py - tools/chemenu/tests/test_install_doc.py
This commit is contained in:
1 parent
b33088f64e
commit
c77bda2004
12 files changed
+633
-69
No files matched your search
@@ -0,0 +1,173 @@
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from chemenu import config, install_doc, prerequisites
|
||||
from chemenu.cli import app
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
MANIFEST = prerequisites.Manifest(
|
||||
limits={},
|
||||
tools=(
|
||||
prerequisites.Tool("python", "3.11", "all", "Python", "why"),
|
||||
prerequisites.Tool("git", None, "all", "Git", "why"),
|
||||
prerequisites.Tool("pwsh", "7", "windows", "PowerShell 7 (pwsh)", "why"),
|
||||
),
|
||||
)
|
||||
|
||||
CURRENT = """# Installation
|
||||
|
||||
Vorher:
|
||||
|
||||
<!-- wikitool:prerequisites -->
|
||||
- **Python** ≥ 3.11
|
||||
- **Git**
|
||||
<!-- /wikitool:prerequisites -->
|
||||
|
||||
Unter Windows zusätzlich:
|
||||
|
||||
<!-- wikitool:prerequisites-windows -->
|
||||
- **PowerShell 7 (pwsh)** ≥ 7
|
||||
<!-- /wikitool:prerequisites-windows -->
|
||||
|
||||
## Was der Agent dich fragt
|
||||
|
||||
- <!-- setup-question: identity --> **Autor-Identität** - Name und E-Mail.
|
||||
"""
|
||||
|
||||
SETUP = """# Set up
|
||||
|
||||
2. <!-- setup-question: identity --> **Decision point - identity.** Ask the user.
|
||||
"""
|
||||
|
||||
|
||||
def _tree(tmp_path, monkeypatch, install=CURRENT, setup=SETUP, manifest=MANIFEST):
|
||||
monkeypatch.setattr(config, "ROOT", tmp_path)
|
||||
monkeypatch.setattr(prerequisites, "load_manifest", lambda path=None: manifest)
|
||||
(tmp_path / "instructions").mkdir()
|
||||
(tmp_path / "INSTALL.md").write_text(install, encoding="utf-8")
|
||||
(tmp_path / "instructions" / "setup-instance.md").write_text(setup, encoding="utf-8")
|
||||
return tmp_path
|
||||
|
||||
|
||||
def test_this_repos_install_doc_matches_the_manifest():
|
||||
assert install_doc.check_prerequisite_regions() == []
|
||||
|
||||
|
||||
def test_this_repos_install_doc_names_every_setup_question():
|
||||
assert install_doc.check_setup_questions() == []
|
||||
|
||||
|
||||
def test_this_repos_setup_instruction_marks_its_questions():
|
||||
"""The check compares two sets; an instruction that lost every marker would
|
||||
compare empty against empty and pass. Guard the real file's own count."""
|
||||
text = install_doc.setup_instruction_path().read_text(encoding="utf-8")
|
||||
assert install_doc.question_keys(text) >= {
|
||||
"identity", "remote", "kb-language", "domain",
|
||||
"personalization", "environment", "telemetry", "task-tracker",
|
||||
}
|
||||
|
||||
|
||||
def test_render_lines_are_label_and_minimum_only():
|
||||
assert install_doc.render_lines(MANIFEST.tools) == [
|
||||
"- **Python** ≥ 3.11",
|
||||
"- **Git**",
|
||||
"- **PowerShell 7 (pwsh)** ≥ 7",
|
||||
]
|
||||
|
||||
|
||||
def test_a_current_install_doc_passes(tmp_path, monkeypatch):
|
||||
_tree(tmp_path, monkeypatch)
|
||||
assert install_doc.check_prerequisite_regions() == []
|
||||
assert install_doc.check_setup_questions() == []
|
||||
|
||||
|
||||
def test_a_manifest_tool_missing_from_install_doc_fails(tmp_path, monkeypatch):
|
||||
"""Acceptance criterion: a tool in the manifest that INSTALL.md lacks fails `docs verify`."""
|
||||
_tree(tmp_path, monkeypatch, install=CURRENT.replace("- **Git**\n", ""))
|
||||
issues = install_doc.check_prerequisite_regions()
|
||||
assert any("no longer matches tools/prerequisites.txt" in issue for issue in issues)
|
||||
|
||||
|
||||
def test_a_new_platform_without_a_region_fails(tmp_path, monkeypatch):
|
||||
manifest = prerequisites.Manifest(
|
||||
limits={},
|
||||
tools=MANIFEST.tools + (prerequisites.Tool("brew", None, "macos", "Homebrew", "why"),),
|
||||
)
|
||||
_tree(tmp_path, monkeypatch, manifest=manifest)
|
||||
issues = install_doc.check_prerequisite_regions()
|
||||
assert any("<!-- wikitool:prerequisites-macos -->" in issue for issue in issues)
|
||||
|
||||
|
||||
def test_a_region_for_a_platform_no_tool_has_fails(tmp_path, monkeypatch):
|
||||
manifest = prerequisites.Manifest(limits={}, tools=MANIFEST.tools[:2])
|
||||
_tree(tmp_path, monkeypatch, manifest=manifest)
|
||||
issues = install_doc.check_prerequisite_regions()
|
||||
assert any("prerequisites-windows" in issue and "no tool" in issue for issue in issues)
|
||||
|
||||
|
||||
def test_a_missing_install_doc_is_reported(tmp_path, monkeypatch):
|
||||
_tree(tmp_path, monkeypatch)
|
||||
(tmp_path / "INSTALL.md").unlink()
|
||||
assert any("missing" in issue for issue in install_doc.check_prerequisite_regions())
|
||||
assert install_doc.check_setup_questions() == []
|
||||
|
||||
|
||||
def test_refresh_touches_nothing_outside_the_regions(tmp_path):
|
||||
stale = CURRENT.replace("≥ 3.11", "≥ 3.9")
|
||||
refreshed, missing = install_doc.refresh(stale, MANIFEST)
|
||||
assert missing == []
|
||||
assert refreshed == CURRENT
|
||||
|
||||
|
||||
def test_refresh_is_idempotent():
|
||||
once, _ = install_doc.refresh(CURRENT, MANIFEST)
|
||||
twice, _ = install_doc.refresh(once, MANIFEST)
|
||||
assert once == twice == CURRENT
|
||||
|
||||
|
||||
def test_a_question_the_install_doc_does_not_name_fails(tmp_path, monkeypatch):
|
||||
"""Acceptance criterion: a new question in setup-instance.md that INSTALL.md
|
||||
does not name fails `docs verify`."""
|
||||
setup = SETUP + "\n3. <!-- setup-question: remote --> **Decision point - remote.**\n"
|
||||
_tree(tmp_path, monkeypatch, setup=setup)
|
||||
issues = install_doc.check_setup_questions()
|
||||
assert len(issues) == 1
|
||||
assert "`remote`" in issues[0] and "does not name it" in issues[0]
|
||||
|
||||
|
||||
def test_a_question_no_longer_asked_fails(tmp_path, monkeypatch):
|
||||
install = CURRENT + "- <!-- setup-question: telemetry --> **Telemetrie**\n"
|
||||
_tree(tmp_path, monkeypatch, install=install)
|
||||
issues = install_doc.check_setup_questions()
|
||||
assert len(issues) == 1
|
||||
assert "`telemetry`" in issues[0] and "no longer asks" in issues[0]
|
||||
|
||||
|
||||
def test_docs_prerequisites_is_a_dry_run_by_default(tmp_path, monkeypatch):
|
||||
stale = CURRENT.replace("≥ 3.11", "≥ 3.9")
|
||||
root = _tree(tmp_path, monkeypatch, install=stale)
|
||||
result = runner.invoke(app, ["docs", "prerequisites"])
|
||||
assert result.exit_code == 0, result.output
|
||||
assert "would change" in result.output
|
||||
assert (root / "INSTALL.md").read_text(encoding="utf-8") == stale
|
||||
|
||||
|
||||
def test_docs_prerequisites_apply_rewrites_the_regions(tmp_path, monkeypatch):
|
||||
root = _tree(tmp_path, monkeypatch, install=CURRENT.replace("≥ 3.11", "≥ 3.9"))
|
||||
result = runner.invoke(app, ["docs", "prerequisites", "--apply"])
|
||||
assert result.exit_code == 0, result.output
|
||||
assert (root / "INSTALL.md").read_text(encoding="utf-8") == CURRENT
|
||||
assert install_doc.check_prerequisite_regions() == []
|
||||
|
||||
|
||||
def test_docs_prerequisites_never_places_a_missing_region(tmp_path, monkeypatch):
|
||||
without_windows = CURRENT.replace(
|
||||
"<!-- wikitool:prerequisites-windows -->\n- **PowerShell 7 (pwsh)** ≥ 7\n"
|
||||
"<!-- /wikitool:prerequisites-windows -->\n",
|
||||
"",
|
||||
)
|
||||
root = _tree(tmp_path, monkeypatch, install=without_windows)
|
||||
result = runner.invoke(app, ["docs", "prerequisites", "--apply"])
|
||||
assert result.exit_code == 1
|
||||
assert "prerequisites-windows" in result.output
|
||||
assert (root / "INSTALL.md").read_text(encoding="utf-8") == without_windows
|
||||
Reference in new issue
Block a user