github-agent 2.4.15__tar.gz → 2.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. {github_agent-2.4.15 → github_agent-2.5.0}/PKG-INFO +2 -6
  2. {github_agent-2.4.15 → github_agent-2.5.0}/README.md +0 -4
  3. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_dependabot.py +2 -0
  4. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_orgs.py +4 -4
  5. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_pages.py +2 -2
  6. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_pulls.py +2 -0
  7. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/auth.py +0 -10
  8. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/mcp_server.py +14 -1
  9. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/certification.json +3 -3
  10. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/github.ttl +8 -5
  11. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/shapes/connector.shacl.ttl +2 -2
  12. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-agent-development/SKILL.md +1 -2
  13. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/PKG-INFO +2 -6
  14. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/SOURCES.txt +1 -0
  15. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/requires.txt +1 -1
  16. {github_agent-2.4.15 → github_agent-2.5.0}/pyproject.toml +2 -2
  17. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_cq_paths.py +1 -1
  18. github_agent-2.5.0/tests/test_destructive_declaration.py +86 -0
  19. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_ontology_parent_link.py +5 -0
  20. {github_agent-2.4.15 → github_agent-2.5.0}/LICENSE +0 -0
  21. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/__init__.py +0 -0
  22. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/__main__.py +0 -0
  23. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/__init__.py +0 -0
  24. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_base.py +0 -0
  25. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_branches.py +0 -0
  26. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_comments.py +0 -0
  27. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_commits.py +0 -0
  28. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_contents.py +0 -0
  29. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_issues.py +0 -0
  30. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_releases.py +0 -0
  31. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_repos.py +0 -0
  32. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_search.py +0 -0
  33. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api/api_client_workflows.py +0 -0
  34. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/api_client.py +0 -0
  35. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/connector_contracts.py +0 -0
  36. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/connector_sources.py +0 -0
  37. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/connectors/__init__.py +0 -0
  38. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/github_gql.py +0 -0
  39. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/github_http.py +0 -0
  40. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/github_input_models.py +0 -0
  41. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/github_response_models.py +0 -0
  42. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/kg_ingest.py +0 -0
  43. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/mcp/__init__.py +0 -0
  44. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/mcp_config.json +0 -0
  45. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/__init__.py +0 -0
  46. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/fixtures/records.json +0 -0
  47. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/mappings/source.yaml +0 -0
  48. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/ontology/migrations/manifest.json +0 -0
  49. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/prompts/__init__.py +0 -0
  50. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/prompts/github-mcp-operator.json +0 -0
  51. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/prompts/github-mcp-release-manager.json +0 -0
  52. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/prompts/github-mcp-repository-administrator.json +0 -0
  53. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/prompts/github-mcp-triage-lead.json +0 -0
  54. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/__init__.py +0 -0
  55. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-actions-ci-review/SKILL.md +0 -0
  56. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-agent-operations/SKILL.md +0 -0
  57. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-backlog-planner/SKILL.md +0 -0
  58. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-backlog-planner/references/addressed-heuristics.md +0 -0
  59. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-backlog-planner/scripts/build_plan.py +0 -0
  60. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-ci-failure-sweep/SKILL.md +0 -0
  61. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-ci-failure-sweep/scripts/summarize_runs.py +0 -0
  62. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-dependabot-review/SKILL.md +0 -0
  63. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-issue-tracking/SKILL.md +0 -0
  64. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-org-remediation-loop/SKILL.md +0 -0
  65. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-org-remediation-loop/scripts/classify_fix_risk.py +0 -0
  66. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-pr-review-sweep/SKILL.md +0 -0
  67. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-pr-review-sweep/scripts/summarize_prs.py +0 -0
  68. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-project-provisioner/SKILL.md +0 -0
  69. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-project-provisioner/scripts/enable_pages.py +0 -0
  70. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-pull-request-create/SKILL.md +0 -0
  71. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-pull-request-review/SKILL.md +0 -0
  72. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-repository-management/SKILL.md +0 -0
  73. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-tools/SKILL.md +0 -0
  74. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-tools/code-reviewer.md +0 -0
  75. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-tools/scripts/fetch_comments.py +0 -0
  76. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-tools/scripts/inspect_pr_checks.py +0 -0
  77. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-triage-resolver/SKILL.md +0 -0
  78. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-triage-resolver/references/resolution-rules.md +0 -0
  79. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-triage-resolver/scripts/classify_safe.py +0 -0
  80. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent/skills/github-triage-resolver/scripts/gh_write.py +0 -0
  81. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/dependency_links.txt +0 -0
  82. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/entry_points.txt +0 -0
  83. {github_agent-2.4.15 → github_agent-2.5.0}/github_agent.egg-info/top_level.txt +0 -0
  84. {github_agent-2.4.15 → github_agent-2.5.0}/setup.cfg +0 -0
  85. {github_agent-2.4.15 → github_agent-2.5.0}/tests/conftest.py +0 -0
  86. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_api_client_endpoints.py +0 -0
  87. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_api_validation.py +0 -0
  88. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_auth_client_edge_cases.py +0 -0
  89. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_default_content_surfaces.py +0 -0
  90. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_fleet_name.py +0 -0
  91. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_github_agent_api_brute_force_coverage.py +0 -0
  92. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_github_agent_brute_force_coverage.py +0 -0
  93. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_github_gql.py +0 -0
  94. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_github_http.py +0 -0
  95. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_ingest_sources.py +0 -0
  96. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_init_dynamics.py +0 -0
  97. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_kg_ingest.py +0 -0
  98. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_model_fields.py +0 -0
  99. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_pages.py +0 -0
  100. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_backlog_build_plan.py +0 -0
  101. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_ci_failure_sweep_summarize_runs.py +0 -0
  102. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_github_tools_fetch_comments.py +0 -0
  103. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_github_tools_inspect_pr_checks.py +0 -0
  104. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_org_remediation_classify_fix_risk.py +0 -0
  105. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_pr_review_sweep_summarize_prs.py +0 -0
  106. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_skill_triage_resolver_classify_safe.py +0 -0
  107. {github_agent-2.4.15 → github_agent-2.5.0}/tests/test_startup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-agent
3
- Version: 2.4.15
3
+ Version: 2.5.0
4
4
  Summary: GitHub Agent for MCP
5
5
  Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
@@ -13,7 +13,7 @@ Requires-Python: >=3.12
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: requests>=2.34.2
16
- Requires-Dist: scion-sdk[graphql,mcp]>=0.9.0
16
+ Requires-Dist: scion-sdk[graphql,mcp]<0.11,>=0.10.2
17
17
  Provides-Extra: mcp
18
18
  Provides-Extra: all
19
19
  Provides-Extra: test
@@ -247,7 +247,6 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
247
247
  "COMMITTOOL": "True",
248
248
  "CONTENTTOOL": "True",
249
249
  "DEPENDABOTTOOL": "True",
250
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
251
250
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
252
251
  "GITHUB_HTTP_READ_TIMEOUT": "30",
253
252
  "GITHUB_TOKEN": "your_github_token_here",
@@ -298,7 +297,6 @@ own runtime secret boundary.
298
297
  "COMMITTOOL": "True",
299
298
  "CONTENTTOOL": "True",
300
299
  "DEPENDABOTTOOL": "True",
301
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
302
300
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
303
301
  "GITHUB_HTTP_READ_TIMEOUT": "30",
304
302
  "GITHUB_TOKEN": "your_github_token_here",
@@ -348,7 +346,6 @@ docker run -i --rm \
348
346
  -e COMMITTOOL=True \
349
347
  -e CONTENTTOOL=True \
350
348
  -e DEPENDABOTTOOL=True \
351
- -e GITHUB_ALLOW_DESTRUCTIVE=False \
352
349
  -e GITHUB_HTTP_CONNECT_TIMEOUT=10 \
353
350
  -e GITHUB_HTTP_READ_TIMEOUT=30 \
354
351
  -e GITHUB_TOKEN=your_github_token_here \
@@ -412,7 +409,6 @@ the detailed transport contract.
412
409
  | `TLS_PROFILE` | `private-ca` | AgentConfig named transport profile |
413
410
  | `TLS_PROFILE_REF` | `secret://transport/provider` | Direct runtime profile reference |
414
411
  | `TLS_PROFILES_REF` | `secret://transport/catalog` | Named runtime profile catalog |
415
- | `GITHUB_ALLOW_DESTRUCTIVE` | `False` | Allow destructive (delete/force) operations |
416
412
  | `GITHUB_HTTP_CONNECT_TIMEOUT` | `10` | HTTP client timeouts (seconds) |
417
413
  | `GITHUB_HTTP_READ_TIMEOUT` | `30` | |
418
414
  | `DEBUG` | `False` | |
@@ -223,7 +223,6 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
223
223
  "COMMITTOOL": "True",
224
224
  "CONTENTTOOL": "True",
225
225
  "DEPENDABOTTOOL": "True",
226
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
227
226
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
228
227
  "GITHUB_HTTP_READ_TIMEOUT": "30",
229
228
  "GITHUB_TOKEN": "your_github_token_here",
@@ -274,7 +273,6 @@ own runtime secret boundary.
274
273
  "COMMITTOOL": "True",
275
274
  "CONTENTTOOL": "True",
276
275
  "DEPENDABOTTOOL": "True",
277
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
278
276
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
279
277
  "GITHUB_HTTP_READ_TIMEOUT": "30",
280
278
  "GITHUB_TOKEN": "your_github_token_here",
@@ -324,7 +322,6 @@ docker run -i --rm \
324
322
  -e COMMITTOOL=True \
325
323
  -e CONTENTTOOL=True \
326
324
  -e DEPENDABOTTOOL=True \
327
- -e GITHUB_ALLOW_DESTRUCTIVE=False \
328
325
  -e GITHUB_HTTP_CONNECT_TIMEOUT=10 \
329
326
  -e GITHUB_HTTP_READ_TIMEOUT=30 \
330
327
  -e GITHUB_TOKEN=your_github_token_here \
@@ -388,7 +385,6 @@ the detailed transport contract.
388
385
  | `TLS_PROFILE` | `private-ca` | AgentConfig named transport profile |
389
386
  | `TLS_PROFILE_REF` | `secret://transport/provider` | Direct runtime profile reference |
390
387
  | `TLS_PROFILES_REF` | `secret://transport/catalog` | Named runtime profile catalog |
391
- | `GITHUB_ALLOW_DESTRUCTIVE` | `False` | Allow destructive (delete/force) operations |
392
388
  | `GITHUB_HTTP_CONNECT_TIMEOUT` | `10` | HTTP client timeouts (seconds) |
393
389
  | `GITHUB_HTTP_READ_TIMEOUT` | `30` | |
394
390
  | `DEBUG` | `False` | |
@@ -2,6 +2,7 @@
2
2
  from typing import Any
3
3
 
4
4
  from scion_sdk.exceptions import require_auth
5
+ from scion_sdk.mcp.destructive import destructive_operation
5
6
 
6
7
  from github_agent.api.api_client_base import BaseApiClient
7
8
  from github_agent.github_response_models import Response
@@ -59,6 +60,7 @@ class Api(BaseApiClient):
59
60
  response.raise_for_status()
60
61
  return Response(response=response, data=response.json())
61
62
 
63
+ @destructive_operation
62
64
  @require_auth
63
65
  def update_dependabot_alert(
64
66
  self,
@@ -111,8 +111,8 @@ class Api(BaseApiClient):
111
111
  """Schedule an organization for deletion. IRREVERSIBLE.
112
112
 
113
113
  GitHub responds 202 Accepted and deletes the organization, all of its
114
- repositories, and all of its data asynchronously. The MCP layer gates
115
- this action behind allow_destructive / GITHUB_ALLOW_DESTRUCTIVE.
114
+ repositories, and all of its data asynchronously. The SDK asks
115
+ the caller to confirm this action.
116
116
 
117
117
  DELETE /orgs/{org}
118
118
  https://docs.github.com/en/rest/orgs/orgs#delete-an-organization
@@ -240,8 +240,8 @@ class Api(BaseApiClient):
240
240
  def remove_organization_member(self, org: str, username: str) -> Response:
241
241
  """Remove a user from an organization (repositories access included).
242
242
 
243
- Destructive: the MCP layer gates this action behind
244
- allow_destructive / GITHUB_ALLOW_DESTRUCTIVE. GitHub responds 204.
243
+ Destructive: the SDK asks the caller to confirm this
244
+ action. GitHub responds 204.
245
245
 
246
246
  DELETE /orgs/{org}/members/{username}
247
247
  https://docs.github.com/en/rest/orgs/members#remove-an-organization-member
@@ -150,8 +150,8 @@ class Api(BaseApiClient):
150
150
  def delete_pages(self, owner: str, repo: str) -> Response:
151
151
  """Disable GitHub Pages for a repository and delete the site.
152
152
 
153
- Destructive: the MCP layer gates this action behind
154
- allow_destructive / GITHUB_ALLOW_DESTRUCTIVE. GitHub responds 204.
153
+ Destructive: the SDK asks the caller to confirm this
154
+ action. GitHub responds 204.
155
155
 
156
156
  DELETE /repos/{owner}/{repo}/pages
157
157
  https://docs.github.com/en/rest/pages/pages#delete-a-apiname-pages-site
@@ -5,6 +5,7 @@ from scion_sdk.exceptions import (
5
5
  ParameterError,
6
6
  require_auth,
7
7
  )
8
+ from scion_sdk.mcp.destructive import destructive_operation
8
9
 
9
10
  from github_agent.api.api_client_base import BaseApiClient
10
11
  from github_agent.github_input_models import (
@@ -107,6 +108,7 @@ class Api(BaseApiClient):
107
108
  response.raise_for_status()
108
109
  return Response(response=response, data=response.json())
109
110
 
111
+ @destructive_operation
110
112
  @require_auth
111
113
  def merge_pull_request(
112
114
  self,
@@ -21,16 +21,6 @@ from github_agent.api_client import Api
21
21
  logger = get_logger(__name__)
22
22
 
23
23
 
24
- def allow_destructive_default() -> bool:
25
- """Fleet-wide default for the destructive-action gate.
26
-
27
- Destructive MCP actions (e.g. organization delete, member removal) are
28
- blocked unless the caller passes allow_destructive=true or the
29
- GITHUB_ALLOW_DESTRUCTIVE environment variable is set truthy.
30
- """
31
- return setting("GITHUB_ALLOW_DESTRUCTIVE", False)
32
-
33
-
34
24
  def _exchange_delegated_token(settings: DelegationSettings) -> str:
35
25
  """Exchange the caller's verified MCP token for a downstream GitHub token."""
36
26
  logger.info(
@@ -29,6 +29,7 @@ from scion_sdk.config import load_config
29
29
  from scion_sdk.connector_identity import connector_version
30
30
  from scion_sdk.mcp.concurrency import run_blocking
31
31
  from scion_sdk.mcp.content import ConnectorContent
32
+ from scion_sdk.mcp.destructive import guard_destructive
32
33
  from scion_sdk.mcp.server import create_mcp_server
33
34
  from scion_sdk.mcp.tool_surface import register_tool_surface
34
35
 
@@ -218,7 +219,7 @@ def register_auto_merge_tools(mcp: FastMCP):
218
219
  """Register the GraphQL-only pull request auto-merge tools."""
219
220
 
220
221
  @mcp.tool(
221
- tags={"pulls"}, annotations={"readOnlyHint": False, "destructiveHint": False}
222
+ tags={"pulls"}, annotations={"readOnlyHint": False, "destructiveHint": True}
222
223
  )
223
224
  async def github_pulls_enable_auto_merge(
224
225
  owner: str = Field(description="Repository owner."),
@@ -228,9 +229,21 @@ def register_auto_merge_tools(mcp: FastMCP):
228
229
  default="MERGE", description="MERGE, SQUASH or REBASE."
229
230
  ),
230
231
  client=Depends(get_client),
232
+ confirm: bool = Field(
233
+ default=False,
234
+ description="Confirm this destructive call when the client cannot be asked.",
235
+ ),
231
236
  ctx: Context | None = Field(default=None, description="MCP context"),
232
237
  ) -> Any:
233
238
  """Turn on auto-merge for a pull request: it merges once required checks pass."""
239
+ refused = await guard_destructive(
240
+ ctx,
241
+ "enable_auto_merge",
242
+ {"owner": owner, "repo": repo, "number": number},
243
+ confirm=confirm,
244
+ )
245
+ if refused is not None:
246
+ return refused
234
247
  try:
235
248
  gql_client = await run_blocking(get_graphql_client)
236
249
  except Exception as e:
@@ -2,10 +2,10 @@
2
2
  "api_version": "graphos.io/v1",
3
3
  "artifacts": {
4
4
  "github_agent/ontology/fixtures/records.json": "12f5b54b0ae98770f279f99e136788d063340042a9d6ff4bac0c22a886d2dc7b",
5
- "github_agent/ontology/github.ttl": "3558c43835211ddcf7d2af622a37c0c370a7e8fe6b40a111b9bc98dd7e91f2ac",
5
+ "github_agent/ontology/github.ttl": "70c68c0ae5cc8b056bd6f21af44eb3cbdf6d3bf213e0764e5c3341ea536fbd20",
6
6
  "github_agent/ontology/mappings/source.yaml": "5142f75b88634aeac6850fe6de5b176958d63073daab2c573cf9c03daa46021c",
7
7
  "github_agent/ontology/migrations/manifest.json": "adf16022502dd031dd303a52abae7a0677ece1135e1e05c21dba24c9ae51935c",
8
- "github_agent/ontology/shapes/connector.shacl.ttl": "709f555b7b8cc6b1e0adddfeb8e077834f5db548bed4a904afd2a195e49aab1c"
8
+ "github_agent/ontology/shapes/connector.shacl.ttl": "0972b7e3b5f56fb0452f070800cd1f7ee790f6cf183f308f1cf69e5a0db716e0"
9
9
  },
10
10
  "checks": {
11
11
  "declared_tool_schema": "passed",
@@ -29,5 +29,5 @@
29
29
  "signer": "UNSIGNED-PREVIEW",
30
30
  "signing_public_key": "",
31
31
  "status": "source-validated",
32
- "validated_at": "2026-11-06T18:41:25Z"
32
+ "validated_at": "2026-11-12T19:19:41Z"
33
33
  }
@@ -2,6 +2,7 @@
2
2
  @prefix foaf: <http://xmlns.com/foaf/0.1/> .
3
3
  @prefix dc: <http://purl.org/dc/terms/> .
4
4
  @prefix : <http://knuckles.team/kg#> .
5
+ @prefix core: <https://knuckles-team.github.io/ontology/core#> .
5
6
  @prefix owl: <http://www.w3.org/2002/07/owl#> .
6
7
  @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7
8
  @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@@ -15,24 +16,26 @@
15
16
  # Shared concepts owned by the epistemic-graph ontology and referenced here, never redeclared:
16
17
  # Repository, PullRequest, Release, Branch, Commit, PipelineRun. Only the GitHub-specific subclasses and properties are declared in this pack.
17
18
 
18
- :Organization a owl:Class .
19
+ :Organization a owl:Class ;
20
+ rdfs:subClassOf core:Organization .
19
21
 
20
22
 
21
23
  :Issue a owl:Class ;
22
- rdfs:subClassOf :WorkItem ;
24
+ rdfs:subClassOf core:WorkItem ;
23
25
  rdfs:label "Issue" ;
24
26
  rdfs:comment "A tracked work item, bug, or discussion in a repository (github_get_issues)." .
25
27
 
26
- :Workflow a owl:Class .
28
+ :Workflow a owl:Class ;
29
+ rdfs:subClassOf core:Workflow .
27
30
 
28
31
 
29
32
  :WorkflowRun a owl:Class ;
30
- rdfs:subClassOf :PipelineRun ;
33
+ rdfs:subClassOf core:PipelineRun ;
31
34
  rdfs:label "Workflow Run" ;
32
35
  rdfs:comment "A single execution of a GitHub Actions workflow for a ref/commit (github_get_workflow_runs)." .
33
36
 
34
37
  :CheckRun a owl:Class ;
35
- rdfs:subClassOf :PipelineRun ;
38
+ rdfs:subClassOf core:PipelineRun ;
36
39
  rdfs:label "Check Run" ;
37
40
  rdfs:comment """A single job/check within a PipelineRun (github_get_workflow_run_jobs workflow-run job or
38
41
  GitHub Checks-API check run). Shares its class name with the twin gitlab-api producer.""" .
@@ -1,5 +1,5 @@
1
- @prefix : <http://knuckles.team/kg#> .
2
- @prefix shape: <http://knuckles.team/kg/github/shape#> .
1
+ @prefix : <https://knuckles-team.github.io/ontology/core#> .
2
+ @prefix shape: <https://knuckles-team.github.io/ontology/connector/github-shapes#> .
3
3
  @prefix sh: <http://www.w3.org/ns/shacl#> .
4
4
  @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5
5
 
@@ -65,8 +65,7 @@ with local copies or bypass a failing check.
65
65
  - Credentials come from `GITHUB_TOKEN`; the endpoint is derived from `GITHUB_URL`
66
66
  (`api.github.com`, or a GitHub Enterprise `/api/v3` host whose GraphQL endpoint
67
67
  is `/api/graphql`). Mock all GitHub calls; never use a real token in a gate.
68
- - Destructive operations stay behind `GITHUB_ALLOW_DESTRUCTIVE`; keep it false
69
- by default and test both states.
68
+ - Destructive operations are declared once with the SDK `destructive_operation` decorator; the SDK asks the caller to confirm (`confirm=true`), and `SCION_ALLOW_DESTRUCTIVE` is the one operator setting. Never add a connector-local knob.
70
69
  - Prefer one aliased `github_graphql` query over many REST calls for cross-repo
71
70
  reads; keep REST and GraphQL parity when adding a tool domain.
72
71
  - Packaged skills under `github_agent/skills/` have their own helper tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-agent
3
- Version: 2.4.15
3
+ Version: 2.5.0
4
4
  Summary: GitHub Agent for MCP
5
5
  Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
@@ -13,7 +13,7 @@ Requires-Python: >=3.12
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: requests>=2.34.2
16
- Requires-Dist: scion-sdk[graphql,mcp]>=0.9.0
16
+ Requires-Dist: scion-sdk[graphql,mcp]<0.11,>=0.10.2
17
17
  Provides-Extra: mcp
18
18
  Provides-Extra: all
19
19
  Provides-Extra: test
@@ -247,7 +247,6 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
247
247
  "COMMITTOOL": "True",
248
248
  "CONTENTTOOL": "True",
249
249
  "DEPENDABOTTOOL": "True",
250
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
251
250
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
252
251
  "GITHUB_HTTP_READ_TIMEOUT": "30",
253
252
  "GITHUB_TOKEN": "your_github_token_here",
@@ -298,7 +297,6 @@ own runtime secret boundary.
298
297
  "COMMITTOOL": "True",
299
298
  "CONTENTTOOL": "True",
300
299
  "DEPENDABOTTOOL": "True",
301
- "GITHUB_ALLOW_DESTRUCTIVE": "False",
302
300
  "GITHUB_HTTP_CONNECT_TIMEOUT": "10",
303
301
  "GITHUB_HTTP_READ_TIMEOUT": "30",
304
302
  "GITHUB_TOKEN": "your_github_token_here",
@@ -348,7 +346,6 @@ docker run -i --rm \
348
346
  -e COMMITTOOL=True \
349
347
  -e CONTENTTOOL=True \
350
348
  -e DEPENDABOTTOOL=True \
351
- -e GITHUB_ALLOW_DESTRUCTIVE=False \
352
349
  -e GITHUB_HTTP_CONNECT_TIMEOUT=10 \
353
350
  -e GITHUB_HTTP_READ_TIMEOUT=30 \
354
351
  -e GITHUB_TOKEN=your_github_token_here \
@@ -412,7 +409,6 @@ the detailed transport contract.
412
409
  | `TLS_PROFILE` | `private-ca` | AgentConfig named transport profile |
413
410
  | `TLS_PROFILE_REF` | `secret://transport/provider` | Direct runtime profile reference |
414
411
  | `TLS_PROFILES_REF` | `secret://transport/catalog` | Named runtime profile catalog |
415
- | `GITHUB_ALLOW_DESTRUCTIVE` | `False` | Allow destructive (delete/force) operations |
416
412
  | `GITHUB_HTTP_CONNECT_TIMEOUT` | `10` | HTTP client timeouts (seconds) |
417
413
  | `GITHUB_HTTP_READ_TIMEOUT` | `30` | |
418
414
  | `DEBUG` | `False` | |
@@ -83,6 +83,7 @@ tests/test_api_validation.py
83
83
  tests/test_auth_client_edge_cases.py
84
84
  tests/test_cq_paths.py
85
85
  tests/test_default_content_surfaces.py
86
+ tests/test_destructive_declaration.py
86
87
  tests/test_fleet_name.py
87
88
  tests/test_github_agent_api_brute_force_coverage.py
88
89
  tests/test_github_agent_brute_force_coverage.py
@@ -1,5 +1,5 @@
1
1
  requests>=2.34.2
2
- scion-sdk[graphql,mcp]>=0.9.0
2
+ scion-sdk[graphql,mcp]<0.11,>=0.10.2
3
3
 
4
4
  [all]
5
5
 
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "github-agent"
7
- version = "2.4.15"
7
+ version = "2.5.0"
8
8
  readme = "README.md"
9
9
  description = "GitHub Agent for MCP"
10
10
  requires-python = ">=3.12"
11
11
  classifiers = [ "Development Status :: 5 - Production/Stable", "License :: Public Domain", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
12
- dependencies = [ "requests>=2.34.2", "scion-sdk[mcp,graphql]>=0.9.0",]
12
+ dependencies = [ "requests>=2.34.2", "scion-sdk[mcp,graphql]>=0.10.2,<0.11",]
13
13
  [[project.authors]]
14
14
  name = "Repository Maintainers"
15
15
  email = "maintainers@knuckles.team"
@@ -35,7 +35,7 @@ def test_state_is_declared_on_the_issue_type() -> None:
35
35
 
36
36
 
37
37
  def test_check_run_extends_pipeline_run() -> None:
38
- assert "rdfs:subClassOf :PipelineRun" in _block("CheckRun")
38
+ assert "rdfs:subClassOf core:PipelineRun" in _block("CheckRun")
39
39
 
40
40
 
41
41
  def test_no_mapping_has_a_null_ontology_class() -> None:
@@ -0,0 +1,86 @@
1
+ """CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R008: destructive operations use the SDK's one declaration and guard."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import importlib
7
+ from unittest.mock import patch
8
+
9
+ import pytest
10
+ import requests
11
+ from fastmcp import Client, FastMCP
12
+
13
+ pytestmark = pytest.mark.spec("CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R008")
14
+
15
+ DECLARED = {
16
+ "github_merge_pull_request",
17
+ "github_update_dependabot_alert",
18
+ "github_pulls_enable_auto_merge",
19
+ }
20
+ CLASSIFIED = {"github_delete_repository", "github_delete_branch"}
21
+
22
+
23
+ def _server() -> FastMCP:
24
+ module = importlib.import_module("github_agent.mcp_server")
25
+ with patch(
26
+ "sys.argv", ["github-mcp", "--transport", "stdio", "--auth-type", "none"]
27
+ ):
28
+ result = module.get_mcp_instance()
29
+ if isinstance(result, FastMCP):
30
+ return result
31
+ return next(value for value in result if isinstance(value, FastMCP))
32
+
33
+
34
+ def test_declared_and_classified_operations_are_destructive_tools_that_ask_first(
35
+ monkeypatch,
36
+ ):
37
+ monkeypatch.delenv("SCION_ALLOW_DESTRUCTIVE", raising=False)
38
+
39
+ async def _run():
40
+ async with Client(_server()) as client:
41
+ tools = {t.name: t for t in await client.list_tools()}
42
+ for name in DECLARED | CLASSIFIED:
43
+ assert tools[name].annotations.destructive_hint is True, name
44
+ assert "confirm" in tools[name].input_schema["properties"], name
45
+ for name, tool in tools.items():
46
+ assert "allow_destructive" not in tool.input_schema["properties"], name
47
+
48
+ asyncio.run(_run())
49
+
50
+
51
+ @pytest.mark.parametrize(
52
+ "name,arguments",
53
+ [
54
+ (
55
+ "github_merge_pull_request",
56
+ {"owner": "o", "repo": "r", "number": 1},
57
+ ),
58
+ (
59
+ "github_delete_branch",
60
+ {"owner": "o", "repo": "r", "branch": "b"},
61
+ ),
62
+ ],
63
+ )
64
+ def test_unconfirmed_call_sends_no_request(name, arguments, monkeypatch):
65
+ monkeypatch.delenv("SCION_ALLOW_DESTRUCTIVE", raising=False)
66
+ monkeypatch.setenv("GITHUB_TOKEN", "test-token")
67
+ sent: list[str] = []
68
+
69
+ def record(self, method, url, **kwargs):
70
+ sent.append(f"{method} {url}")
71
+ raise AssertionError("no request may be made without confirmation")
72
+
73
+ monkeypatch.setattr(requests.Session, "request", record)
74
+
75
+ async def _run():
76
+ async with Client(_server()) as client:
77
+ refused = await client.call_tool(name, arguments, raise_on_error=False)
78
+ assert refused.structured_content["cancelled"] is True
79
+
80
+ asyncio.run(_run())
81
+ assert sent == []
82
+
83
+
84
+ def test_no_connector_local_knob_remains():
85
+ auth = importlib.import_module("github_agent.auth")
86
+ assert not hasattr(auth, "allow_destructive_default")
@@ -30,6 +30,11 @@ PARENT_CLASSES = frozenset(
30
30
  "http://knuckles.team/kg#Workflow",
31
31
  )
32
32
  )
33
+ # The core ontology is addressed under its one HTTPS base; a pack class rolls up to a core class by that IRI.
34
+ CORE_BASE = "https://knuckles-team.github.io/ontology/core#"
35
+ PARENT_CLASSES = PARENT_CLASSES | frozenset(
36
+ CORE_BASE + iri.rsplit("#", 1)[1] for iri in PARENT_CLASSES
37
+ )
33
38
  # Classes for which the parent ontology has no fitting class yet. Each is a candidate for a new
34
39
  # parent class (see the orphan mapping report); a class leaves this set when it gains a parent.
35
40
  PENDING_NEW_PARENT: frozenset[str] = frozenset()
File without changes
File without changes