Skip to content
Merged
72 changes: 72 additions & 0 deletions .github/agents/github-operator.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
name: GitHub Operator
description: GitHub workflow specialist for repository tasks that should stay out of the main implementation context. Use when you need to create or update issues, write issue comments, link sub-issues, inspect or manage pull request discussions, resolve GitHub-side workflow tasks, or interact with GitHub through the official MCP tools, GitHub CLI, or raw GitHub APIs.
argument-hint: Describe the GitHub task, target repo, issue or PR numbers, and the expected outcome. Include whether the agent should only perform GitHub operations or also prepare a draft message for review first.
tools: [execute, read, search, todo]
user-invocable: true
disable-model-invocation: false
---

You are the repository's GitHub workflow specialist. Your job is to complete GitHub-related tasks
reliably while keeping the caller's main context focused on domain or implementation work.

You handle GitHub operations, not general feature implementation.

## Primary Use Cases

Use this agent for tasks such as:

- Creating new issues from approved specifications
- Updating issue titles, labels, bodies, assignees, or comments
- Linking sub-issues to parent issues
- Fetching, summarizing, replying to, or resolving pull request review threads
- Handling GitHub metadata or workflow tasks that would otherwise pollute the main agent context

## Tool Preference Order

Always prefer the most structured interface first:

1. **Official GitHub MCP tools** when available for the requested operation
2. **GitHub CLI** (`gh issue`, `gh pr`, `gh api`) when MCP coverage is missing or limited
3. **Raw GitHub REST or GraphQL API calls** via `gh api` only when needed

Do not jump directly to raw API calls if a dedicated MCP or CLI command covers the task clearly.

## Required Workflow

1. Identify the exact GitHub task and target object: repository, issue number, PR number, comment,
review thread, or label.
2. Read any local specification or context file needed to perform the task correctly.
3. Load the relevant repository skill when one exists.
4. Choose the highest-level GitHub interface that can perform the task safely.
5. Execute the operation with the minimum number of calls needed.
6. Verify the result by reading the updated GitHub object or returned URL.
7. Report only the outcome and key identifiers back to the caller.

## Repository Guidance

- Follow `AGENTS.md` for repository-wide standards.
- Prefer these skills when relevant:
- `.github/skills/dev/planning/create-issue/SKILL.md` for issue creation workflow
- `.github/skills/dev/github/link-subissue-to-parent-issue/SKILL.md` for parent/sub-issue linking
- `.github/skills/dev/pr-reviews/fetch-review-threads/SKILL.md` for review thread retrieval
- `.github/skills/dev/pr-reviews/resolve-review-threads/SKILL.md` for closing review threads

## Important Rules

- Do not guess repository names, labels, issue numbers, PR numbers, or comment IDs.
- Do not assume the visible issue number is the same identifier required by a GitHub API.
- For sub-issue linking, remember that the REST API expects the child issue's internal GitHub ID,
not its visible issue number.
- Do not mix GitHub task execution with unrelated code changes.
- If a PR review comment requires code changes, stop after identifying the actionable request and
hand control back to the caller or a code-focused agent.
- Keep the workflow deterministic: inspect, act, verify.

## Output Expectations

When finishing a task, return:

1. What was changed or verified
2. The key GitHub identifiers or URLs
3. Any blockers, permissions issues, or follow-up needed
12 changes: 12 additions & 0 deletions .github/agents/implementer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ Reference: [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.ht
- `.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md` — error handling.
- `.github/skills/dev/git-workflow/commit-changes/SKILL.md` — commit conventions.

### ADR Discoverability Convention

When a change introduces or updates an ADR that affects a specific code area:

- Link the ADR to the key affected code files (for example in an "Affected Code"
section).
- Add concise module-level comments in those code files that link back to the
ADR.

Goal: contributors can discover the relationship from either side (code-first
or docs-first) without prior context.

## Required Workflow

### Step 1 — Analyse the Task
Expand Down
126 changes: 126 additions & 0 deletions .github/skills/dev/github/link-subissue-to-parent-issue/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
name: link-subissue-to-parent-issue
description: Guide for linking an existing GitHub issue as a sub-issue of a parent issue in the torrust-tracker project. Covers the GitHub REST API flow, the required internal issue ID for the child issue, verification, and common failure modes. Use when setting a parent issue for a sub-issue, attaching a child issue to an epic, or linking an existing issue under another issue. Triggers on "set parent issue", "link subissue", "add sub-issue", "attach child issue", or "make issue a subissue".
metadata:
author: torrust
version: "1.0"
---

# Linking a Sub-Issue to a Parent Issue

This skill covers the workflow for linking an existing GitHub issue under a parent issue.

## When to Use

Use this when:

- A child issue already exists and needs to be attached to an epic or parent issue
- You need to set or fix the parent issue of an existing sub-issue
- You want to verify that a sub-issue link was created correctly

## Important Detail

The GitHub sub-issues REST API expects the **internal GitHub issue ID** for the child issue,
not the visible issue number.

- Issue number example: `1715`
- Internal issue ID example: `4349463336`

If you send the issue number as `sub_issue_id`, GitHub returns a `422` validation error.

## Standard Workflow

### 1. Confirm the parent and child issue numbers

Decide which issue is the parent and which is the child.

- Parent issue number: the epic or container issue
- Child issue number: the issue to attach under the parent

### 2. Get the internal ID for the child issue

```bash
gh api /repos/torrust/torrust-tracker/issues/{child-issue-number} --jq '.id'
```

Example:

```bash
gh api /repos/torrust/torrust-tracker/issues/1715 --jq '.id'
```

### 3. Link the child issue to the parent issue

```bash
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/torrust/torrust-tracker/issues/{parent-issue-number}/sub_issues \
--input - <<'EOF'
{"sub_issue_id": {child-internal-id}}
EOF
```

Example:

```bash
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/torrust/torrust-tracker/issues/1525/sub_issues \
--input - <<'EOF'
{"sub_issue_id": 4349463336}
EOF
```

### 4. Verify the link

Check the child issue's `parent_issue_url`:

```bash
gh api /repos/torrust/torrust-tracker/issues/{child-issue-number} --jq '.parent_issue_url'
```

Example:

```bash
gh api /repos/torrust/torrust-tracker/issues/1715 --jq '.parent_issue_url'
```

Expected result:

```text
https://api.github.com/repos/torrust/torrust-tracker/issues/1525
```

## Common Failure Modes

### `422` Invalid property `/sub_issue_id`

Cause: you passed the child issue number instead of the child's internal issue ID.

Fix: fetch the child issue with `gh api ... --jq '.id'` and use that value.

### `404 Not Found`

Possible causes:

- Wrong repository path
- Wrong parent issue number
- Missing permissions for sub-issue management
- The repository or issue does not support the operation in the current context

Fix: verify the repo, the parent issue number, and your GitHub permissions.

## Optional MCP Alternative

If GitHub MCP tools are available, prefer the dedicated sub-issue tool over raw API calls.
Still make sure you pass the **internal issue ID** for the child issue, not the issue number.

## Notes for Torrust Tracker

- Parent issues are often EPICs in `docs/issues/`
- Child issues usually have their own spec file and implementation branch
- After creating and linking a new issue, rename the local spec file to include the assigned issue number
15 changes: 15 additions & 0 deletions .github/skills/dev/planning/create-adr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ Add a row to the index table in `docs/adrs/index.md`:
- The first column links to the ADR file using the timestamp as display text.
- The short description should allow a reader to understand the decision without opening the file.

### Step 3.5: Cross-link ADR and Affected Code

When an ADR affects a specific area of code, keep discovery bidirectional:

- Add a short "Affected Code" section in the ADR with links to key files
(module entry points, traits, setup/wiring files).
- Add concise module-level doc comments in those code files pointing back to
the ADR.

This keeps rationale discoverable whether a contributor starts from docs or
from code.

### Step 4: Validate and Commit

```bash
Expand All @@ -106,6 +118,9 @@ git commit -S -m "docs(adrs): add ADR for {short description}"
git push {your-fork-remote} {branch}
```

If code comments were added to establish ADR links, include those files in the
same commit when practical.

## Example ADR

For a real example, see
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,31 @@ between two trait objects would be a different story, but is not needed here.
about — but it is a mechanical change across test files.
- `Database` will persist as long as `Arc<Box<dyn Database>>` wiring exists.
That wiring will be replaced in subissue #1525-04b
([docs/issues/1525-04b-migrate-consumers-to-narrow-traits.md](../issues/1525-04b-migrate-consumers-to-narrow-traits.md))
([docs/issues/1715-1525-04b-migrate-consumers-to-narrow-traits.md](../issues/1715-1525-04b-migrate-consumers-to-narrow-traits.md))
by a plain `DatabaseStores` struct (one `Arc<dyn XxxStore>` field per
context). `TrackerCoreContainer` will hold `DatabaseStores` instead of
`Arc<Box<dyn Database>>`; each service is wired at construction time by
passing only the narrow store it needs. At that point `Database` can be
made fully private or removed.

### Clarification And Revisit Criteria

For now, `TorrentMetricsStore` keeps both per-torrent downloads (stored in
`torrents`) and the global aggregate metric `TORRENTS_DOWNLOADS_TOTAL`
(stored in `torrent_aggregate_metrics`). This is intentional: in the current
domain model there is only one persisted per-torrent metric and one persisted
global metric, and they are strongly related.

There is no near-term plan to add more tables, fields, or persisted objects in
this area. Therefore, introducing another split (for example,
`TorrentAggregateMetricStore`) is deferred to avoid extra API churn without
clear short-term benefit.

This decision should be reconsidered if persistence scope changes, especially
if aggregate metrics grow and are no longer torrent-specific (for example,
global tracker metrics such as total unique peers that ever announced), or if
method count/responsibility in `TorrentMetricsStore` increases materially.

## Date

2026-04-29
Expand Down
2 changes: 1 addition & 1 deletion docs/issues/1525-overhaul-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ You can then browse or search it while working in the main repository.

### 4b) Migrate consumers to narrow persistence traits

- Spec file: `docs/issues/1525-04b-migrate-consumers-to-narrow-traits.md`
- Spec file: `docs/issues/1715-1525-04b-migrate-consumers-to-narrow-traits.md`
- Outcome: every consumer holds only the narrow trait(s) it uses; `Database`
becomes a private compile-time guard inside `databases/`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ re-exporting it from `databases/mod.rs`. Keep it accessible inside
## References

- EPIC: #1525
- GitHub Issue: #1715
- Predecessor: [docs/issues/1713-1525-04-split-persistence-traits.md](1713-1525-04-split-persistence-traits.md)
- ADR: [docs/adrs/20260429000000_keep_database_as_aggregate_supertrait.md](../adrs/20260429000000_keep_database_as_aggregate_supertrait.md)
- Successor: [docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md](1525-05-migrate-sqlite-and-mysql-to-sqlx.md)
73 changes: 39 additions & 34 deletions docs/packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
- [Package Conventions](#package-conventions)
- [Package Catalog](#package-catalog)
- [Architectural Philosophy](#architectural-philosophy)
- [Design Decisions](#design-decisions)
- [Protocol Implementation Details](#protocol-implementation-details)
- [Architectural Philosophy](#architectural-philosophy)

```output
packages/
Expand Down Expand Up @@ -42,48 +42,53 @@ contrib/

## Package Conventions

| Prefix | Responsibility | Dependencies |
|-----------------|-----------------------------------------|---------------------------|
| `axum-*` | HTTP server components using Axum | Axum framework |
| `*-server` | Server implementations | Corresponding *-core |
| `*-core` | Domain logic & business rules | Protocol implementations |
| `*-protocol` | BitTorrent protocol implementations | BitTorrent protocol |
| `udp-*` | UDP Protocol-specific implementations | Tracker core |
| `http-*` | HTTP Protocol-specific implementations | Tracker core |
| Prefix | Responsibility | Dependencies |
| ------------ | -------------------------------------- | ------------------------ |
| `axum-*` | HTTP server components using Axum | Axum framework |
| `*-server` | Server implementations | Corresponding \*-core |
| `*-core` | Domain logic & business rules | Protocol implementations |
| `*-protocol` | BitTorrent protocol implementations | BitTorrent protocol |
| `udp-*` | UDP Protocol-specific implementations | Tracker core |
| `http-*` | HTTP Protocol-specific implementations | Tracker core |

Key Architectural Principles:

1. **Separation of Concerns**: Servers contain only network I/O logic.
2. **Protocol Compliance**: `*-protocol` packages strictly implement BEP specifications.
3. **Extensibility**: Core logic is framework-agnostic for easy protocol additions.

## Design Decisions

- Persistence trait boundaries and the aggregate supertrait choice:
[docs/adrs/20260429000000_keep_database_as_aggregate_supertrait.md](adrs/20260429000000_keep_database_as_aggregate_supertrait.md)

## Package Catalog

| Package | Description | Key Responsibilities |
|---------|-------------|----------------------|
| **axum-*** | | |
| `axum-server` | Base Axum HTTP server infrastructure | HTTP server lifecycle management |
| `axum-http-tracker-server` | BitTorrent HTTP tracker (BEP 3/23) | Handle announce/scrape requests |
| `axum-rest-tracker-api-server` | Management REST API | Tracker configuration & monitoring |
| `axum-health-check-api-server` | Health monitoring endpoint | System health reporting |
| **Core Components** | | |
| `http-tracker-core` | HTTP-specific implementation | Request validation, Response formatting |
| `udp-tracker-core` | UDP-specific implementation | Connectionless request handling |
| `tracker-core` | Central tracker logic | Peer management |
| **Protocols** | | |
| `http-protocol` | HTTP tracker protocol (BEP 3/23) | Announce/scrape request parsing |
| `udp-protocol` | UDP tracker protocol (BEP 15) | UDP message framing/parsing |
| **Domain** | | |
| `torrent-repository` | Torrent metadata storage | InfoHash management, Peer coordination |
| `configuration` | Runtime configuration | Config file parsing, Environment variables |
| `primitives` | Domain-specific types | InfoHash, PeerId, Byte handling |
| **Utilities** | | |
| `clock` | Time abstraction | Mockable time source for testing |
| `located-error` | Diagnostic errors | Error tracing with source locations |
| `test-helpers` | Testing utilities | Mock servers, Test data generation |
| **Client Tools** | | |
| `tracker-client` | CLI client | Tracker interaction/testing |
| `rest-tracker-api-client` | API client library | REST API integration |
| Package | Description | Key Responsibilities |
| ------------------------------ | ------------------------------------ | ------------------------------------------ |
| **axum-\*** | | |
| `axum-server` | Base Axum HTTP server infrastructure | HTTP server lifecycle management |
| `axum-http-tracker-server` | BitTorrent HTTP tracker (BEP 3/23) | Handle announce/scrape requests |
| `axum-rest-tracker-api-server` | Management REST API | Tracker configuration & monitoring |
| `axum-health-check-api-server` | Health monitoring endpoint | System health reporting |
| **Core Components** | | |
| `http-tracker-core` | HTTP-specific implementation | Request validation, Response formatting |
| `udp-tracker-core` | UDP-specific implementation | Connectionless request handling |
| `tracker-core` | Central tracker logic | Peer management |
| **Protocols** | | |
| `http-protocol` | HTTP tracker protocol (BEP 3/23) | Announce/scrape request parsing |
| `udp-protocol` | UDP tracker protocol (BEP 15) | UDP message framing/parsing |
| **Domain** | | |
| `torrent-repository` | Torrent metadata storage | InfoHash management, Peer coordination |
| `configuration` | Runtime configuration | Config file parsing, Environment variables |
| `primitives` | Domain-specific types | InfoHash, PeerId, Byte handling |
| **Utilities** | | |
| `clock` | Time abstraction | Mockable time source for testing |
| `located-error` | Diagnostic errors | Error tracing with source locations |
| `test-helpers` | Testing utilities | Mock servers, Test data generation |
| **Client Tools** | | |
| `tracker-client` | CLI client | Tracker interaction/testing |
| `rest-tracker-api-client` | API client library | REST API integration |

## Protocol Implementation Details

Expand Down
Loading