#!/usr/bin/env bash # mcp-menu.sh — Repository-root operator menu for MCP/Gitea workflow onboarding. # # Safe by default: read-only status and copy-paste prompts unless an action is # explicitly labeled and confirmed. No branch deletion, force-push, lock-file # editing, or raw API bypass. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$SCRIPT_DIR" pause() { read -r -p "Press Enter to return to the menu..." } print_banner() { printf '\n=== Gitea-Tools MCP Operator Menu ===\n' printf 'Repository: %s\n' "$REPO_ROOT" printf 'Safe by default — destructive actions require explicit confirmation.\n\n' } show_root_checkout_health() { printf '\n--- Project status / root checkout health ---\n\n' printf 'Current directory: %s\n' "$(pwd)" local branch head_sha prgs_master_sha dirty branch="$(git -C "$REPO_ROOT" branch --show-current 2>/dev/null || true)" if [[ -z "$branch" ]]; then branch="(detached HEAD)" fi printf 'Current branch: %s\n' "$branch" printf '\nGit status (short, branch):\n' git -C "$REPO_ROOT" status --short --branch || true head_sha="$(git -C "$REPO_ROOT" rev-parse HEAD 2>/dev/null || echo 'unknown')" printf '\nHEAD SHA: %s\n' "$head_sha" if git -C "$REPO_ROOT" rev-parse --verify prgs/master >/dev/null 2>&1; then prgs_master_sha="$(git -C "$REPO_ROOT" rev-parse prgs/master)" printf 'prgs/master SHA: %s\n' "$prgs_master_sha" if [[ "$head_sha" != "$prgs_master_sha" ]]; then printf '\nWARNING: root checkout HEAD does not match prgs/master.\n' printf 'Keep the stable control checkout on master/prgs/master.\n' fi else printf 'prgs/master SHA: unavailable (remote ref not fetched)\n' fi if [[ -n "$(git -C "$REPO_ROOT" status --porcelain 2>/dev/null || true)" ]]; then printf '\nWARNING: root checkout has uncommitted changes (dirty).\n' printf 'Author mutations belong in a session worktree under branches/.\n' fi if [[ "$branch" != "master" && "$branch" != "main" && "$branch" != "dev" ]]; then printf '\nWARNING: root checkout is not on a stable base branch (master/main/dev).\n' printf 'Return to master before using the control checkout.\n' fi pause } print_prompt_block() { local title="$1" local body="$2" printf '\n--- %s ---\n\n' "$title" printf '%s\n' "$body" printf '\n(Copy the prompt above into your LLM session.)\n' pause } show_author_prompts() { while true; do printf '\n--- Author workflow prompts ---\n' printf ' 1) Work issue (author/coder)\n' printf ' 2) Conflict-fix author session\n' printf ' 3) Root checkout recovery session\n' printf ' 0) Back\n' read -r -p 'Choice: ' choice case "$choice" in 1) print_prompt_block "Author — work issue" \ "You are the AUTHOR session for /. Goal: implement issue # only. Workflow: 1. Preflight: prove identity, work_issue/create_pr capability, clean session worktree under branches/. 2. gitea_lock_issue for issue # and branch feat/issue--. 3. Implement in the locked worktree only — never mutate the root control checkout. 4. Validate, commit, push, gitea_create_pr. Final report with issue, branch, SHA, PR, tests, mutation ledger." ;; 2) print_prompt_block "Author — conflict-fix session" \ "You are the AUTHOR session for / in conflict-fix mode. Goal: resolve merge conflicts on PR #

/ branch only. Workflow: 1. Preflight: prove author identity and exact push/commit capability for the locked PR branch. 2. Confirm conflict-fix lease and stale-head protection before pushing. 3. Work only in the session-owned worktree under branches/ — never the root checkout. 4. Rebase or merge target branch, run tests, push, update PR. No force-push without explicit operator approval. 5. Final report: conflict resolution proof, new HEAD SHA, tests, mutation ledger." ;; 3) print_prompt_block "Author — root checkout recovery" \ "You are a RECOVERY session for /. Goal: restore the stable root control checkout to clean master/prgs/master. Workflow: 1. Inspect root checkout: branch, git status --short --branch, HEAD vs prgs/master. 2. Do not implement features from the root checkout. Stash or move work to branches/ first. 3. Return root to master (or main/dev per project policy) matching prgs/master with no dirty tracked files. 4. Report before/after branch, SHA, dirty state, and safe next action for author worktree creation." ;; 0) return ;; *) printf 'Invalid choice.\n' ;; esac done } show_reviewer_prompts() { while true; do printf '\n--- Reviewer workflow prompts ---\n' printf ' 1) Standard PR review\n' printf ' 2) Skip already-reviewed stale REQUEST_CHANGES PR and hand off to author\n' printf ' 0) Back\n' read -r -p 'Choice: ' choice case "$choice" in 1) print_prompt_block "Reviewer — PR review" \ "You are the REVIEWER session for /. Goal: review PR #

only — do not merge unless explicitly switched to merger mode. Workflow: 1. Load canonical workflow: skills/llm-project-workflow/workflows/review-merge-pr.md 2. Preflight: prove reviewer identity, review_pr capability, clean review worktree. 3. gitea_view_pr, validate scope, run required checks in the correct worktree. 4. gitea_review_pr with approve, request-changes, or comment as warranted. 5. Final report: PR head SHA, verdict, validation evidence, mutation ledger. No merge in reviewer-only runs." ;; 2) print_prompt_block "Reviewer — skip already-reviewed stale REQUEST_CHANGES PR and hand off to author" \ "You are the REVIEWER session for /. Goal: review PR #

only far enough to determine whether the current head already has a non-stale REQUEST_CHANGES verdict. If it does, do NOT submit another terminal review mutation — produce an author handoff and stop. Workflow: 1. gitea_view_pr; pin the current head SHA. 2. Load prior reviews; find the latest REQUEST_CHANGES and the head SHA it was bound to. 3. If that REQUEST_CHANGES is still bound to the current head (non-stale), do not submit another terminal review mutation. Confirm the binding and summarize the blockers. 4. Run only the diagnostics needed to produce a useful author handoff — no full re-review. 5. Duplicate/supersession check: confirm no newer canonical PR or superseding head changes the decision. 6. Stop — no new review mutation. Return: - selected PR and issue - current head SHA - prior REQUEST_CHANGES proof (review id + bound head SHA) - duplicate/supersession analysis - validation summary - why no new review mutation was submitted - corrected mutation ledger, including local worktree create/remove if used - author-ready fix prompt" ;; 0) return ;; *) printf 'Invalid choice.\n' ;; esac done } show_merger_prompts() { print_prompt_block "Merger — PR merge" \ "You are the MERGER session for /. Goal: merge PR #

only after every gate passes. Workflow: 1. Load canonical workflow: skills/llm-project-workflow/workflows/review-merge-pr.md 2. Preflight: prove merger identity and exact merge_pr capability for the current PR head SHA. 3. Confirm approval pins the current head SHA; re-validate if the branch moved. 4. gitea_merge_pr only on explicit operator approval after all gates pass. 5. Final report: merged SHA, cleanup handoff, mutation ledger." } show_reconciler_prompts() { print_prompt_block "Reconciler — already-landed / closed PR cleanup" \ "You are the RECONCILER session for /. Goal: reconcile already-landed open PRs — close or comment only when exact capability is proven. Workflow: 1. Load canonical workflow: skills/llm-project-workflow/workflows/reconcile-landed-pr.md 2. Preflight: prove reconciler identity and gitea.pr.close (or authorized close) capability. 3. Do not review, merge, implement code, or create branches. 4. gitea_scan_already_landed_open_prs / gitea_reconcile_already_landed_pr as appropriate. 5. Final report: PR numbers handled, close proof, mutation ledger." } show_onboarding_prompt() { print_prompt_block "Onboarding — new project to MCP workflow" \ "Onboard / into the MCP Control Plane workflow. Checklist: 1. Prove identity and task capability via gitea_whoami and gitea_resolve_task_capability. 2. Configure separate MCP namespaces/profiles: author, reviewer, merger/reconciler as needed. 3. Register gitea-tools (and jenkins-mcp / glitchtip-mcp if applicable) in the client MCP config. 4. Copy skills/llm-project-workflow/SKILL.md guidance into the target repo or ECC install. 5. Verify gitea_get_runtime_context, gitea_lock_issue, and worktree rules under branches/. 6. Run ./mcp-menu.sh for day-to-day prompts; use docs/mcp-menu.md and docs/llm-workflow-runbooks.md. Canonical router: skills/llm-project-workflow/SKILL.md" } show_proxmox_placeholder() { printf '\n--- Proxmox deployment (placeholder) ---\n\n' printf 'Push this project to Proxmox — TODO / issue-backed\n' printf 'Create Proxmox LXC — TODO / issue-backed\n\n' printf 'These actions are NOT implemented yet.\n' printf 'Track deployment automation in dedicated Gitea issues before enabling here.\n' printf 'This menu will not run deploy scripts until sanctioned tooling exists.\n' pause } run_tests() { printf '\n--- Run tests ---\n\n' if [[ -x "$REPO_ROOT/run-tests.sh" ]]; then printf 'Running ./run-tests.sh ...\n\n' (cd "$REPO_ROOT" && ./run-tests.sh) pause return fi if [[ -x "$REPO_ROOT/venv/bin/python" ]]; then printf 'run-tests.sh not found; falling back to venv/bin/python -m pytest\n\n' (cd "$REPO_ROOT" && ./venv/bin/python -m pytest) pause return fi printf 'ERROR: No test runner available (fail closed).\n' >&2 printf 'Expected ./run-tests.sh or venv/bin/python for pytest fallback.\n' >&2 exit 1 } main_menu() { while true; do print_banner printf ' 1) Project status / root checkout health\n' printf ' 2) Author workflow prompts\n' printf ' 3) Reviewer workflow prompts\n' printf ' 4) Merger workflow prompts\n' printf ' 5) Reconciler workflow prompts\n' printf ' 6) Onboarding new project to this MCP workflow\n' printf ' 7) Proxmox deployment menu placeholder\n' printf ' 8) Create Proxmox LXC placeholder\n' printf ' 9) Run tests\n' printf ' 0) Exit\n' read -r -p 'Choice: ' choice case "$choice" in 1) show_root_checkout_health ;; 2) show_author_prompts ;; 3) show_reviewer_prompts ;; 4) show_merger_prompts ;; 5) show_reconciler_prompts ;; 6) show_onboarding_prompt ;; 7|8) show_proxmox_placeholder ;; 9) run_tests ;; 0) printf 'Goodbye.\n'; exit 0 ;; *) printf 'Invalid choice.\n'; pause ;; esac done } main_menu