Compare commits

...

3 Commits

Author SHA1 Message Date
sulthan f594a71d7c docs: name the Stall and the Correction in CONTEXT.md 2026-08-21 15:23:12 +07:00
sulthan 249f11e1fe docs: name the admin dashboard's domain terms in CONTEXT.md (#128)
Glossary-only change; no code touched.

Charting the admin dashboard map (#114) settled four terms the glossary did not carry:

- **Orphan Series** (#125) — a Series no Reader bookmarks; a state of the Series, never a Lifecycle bucket.
- **Lane Pass** (#117) — one sweep of a Poll Lane, including a pass that declined to work and why.
- **Forced Poll** (#119, #120) — a Poll the owner asks for by marking the Series, which jumps the waiting rules but never the Site's refusal, and which may replace a Cover.
- **Paused Lane** (#119) — a bounded, restart-surviving stop on one Site, distinct from the deploy-time kill switch.

**Acquisition** is amended in the same pass: establishing a Cover is no longer unique to it, since a Forced Poll can replace one.

Reviewed-on: #128
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
2026-08-19 19:00:25 +07:00
sulthan f5d3fe58ec Add a gitea skill; point AGENTS.md at it (#126)
Forge usage lived in three places (`AGENTS.md`, `docs/agents/issue-tracker.md`, and habit). This moves the how-to-run-`tea` half into a model-invoked skill that fires on any issue/PR task, and reduces `AGENTS.md` to identity plus pointers.

- **new** `.claude/skills/gitea/SKILL.md` — command table plus the traps `tea <cmd> --help` will not tell you.
- `AGENTS.md` — Forge section is now one line: Gitea not GitHub, `gh` and the `issue://`/`pr://` URIs fail, then pointers to the skill, `docs/agents/issue-tracker.md`, and `docs/agents/triage-labels.md`.
- `.claude/skills/implement-tickets/SKILL.md` — pointer split: tracker conventions to the doc, `tea` usage to the skill.

Both `docs/agents/` files are untouched; the skill cites them instead of restating them.

Facts in the skill are measured against `tea` 0.14.2 on 2026-08-17, not remembered:

- `gh` is not installed, so `read issue://71` errors — there is no fallback to add.
- **A bare read is a truncated read.** Without `--comments`, `tea issue <n>` drops every comment silently, with no prompt under a non-TTY: issue #123 prints 40 lines bare, 132 with the flag. The skill makes `--comments` mandatory for any read meant to understand a ticket, with `tea issue list --fields index,comments` as the checkable count.
- Issues and PRs share one index space; output is rendered boxes so parsing needs `-o json`; `close` takes no `--comment`; labels never auto-create; multi-line bodies need a heredoc; `tea` exposes neither sub-issues nor dependencies.

Unmeasured and marked as such: whether `--comments` covers a PR's review-comment stream — no PR in this repo has comments, so `tea pr review-comments <n>` is named without a claim about overlap.

Reviewed-on: #126
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
2026-08-17 17:52:16 +07:00
4 changed files with 130 additions and 12 deletions
+75
View File
@@ -0,0 +1,75 @@
---
name: gitea
description: Use for every forge operation in this repo — read, create, comment on, label, close, or search an issue; create, review, merge, or check out a PR; and whenever `gh`, `issue://`, or `pr://` fails or a ticket number is ambiguous. This repo's forge is self-hosted Gitea driven by `tea`, not GitHub.
---
# Gitea, not GitHub
`origin` is the self-hosted Gitea instance `gitea.violetcrown.my.id`, repo
`sulthan/mangaBookmark`. Everything past plain git goes through
[`tea`](https://gitea.com/gitea/tea) (0.14.2 on this machine).
**`gh` is not installed**, so the harness's `issue://<n>` and `pr://<n>` URIs
error out (`GitHub CLI (gh) is not installed`, measured 2026-08-17). There is no
fallback to add — read tickets with `tea`.
`tea` infers the repo from `origin`; auth lives in `tea login`, never a
`GH_TOKEN`. Your Gitea username comes from `tea login list` — `tea` has no `@me`.
Flags are the environment's job: run `tea <command> --help` rather than trusting
a remembered flag. This file carries only what `--help` will not tell you.
## Commands
| Job | Command |
|---|---|
| Read | `tea issue <n> --comments` / `tea pr <n> --comments` — `--comments` is not optional |
| List | `tea issue list --state open\|closed\|all -o json --fields index,title,body,labels,state,author` |
| Search | `tea issue list -k "<keyword>" -L "<label>" -A "<author>"` (`-K all` also searches PRs) |
| Create | `tea issue create -t "..." -d "..."` (`-L`, `-a` optional) |
| Comment | `tea comment <n> "..."` |
| Label | `tea issue edit <n> --add-labels "..."` / `--remove-labels "..."` |
| Close | `tea issue close <n>` / `tea pr close <n>` |
| PR | `tea pr create --head <branch> --base main -t "..." -d "..."`, `tea pr checkout <n>`, `tea pr review <n>`, `tea pr merge <n>` |
## Traps
- **A bare read is a truncated read.** Without `--comments`, `tea issue <n>` and
`tea pr <n>` print the opening body and drop every comment silently — no
prompt, no marker, no hint that more exists (measured 2026-08-17: issue #123
prints 40 lines bare, 132 with `--comments`). The comments are where the
decisions live and the body is usually the stalest part of the ticket, so
**every read that exists to understand an issue or PR passes `--comments`**,
and understanding means body plus all comments plus whatever ticket they point
at. Comment count is `tea issue list --fields index,comments`, so a read that
shows fewer than that is incomplete. A PR's review comments are a second
stream: `tea pr review-comments <n>`.
- **One index space for issues and PRs.** A bare `#42` may be either: try
`tea pr 42`, fall back to `tea issue 42`. Say which one you found.
- **Output is rendered boxes**, not plain text. Anything you parse needs
`-o json`, plus `--fields` to keep the payload small. `tea pr create` prints
the PR URL on its last line.
- **`close` takes no `--comment`.** Comment with `tea comment <n>`, then close.
- **Gitea will not auto-create a label.** `tea labels list` first; missing one
gets `tea labels create --name "..." --color "#rrggbb"` before the `edit`.
- **Multi-line bodies go through a heredoc**, never inline escapes:
```bash
tea issue create -t "Title" -d "$(cat <<'EOF'
body line one
- acceptance criterion
EOF
)"
```
- **No sub-issue and no dependency command.** Gitea's API has issue
dependencies, `tea` does not expose them, so parentage and blocking live as
body lines — the shapes are in `docs/agents/issue-tracker.md`.
## Conventions this repo layers on top
Ticket bodies, wayfinding issues, and the PR-as-request-surface flag:
`docs/agents/issue-tracker.md`. Triage label strings: `docs/agents/triage-labels.md`.
A label named there still has to exist in the tracker before `--add-labels`.
Finish a forge action by stating the number you touched and its state after —
"commented and closed #71" — so the write is checkable without a second query.
+1 -1
View File
@@ -11,7 +11,7 @@ to the tracker. You do not write the implementation — every line of ticket cod
is written by a `ticket-implementer` subagent in its own git worktree. Reach for is written by a `ticket-implementer` subagent in its own git worktree. Reach for
the editor yourself only for a merge conflict resolution. the editor yourself only for a merge conflict resolution.
Ticket source and `tea` usage: `docs/agents/issue-tracker.md`. Ticket source and tracker conventions: `docs/agents/issue-tracker.md`. `tea` usage: skill `gitea`.
## 1. Collect the tickets ## 1. Collect the tickets
+1 -8
View File
@@ -67,14 +67,7 @@ Smoke test: `curl` endpoints with `Authorization: Bearer <token>`; confirm `OPTI
## Forge: Gitea, not GitHub ## Forge: Gitea, not GitHub
`origin` is self-hosted Gitea instance (`gitea.violetcrown.my.id`, repo `sulthan/mangaBookmark`), so **`gh` don't work here — use `tea` (Gitea CLI) for anything past plain git.** `tea` infers the repo from `origin`; auth lives in `tea login`, not a `GH_TOKEN` env var. It prints rendered boxes rather than plain text, so pass `-o json` when parsing; a PR URL lands on the last line. `origin` is self-hosted Gitea (`gitea.violetcrown.my.id`, repo `sulthan/mangaBookmark`), so **`gh` don't work here and the `issue://`/`pr://` URIs error out — drive the forge with `tea`.** How to run it — commands, traps, JSON output: skill `gitea`. Tracker conventions (ticket bodies, wayfinding, PR-as-request-surface flag): `docs/agents/issue-tracker.md`. Triage label strings: `docs/agents/triage-labels.md`.
- PRs: `tea pr create --head <branch> --base main --title "..." --description "..."`, `tea pr list`, `tea pr <n>`, `tea pr checkout <n>`.
- Issues: `tea issue create --title "..." --description "..."` (`--labels`, `--assignees` optional), `tea issue <n> --comments`, `tea issue list --state open|closed|all -o json`, `tea issue close <n>`.
- Comments: `tea comment <n> "..."` — `tea issue close` takes no `--comment` flag.
- Labels: `tea issue edit <n> --add-labels "..."` / `--remove-labels "..."`. Gitea will **not** auto-create a label, so `tea labels create --name "..." --color "#rrggbb"` first.
- Triage vocabulary is `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`.
- Gitea shares one index space across issues and PRs, so a bare `#42` may be either — try `tea pr 42`, fall back to `tea issue 42`.
## Design system ## Design system
+53 -3
View File
@@ -43,6 +43,13 @@ Readers: Progress, Favourite, Lifecycle bucket. Facts about the Series itself be
to the Series, not here. to the Series, not here.
_Avoid_: entry, item, record, subscription _Avoid_: entry, item, record, subscription
**Orphan Series**:
A Series no Reader bookmarks. Removing a Bookmark never removes the Series, so the row
outlives every relationship to it: nothing reads it, no Poll visits it, and it still owns
a Cover. A state of the Series, not a Lifecycle bucket — it says how many Readers hold it,
never anything about a Reader.
_Avoid_: dangling, unused, dead series, stale
**Library**: **Library**:
One of the two halves of the collection — manga or novel — selected by a Bookmark's One of the two halves of the collection — manga or novel — selected by a Bookmark's
`kind`. The web UI and the userscripts each address exactly one Library at a time. `kind`. The web UI and the userscripts each address exactly one Library at a time.
@@ -76,6 +83,41 @@ asked. Every Site has exactly one and no Lane can slow, block or borrow from ano
a Reader never has one and never influences one. a Reader never has one and never influences one.
_Avoid_: worker, queue, scheduler, batch, wave _Avoid_: worker, queue, scheduler, batch, wave
**Lane Pass**:
One sweep of a Poll Lane over the Series due on its Site: what it found waiting, how many it
read, and whether it declined to work at all. A fact about the Lane rather than about any
Series — a pass that read nothing is still a pass, and one that declined carries the reason it
declined, since a Lane resting and a Lane stuck look identical from a count alone. Its record
outlives the process that made it: "the poller has done nothing for six hours" is only
answerable by something written down.
_Avoid_: run, cycle, tick, batch, poll history
**Forced Poll**:
A Poll the owner asks for by hand instead of waiting for the Series's turn. It jumps its
Lane's queue and ignores every waiting rule — the rest between Polls, a Sighting standing
in for a check, a Series only finished Readers hold — but never overrules a Site that is
refusing us, the Lane's spacing between fetches, or a Series with no page to fetch. Asked
for by marking the Series, never by commanding the poller, so it happens on the Lane's
next pass rather than at the moment of asking.
It also takes whatever Cover the Site publishes today: asking for one is asking to accept the
page as it now stands, so it is the only read after Acquisition that can replace a Cover.
_Avoid_: manual poll, refresh, retry, force refresh
**Paused Lane**:
A Poll Lane the owner has stopped for a bounded time. It makes no Polls until the pause
expires, so its Series stay due and unstamped exactly as they do when a Site cannot be
reached. Every pause carries an expiry — a Lane cannot be stopped indefinitely — and it
outlives a restart, being a fact about the Site rather than about the running process.
_Avoid_: disabled, off, stopped, suspended, kill switch (that is the deploy-time switch)
**Stall**:
A Poll Lane that owed Polls, made none, and has nothing to say for it. Distinct from the
two conditions it resembles: a Site that refuses is exercising the pace it is entitled to,
and a Lane the owner paused was told to stop — a Stall is neither asked for nor explained.
It is the one fault no Reader surface can show: every Bookmark still opens, Progress still
syncs, and Latest Chapter is quietly wrong for as long as it lasts.
_Avoid_: outage, downtime, failure, backlog, lag
**Sighting**: **Sighting**:
What a Reader's browser happened to see of a Series's Latest Chapter while that Reader What a Reader's browser happened to see of a Series's Latest Chapter while that Reader
was on the page. It reports the same fact as a Poll but carries none of its authority: was on the page. It reports the same fact as a Poll but carries none of its authority:
@@ -88,11 +130,19 @@ _Avoid_: client report, user poll, observation, claim
The single read of a Series page made the moment the Series first exists, giving it The single read of a Series page made the moment the Series first exists, giving it
both its Latest Chapter and its Cover without waiting for the Lane's pace. Distinct both its Latest Chapter and its Cover without waiting for the Lane's pace. Distinct
from a Poll in the two ways that matter: a Reader is present — it is triggered by from a Poll in the two ways that matter: a Reader is present — it is triggered by
their first Bookmark of that Series — and it is the only read that establishes a their first Bookmark of that Series — and it establishes a Cover rather than refreshing
Cover rather than refreshing facts. It happens once in a Series's life; every later facts, which no Poll does unless the owner forces one. It happens once in a Series's
read of the same page is a Poll. life; every later read of the same page is a Poll.
_Avoid_: initial poll, first fetch, prefetch, warm-up _Avoid_: initial poll, first fetch, prefetch, warm-up
**Correction**:
A Latest Chapter the owner sets by hand, on a Series no Poll can read. It reports the
same fact as a Poll and carries even less authority than a Sighting: the next Poll
overwrites it, so does any Reader's Sighting, and it is never a floor or a pin. It
exists only because the Site page is unreadable — where a Poll can read the page, the
Poll is the answer and a Correction is not wanted.
_Avoid_: override, pin, manual value, fix
**New Chapter**: **New Chapter**:
The state where Latest Chapter is ahead of Progress. The single condition the ember The state where Latest Chapter is ahead of Progress. The single condition the ember
accent is permitted to signal. accent is permitted to signal.