Merge remote-tracking branch 'prgs/master' into feat/issue-514-branch-delete-guard

# Conflicts:
#	gitea_mcp_server.py
This commit is contained in:
2026-07-09 09:35:55 -04:00
44 changed files with 2932 additions and 61 deletions
+59 -2
View File
@@ -477,7 +477,7 @@ def assess_preflight_status(worktree_path: str | None = None) -> dict:
def _clear_preflight_capability_state() -> None:
"""Drop resolved capability proof (consumed by a mutation or fresh resolve)."""
global _preflight_capability_called, _preflight_capability_violation
global _preflight_resolved_task
global _preflight_resolved_task, _preflight_resolved_role
global _preflight_capability_baseline_porcelain, _preflight_capability_violation_files
global _preflight_reviewer_violation_files
@@ -486,6 +486,7 @@ def _clear_preflight_capability_state() -> None:
_preflight_capability_violation_files = []
_preflight_capability_baseline_porcelain = None
_preflight_resolved_task = None
_preflight_resolved_role = None
_preflight_reviewer_violation_files = []
@@ -828,9 +829,11 @@ import reconciliation_workflow # noqa: E402
import audit_reconciliation_mode # noqa: E402
import review_merge_state_machine # noqa: E402
import pr_work_lease # noqa: E402
import workflow_skill # noqa: E402
import conflict_fix_classification # noqa: E402
import native_mcp_preference # noqa: E402
import branch_cleanup_guard # noqa: E402
import thread_state_ledger_validator # noqa: E402
import master_parity_gate # noqa: E402
# Master-parity baseline (#420): the commit this server process started at.
@@ -6865,6 +6868,23 @@ def gitea_list_issue_comments(
return {"success": True, "issue_number": issue_number, "comments": out}
def _two_comment_workflow_comment_gate(body: str) -> list[str]:
"""Fail closed on invalid tagged workflow comments (#507)."""
text = body or ""
reasons: list[str] = []
if thread_state_ledger_validator.has_controller_handoff_marker(text):
result = thread_state_ledger_validator.assess_controller_handoff_comment(
text
)
reasons.extend(result.get("reasons") or [])
if thread_state_ledger_validator.has_thread_state_ledger_marker(text):
result = thread_state_ledger_validator.assess_thread_state_ledger_comment(
text
)
reasons.extend(result.get("reasons") or [])
return reasons
@mcp.tool()
def gitea_create_issue_comment(
issue_number: int,
@@ -6909,6 +6929,8 @@ def gitea_create_issue_comment(
reasons = list(gate_reasons)
if not (body or "").strip():
reasons.append("comment body must be a non-empty string")
if not reasons:
reasons.extend(_two_comment_workflow_comment_gate(body))
if reasons:
blocked = {"success": False, "performed": False,
"issue_number": issue_number, "reasons": reasons}
@@ -7417,6 +7439,9 @@ _PROJECT_SKILLS = {
},
}
# Canonical workflow router skill names for Claude/Codex/Gemini parity (#551).
_PROJECT_SKILLS.update(workflow_skill.workflow_skill_registry_entries())
@mcp.tool()
def mcp_get_control_plane_guide(
@@ -7538,7 +7563,7 @@ def mcp_get_control_plane_guide(
@mcp.tool()
def mcp_list_project_skills() -> dict:
"""List the project's workflow skills and when to use them (#128).
"""List the project's workflow skills and when to use them (#128, #551).
Read-only; makes no API calls. Each skill reports its name,
description, when-to-use guidance, required operations, status
@@ -7546,6 +7571,9 @@ def mcp_list_project_skills() -> dict:
'operator-only'), and whether the current profile's operations permit it. Use
mcp_get_skill_guide(name) for the step-by-step guide.
Includes the canonical workflow router under gitea-workflow,
llm-project-workflow, and git-pr-workflows (#551).
Returns:
dict with 'read_only', 'count', and 'skills' (list). Never secrets.
"""
@@ -7570,10 +7598,39 @@ def mcp_list_project_skills() -> dict:
}
if meta.get("notes"):
entry["notes"] = meta["notes"]
if meta.get("repo_path"):
entry["repo_path"] = meta["repo_path"]
if meta.get("canonical"):
entry["canonical"] = True
skills.append(entry)
return {"read_only": True, "count": len(skills), "skills": skills}
@mcp.tool()
def mcp_check_workflow_skill_preflight(
project_root: str | None = None,
) -> dict:
"""Fail-closed preflight for the canonical workflow skill wall (#551).
Verifies skills/llm-project-workflow/SKILL.md exists in the project tree
and reports whether Codex has a matching mount under ~/.codex/skills.
Call before git/Gitea mutations when the controller requires gitea-workflow.
Args:
project_root: Optional override; defaults to this MCP process root.
Returns:
dict with workflow_skill_ready, blocked, canonical_names, codex mount
status, and safe_next_action. Never secrets.
"""
root = (project_root or PROJECT_ROOT).strip()
result = workflow_skill.assess_workflow_skill_presence(root)
result["success"] = not result.get("blocked")
result["project_root"] = root
result["read_only"] = True
return result
@mcp.tool()
def mcp_get_skill_guide(skill_name: str) -> dict:
"""Step-by-step guide for one named project skill (#128).