Merge remote-tracking branch 'prgs/master' into feat/issue-514-branch-delete-guard
# Conflicts: # gitea_mcp_server.py
This commit is contained in:
+59
-2
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user