ckb/.agents/skills/ckb-module/SKILL.md
Michał Kopeć 6c0d70976c Add release channels: main, test, experimental
The template repo now keeps three branches with fixed meanings — main is
stable, test is the release candidate, experimental is development — and
ckb-init/ckb-upgrade can source from any of them instead of only main.

Selection is per-invocation, in words the user already uses ("initialize
from the test branch", "check experimental for updates", "switch back to
stable"), and sticky: the resolved repo and branch are written to a
template: block in ckb.yaml. Without persistence, a KB bootstrapped from
experimental would be silently pulled back to main by its next upgrade.
A missing file or missing block both mean main, so every KB predating
this convention behaves exactly as before.

One consequence needed explicit handling. A KB tracking test or
experimental can sit on a VERSION main has not released yet, so comparing
it against main finds nothing newer — which the version check would have
reported as "up to date". That is true and misleading. ckb-upgrade now
reports it as "ahead", and treats a move back to main as a downgrade:
explicitly confirmed, with the specific losses named, and blocked
outright where kb_schema_version would drop below what local pages are
already written against.

ckb-module is told not to clobber the template: block — a module install
that silently reset a KB's channel would change what its next upgrade
pulls, which is not a module's business.

Documented in both READMEs, both MANUALs and both CHANGELOGs. VERSION
1.8.0 -> 1.9.0; kb_schema_version stays 1.5, since this is tooling rather
than a content contract.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 08:29:45 +02:00

178 lines
8.2 KiB
Markdown

---
name: ckb-module
description: Install, list, or uninstall an optional Cascade KB module from .agents/modules/<name>/ — copying its skills into .agents/skills/, creating its scaffold directories, appending its routing block to AGENTS.md and its rules to .gitignore, and recording it in the root ckb.yaml manifest. Use when the user says "install the software module", "add the <name> module", "what modules are available", "which modules are installed", "uninstall the <name> module", or asks to make this KB handle source code / a capability the base KB doesn't have. Distinct from `ckb-init` (bootstraps a whole new KB) and `ckb-upgrade` (catches the template layer up with upstream); this skill toggles optional capabilities within an existing KB.
---
# Module skill
## Purpose
The base KB ships every skill always-loaded. Some capabilities are only useful to
*some* knowledge bases, and their skill descriptions would otherwise sit in
context for every KB that will never need them.
Optional capabilities therefore live in `.agents/modules/<name>/` — present in the
repo, inert until installed. This skill is the install/uninstall path. See
[D-0001](/wiki/decisions/0001-opt-in-file-based-kb-modules.md) for why this is
files-in-the-repo rather than a native agent plugin: a module is a property of the
knowledge base, so it must travel with a clone and work for any agent that reads
`AGENTS.md`.
## Trigger phrases
- "install the `<name>` module" / "add the `<name>` module" / "enable `<name>`"
- "what modules are available" / "which modules are installed"
- "uninstall the `<name>` module" / "remove `<name>`" / "disable `<name>`"
- "make this KB handle source code" (→ offer the `software` module)
## The manifest
Installed modules are recorded in `ckb.yaml` at the repo root:
```yaml
template: # written by ckb-init, read and updated by ckb-upgrade
repo: https://git.wierzbowa.cloud/michal/ckb.git
branch: main # main | test | experimental, or any branch of a fork
kb_modules:
- name: software
version: 1.0.0
installed_on: 2026-09-20
config:
src_repos: []
```
`ckb.yaml` holds repo-level configuration — what's installed, what it's
configured with. It is **not** the wiki's content contract: `kb_schema_version`
stays in `wiki/index.md` where it has always been. Two different things, two
different homes.
The `template:` block records which upstream repo and **branch** this KB takes
its tooling from. It belongs to `ckb-init` (writes it) and `ckb-upgrade` (reads
it as the default source, updates it when the user switches channel). This
skill must **never** drop or rewrite it: a module install that silently reset a
KB from the `experimental` channel back to `main` would change what its next
upgrade pulls, which is not a module's business. Read `ckb.yaml`, edit the
`kb_modules:` list, write it back with everything else intact.
If `ckb.yaml` doesn't exist, no modules are installed and no template source is
recorded; create it on first install, carrying forward any `template:` block
that a later `ckb-upgrade` may add.
## Installing
### Step 1 — Resolve and read the module
Find `.agents/modules/<name>/module.yaml`. If the name doesn't match, list what's
actually in `.agents/modules/` rather than guessing at a near-miss.
Read the manifest: `skills`, `scaffold`, `agents_fragment`, `gitignore_fragment`,
`schema_additions`, `depends_on`, `requires_kb_schema`.
### Step 2 — Check preconditions, and report them before writing anything
- **Already installed?** If `ckb.yaml` lists it, say so and offer to reinstall
(refresh the files) or stop. Don't silently re-copy.
- **Schema.** If `requires_kb_schema` is above `wiki/index.md`'s
`kb_schema_version`, the bump is part of this install (Step 4) — additive only.
If the module needs a *major* version above the KB's, stop and hand it to
`ckb-upgrade`.
- **Dependencies.** Run each `check`. A failing **optional** dependency is a
warning, not a blocker — report it plainly and continue. A failing required one
stops the install.
- **Collisions.** If a skill name in `skills:` already exists in
`.agents/skills/`, or a scaffold path exists with unrelated content, stop and
ask. Never overwrite a skill the user may have edited.
Report all findings **before** the first write, then proceed (or ask, if anything
needs a decision). A half-installed module is worse than an uninstalled one.
### Step 3 — Copy the payload
```bash
cp -r .agents/modules/<name>/skills/<skill> .agents/skills/<skill>
```
`.claude/skills` is a symlink to `.agents/skills` (git mode `120000`), so the
skills appear under `.claude/` automatically. **Do not create a second copy
there** — that symlink is a deliberate choice, and duplicating it creates two
things to keep in sync.
Create each `scaffold` path, copying any `from` template to its `as` destination.
Never overwrite an existing scaffold file — skip it and note the skip.
### Step 4 — Patch the shared files
Both patches are wrapped in markers so uninstall is exact:
```
<!-- ckb-module:<name> START -->
...fragment...
<!-- ckb-module:<name> END -->
```
- **`AGENTS.md`** — append `agents_fragment` at the end of the file, inside
markers. `CLAUDE.md` is a symlink to `AGENTS.md`, so it updates for free;
never write `CLAUDE.md` directly.
- **`.gitignore`** — append `gitignore_fragment`, inside markers (`#`-commented).
- **`wiki/index.md`** — bump `kb_schema_version` to `requires_kb_schema` if the
module's additions raise it. Additive only, per `ckb-upgrade`'s versioning
policy.
### Step 5 — Record, log, report
- Add the module to `ckb.yaml` with its version and today's date.
- Log to `wiki/log.md` per Rule B **only** for the `wiki/index.md` change — the
rest is template layer, not wiki content.
- Append to `workload/YYYY-MM-DD_summary.md` per Rule D.
- Report: skills now available and what they do, directories created, files
patched, dependency warnings, schema bump if any. Then the standard reminder —
on disk, not committed.
Offer to record a decision (`ckb-decide`) if installing the module was a real
choice for this KB rather than following a prior one.
## Uninstalling
Reverse Step 3 and 4, in this order, and be conservative about data:
1. Remove `.agents/skills/<skill>` for each skill the manifest lists — **but
first diff it against `.agents/modules/<name>/skills/<skill>`.** If the
installed copy was edited, show the diff and ask before deleting. Offer to
copy the edits back into the module folder so they survive.
2. Strip the marked blocks from `AGENTS.md` and `.gitignore`.
3. Remove the module's entry from `ckb.yaml`.
**Never remove scaffold directories or any content under them.** `src/` may hold
the user's clones, `openspec/` their specs. Say explicitly what was left behind
and why, so nothing looks like an oversight.
**Never remove wiki pages the module's skills created**, and never lower
`kb_schema_version`. Those pages are knowledge; the module produced them but does
not own them, and they must stay readable without it. Say which page types
(`repository`, `component`, `spec`) will now have no skill maintaining them.
## Listing
On "what modules are available": list `.agents/modules/*/module.yaml` with each
`title` and `summary`, marking which are installed per `ckb.yaml`. Keep it short
— name, one line, installed or not.
## Edge cases
- **A module directory with no `module.yaml`** — not a module. Report it as
malformed; don't try to infer its contents from its file layout.
- **The user asks for a capability no module provides** — say so, and don't
install a near-match hoping it fits. Offer to note it in `wiki/query-gaps.md`.
- **`ckb-upgrade` brought a newer version of an installed module** — the installed
skill copies are stale. Offer to reinstall; show what changed before doing it.
- **Markers missing at uninstall** (someone hand-edited `AGENTS.md`) — don't
guess at the block's boundaries. Show the fragment and ask the user to remove
it, or point at exactly what to delete.
- **A module's skill was renamed upstream** — treat as collision (Step 2), ask.
Don't delete the old name automatically.
---
*Licensed under the Apache License, Version 2.0 — see [LICENSE](../../../LICENSE)
at the repository root, or <http://www.apache.org/licenses/LICENSE-2.0>.*