Replace fetch_issue.py with four scripts around a flat, greppable cache in tmp/issues/. Planning stays offline and issues reach Gitea in one push: - issue_get.py: fetch by key or by filter (--milestone/--label/-q). The list endpoint carries issue bodies, so a whole milestone costs one request per 50 issues. Gitea silently ignores an unresolvable milestones= filter and returns the entire backlog, so the milestone is resolved up front and every returned issue is re-checked locally. --deps walks the dependency graph downwards via the structured sections plus native dependencies and writes tree-<slug>.md. - issue_push.py: validate a local draft against the canonical format, create missing labels with the right colors and exclusivity, POST, delete the draft. - issue_list.py: discovery to stdout, writes nothing. - issue_index.py: rebuild INDEX.md from what is on disk. Files use one metadata field per line with inline lists so plain grep works without a parser. This is a cache and a drafting area, not a mirror: no drift tracking, no sync back. Projects are not fetchable — the projects API is 404 on Gitea 1.26; documented alongside the milestone caveat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.2 KiB
name, description
| name | description |
|---|---|
| issue | Create a Gitea issue in the project's canonical format. Run when the user asks to file/create an issue, or types /tea:issue. Writes a local draft during planning, then pushes it with issue_push.py, which validates the format, ensures exclusive type/* labels exist, and posts via tea api. |
/tea:issue — draft locally, push when agreed
Thin procedure on top of the canonical format defined in
../use/references/issue-format.md.
Read that file first — it is the single source of truth for types, labels,
templates, and language rules.
Two phases, deliberately separated: planning writes local files only (no
network, no tea), and one push turns them into real issues. Scripts live in
../use/scripts/ (see /tea:use for the full set).
Phase 1 — draft (no network)
-
Read the format: load
../use/references/issue-format.md. -
Pick the type —
bug,task,refactor,test,feature(a container for several issues with one business value), ordraft(for ideas not ready for work). If it is not obvious from the request, ask the user (one question). -
Write
tmp/issues/drafts/<slug>.md: a metadata block carryinglabels:only, then# Title, then the type's template.--- labels: [type/task, tech/sql, comp/appclick] --- # Wire sqlc into the appclick repo layer ## Summary ...English imperative title with no type prefix; every section of the template present and in order; headers English, prose Russian;
## Specfilled with a repo path, a URL, or the literalnone— ask the user if you cannot determine which. Add## Depends onright after## Specwhen the issue depends on others (one#Nper line); omit it otherwise. One draft file = one issue. Several related issues = several drafts. -
Check the format without posting (optional, free):
python3 ../use/scripts/issue_push.py --all --dry-run
Phase 2 — push (once the plan is agreed)
python3 ../use/scripts/issue_push.py --all
The script validates the format (exactly one type/*, at most one
severity/*, English title, ## Summary / ## Spec / ## Acceptance criteria present), creates any missing labels — exclusive: true for
type/* and severity/*, canonical colors from the format doc — POSTs each
issue, prints #N <url>, and deletes the draft. The issue lives in Gitea
now; the local copy is not a mirror and must not linger.
Flags: --keep writes tmp/issues/<n>.md instead of deleting, --dry-run
validates only, --force posts despite format violations (say why).
Report the issue URLs and the applied labels to the user.
Editing an existing issue
Drafts only create. To bring an existing issue to the format: fetch it with
python3 ../use/scripts/issue_get.py <n> (writes tmp/issues/<n>.md,
prints a compact line), restructure the body into the type's template without
losing information, then PATCH repos/{owner}/{repo}/issues/{n} via tea api
with the new title/body and ensure exactly one type/* label is set. Login is
always the placeholder --login "$GITEA_LOGIN" (see /tea:use).