- Update HANDOVER.md with AI agent skill section, API gotchas, session log - Add lessons-learned.md with Gitea API findings and debugging insights Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.8 KiB
Lessons Learned
Session: 2026-02-18 -- Gitea Agent Skill Implementation
Technical Discoveries
-
Gitea 1.22.6 has no project board REST API
/api/v1/user/projectsreturns 404- The existing SKILL.md had endpoints that do not exist
- Project board API is tracked in Gitea issue #14299, targeted for 1.26+
- Mitigation: Use milestones as project containers -- they have built-in progress tracking
-
Scoped label exclusivity is UI-only in Gitea 1.22.6
- Labels with
exclusive: truedisplay mutual exclusivity in the web UI - The API
POST /repos/{owner}/{repo}/issues/{index}/labelsonly appends -- it does NOT remove conflicting scoped labels - Fix: Use a swap pattern: GET current labels, filter out old scope, add new label ID, PUT full set atomically
- This was the single biggest "gotcha" -- the documentation implies API enforcement that does not exist
- Labels with
-
POST /issues/{index}/assignees does not exist in Gitea 1.22.6
- Returns 404
- Fix: Use
PATCH /repos/{owner}/{repo}/issues/{index}with{"assignees": ["username"]} - This is a general issue edit endpoint, not a dedicated assignee endpoint
-
Issue dependency format is IssueMeta, not simple ID
- Wrong:
{"depends_on_id": 2}-- returns "repository does not exist [id: 0]" - Correct:
{"owner": "terraphim", "repo": "agent-tasks", "index": 2} - Must check the Swagger spec for exact body format rather than guessing
- Wrong:
Debugging Approaches That Worked
-
Test against live API first, then write code
- Verified all 7 open questions against the live Gitea instance before writing any helper functions
- This caught the project board API gap before writing fake endpoints
-
Integration tests with real cleanup
- Each test run creates a timestamped repo (
skill-test-{timestamp}), runs all tests, then deletes it - Trap on EXIT ensures cleanup even on failure
- No mocks -- tests prove the actual API behavior
- Each test run creates a timestamped repo (
-
Incremental testing (run, fail, fix, rerun)
- First test run: 23/26 pass, 3 fail -- immediately identified the label/assignee issues
- Fixed the swap pattern and PATCH approach, second run: 26/26 pass
Pitfalls to Avoid
-
Do not trust Gitea documentation for API behavior -- always verify against the live instance. The swagger spec is the source of truth, but even that can be misleading for edge cases like scoped label exclusivity.
-
Do not assume POST endpoints exist for every resource subpath -- Gitea's API is inconsistent. Some resources (labels) have POST, others (assignees) only work via PATCH on the parent resource.
-
Do not rely on UBS scanner for infrastructure projects -- UBS found no scannable language files (expected for a project with only shell scripts, YAML, and markdown). Pre-commit hooks are more useful here.
-
Pre-commit python version -- The system may not have the Python version specified in
.pre-commit-config.yaml. Changed frompython3.9topython3.12to match the system. Also neededpython3.12-venvapt package for virtualenv support.
Best Practices Discovered
-
Disciplined development phases work well for API integration
- Phase 1 (Research): Discovered the project board API gap before design
- Phase 2 (Design): Created the label swap architecture before implementation
- Phase 3 (Implementation): Tests caught 3 API bugs on first run
-
Default repository pattern -- Using env vars with defaults (
GITEA_OWNER=${GITEA_OWNER:-terraphim}) lets agents work out of the box while remaining configurable. -
JSON output from all helpers -- Every shell function outputs valid JSON, making it trivial for agents to parse results with jq.
-
Idempotent setup scripts --
setup-labels.shchecks for existing resources before creating, making it safe to run repeatedly.