MEDIUM — reversible (can unarchive), but visibility changes are significant. private: false should trigger ntfy confirmation.
Implementation notes
Only send fields that are explicitly set (use pointers)
Special case: private: false (making public) should warn in tool description
Test cases: archive, unarchive, description update, make template
Motivation
ingestion-svc needed archiving — had to do README tombstone instead
template-go-agent and template-go-web have template: false — should be true
Future: hyperguild new-project will need to set description + template flag on newly created repos
## Summary
Add `repo_update` tool to modify repository metadata — most importantly the `archived` flag to mark repos as read-only without deleting them.
## Gitea API
`PATCH /api/v1/repos/{owner}/{repo}`
## Tool spec
```
tool: repo_update
params:
owner: string
name: string
archived: bool? // mark repo as archived (read-only)
description: string? // update description
private: bool? // toggle visibility
website: string? // update homepage URL
template: bool? // toggle template repo flag
```
## Required token permission
`write:repository` scope on the Gitea API token.
## Risk classification
**MEDIUM** — reversible (can unarchive), but visibility changes are significant. `private: false` should trigger ntfy confirmation.
## Implementation notes
- Only send fields that are explicitly set (use pointers)
- Special case: `private: false` (making public) should warn in tool description
- Test cases: archive, unarchive, description update, make template
## Motivation
1. `ingestion-svc` needed archiving — had to do README tombstone instead
2. `template-go-agent` and `template-go-web` have `template: false` — should be `true`
3. Future: `hyperguild new-project` will need to set description + template flag on newly created repos
And in internal/tools/repo_update.go input schema + repoUpdateArgs struct:
"archived":{"type":"boolean","description":"Mark repo as archived (read-only)."},"template":{"type":"boolean","description":"Toggle template repo flag."}
Gap 2 — confirm guard missing for archived=true (LOW)
The confirm guard currently only protects private=false (making a repo public).
Archiving (archived=true) is effectively irreversible in practice and should require
the same confirm pattern:
ifargs.Archived!=nil&&*args.Archived{ifargs.Confirm!=args.Name{returnnil,fmt.Errorf("setting archived=true is irreversible: set confirm=%q to proceed",args.Name)}}
Acceptance criteria additions
archived field added to UpdateRepoArgs, tool schema, and args struct
template field added to UpdateRepoArgs, tool schema, and args struct
archived=true requires confirm=<repo name>
Tests cover: set archived, set template, archived confirm guard
## Review finding — missing fields (2026-05-14)
Code review of `internal/tools/repo_update.go` against the original spec revealed two gaps:
### Gap 1 — `archived` and `template` fields missing (HIGH)
The original issue spec required:
```
archived: bool? // mark repo as archived (read-only)
template: bool? // toggle template repo flag
```
Current implementation only handles: `description`, `private`, `website`, `default_branch`.
**Impact:**
- Cannot archive `ingestion-svc` (workaround: manual web UI)
- Cannot set `template: true` on `template-go-web` and `template-go-agent` (blocks create_project_from_template working correctly)
- Cannot toggle template flag as part of `hyperguild new-project` flow
**Fix needed in `internal/gitea/repos.go` → `UpdateRepoArgs` struct:**
```go
type UpdateRepoArgs struct {
Description *string
Private *bool
Website *string
DefaultBranch *string
Archived *bool // add this
Template *bool // add this
}
```
And in `internal/tools/repo_update.go` input schema + `repoUpdateArgs` struct:
```json
"archived": {"type": "boolean", "description": "Mark repo as archived (read-only)."},
"template": {"type": "boolean", "description": "Toggle template repo flag."}
```
### Gap 2 — confirm guard missing for `archived=true` (LOW)
The confirm guard currently only protects `private=false` (making a repo public).
Archiving (`archived=true`) is effectively irreversible in practice and should require
the same confirm pattern:
```go
if args.Archived != nil && *args.Archived {
if args.Confirm != args.Name {
return nil, fmt.Errorf("setting archived=true is irreversible: set confirm=%q to proceed", args.Name)
}
}
```
## Acceptance criteria additions
- [ ] `archived` field added to `UpdateRepoArgs`, tool schema, and args struct
- [ ] `template` field added to `UpdateRepoArgs`, tool schema, and args struct
- [ ] `archived=true` requires `confirm=<repo name>`
- [ ] Tests cover: set archived, set template, archived confirm guard
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Add
repo_updatetool to modify repository metadata — most importantly thearchivedflag to mark repos as read-only without deleting them.Gitea API
PATCH /api/v1/repos/{owner}/{repo}Tool spec
Required token permission
write:repositoryscope on the Gitea API token.Risk classification
MEDIUM — reversible (can unarchive), but visibility changes are significant.
private: falseshould trigger ntfy confirmation.Implementation notes
private: false(making public) should warn in tool descriptionMotivation
ingestion-svcneeded archiving — had to do README tombstone insteadtemplate-go-agentandtemplate-go-webhavetemplate: false— should betruehyperguild new-projectwill need to set description + template flag on newly created reposReview finding — missing fields (2026-05-14)
Code review of
internal/tools/repo_update.goagainst the original spec revealed two gaps:Gap 1 —
archivedandtemplatefields missing (HIGH)The original issue spec required:
Current implementation only handles:
description,private,website,default_branch.Impact:
ingestion-svc(workaround: manual web UI)template: trueontemplate-go-webandtemplate-go-agent(blocks create_project_from_template working correctly)hyperguild new-projectflowFix needed in
internal/gitea/repos.go→UpdateRepoArgsstruct:And in
internal/tools/repo_update.goinput schema +repoUpdateArgsstruct:Gap 2 — confirm guard missing for
archived=true(LOW)The confirm guard currently only protects
private=false(making a repo public).Archiving (
archived=true) is effectively irreversible in practice and should requirethe same confirm pattern:
Acceptance criteria additions
archivedfield added toUpdateRepoArgs, tool schema, and args structtemplatefield added toUpdateRepoArgs, tool schema, and args structarchived=truerequiresconfirm=<repo name>