From b88e644fd318a0ccd7967e539790fbd9b8fa79cf Mon Sep 17 00:00:00 2001 From: Jason Walker <913443@dadeschools.net> Date: Thu, 2 Jul 2026 19:14:25 -0400 Subject: [PATCH] docs: document dual-profile MCP launcher pattern and add identity checklist (#109) --- docs/llm-workflow-runbooks.md | 31 +++++++++++++++++-- skills/llm-project-workflow/SKILL.md | 15 ++++----- .../templates/merge-pr.md | 11 +++++-- .../templates/review-pr.md | 11 +++++-- .../templates/start-issue.md | 11 +++++-- 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/docs/llm-workflow-runbooks.md b/docs/llm-workflow-runbooks.md index 868f6c0..57a0cd3 100644 --- a/docs/llm-workflow-runbooks.md +++ b/docs/llm-workflow-runbooks.md @@ -124,8 +124,35 @@ and the two `GITEA_MCP_*` variables — never a token or password: } ``` -Run the same server as several launcher entries (e.g. `-author`, `-reviewer`, -`-merger`), each pointing at a different `GITEA_MCP_PROFILE`. +### Dual-profile MCP launcher pattern (Recommended) + +To avoid the bottleneck of relaunching/restarting the MCP server to switch between author and reviewer roles, the client should register **both** profiles concurrently as separate server instances in the client's MCP configuration: + +```json +"gitea-author": { + "command": "/path/to/Gitea-Tools/venv/bin/python3", + "args": ["/path/to/Gitea-Tools/mcp_server.py"], + "env": { + "GITEA_MCP_CONFIG": "/path/to/.config/gitea-tools/profiles.json", + "GITEA_MCP_PROFILE": "prgs-author" + } +}, +"gitea-reviewer": { + "command": "/path/to/Gitea-Tools/venv/bin/python3", + "args": ["/path/to/Gitea-Tools/mcp_server.py"], + "env": { + "GITEA_MCP_CONFIG": "/path/to/.config/gitea-tools/profiles.json", + "GITEA_MCP_PROFILE": "prgs-reviewer" + } +} +``` + +* **Tool Namespaces:** Tool calls become distinct and identity-scoped in the client UI: + * `mcp__gitea-author__*` (for creating issues, pushing branches, creating PRs) + * `mcp__gitea-reviewer__*` (for reviewing PRs, approving, requesting changes, merging) +* **Trust Model:** Separate tokens remain separate in the keychain/environment. Each instance operates under its own `GITEA_MCP_PROFILE` and enforces its own `allowed_operations`. A runtime `whoami` identity check is still performed independently, and self-review/self-merge checks remain strictly mandatory. The dual-server pattern is a operational convenience and never a security bypass. +* **Reviewer-Identity PR Creation Deadlock:** Reviewer/merge identities must not create PRs or push branches. Doing so makes the reviewer identity the PR author in Gitea, blocking subsequent independent review and causing a review deadlock. Normally, PRs must be created by the author/work identity (`gitea-author`), leaving the reviewer identity (`gitea-reviewer`) clean and available for independent review and merge. +* **Fallback:** If the dual-profile MCP launcher pattern is not supported or configured in the client, the LLM must relaunch or restart the client/MCP with the correct profile environment variable before claiming or working on any tasks. ## Setup runbook — interactive menu diff --git a/skills/llm-project-workflow/SKILL.md b/skills/llm-project-workflow/SKILL.md index 2cd53a4..6b94412 100644 --- a/skills/llm-project-workflow/SKILL.md +++ b/skills/llm-project-workflow/SKILL.md @@ -116,16 +116,17 @@ interpreter path, or create a venv inside the branch folder. ## C. Identity and profile safety -- Use canonical execution profiles where available; the profile is the role, not - the LLM. A task selects a profile; a profile is not permanently assigned. +- Use canonical execution profiles where available; the profile is the role, not the LLM. A task selects a profile; a profile is not permanently assigned. - **Author and reviewer identities must be distinct.** -- Never place raw tokens/passwords in an LLM/MCP client config. Reference secrets - by keychain id or environment variable name only. Prefer a single canonical - config file selected by two env vars, e.g.: +- Never place raw tokens/passwords in an LLM/MCP client config. Reference secrets by keychain id or environment variable name only. Prefer a single canonical config file selected by two env vars, e.g.: - `GITEA_MCP_CONFIG` — path to the canonical profiles file - `GITEA_MCP_PROFILE` — the profile to activate -- **If the authenticated user equals the PR author, stop** — no self-review, no - self-merge. +- **Dual-Profile MCP Launcher Pattern (Recommended):** To avoid relaunch bottlenecks and PR-author deadlocks, register multiple instances of the same MCP server in the client's configuration simultaneously (e.g., `gitea-author` and `gitea-reviewer`), each pointing to its respective `GITEA_MCP_PROFILE`. + - Tool calls become namespace-scoped: `mcp__gitea-author__*` and `mcp__gitea-reviewer__*`. + - **Trust Model:** Separate tokens remain separate. Profile gates enforce allowed operations, `whoami` is still checked, and self-review/self-merge prevention remains mandatory. This pattern is for convenience and does not bypass security gates. + - **Deadlock Warning:** Reviewer/merge identities must not be used to create PRs, as this makes the reviewer the PR author in Gitea and blocks independent review. PRs should normally be created by the author/work identity, keeping the reviewer identity available for reviews. + - **Fallback:** If a dual-server launcher is not available in the client, relaunch or restart the client with the correct profile environment variable before claiming work. +- **If the authenticated user equals the PR author, stop** — no self-review, no self-merge. ## D. Branch naming diff --git a/skills/llm-project-workflow/templates/merge-pr.md b/skills/llm-project-workflow/templates/merge-pr.md index 4ae7db6..5d7266d 100644 --- a/skills/llm-project-workflow/templates/merge-pr.md +++ b/skills/llm-project-workflow/templates/merge-pr.md @@ -13,9 +13,14 @@ Rules (llm-project-workflow): - If the PR is closed but `merged=false`, STOP and run reconciliation. Do not clean up. Steps: -1. Verify authenticated identity + active profile. -2. Confirm PR #: author (not you), state open, mergeable, review approved. -3. If any gate fails → STOP and report. +1. Identity Checklist: Before claiming/working on merge, verify and state: + - Required identity/profile for this task: merger (allowed to merge PRs) + - Current authenticated identity (from whoami): + - Target task role: merger identity (must NOT be the PR author) + *If the current identity does not match the required role (or is the PR author), STOP. Relaunch/switch to the correct profile first.* +2. Verify authenticated identity + active profile. +3. Confirm PR #: author (not you), state open, mergeable, review approved. +4. If any gate fails → STOP and report. 4. Merge with explicit confirmation (e.g. confirmation="MERGE PR "), optionally pinning the reviewed head SHA / changed-file set. 5. Confirm remote master now contains the merge commit. diff --git a/skills/llm-project-workflow/templates/review-pr.md b/skills/llm-project-workflow/templates/review-pr.md index afd44d1..778b835 100644 --- a/skills/llm-project-workflow/templates/review-pr.md +++ b/skills/llm-project-workflow/templates/review-pr.md @@ -13,9 +13,14 @@ Rules (llm-project-workflow): - Do not merge if any check fails. Steps: -1. Verify your authenticated identity (whoami) and the active profile. -2. Fetch the PR facts: PR author, head SHA, state (must be open), base branch. -3. If authenticated user == PR author → STOP (no self-review). +1. Identity Checklist: Before claiming/working on review, verify and state: + - Required identity/profile for this task: reviewer (allowed to review/approve/request_changes) + - Current authenticated identity (from whoami): + - Target task role: reviewer identity (must NOT be the PR author) + *If the current identity does not match the required role (or is the PR author), STOP. Relaunch/switch to the correct profile first.* +2. Verify your authenticated identity (whoami) and the active profile. +3. Fetch the PR facts: PR author, head SHA, state (must be open), base branch. +4. If authenticated user == PR author → STOP (no self-review). 4. scripts/worktree-review # detached, branches/review-* cd branches/review- 5. Confirm the worktree is clean. Inspect the FULL diff; confirm scope matches diff --git a/skills/llm-project-workflow/templates/start-issue.md b/skills/llm-project-workflow/templates/start-issue.md index aec81e5..58d982e 100644 --- a/skills/llm-project-workflow/templates/start-issue.md +++ b/skills/llm-project-workflow/templates/start-issue.md @@ -13,9 +13,14 @@ Rules (llm-project-workflow): - Do not self-review or self-merge. Steps: -1. Verify the orchestration checkout is the right repo and clean. -2. git fetch --prune; confirm local master == /master (0 0). -3. Create the issue "" (problem, scope, acceptance) and claim it +1. Identity Checklist: Before claiming work, verify and state: + - Required identity/profile for this task: author (allowed to push branches / create PRs) + - Current authenticated identity (from whoami): <username> + - Target task role: author/work identity + *If the current identity does not match the required role (or lacks push/PR permissions), STOP before claiming the issue. Relaunch/switch to the correct profile first.* +2. Verify the orchestration checkout is the right repo and clean. +3. git fetch <remote> --prune; confirm local master == <remote>/master (0 0). +4. Create the issue "<title>" (problem, scope, acceptance) and claim it (status:in-progress + a "starting work" comment naming the branch). 4. scripts/worktree-start <type>/issue-<n>-<slug> # type = fix|feat|docs cd branches/<type>-issue-<n>-<slug> -- 2.43.7