From a3453c5d6f38be75dd4eb7f7b3c73eec0855fee7 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Tue, 22 Sep 2026 19:24:48 +0000 Subject: [PATCH] docs(adr): supersede ADR-0007, plan OneDev migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This repo's own hosting, issue tracking, and pull requests move from Gitea to OneDev (ADR-0029), keeping the Gitea repo as a read-only archive rather than deleting it. plugins/gitea is unaffected — it continues to ship as a marketplace product regardless of what this repo hosts itself on. Records the full execution plan (prerequisites, mirror/issue/PR/release phases, verification checklist) and updates CONTEXT.md's Issue entry and AGENTS.md's source-of-truth line to name OneDev instead of Gitea. ADR: 0029 Refs: ADR-0007 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01GGCPJBXPLJP5FprL4C8nu3 --- AGENTS.md | 2 +- CONTEXT.md | 5 +- .../adr/0007-gitea-canonical-issue-tracker.md | 2 + ...onedev-supersedes-gitea-canonical-forge.md | 43 ++++++ docs/notes/onedev-migration-plan.md | 130 ++++++++++++++++++ 5 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 docs/adr/0029-onedev-supersedes-gitea-canonical-forge.md create mode 100644 docs/notes/onedev-migration-plan.md diff --git a/AGENTS.md b/AGENTS.md index 7cfb38f..5686082 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,7 +31,7 @@ Fall back to raw shell only when no skill covers it. - **`apm.lock.yaml` turning up modified is expected, not a bug.** kyberforge's `SessionStart` hook keeps the install current on launch and rewrites the lock in the process (ADR-0019). On `main`, commit or discard it deliberately. On a feature branch, discard it (`git checkout -- apm.lock.yaml`, then `apm install`). This keeps unrelated lock churn out of the branch diff and keeps `apm pack --check-clean` consistent with the committed lock. The session then runs the older `main` that the lock records, which is accepted on a branch, and the next session start refreshes again. - **A `.apm/` edit is not live until it is on the remote's `main`.** The six dependencies resolve from the holocron remote, unpinned against the default branch, so pushing a feature branch does not deploy it (ADR-0019). `apm install` deploys from the lock; `apm update` is what re-resolves refs. - **No pre-push hook needs the network — once `apm install` has run.** Root `apm.yml`'s marketplace has no remote package entries, so every hook resolves locally. The guarantee is a property of a populated `apm_modules/`, not of the hook set: on a fresh clone `apm-audit-ci`'s `deployed-files-present` fails outright, and its `drift` and `config-consistency` install-replays have no cache to replay from and clone from the remote. Run `apm install` once on a new checkout and the offline guarantee holds from then on (`docs/spec/gates.md`, "Pushing without a network"). -- **This repo and Gitea are the only source of truth.** All project state, decisions, and working conventions live here. Do not use an external memory system for this project — cached state diverges from the repo and you get a split brain. Before answering any design or architecture question, check `docs/adr/` for an existing decision. +- **This repo and OneDev are the only source of truth.** All project state, decisions, and working conventions live here. Do not use an external memory system for this project — cached state diverges from the repo and you get a split brain. Before answering any design or architecture question, check `docs/adr/` for an existing decision. ## Key documents diff --git a/CONTEXT.md b/CONTEXT.md index 62ad8ec..f90ef09 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -133,8 +133,9 @@ than to enumerate siblings. Detail: `factory-audit/references/skill-description- _Avoid_: overlap, similar skill **Issue**: -The cross-provider term for a tracked unit of work. Gitea is this repo's canonical tracker -(ADR-0007), but skills say "linked issue" generically rather than naming a provider. +The cross-provider term for a tracked unit of work. OneDev is this repo's canonical tracker +(ADR-0007, superseded by ADR-0029), but skills say "linked issue" generically rather than naming +a provider. _Avoid_: ticket, card, task **Family prefix**: diff --git a/docs/adr/0007-gitea-canonical-issue-tracker.md b/docs/adr/0007-gitea-canonical-issue-tracker.md index e79313b..ad9047b 100644 --- a/docs/adr/0007-gitea-canonical-issue-tracker.md +++ b/docs/adr/0007-gitea-canonical-issue-tracker.md @@ -1,5 +1,7 @@ # Gitea is the exclusive issue tracker — file-based fallback removed +**Superseded by:** ADR-0029 (OneDev supersedes Gitea as this repo's canonical forge — this repo's own hosting, issue tracking, and PRs move to OneDev; `gitea/` continues to ship as a marketplace product regardless) + **Supersedes:** ADR-0011 (provider-agnostic issue tracker with file-based default — archived during refactoring) > **Note on the ADR-0011 number.** Every "ADR-0011" on this page means the *archived* provider-agnostic issue tracker ADR, which no longer exists in `docs/adr/` — it was removed when it was superseded, and the number 0011 was later reused for an unrelated decision, `docs/adr/0011-gitea-skill-deep-modules.md` (the gitea skill's split into deep modules). That file is not the ADR referenced below. The number is not renumbered here: these ADRs are a published record and renumbering would break every citation that already points at either one. The archived text is recoverable from git history. diff --git a/docs/adr/0029-onedev-supersedes-gitea-canonical-forge.md b/docs/adr/0029-onedev-supersedes-gitea-canonical-forge.md new file mode 100644 index 0000000..80b44be --- /dev/null +++ b/docs/adr/0029-onedev-supersedes-gitea-canonical-forge.md @@ -0,0 +1,43 @@ +# OneDev supersedes Gitea as this repo's canonical forge + +**Supersedes:** ADR-0007 (Gitea as the exclusive issue tracker) + +This repo's own hosting, issue tracking, and pull requests move from Gitea (`git.dev.rkdr.net`) to +OneDev (`onedev.dev.rkdr.net/Holocron`). Gitea is frozen and kept reachable read-only as a historical +archive rather than deleted, so commit messages, branch names, and ADRs that cite Gitea issue/PR +numbers (e.g. `#124`, `#140`) stay resolvable. `plugins/gitea/` is unaffected — it continues to ship +as a marketplace product for consumers with Gitea repos of their own; this decision is about what +*this* repo uses on itself, not what this repo authors and distributes. + +## Considered and rejected + +- **Preserving Gitea's issue/PR numbers in OneDev.** Rejected: OneDev issues and pull requests use + independent per-type counters, unlike Gitea's single shared sequence — there is no API path to + reproduce both simultaneously without a fragile create/delete padding hack. Migrated issues carry a + back-link to their original Gitea URL instead; new work uses OneDev's own numbers from the cutover + point forward. +- **Recreating historical PR objects (title/description/reviews) in OneDev.** Rejected for the + existing ~140 closed/merged PRs: `tod pr create` requires a live source branch, and Gitea already + deletes head branches on merge, so recreating them means resurrecting deleted branches from + merge-commit parent SHAs, opening throwaway PRs, and discarding them without merging (to avoid a + second, divergent merge commit alongside the mirrored git history). The git mirror already carries + every commit, message, author, and merge losslessly; the archived Gitea instance still holds the + original PR/review UI for anyone who needs it. Any PRs genuinely open and in flight at cutover time + are migrated for real, not archived. +- **Recreating Gitea's `Reviewed/*`, `Status/*`, and `Compat/Breaking` labels as new OneDev labels.** + Rejected in favor of OneDev's own out-of-the-box shape: structured `Type`/`Priority` fields (which + `Kind/*` and `Priority/*` map onto directly) plus the native three-state workflow (`Open` / + `In Progress` / `Closed`, no built-in disposition states). Disposition information that has no + native home becomes a one-line note in the migrated issue body instead of a second, parallel, + unstructured label taxonomy next to the real fields. + +## Consequences + +- Gitea issue/PR numbers cited in existing commit messages and docs remain valid only as long as the + archived Gitea instance stays reachable; they are not remapped to OneDev numbers anywhere. +- The six first-party `apm.yml` plugin dependencies (`git`, `gitea`, `kyberforge`, `lint`, `core`, + `bin`), previously resolved unpinned against `git@git.dev.rkdr.net:Defame1297/holocron.git`, are + repointed to the OneDev remote as part of this migration — apm's own dependency resolution must + track the now-canonical remote, not a frozen archive. +- `AGENTS.md`'s "this repo and Gitea are the only source of truth" language is updated to name + OneDev. diff --git a/docs/notes/onedev-migration-plan.md b/docs/notes/onedev-migration-plan.md new file mode 100644 index 0000000..fa16315 --- /dev/null +++ b/docs/notes/onedev-migration-plan.md @@ -0,0 +1,130 @@ +# Gitea → OneDev migration plan + +Executes ADR-0029 (supersedes ADR-0007). Scope: this repo's own self-hosting only — git history, +issues, milestones, wiki (already mirrored), and this repo's own tooling config. `plugins/gitea/` +ships unchanged as a marketplace product. Historical PR objects and Gitea's exact issue/PR numbering +are explicitly not migrated (see ADR-0029's "Considered and rejected"). + +Source: `Defame1297/holocron` on `git.dev.rkdr.net`. Target: `Holocron` (project id 1, currently +empty) on `onedev.dev.rkdr.net`. + +## Prerequisites + +- [x] `tod` installed and configured — `~/.config/tod/config` already has `server-url` and + `access-token`; `~/.bashrc` sources `~/.config/tod/env` automatically (`set -a; . env; set +a`), + but non-interactive shells (scripts, CI, this tool) must source it explicitly per invocation. +- [x] OneDev project `Holocron` exists (`tod project get Holocron`), `codeManagement` / + `issueManagement` enabled, currently no `defaultBranch` (empty repo). +- [ ] **Gotcha to build scripts around:** `tod issue`/`tod pr` subcommands resolve their target + project from the working directory's git remote, not from `--project` (verified — `--project` + is accepted by the flag parser but ignored; commands fail outside a repo with a OneDev remote). + Every migration script step below must run from inside a local clone with a remote pointing at + `onedev.dev.rkdr.net/Holocron`. +- [ ] Create the 7 OneDev **Iterations** (milestone equivalent) manually via the OneDev web UI — + `tod` has no iteration-create command. Names, verbatim, to match Gitea milestones for clean + `--iteration` references on migrated issues: + `Governance: enforcement`, `Kyberforge basics`, `Legacy / Triage`, `Road to homelab - prep`, + `Skills & Agents`, `The great refactoring`, `Tooling`. +- [ ] Freeze Gitea: stop merging PRs there once Phase 1 starts. Solo-maintainer repo, so this is just + "don't push to `git.dev.rkdr.net` after the mirror point." + +## Phase 1 — Mirror git history (lossless, zero risk) + +1. `git remote add onedev https://onedev.dev.rkdr.net/Holocron` in the local clone. +2. `git push onedev refs/heads/*:refs/heads/* refs/tags/*:refs/tags/*` (explicit branch+tag push, + not `--mirror` — avoids touching any Gitea-internal refs that aren't real branches). +3. Verify: `tod project get Holocron` shows `defaultBranch` populated; HEAD of `main` on OneDev + matches Gitea `main` HEAD (`d654dca...` as of this plan). +4. This alone carries every commit, author, message, and merge losslessly — nothing else in this + plan is required for code-level fidelity. + +## Phase 2 — Issues (~95 total: 81 closed + 14 open across 7 milestones, per Gitea milestone counts) + +Field mapping (OneDev's out-of-the-box `Type`/`Priority` fields, no new labels created): + +| Gitea label | OneDev field | +|---|---| +| `Kind/Bug` | `Type: Bug` | +| `Kind/Feature` | `Type: New Feature` | +| `Kind/Enhancement` | `Type: Improvement` | +| `Kind/Documentation`, `Kind/Testing` | `Type: Task` | +| `Kind/Security` | `Type: Bug` | +| `Priority/Critical` | `Priority: Critical` | +| `Priority/High` | `Priority: Major` | +| `Priority/Medium` | `Priority: Normal` | +| `Priority/Low` | `Priority: Minor` | +| `Reviewed/*`, `Status/*`, `Compat/Breaking` | no field/state equivalent — fold into a one-line note in the migrated body | + +State mapping: Gitea `open` → OneDev `Open` (default, no action); Gitea `closed` → +`tod issue change-state Closed`. OneDev's out-of-the-box workflow only has +Open/In Progress/Closed — no disposition states, confirmed by probing the live server. + +Per issue: +5. `tod issue create "" --field Type=<mapped> --field Priority=<mapped> --iteration "<milestone>" --description "<body>\n\n---\nMigrated from git.dev.rkdr.net/Defame1297/holocron/issues/<N>.[\nGitea disposition: <label>.]"` +6. Replay comments via `tod issue add-comment` (low effort, worth doing for continuity). +7. `tod issue change-state <new-ref> Closed` for originally-closed issues. +8. Spot-check a sample (e.g. 5 issues across different milestones) against the Gitea source. + +Numbers will not match Gitea's (accepted — ADR-0029). Author/submitter on migrated issues will be +the migration token's own OneDev account, not the original Gitea author — no CLI-exposed way to +override this (the `onBehalfOf` field exists in OneDev's issue schema but isn't exposed through `tod`; +using it would mean raw, unverified REST calls, not worth it for this scope). + +## Phase 3 — Pull requests + +- **Currently-open PRs only** (check at execution time: `list_pull_requests state=open`): migrate for + real via `tod pr create`, since the source branch still exists. Add description, reviewers. +- **Closed/merged historical PRs (~140 of them): explicitly skipped.** Per ADR-0029, their content + survives losslessly in the Phase 1 git mirror; the archived Gitea instance remains the record for + anyone who wants the original review thread. + +## Phase 4 — Releases + +Git tags (`v1.0.0`, `v2.0.0`, `v2.0.1`) carry over automatically in Phase 1. OneDev has no confirmed +first-class "Release" object with a rendered markdown body the way Gitea does — this needs a quick +check against the live server before deciding further (not yet verified in this session). Fallback if +none exists: leave the 3 release-note bodies in the archived Gitea (read-only) and optionally fold +them into a `CHANGELOG.md` in the repo for local discoverability. **Flag this to the user before +executing Phase 4** — not fully resolved. + +## Phase 5 — Wiki + +Nothing to do. `docs/wiki/HUMANS.md` and `docs/wiki/Home.md` already mirror the two Gitea wiki pages +in-repo (confirmed identical), and OneDev has no separate wiki feature to migrate into (confirmed: no +wiki flag on the project object, no wiki REST resource). They travel with Phase 1 automatically. + +## Phase 6 — Repo self-reference updates (code changes) + +9. Repoint the six first-party `apm.yml` plugin dependencies (`git`, `gitea`, `kyberforge`, `lint`, + `core`, `bin`) from `git@git.dev.rkdr.net:Defame1297/holocron.git` to the OneDev remote. +10. Update `AGENTS.md`'s routing table (currently: *"Issues, PRs, labels, milestones → + `gitea-issues`, `gitea-prs`, `gitea-labels-milestones`..."*) to route this repo's own + issue/PR operations to the OneDev/tod skills instead (`using-tod` as the catch-all, plus + `work-on-issue`, `work-on-pull-request`, `submit-issue-work`, `submit-pull-request-work`). This + needs a deliberate mapping pass, not a mechanical find-replace — the tod skillset is + workflow-shaped, not CRUD-shaped like the gitea skills it replaces. +11. Update local `origin` remote to point at OneDev; rename the old one (e.g. `git remote rename + origin gitea-archive`) rather than deleting it. +12. Run `apm install` against the repointed remote and verify it resolves cleanly. +13. Sweep `README.md` and any other doc prose that names Gitea as *this repo's own* host (separate + from `plugins/gitea/`'s own product documentation, which is unaffected). + +## Phase 7 — Freeze and archive Gitea + +14. Set the Gitea repository to read-only/archived via the Gitea web UI (no MCP tool exposes this — + manual step). + +## Verification checklist + +- [ ] `tod project get Holocron` → `defaultBranch: main`, HEAD SHA matches Gitea's `main`. +- [ ] Issue count on OneDev matches Gitea's ~95 (open + closed). +- [ ] `apm install` succeeds from a fresh clone against the new remote. +- [ ] Pre-commit hooks (`pre-commit run --all-files`) pass in a fresh OneDev clone. +- [ ] Gitea repo is read-only; a test push to it fails as expected. + +## Explicitly out of scope (deferred, per earlier decisions) + +- `.onedev-buildspec.yml` / CI setup — no Gitea Actions exist today to migrate; separate follow-up + task via the `edit-build-spec` skill. +- Sunsetting `plugins/gitea/` as a marketplace product — agreed as a *later* phase, not part of this + migration.