Files
Gitea-Tools/docs/mcp-tool-inventory.md
T
sysadminandClaude Opus 4.8 b4c9f55890 test(author): execute the native #953 tool functions and compensation paths (#953)
Review 632 F4. Every prior reference to `gitea_recover_incomplete_bootstrap_lock`
and `gitea_inspect_issue_lock_contract` under `tests/` was a string literal — a
`tool=` argument, an assertion on returned prose, or a docs substring check —
and the suite reconstructed the recovery sequence by hand from
`assess_bootstrap_lock_recovery`, `build_canonical_issue_lock`,
`build_recovery_record`, and `bind_session_lock`. A hand-written sequence
validates the decision layer but cannot see a divergence between itself and
the tool body, which is exactly how F1 and F2 — both call-site defects —
survived 61 passing cases.

The new cases drive the registered functions against a real `git init`
repository, a real durable lock file, and config-backed profiles:

* `NamespaceMutationWallOnRecovery` — the gate is reached with this task and
  `author_role_exclusive=True`; its return value aborts the tool rather than
  being computed and discarded; the author namespace succeeds and produces a
  canonical lock; a reviewer namespace is refused with `namespace_block` even
  when the claimant data would otherwise match, and emits the standard BLOCKED
  audit record; merger is refused; a mismatched claimant profile is refused by
  the exact-owner layer with the namespace wall explicitly clear; a mismatched
  head is refused; every refusal leaves the lock bytes, generation, branch,
  worktree, and an unrelated lock untouched. A subtest matrix asserts the
  role-kind wall admits `author` and refuses reviewer, merger, limited, and
  mixed.
* `InspectionToolExecutes` — the registered read-only tool reports the contract
  and the recovery preview while leaving lock bytes, mtime, HEAD, and porcelain
  status unchanged, and reports an absent lock without creating one.
* `Ac7PostCompensationGuidance` — drives the real bootstrap to its AC7 refusal
  with a forced partial lock and asserts the returned action against the state
  the rollback actually left: complete cleanup directs to a bootstrap retry and
  that retry is then executed and succeeds, leaving exactly one canonical lock
  and one branch; partial cleanup with a surviving lock, and with a surviving
  branch and worktree, each get their own executable action; a rollback that
  never completed is distinguished from both; no recommendation names a deleted
  artifact; unrelated locks are byte-identical afterwards. Two cases cover
  `release_session_lock` directly — that the rollback now really removes the
  lock, and that it refuses a lock owned by another session.
* `NativeEndToEndBootstrapToCreatePr` — bootstrap, inspect, heartbeat,
  legitimate divergence (commit and push), pre-mutation ownership re-check, and
  the unchanged #447 create-PR provenance guard, in one sequence against a real
  origin. `gitea_lock_issue` is patched to fail the test if anything reaches for
  it, so the bootstrap lock is proved to carry the whole cycle unrepaired.
* `DeadProvenanceConstantRemoved` — the removed constant stays removed and the
  sanctioned source set stays unwidened.

`_NativeToolBase` clears `role_session_router` route state per test: the sticky
reviewer-stop marker is process-global and, now that this task is registered in
`AUTHOR_TASKS`, an earlier suite leaving it set would make the first gate refuse
before the namespace gate under test is reached.

Also documents both new tools in `docs/mcp-tool-inventory.md`, so this branch
adds no drift to `test_documented_inventory_equals_registered_tools`; the
failure reason there is now identical to the pinned base's.

Suite: 61 -> 92 cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-28 02:08:21 -04:00

180 lines
6.1 KiB
Markdown

# Registered MCP tool inventory
This is the canonical list of tools the Gitea-Tools MCP server registers. It
exists because documentation and the registered inventory drifted: the workflow
documented a `gitea_edit_issue` tool that no namespace had ever registered, so a
mutation could be planned against a tool that did not exist and only fail at
execution time (#781).
## The rule
**Documentation must never name a tool an actor cannot reach.**
Two guards enforce it, both in `tests/test_issue_781_edit_issue_tool.py`:
1. The list below must equal the registered tool set exactly — sorted, no
duplicates, nothing missing in either direction. Adding a tool without
documenting it fails, and documenting a tool without registering it fails.
2. Every backticked `gitea_*` / `mcp_*` identifier in `skills/**/*.md` must be a
registered tool. Module and script names that share the prefix are listed
explicitly in `mcp_tool_inventory.NON_TOOL_IDENTIFIERS` rather than being
waved through by a looser pattern.
## Updating this file
When you add or remove an `@mcp.tool()`, regenerate the block below:
```bash
PYTEST_CURRENT_TEST=1 venv/bin/python -c "
import mcp_server, mcp_tool_inventory
print(mcp_tool_inventory.render_inventory_block(
mcp_server.mcp._tool_manager._tools))
"
```
Replace everything between the markers with that output. Do not hand-edit
individual entries — the generator and the guard share one ordering rule.
## Registered tools
Namespaces (`gitea-tools`, `gitea-reviewer`, `gitea-merger`, `gitea-reconciler`)
register the same tool set; what differs per namespace is the execution profile
that gates each call, not which tools exist.
<!-- BEGIN REGISTERED TOOL INVENTORY -->
- `gitea_abandon_workflow_lease`
- `gitea_acquire_conflict_fix_lease`
- `gitea_acquire_merger_pr_lease`
- `gitea_acquire_reviewer_pr_lease`
- `gitea_activate_profile`
- `gitea_adopt_merger_pr_lease`
- `gitea_adopt_workflow_lease`
- `gitea_allocate_next_work`
- `gitea_assess_already_landed_reconciliation`
- `gitea_assess_conflict_fix_classification`
- `gitea_assess_conflict_fix_push`
- `gitea_assess_gitea_operation_path`
- `gitea_assess_master_parity`
- `gitea_assess_mcp_namespace_health`
- `gitea_assess_pr_sync_status`
- `gitea_assess_review_merge_state_machine`
- `gitea_assess_reviewer_pr_lease`
- `gitea_assess_terminal_label_hygiene`
- `gitea_assess_work_issue_duplicate`
- `gitea_assess_worktree_cleanup_integrity`
- `gitea_audit_config`
- `gitea_audit_runtime_recovery_contamination`
- `gitea_audit_stable_branch_contamination`
- `gitea_audit_worktree_cleanup`
- `gitea_authorize_reconciliation_cleanup_phase`
- `gitea_authorize_review_correction`
- `gitea_bootstrap_author_issue_worktree`
- `gitea_capability_stop_terminal_report`
- `gitea_capture_branches_worktree_snapshot`
- `gitea_check_pr_eligibility`
- `gitea_cleanup_merged_pr_branch`
- `gitea_cleanup_obsolete_reviewer_comment_lease`
- `gitea_cleanup_post_merge_moot_lease`
- `gitea_cleanup_stale_claims`
- `gitea_cleanup_stale_review_decision_lock`
- `gitea_cleanup_terminal_pr_labels`
- `gitea_close_issue`
- `gitea_commit_files`
- `gitea_consume_irrecoverable_decision_lock_provenance`
- `gitea_create_issue`
- `gitea_create_issue_comment`
- `gitea_create_label`
- `gitea_create_pr`
- `gitea_delete_branch`
- `gitea_diagnose_review_decision_lock`
- `gitea_diagnose_reviewer_pr_lease_handoff`
- `gitea_diagnose_terminal`
- `gitea_dry_run_pr_review`
- `gitea_edit_issue`
- `gitea_edit_pr`
- `gitea_expire_workflow_leases`
- `gitea_get_authenticated_user`
- `gitea_get_current_user`
- `gitea_get_file`
- `gitea_get_pr_review_feedback`
- `gitea_get_profile`
- `gitea_get_runtime_context`
- `gitea_get_shell_health`
- `gitea_heartbeat_issue_lock`
- `gitea_heartbeat_reviewer_pr_lease`
- `gitea_inspect_issue_lock_contract`
- `gitea_inspect_workflow_lease`
- `gitea_issue_irrecoverable_provenance_authorization`
- `gitea_list_dependency_edges`
- `gitea_list_issue_comments`
- `gitea_list_issues`
- `gitea_list_labels`
- `gitea_list_profiles`
- `gitea_list_prs`
- `gitea_list_workflow_leases`
- `gitea_load_review_workflow`
- `gitea_lock_issue`
- `gitea_mark_final_review_decision`
- `gitea_mark_issue`
- `gitea_merge_pr`
- `gitea_mirror_refs`
- `gitea_observability_link_issue`
- `gitea_observability_list_projects`
- `gitea_observability_reconcile_incident`
- `gitea_post_heartbeat`
- `gitea_publish_unpublished_issue_branch`
- `gitea_quarantine_contaminated_review`
- `gitea_reclaim_expired_workflow_lease`
- `gitea_reconcile_already_landed_pr`
- `gitea_reconcile_issue_claims`
- `gitea_reconcile_merged_cleanups`
- `gitea_reconcile_superseded_by_merged_pr`
- `gitea_record_daemon_process_kill_attempt`
- `gitea_record_irrecoverable_decision_lock_provenance`
- `gitea_record_pre_review_command`
- `gitea_record_shell_spawn_outcome`
- `gitea_record_stable_branch_push_attempt`
- `gitea_recover_incomplete_bootstrap_lock`
- `gitea_release_merger_pr_lease`
- `gitea_release_reviewer_pr_lease`
- `gitea_release_workflow_lease`
- `gitea_request_mcp_reconnect`
- `gitea_request_mcp_restart`
- `gitea_resolve_task_capability`
- `gitea_resume_review_draft`
- `gitea_review_pr`
- `gitea_route_task_session`
- `gitea_save_review_draft`
- `gitea_scan_already_landed_open_prs`
- `gitea_sentry_get_issue_events`
- `gitea_sentry_link_gitea_issue`
- `gitea_sentry_list_issues`
- `gitea_sentry_reconcile_issue`
- `gitea_sentry_watchdog`
- `gitea_set_issue_labels`
- `gitea_submit_pr_review`
- `gitea_update_pr_branch_by_merge`
- `gitea_validate_review_final_report`
- `gitea_view_issue`
- `gitea_view_pr`
- `gitea_whoami`
- `gitea_workflow_dashboard`
- `mcp_check_workflow_skill_preflight`
- `mcp_get_control_plane_guide`
- `mcp_get_skill_guide`
- `mcp_list_project_skills`
<!-- END REGISTERED TOOL INVENTORY -->
## Issue-content editing
`gitea_edit_issue` is the only path that changes an issue's title or body. It
PATCHes the issue endpoint, refuses a pull-request number, sends only the fields
the caller named, and proves the result by read-after-write — including that
state, labels, assignees, and milestone did not move.
`gitea_edit_pr` remains pull-request-only. The two paths never merge: a single
tool that accepted either kind would make the narrower capability reachable
through the wider one.