ae1531835d
We use Gitea, not an abstract forge. Reword the docs added in this branch: "forge thread" -> "Gitea thread", and the research note's generic "forge" -> "Gitea" / "hosting provider" as context demands, keeping its portability argument coherent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
197 lines
10 KiB
Markdown
197 lines
10 KiB
Markdown
# Tracking feature requests in Gitea vs. in-repo decision history
|
|
|
|
Research into whether bot-bottle should track feature requests (and the
|
|
decision-making around them) as Gitea issues, given that the project
|
|
already records specs in-repo as PRDs (`docs/prds/`) and rationale as
|
|
research notes (`docs/research/`). The stated constraint is that the
|
|
*history of why we decided things* should be durable and portable —
|
|
not locked into a single hosting provider (Gitea today, conceivably
|
|
GitHub or something else tomorrow).
|
|
|
|
## Summary
|
|
|
|
Keep using issues, but demote them. The repository — not Gitea — is
|
|
the system of record for any decision you would be unhappy to lose.
|
|
Issues are an excellent **inbox and coordination surface** (cheap
|
|
capture, triage, async discussion, notifications, auto-linking) and a
|
|
**poor archive** (provider-locked storage, brittle numeric references,
|
|
rationale stranded in comment threads). The failure mode to avoid is the
|
|
one already present in the repo: a PRD whose reasoning is only complete
|
|
if you also read a Gitea issue thread.
|
|
|
|
The fix is a discipline, not a tool: **every load-bearing decision gets
|
|
reified into a versioned file in the repo before the issue that prompted
|
|
it is closed.** PRDs already do this for features; the gap is (a) small
|
|
requests that never merit a PRD and (b) decisions that aren't features
|
|
at all (e.g. "we merge with rebase," "author identity is claimed-not-
|
|
vouched"). Close that gap with a lightweight in-repo decision log. Then
|
|
issues can be as disposable as Gitea makes them, and migrating off
|
|
Gitea costs you triage state, not history.
|
|
|
|
## Why this even comes up here
|
|
|
|
The project already leans on the repo for durable artifacts:
|
|
|
|
- **PRDs** (`docs/prds/0001…0027`) — the spec and its rationale.
|
|
- **Research notes** (`docs/research/`) — the "why," with tradeoffs.
|
|
- **Conventional-commit history** — a machine-greppable change log.
|
|
|
|
But the issue layer has quietly become load-bearing in places:
|
|
|
|
- PRD 0025 says it picked "option 3" *"from the #88 design
|
|
discussion"* and that the rejected alternative lives "in issue #88's
|
|
comment thread." The PRD's rationale is therefore **incomplete without
|
|
the issue**. If Gitea is gone, the strongest argument for the chosen
|
|
design is gone with it.
|
|
- PR #89's description links `…/didericis/claude-bottle/issues/88` —
|
|
the **pre-rename** repo path (the project was Codex-bottle/claude-
|
|
bottle before the bot-bottle rebrand). That link is already
|
|
half-dead: a concrete demonstration that Gitea URLs rot under the
|
|
most routine event imaginable, a rename.
|
|
- Issue/PR numbers (`#88`, `#90`, `#94`, `#95`) are **Gitea-assigned
|
|
from a shared sequence**. They cannot be reconstructed from a clone,
|
|
and they collide/renumber on import into a different tracker.
|
|
|
|
So the question isn't academic. The current practice is already
|
|
producing references that don't survive a rename, let alone a migration.
|
|
|
|
## What each medium is actually good at
|
|
|
|
| Concern | Gitea issue | In-repo file (PRD / note / log) |
|
|
|---|---|---|
|
|
| Capture friction | Near-zero — file a one-line idea | High — a PRD is a heavy artifact; a note less so |
|
|
| Triage (labels, milestones, open/closed, assignee) | Native, good | Absent / hand-rolled |
|
|
| Async discussion + notifications | Native (threads, @mentions, watch) | None — needs a PR review or out-of-band chat |
|
|
| Auto-linking (`Closes #N`, PR↔issue, commit↔issue) | Native | Manual cross-reference |
|
|
| Version control of the content | None — lives in Gitea's DB | Full — diff, blame, branch, revert |
|
|
| Travels with `git clone` | No | Yes |
|
|
| Survives a move off Gitea | Degrades (export/import; threads, authors, timestamps, refs lossy) | Unaffected |
|
|
| Survives a Gitea outage | Inaccessible | Local clone has it |
|
|
| Greppable offline / by tooling | Only via API | `grep docs/` |
|
|
| Reproducible identifiers | Gitea-assigned numbers | Filenames you control (`0027-…`) |
|
|
|
|
The split is clean: **issues win on the live, social, coordination axes;
|
|
the repo wins on every durability and portability axis.** Nothing about
|
|
that table says "pick one." It says "use each for what it's good at, and
|
|
don't let the durable thing depend on the ephemeral one."
|
|
|
|
## Lock-in failure modes (the cons, concretely)
|
|
|
|
1. **Stranded rationale.** The single most valuable output of a feature
|
|
discussion — *why we rejected the obvious alternative* — usually
|
|
emerges in a thread and dies there unless someone copies it into the
|
|
spec. PRD 0025 is already in this state.
|
|
2. **Reference rot.** `Closes #88` / "see issue #90" are meaningful only
|
|
against one Gitea instance at one point in time. A rename already
|
|
broke one such link; a migration would break all of them and
|
|
silently renumber the survivors.
|
|
3. **Two sources of truth.** A PRD carries `Status: Draft`; the issue
|
|
carries open/closed. They drift. Which is authoritative?
|
|
4. **Availability coupling.** Self-hosted Gitea down (or the Tailscale
|
|
path to it down) means the backlog and its history are unreachable,
|
|
even though the code and PRDs are right there in the clone.
|
|
5. **Export is lossy.** Gitea→GitHub (or the reverse) moves issue *text*
|
|
tolerably but mangles cross-references, comment authorship for
|
|
non-mapped users, timestamps, and reactions. The graph of "#88 → PR
|
|
#89 → commit abc" does not survive intact.
|
|
|
|
None of these are arguments against *having* issues. They're arguments
|
|
against issues being the **only** place a decision is recorded.
|
|
|
|
## Pros of keeping issues anyway
|
|
|
|
Worth stating plainly, because "just use the repo for everything"
|
|
overcorrects:
|
|
|
|
- A PR per half-formed idea is absurd; issues are the right weight for
|
|
"someone should look at X someday."
|
|
- Triage state (priority, milestone, assignee, open/closed) is genuine
|
|
project-management value the repo does not natively provide.
|
|
- Notifications and threaded discussion are how a decision *gets made*
|
|
before it's ready to be written down. Killing issues doesn't move that
|
|
conversation into the repo — it moves it into chat/DMs, which is
|
|
*worse* for durability, not better.
|
|
- `Closes #N` automation and PR↔issue linkage are real ergonomics.
|
|
|
|
The goal is not to abandon the tracker. It's to make sure that when the
|
|
tracker eventually goes away, you lose the *backlog*, not the *history*.
|
|
|
|
## What belongs where
|
|
|
|
- **Gitea issue** — intake, triage, status, and the live discussion.
|
|
Treat it as a **cache**: useful now, expendable later.
|
|
- **PRD (`docs/prds/`)** — the durable spec for anything that warrants
|
|
one. Rule: a PRD must be **self-contained**. Synthesize the issue
|
|
discussion into the Problem / Design / Open-questions sections;
|
|
reference the issue as a convenience pointer, never as the only home
|
|
of a load-bearing argument. (Retrofit PRD 0025: inline the #88
|
|
"option 3 vs `bottle_config:`" reasoning so the PRD stands alone.)
|
|
- **Research note (`docs/research/`)** — the durable "why," exactly like
|
|
this file. Comparative analysis, landscape surveys, tradeoffs.
|
|
- **Commit message** — the durable "what changed and why, at this point
|
|
in the diff."
|
|
- **Decision log (proposed, see below)** — durable record of decisions
|
|
that aren't features and don't merit a PRD.
|
|
|
|
## Closing the gap: a portable decision record
|
|
|
|
Two classes of decision currently have no in-repo home:
|
|
|
|
- **Sub-PRD feature requests** — too small for a PRD, but you still want
|
|
a tracked "we will / won't do this, because." Today these live only as
|
|
issues.
|
|
- **Non-feature decisions** — "merge with rebase, not merge-commit,"
|
|
"agent identity is claimed-not-vouched," "bottles are home-only."
|
|
Some land inside a PRD that happens to touch them; many are folded
|
|
into chat and lost.
|
|
|
|
Options, cheapest first:
|
|
|
|
1. **An ADR-lite log under `docs/decisions/`.** One short Markdown file
|
|
per decision: context, decision, consequences, date, links. This is
|
|
the industry-standard Architecture Decision Record pattern, and it's
|
|
a near-exact fit for "track decision history, portably." Numbered
|
|
like PRDs (`0001-merge-with-rebase.md`). ~10 lines each; the
|
|
discipline is writing them, not the format.
|
|
2. **Reuse the journal.** The repo ships an `init-entry` skill that
|
|
writes timestamped prose to `docs/JOURNAL.md` (not yet created here).
|
|
A stream-of-thought journal is a fine home for decision *narrative*
|
|
and is already part of the toolchain — lower ceremony than ADRs, less
|
|
structured for later retrieval. The `tag-entries` skill could tag
|
|
decision entries for grep-ability.
|
|
3. **Periodic issue export.** Belt-and-suspenders: a scheduled job hits
|
|
the Gitea API and dumps open/closed issues + comments to JSON under
|
|
`docs/issues-archive/`, committed. Preserves the raw thread against
|
|
losing Gitea without changing daily workflow. Mechanical, not a
|
|
substitute for reifying rationale (a JSON dump of a thread is
|
|
evidence, not a decision).
|
|
|
|
These compose: ADRs/journal for the *decision*, optional export for the
|
|
*raw evidence*, issues for *live coordination*.
|
|
|
|
## Recommendation
|
|
|
|
1. **Keep Gitea issues for intake, triage, and discussion.** Don't fight
|
|
Gitea on the things it's good at.
|
|
2. **Make the repo the system of record.** Adopt the rule: no decision
|
|
is "done" until its rationale exists in a versioned file (PRD,
|
|
research note, or decision log). The issue is a pointer, never the
|
|
sole source.
|
|
3. **Add `docs/decisions/` (ADR-lite).** Smallest change that closes the
|
|
real gap — sub-PRD requests and non-feature decisions. Start by
|
|
back-filling the few decisions already made only in threads or chat
|
|
(rebase-merge policy; the agent-identity trust call from PRD 0027).
|
|
4. **Retrofit PRD 0025** to inline its #88 rationale, removing the one
|
|
existing hard dependency on a Gitea thread.
|
|
5. **Treat issue numbers as disposable.** When a PRD/commit cites an
|
|
issue, ensure the cited content is mirrored in-repo so the citation
|
|
degrades to a dead-but-harmless link, not lost information. (The
|
|
already-broken `claude-bottle/issues/88` link is the warning.)
|
|
6. **Optional:** automate a Gitea issue export into the repo if you want
|
|
the raw threads preserved without manual transcription.
|
|
|
|
Net: issues stay, because the alternative to issues is chat, which is
|
|
worse. But the project's durable memory must live where the project
|
|
already lives — in the clone — so that moving off Gitea, or losing it,
|
|
costs you a backlog you can rebuild, never a history you can't.
|