diff --git a/codeframe/cli/proof_commands.py b/codeframe/cli/proof_commands.py index 4310742b..821ff78c 100644 --- a/codeframe/cli/proof_commands.py +++ b/codeframe/cli/proof_commands.py @@ -8,6 +8,7 @@ from pathlib import Path from typing import Optional +import click import typer from rich.console import Console from rich.table import Table @@ -75,12 +76,14 @@ def capture( if not severity: severity = typer.prompt( "Severity", default="medium", - type=typer.Choice(["critical", "high", "medium", "low"]), + # click.Choice — typer has no Choice; typer.prompt delegates to + # click.prompt, so this constrains the interactive input (#723). + type=click.Choice(["critical", "high", "medium", "low"]), ) if not source: source = typer.prompt( "Source", default="qa", - type=typer.Choice(["production", "qa", "dogfooding", "monitoring", "user_report"]), + type=click.Choice(["production", "qa", "dogfooding", "monitoring", "user_report"]), ) try: diff --git a/tests/cli/test_proof_commands.py b/tests/cli/test_proof_commands.py index 9304d999..d2a1effb 100644 --- a/tests/cli/test_proof_commands.py +++ b/tests/cli/test_proof_commands.py @@ -78,6 +78,28 @@ def test_capture_creates_req_and_persists(self, ws): assert req.title == "Login rejects valid credentials" assert req.status == ReqStatus.OPEN + def test_capture_interactive_prompts_do_not_crash(self, ws): + """#723: severity/source were prompted with the nonexistent typer.Choice, + so any interactive `cf proof capture` (no --severity/--source) raised + AttributeError. Drive the interactive branch via stdin and assert it + captures cleanly.""" + workspace, workspace_path = ws + result = runner.invoke( + app, + [ + "proof", "capture", "-w", str(workspace_path), + "--title", "T", "--description", "D", "--where", "src/x.py", + ], + input="high\nqa\n", # severity Choice, then source Choice + ) + assert result.exit_code == 0, result.output + assert "REQ-0001" in result.output + req = ledger.get_requirement(workspace, "REQ-0001") + assert req is not None + # Both repaired Choice prompts (severity + source) took effect. + assert req.severity.value == "high" + assert req.source.value == "qa" + def test_capture_second_req_increments_id(self, ws_with_req): """A second capture should produce REQ-0002.""" workspace, workspace_path = ws_with_req