Make the interactive profile menu feel like a real terminal menu, via a new
injectable MenuIO abstraction (no menu logic change, no auth/secret-storage
change).
- Single-key top-level actions in a TTY (termios/tty raw read); no Enter
needed. Non-TTY / test runs fall back to line input.
- Enter backs out: Enter (or 0) on the main menu quits; Enter cancels any
submenu/profile prompt and returns.
- Profile chooser: everywhere a profile is needed, show a numbered list and
pick by key (1-9), with an explicit 'm) type a name manually' path and Enter
to cancel. Empty config handled gracefully.
- Clear screen before redrawing the main menu and chooser — TTY only; never
emits clear codes in non-TTY/test runs.
- Result actions (validate/test-auth/whoami/eligibility) print a concise result
then pause for a keypress in a TTY; non-TTY never blocks.
Helpers: read_key (via default_io) / choose_menu_option / choose_profile /
clear_screen / pause_for_key, plus MenuIO(is_tty, clear_enabled). TTY detected
with sys.stdin.isatty() and sys.stdout.isatty(); stdlib only.
Safety unchanged: no tokens/passwords printed, no raw config dumps, no
.env.personal, no change to auth behavior or secret storage.
Tests: rewrote menu tests around a scripted _FakeIO (no real terminal): single-
key select + clear, main-menu Enter/0 quit, submenu Enter cancel (no change),
chooser lists/selects/no-profiles/manual/out-of-range, non-TTY line fallback,
clear-only-when-enabled, pause never hangs non-TTY, and add-flow proving the
token value never reaches disk or stdout.
Docs: runbook note on single-key nav / Enter back-out / numbered chooser.
scripts/gitea-config-menu unchanged.
Closes#36. Refs #31, #34.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add docs/llm-workflow-runbooks.md — the final roadmap #10 deliverable:
operational runbooks for LLM-operated Gitea workflows, built on the shipped
canonical profiles + interactive menu + gated review/merge + audit logging.
Covers:
- Principle: the profile is the role, not the LLM (task-scoped, not assigned).
- Canonical config: GITEA_MCP_CONFIG / GITEA_MCP_PROFILE, version, profiles,
keychain + env auth references, precedence, legacy env-only fallback.
- Interactive menu (python gitea_config.py menu): create author/reviewer
profiles, generate Claude/Gemini/Codex launcher snippets, validate auth,
check PR reviewer eligibility.
- Thin-launcher pattern: LLM configs carry only command/args + the two
GITEA_MCP_* vars — never raw tokens/passwords.
- Migration away from duplicated GITEA_USER_*/GITEA_PASS_*/GITEA_SITE_* blocks;
secrets referenced by keychain id or env var name only.
- Per-workflow runbooks (create issue/children, implement+PR, review/request-
changes/approve, merge, close-after-merge, stop-on-blocker) with safe prompts.
- Fail-closed behavior table (unknown identity/profile, self-author, moved head,
unexpected files, detected secrets, production/deploy) and no self-review/merge.
Docs-only: no implementation code. Safe placeholder examples only (no real
tokens, passwords, usernames, or private config). README links the new runbook.
Closes#17. Refs #10.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address reviewer blockers on PR #8:
- Remove trailing whitespace in credential-isolation.md and release-workflows.md
- Add approved naming coverage (MCP Control Plane / mcp-control-plane project
and repo names; common, gitea-mcp, jenkins-mcp, ops-mcp, release-mcp packages)
to tool-boundaries.md
Documentation-only. No code, scaffolding, or config changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>