Vancetope — Project Kits Catalog
Tenant-wide catalog of pre-configured Kits, serving as a selection list during Project creation. Supplements kits.md (what a Kit is and how it is installed) by addressing the question “which Kits are actually suggested to the user when creating a Project?”.
See also: kits | project-lifecycle | architektur-scopes-clients
1. Purpose
Vancetope has the Kit system from kits.md — bundles of Documents/Settings/Tools that are imported into a Project from a Git repo. When creating a new Project, users should be able to directly install one of these Kits without needing to know the Git URL.
The Project-Kits-Catalog is the list of named Kit sources curated by the Tenant. It has three consumers:
- Web-UI displays it as a dropdown in the Project-Create dialog.
- Foot CLI accepts
--kit <name>withproject create. - Eddie can select a Kit name when creating a Sub-Project and read the list via a Tool to match a suitable entry to the user’s request (“Software Project”).
What is not part of the Catalog: auto-discovery of arbitrary Git URLs,
Kit repository browsing, version tracking per Kit. To use an unlisted Kit,
install it manually after Project creation via kit install <url>
(see kits.md §6.1).
2. Storage Location
For each Tenant, exactly one Catalog file as a Document in the _tenant Project:
tenant=<tenantName>, project=_tenant, path=config/project-kits.yaml
No Cascade. Unlike Recipes/Settings/Skills, the Catalog is not merged across Tenants. During Project creation, the new Project does not yet exist — there is no meaningful Project Scope for a Cascade, and the Tenant Admin should be able to curate autonomously.
The System Tenant _tenant is the source for new Tenants (see §5);
otherwise, each Tenant Admin configures their Catalog autonomously.
3. Format
# config/project-kits.yaml (in the Tenant's _tenant Project)
version: 1
kits:
- name: base/research
title: Research Base
description: General-purpose research kit with web-search tools
git:
url: https://github.com/mhus/vance-kits.git
subPath: kits/research
ref: main
- name: base/dev/java
title: Java Development
git:
url: https://github.com/mhus/vance-kits.git
subPath: kits/dev-java
ref: main
| Field | Type | Required | Description |
|---|---|---|---|
version |
Int | yes | Catalog schema version. Currently 1. |
kits[].name |
String | yes | Catalog lookup key, unique within the file. May contain / as a free string — the Catalog code does not parse this as a path. Clients may group visually but are not required to. |
kits[].title |
String | yes | Display name for UI/CLI. |
kits[].description |
String | no | One-sentence description, used as tooltip/subtitle in Web-UI. |
kits[].git.url |
String | yes | Git repo URL (HTTPS/SSH). |
kits[].git.subPath |
String | no | Path within the repo, if mono-repo. Empty = repo root. |
kits[].git.ref |
String | no | Branch/Tag/SHA. Default main. |
The Catalog name is only a lookup key; the actual Kit has its own name
from kit.yaml#name (see kits.md §3.1). Both do not have to
match — the Catalog can offer the same Kit multiple times with different
Refs (base/dev/java, base/dev/java-experimental), both pointing to
the same kit.yaml#name.
Validation on write: name uniqueness, git.url non-empty, version
known. If violated, the service throws IllegalArgumentException, Anus
update rejects.
4. Read API
4.1. ProjectKitsCatalogService
In vance-shared:
public interface ProjectKitsCatalogService {
/** Loads the Catalog. If the Document is missing: empty Catalog. */
ProjectKitsCatalogDto load(String tenantId);
/** Returns an entry by name, or null. */
@Nullable ProjectKitEntry findByName(String tenantId, String name);
/** Persists the Catalog. Validates before save (§3). */
void save(String tenantId, ProjectKitsCatalogDto catalog);
}
Data sovereignty: this service is the only access to
config/project-kits.yaml. Web-/Foot-/Eddie-paths all go through it.
4.2. REST + WS
- REST:
GET /brain/{tenant}/project-kits→ProjectKitsCatalogDto - WS:
LIST_PROJECT_KITSRequest →PROJECT_KITS_LISTResponse
Both deliver the same DTO. Auth: Tenant membership is sufficient — the Catalog is not sensitive; it lists public Git URLs.
4.3. Eddie Tool
New server Tool kit_list:
kit_list() → { kits: [{ name, title, description }] }
Without Git details, so the LLM does not pull URL spam into the context.
If Eddie is to install a Kit, it passes the name string to
project_create; this performs the Git lookup internally.
Eddie additionally calls project_create(tenantId, name, ..., kitName?)
with the chosen Catalog name. This is an additional optional parameter
to the existing Tool, not a new Tool.
No Jeltz needed. Eddie is in the LLM loop and can evaluate the list
in the same turn. If the user says “Software development project”, Eddie
sees the kit_list response and selects base/dev/java itself. A
specialized Jeltz Recipe would only be useful if a non-LLM-caller
needed the matching — this use case is not present in v1.
5. Tenant Bootstrap
During TenantService.create(...) (after mandatory Tenant setup, before return),
the Catalog is copied from the System Tenant _tenant to the new Tenant:
source: tenant=_tenant, project=_tenant, path=config/project-kits.yaml
target: tenant=<new>, project=_tenant, path=config/project-kits.yaml
If the source is missing (fresh setup, Anus not yet run): do not create
a file; the new Tenant’s Catalog is empty. Foot default is “no Kit”, Web
default is the none option, Eddie reports “no Kits configured”.
What is not copied: Kit contents themselves — the Catalog is only the
list, not the Kits. Kit contents only land in the target Project during
kit install / Project creation.
6. Usage during Project Creation
6.1. Foot CLI
vance project create --name <n> [--title <t>] [--group <g>] [--kit <name>]
- Without
--kit→ no Kit installation. --kit <name>→ after successful Project creation, the Kit from the Catalog entry is installed (existingkit installpath, kits.md §6.1, usinggit.url/git.subPath/git.reffrom the entry).
If <name> is not in the Catalog: Foot reports “kit ‘
6.2. Web-UI
Project-Create dialog in vance-face shows dropdown:
- First option: “No Kit” (implicit, not from YAML).
- Other options: Catalog entries, rendered as
title. Subtitle =description, if present.
On submit: POST /brain/{tenant}/projects with kitName field (or
null for “no kit”). Backend installs Kit synchronously — Web waits
for a response before the editor opens. In case of a Kit install error:
Project remains created, UI shows Warning “Project created, kit install
failed:
6.3. Eddie (Sub-Project Creation)
Eddie can create a Sub-Project at the user’s request:
- User: “create a Java project”
- Eddie calls
kit_list()→ seesbase/dev/java - Eddie calls
project_create(..., kitName="base/dev/java") - Brain installs Kit after Project creation
If the Catalog is empty or no entry matches: Eddie creates the Project without a Kit and informs the user.
7. Anus Bootstrap and Update
7.1. Source Repo Convention
Source: a Git repo with a kits/ subfolder. Each direct subdirectory
under kits/ is a Kit source (i.e., has its own kit.yaml). Optionally,
a kits/catalog.yaml can be located in the repo root with Title/Description
overrides per Kit:
# kits/catalog.yaml in the Source Repo
overrides:
research: # = subdir-name
name: base/research # Catalog lookup name (default: subdir)
title: Research Base
description: General-purpose research kit
dev-java:
name: base/dev/java
title: Java Development
If catalog.yaml is missing: name = <subdir>, title = <subdir> by
default. This allows importing a repo without overrides.
7.2. Anus Commands
anus project-kits show --tenant <t>
anus project-kits import --tenant <t> [--git <url>] [--ref <r>]
anus project-kits update --tenant <t> [--mode merge|overwrite] [--dry-run]
Default Git is https://github.com/mhus/vance-kits.git, default Ref
is main — both can be overridden via --git/--ref (e.g., if the
Tenant maintains its own curated Kit list).
Modes for update:
merge(Default): Upsert byname. Git entries replace Tenant entries with the same name. Tenant entries without a match in Git are retained. New Git entries are appended to the end (Tenant order is otherwise not touched).overwrite: Complete replacement with the Git state. Tenant-specific entries are lost.
--dry-run shows the diff (added / updated / removed / kept)
without writing.
import rejects if the Catalog exists. update creates it if it is missing.
Pipeline:
- Clone repo to
tmp/<uuid>/(at the Ref). - Scan
kits/subdirs → list of Kit sources. - Read optional
kits/catalog.yamlfor overrides. - Build Catalog entries (
name,title,description,git.url,git.subPath=kits/<subdir>,git.ref). - Load existing Tenant Catalog (or empty).
- Apply mode (merge/overwrite).
- Validate (§3).
--dry-run→ output diff, end.- Otherwise:
ProjectKitsCatalogService.save(...).
Recommended initial call (System Tenant bootstrap):
anus project-kits update --tenant _tenant --mode overwrite
Writes the Catalog to _tenant — it will be automatically copied to
new Tenants upon creation (§5).
8. What is NOT in v1
- Auto-Refresh of the Catalog from Git. Updates are manual via Anus.
- Per-Catalog-Git-Auth. The source repo is cloned with the Brain Pod’s default Git setup (SSH key or anonymous). Anus cannot authorize private repos in v1.
- Kit Versioning in the Catalog.
git.refpoints to a branch or tag — for reproducibility, pin a tag. No lockfile, no “last installed commit” per Catalog entry. - Catalog Editor in the Web-UI. Maintenance is done via Anus. If this comes later: separate plan.
- Inherits in the Catalog. Catalog entries are flat; they refer to
a Kit. Inherits live in the
kit.yamlof the Kit repo (see kits.md §5).
9. Prerequisites
- kits.md §6.1 (
kit installpipeline) — Project-Create integration builds upon this. - project-lifecycle.md — Project-Create path, status set.
DocumentServiceforconfig/project-kits.yamlin the_tenantProject.TenantService.create(...)hook for bootstrap copy (§5).- Anus with Git clone capability (new in v1, see plan).
10. Reference
- kits — What a Kit is, install pipeline, manifest, apply, export.
- project-lifecycle — Project-Create path, status set, Pod ownership.
- architektur-scopes-clients — Tenant / Project-Group / Project / Session / Think-Process.