Skip to content

feat: interactive init wizard with CI pipeline#3

Merged
iSamBa merged 14 commits into
mainfrom
feature/002-interactive-init-wizard
Mar 13, 2026
Merged

feat: interactive init wizard with CI pipeline#3
iSamBa merged 14 commits into
mainfrom
feature/002-interactive-init-wizard

Conversation

@iSamBa
Copy link
Copy Markdown
Owner

@iSamBa iSamBa commented Mar 13, 2026

Summary

  • Interactive setup wizard (pdf2mcp init -i): 6-step guided flow collecting all configuration (API key, docs dir, embedding settings, server settings, OCR) with Rich TUI prompts
  • Post-setup actions: optional PDF ingestion and MCP client config snippet generation after wizard completes
  • CI pipeline: lint (ruff format + ruff check + mypy strict), tests (pytest across Python 3.10–3.13), and build verification (wheel build + import/CLI smoke tests)
  • Docs & housekeeping: README updated with wizard documentation, version bumped to 0.5.0, mypy type-ignore cleanup, ruff formatting applied

Test plan

  • Run pdf2mcp init -i ./test-project and walk through all 6 wizard steps
  • Verify .env is created with correct values and 0600 permissions
  • Verify post-setup ingestion offer works when PDFs are present
  • Verify post-setup config snippet generation for all 4 clients
  • Verify pdf2mcp init ./test-project (non-interactive) still works
  • Confirm CI pipeline passes on GitHub Actions (lint, test, build jobs)

🤖 Generated with Claude Code

iSamBa and others added 14 commits March 13, 2026 21:36
…ities

- Created src/pdf2mcp/interactive.py with text_prompt, secret_prompt,
  confirm_prompt, select_prompt, print_banner, and print_step functions
- Added WizardCancelledError exception for Ctrl+C handling
- All output directed to stderr (Console with stderr=True)
- Added 22 unit tests in tests/test_interactive.py
- All quality gates pass (ruff, mypy, pytest)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename module-level console to _console (private convention)
- Use MagicMock type for test mock parameters
- Use injected mocks directly instead of re-importing module
- Fix import from rich.console (not rich._console)
- Update story specs to use WizardCancelledError name
- Added 2 more test cases (24 total)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
….env generation

- Added WizardResult dataclass holding all collected settings
- Added 6-step wizard flow: project dir, API key, docs dir, embedding, server, OCR
- Added generate_env_content() with smart commenting (defaults commented, custom uncommented)
- Added apply_wizard_result() with summary panel, overwrite protection
- API key validated (not empty, starts with sk-), masked in summary display
- Conditional prompts: stdio skips host/port, OCR disabled skips language/DPI
- Added 19 unit tests in tests/test_wizard.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

- Added --interactive / -i flag to init subparser
- Refactored cmd_init into _cmd_init_scaffold and _cmd_init_interactive
- Lazy import of interactive module (only when --interactive is used)
- WizardCancelledError caught with exit code 130 and friendly message
- Fixed existing test_cli.py tests to set args.interactive = False
- Added 11 unit tests in tests/test_cli_init.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _int_prompt() with validation loop for numeric inputs (prevents
  ValueError crash on non-numeric input in chunk size, port, DPI)
- Safe key masking in summary (handles keys shorter than 12 chars)
- Set .env file permissions to 0o600 (owner-only) after write
- Extract _write_env() helper to avoid duplication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add run_post_setup() to offer PDF ingestion and config generation after wizard
- Extract build_config_snippet() and client constants as shared helpers
- Add wizard_result_to_settings() to construct ServerSettings from wizard values
- Refactor cli.py cmd_config() to reuse shared helpers (no duplication)
- Added 17 unit tests covering all post-setup scenarios
- Updated test_cli_init.py to mock new run_post_setup call

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Changed sk- prefix validation from hard-rejection to warning with confirmation
  (supports Azure OpenAI, Groq, and other OpenAI-compatible providers)
- Fixed version test assertion (0.3.0 → 0.4.0)
- Added test for non-sk key acceptance when user confirms
- Fixed ruff import ordering in wizard_result_to_settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… post-setup

Match the behavior of discover_pdfs() which uses **/*.pdf to find PDFs
in subdirectories. The shallow *.pdf glob would miss nested PDFs and
incorrectly skip the ingestion offer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version assertion now uses __version__ instead of hardcoded string.
TestCmdConfig gets an autouse fixture to set OPENAI_API_KEY so
get_settings() succeeds in CI where no .env file exists.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@iSamBa iSamBa self-assigned this Mar 13, 2026
@iSamBa iSamBa merged commit e3e96f8 into main Mar 13, 2026
6 checks passed
@iSamBa iSamBa deleted the feature/002-interactive-init-wizard branch March 13, 2026 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant