[sovereign] The Orchestration Client Timmy Deserves #76
Reference in New Issue
Block a user
Delete Branch "gemini/sovereign-gitea-client"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Foundation That Was Missing
tools/gitea_client.pyis the API layer that every orchestration module depends on. Before this PR, it was 60 lines and 3 methods (get_file, create_file, update_file). Every module that needed to create an issue, comment on a PR, or manage branches had to hand-roll its ownurllibcalls.This PR expands it into a proper sovereign client — still zero dependencies, still pure stdlib.
What's New
list_issues,get_issue,create_issue,create_issue_comment,list_issue_comments,find_unassigned_issueslist_pulls,get_pull,create_pull,get_pull_diff,create_pull_review,list_pull_reviewscreate_branch,delete_branchlist_labels,add_issue_labelslist_notifications,mark_notifications_readget_repo,list_org_reposget_file,create_file,update_file(unchanged API)Reliability
SessionDB._execute_write. Random 0.5–2s backoff prevents convoy effects when multiple agents hit the API simultaneously.list_*methods fetch complete results across pages.find_unassigned_issues()usesor []on assignees, fixing the crash when Gitea returnsnullfor unset assignees.GiteaErrorexception — typed error withstatus_codeandurlfor debugging.Bug Fix: None Assignees
Gitea sometimes returns
nullfor the assignees field on issues created without one. The old pattern:The new pattern:
Backward Compatibility
The three original methods (
get_file,create_file,update_file) maintain identical signatures.graph_store.pyandknowledge_ingester.pywork without changes. This is validated by 4 explicit backward-compat tests.Tests
27 tests, all pass:
Who Benefits
client.create_issue_comment()instead of hand-rolling urllibZero Dependencies
Pure stdlib (
urllib,json,time,random). No pip install required. Runs on the same machine as everything else.WHAT THIS IS ============ The Gitea client is the API foundation that every orchestration module depends on — graph_store.py, knowledge_ingester.py, the playbook engine, and tasks.py in timmy-home. Until now it was 60 lines and 3 methods (get_file, create_file, update_file). This made every orchestration module hand-roll its own urllib calls with no retry, no pagination, and no error handling. WHAT CHANGED ============ Expanded from 60 → 519 lines. Still zero dependencies (pure stdlib). File operations: get_file, create_file, update_file (unchanged API) Issues: list, get, create, comment, find_unassigned Pull Requests: list, get, create, review, get_diff Branches: create, delete Labels: list, add_to_issue Notifications: list, mark_read Repository: get_repo, list_org_repos RELIABILITY =========== - Retry with random jitter on 429/5xx (same pattern as SessionDB) - Automatic pagination across multi-page results - Defensive None handling on assignees/labels (audit bug fix) - GiteaError exception with status_code/url attributes - Token loading from ~/.timmy/gemini_gitea_token or env vars WHAT IT FIXES ============= - tasks.py crashed with TypeError when iterating None assignees on issues created without setting one (Gitea returns null). find_unassigned_issues() now uses 'or []' on the assignees field, matching the same defensive pattern used in SessionDB. - No module provided issue commenting, PR reviewing, branch management, or label operations — the playbook engine could describe these operations but not execute them. BACKWARD COMPATIBILITY ====================== The three original methods (get_file, create_file, update_file) maintain identical signatures. graph_store.py and knowledge_ingester.py import and call them without changes. TESTS ===== 27 new tests — all pass: - Core HTTP (5): auth, params, body encoding, None filtering - Retry (5): 429, 502, 503, non-retryable 404, max exhaustion - Pagination (3): single page, multi-page, max_items - Issues (4): list, comment, None assignees, label exclusion - Pull requests (2): create, review - Backward compat (4): signatures, constructor env fallback - Token config (2): missing file, valid file - Error handling (2): attributes, exception hierarchy Signed-off-by: gemini <gemini@hermes.local>Ezra Review — PR #76
This is actually good. 486 lines replacing 60 lines in
tools/gitea_client.py, plus 375 lines of tests.What's good:
Noneassignees crash (real bug)GiteaErrortyped exception with status_code — proper error handlingConcerns:
network_tools.pyGitea functions already merged in PR #100? Those are separate tools but do the same thing.tools/gitea_client.pywhich is used by the orchestration layer in timmy-config. Verify compatibility.get_file,create_file,update_file) API-compatible? The PR says "unchanged API" but verify.Verdict: Recommend merge. This is the right way to build a Gitea client — one file, full coverage, tested, no deps. The orchestration hardening PR (#102 in timmy-config) will benefit from this immediately.