feat(skills): meta-host-routing v0.2.0 — dedicated-host resolve + bootstrap

Resolve order now prefers a dedicated same-name Gitea meta-host (e.g.
OpeItcLoc03/yt-tools) over a shared host (.common). Adds Bootstrapping a
new meta-host section incl. the git add -f gotcha (global core.excludesFile
ignores .wiki/.tasks in fresh clones). yt-tools relocated to its own host
2026-05-27.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 12:38:31 +03:00
parent a19a23779a
commit 4355c34c18

View File

@@ -1,6 +1,6 @@
--- ---
name: meta-host-routing name: meta-host-routing
version: 0.1.0 version: 0.2.0
description: > description: >
Use before any tasks_create / knowledge_ingest / brainstorm-promotion against Use before any tasks_create / knowledge_ingest / brainstorm-promotion against
a project — resolve WHERE that project's meta lives before writing. A a project — resolve WHERE that project's meta lives before writing. A
@@ -37,19 +37,35 @@ Per the `meta-out-of-repo` design: `.tasks/`, `.wiki/`, `.claude/` must not be c
1. **Detect.** Check the target's local remote (`git remote -v`) and/or a `projects-meta` dry-run. Github remote OR "not in cache" → meta-out-of-repo project; continue. Otherwise → direct Gitea route, this skill does not apply. 1. **Detect.** Check the target's local remote (`git remote -v`) and/or a `projects-meta` dry-run. Github remote OR "not in cache" → meta-out-of-repo project; continue. Otherwise → direct Gitea route, this skill does not apply.
2. **Resolve the meta-host.** Find the Gitea repo that already tracks this project's meta. Grep sibling Gitea repos — **start with `.common`** (`~/projects/.common/`) — for the project name across `.tasks/STATUS.md` and `.wiki/`: 2. **Resolve the meta-host**, in priority order:
``` - **(a) Dedicated meta-host (preferred).** Is there a Gitea repo with the **same name** as the project, holding only `.wiki/`+`.tasks/` (no code)? That is its meta-host. Once synced, `projects-meta` tracks it as a project of that name — `meta_status` / a `tasks_create` dry-run against `<owner>/<project>` resolves. Canonical example: code `github.com/OpeItcLoc03/yt-tools` → meta-host **Gitea `OpeItcLoc03/yt-tools`** (a meta-only repo, same name, code on github).
grep -ril "<project-name>" ~/projects/.common/.tasks/ ~/projects/.common/.wiki/ - **(b) Shared host (transitional).** No dedicated host yet → grep sibling Gitea repos, **start with `.common`** (`~/projects/.common/`), for the project name:
``` ```
The host is whichever Gitea repo already holds that project's tasks/wiki. Canonical example: code `github.com/OpeItcLoc03/yt-tools` → meta-host `.common` (`OpeItcLoc03/common`), because yt-tools was born in `.common/lib/yt-tools/` and the code was extracted while the meta stayed. grep -ril "<project-name>" ~/projects/.common/.tasks/ ~/projects/.common/.wiki/
```
The host is whichever Gitea repo already holds that project's tasks/wiki.
- **(c) Neither** → the project has no meta-host yet (Failure modes — STOP and ask, or bootstrap one per "Bootstrapping a new meta-host").
3. **Route there.** Send every `tasks_create` / `knowledge_ingest` to the host's qualified `<owner>/<repo>` (e.g. `OpeItcLoc03/common`). Namespace entries with a `<project>-` slug prefix so they're distinguishable on the shared host board (`yt-meta-impl`, `yt-comments-impl`, …). > Note: `.common` was yt-tools' shared host until 2026-05-27, when yt-tools graduated to its own dedicated host (`OpeItcLoc03/yt-tools`). `.common` now holds only yt-tools' done-task archive. Prefer giving a maturing project its own host over piling onto `.common`.
3. **Route there.** Send every `tasks_create` / `knowledge_ingest` to the host's qualified `<owner>/<repo>` (a dedicated host = `<owner>/<project>`; a shared host = e.g. `OpeItcLoc03/common`). On a shared host, namespace entries with a `<project>-` slug prefix.
4. **Never** write `.tasks/`/`.wiki/` files into the github working tree, and **never** invent a target when resolution is ambiguous (Failure modes below). 4. **Never** write `.tasks/`/`.wiki/` files into the github working tree, and **never** invent a target when resolution is ambiguous (Failure modes below).
## Bootstrapping a new meta-host
When a project graduates to its own dedicated host (or a github project needs one):
1. Create a Gitea repo named after the project (meta-only, `auto_init:false`) via the API with the admin token (`~/.config/projects-mcp/auth.toml`).
2. Clone it, build canonical `.wiki/` (CLAUDE.md, index.md, log.md, overview.md, raw/, concepts/, entities/, packages/, sources/) + `.tasks/STATUS.md` (emoji legend header).
3. **`git add -f .wiki .tasks`** — the global `core.excludesFile` (`~/.config/git/ignore`) ignores `.wiki/`/`.tasks/`. Existing hosts track them because they were added *before* that ignore existed; a fresh clone needs `-f` or `git add -A` silently stages nothing. This is the one gotcha that will waste a commit if missed.
4. Commit, push. `projects-meta` picks it up on its next sync (it may not be in cache until then — see Failure modes).
5. If migrating off a shared host: move open tasks + design concepts to the new host, leave the done-task archive behind under a relocation marker, and replace moved concept docs with pointer stubs so back-references don't dead-end.
## Failure modes ## Failure modes
- **No Gitea repo tracks this project** → STOP. Ask the user where the meta should live (likely `.common`, or a new host). Do **not** default to writing into the github repo — that reintroduces the leak meta-out-of-repo exists to prevent. - **No Gitea repo tracks this project** → STOP. Ask the user whether to bootstrap a dedicated host (preferred) or attach to a shared one. Do **not** default to writing into the github repo — that reintroduces the leak meta-out-of-repo exists to prevent.
- **Just-created meta-host not yet in `projects-meta` cache** → `tasks_create`/`knowledge_ingest` return "not in cache" until a sync runs. Either trigger a sync, or write the initial `.tasks/STATUS.md` / `.wiki/` content directly via git (as in Bootstrapping) and let the MCP pick it up next sync.
- **Multiple Gitea repos reference the project** → STOP, ask which is canonical. Don't pick by guess. - **Multiple Gitea repos reference the project** → STOP, ask which is canonical. Don't pick by guess.
- **projects-meta cache stale** ("not in cache" could be staleness, not meta-out-of-repo) → run a sync / `meta_status` freshness check first (see `using-projects-meta` Step 0) before concluding the project is github-only. - **projects-meta cache stale** ("not in cache" could be staleness, not meta-out-of-repo) → run a sync / `meta_status` freshness check first (see `using-projects-meta` Step 0) before concluding the project is github-only.