diff --git a/.agents/modules/software/README.md b/.agents/modules/software/README.md new file mode 100644 index 0000000..b08c826 --- /dev/null +++ b/.agents/modules/software/README.md @@ -0,0 +1,68 @@ +# `software` module + +Opt-in. Install with "install the software module"; remove with "uninstall the +software module". Nothing in here is active until installed — the skills below +live in this folder, not in `.agents/skills/`, precisely so their descriptions +stay out of context for knowledge bases that don't document software. + +## What it assumes + +You are building software, and this KB holds the knowledge *about* it. The code +itself lives in `src//` as plain clones — **gitignored**, each with its own +remote and its own history. One KB can hold several. + +The code is not part of the KB's history and may be absent entirely from a fresh +clone. That is deliberate, and it is why the module writes a `type: repository` +entity page for every repo: remote URL, default branch, language, build command, +path, owner. **That page is the durable artifact; the clone is a convenience.** + +## What it adds + +| Skill | Does | +|---|---| +| `ckb-code-map` | Reads a `src/` clone and writes it into `wiki/entities/` as a repository page plus component pages, stamped with the commit it was generated from so staleness is detectable. | +| `ckb-spec` | Owns KB-root specs, delegates per-repo specs to OpenSpec, and bridges both into `wiki/` — archived changes become decision records, current specs become `type: spec` pages. | + +Plus: `src/` and `openspec/` scaffold, a routing block in `AGENTS.md`, `.gitignore` +rules for `src/*`, and the `repository`/`component`/`spec` types. + +## Two spec levels + +Specs live at **both** levels, and the split is the point: + +- **`openspec/` at the KB root** — what and why, across repos. Cross-cutting + contracts that no single repo owns. Served by `ckb-spec` directly, because a + root `openspec/` is not a normal OpenSpec install: there is no code beneath it. +- **`src//openspec/`** — how this repo implements it. OpenSpec's native + case: travels with the code, rides along in the repo's own PRs. Served by + OpenSpec's own instructions; `ckb-spec` defers to them and says so plainly when + the CLI isn't installed rather than improvising a replacement. + +The levels are linked by `implements:` / `implemented_by:` frontmatter, which +becomes graph edges. This exists so that two spec levels produce a **lint signal** +when they disagree, instead of two silently divergent truths. A KB-root spec with +no implementer, or a repo-level spec whose parent was archived, is a finding. + +## What it does not do + +- **`src/` is not a cascade layer.** It is primary evidence, like `raw/archive/`. + `ckb-retrieve` may open and cite it to verify a claim; it never answers "what is + entity X", and `ckb-ingest` does not treat code as inbox material. Without this + rule every ingest would turn your codebase into wiki pages. +- **It does not commit or push `src/` repos.** They are separate repos with + separate remotes. `ckb-sync-changes` never `git add`s under `src/`. + +## Setting up OpenSpec + +See [OPENSPEC.md](../../../OPENSPEC.md) ([Polski](../../../OPENSPEC.pl.md)) for +install steps, the daily propose → apply → archive loop, and the reason +`openspec init` must never run at the KB root. + +## Design record + +- [D-0001](../../../wiki/decisions/0001-opt-in-file-based-kb-modules.md) — why modules are files in the repo. +- [D-0002](../../../wiki/decisions/0002-software-module-design.md) — why gitignored clones, both spec levels, hybrid vendoring. + +--- + +*Licensed under the Apache License, Version 2.0 — see [LICENSE](../../../LICENSE).* diff --git a/.agents/modules/software/fragments/agents-routing.md b/.agents/modules/software/fragments/agents-routing.md new file mode 100644 index 0000000..3e26e93 --- /dev/null +++ b/.agents/modules/software/fragments/agents-routing.md @@ -0,0 +1,23 @@ +## MODULE: software + +This KB documents software being built here. Source repos live in `src//` +as **gitignored plain clones**, each with its own remote and history. + +- `src/` is **evidence, not a cascade layer.** `ckb-retrieve` may open and cite + code to verify a claim; it never answers "what is entity X", and `ckb-ingest` + never treats code as inbox material. +- **Never `git add` under `src/`.** Those are separate repos. `ckb-sync-changes` + reports each one's dirty/ahead state separately and commits none of them. +- Every repo has a `type: repository` page in `wiki/entities/` — the durable + record, since the clone may be absent from a fresh checkout. +- Specs live at two levels: `openspec/` at the KB root (cross-cutting, owned by + `ckb-spec`) and `src//openspec/` (per-repo, owned by OpenSpec itself). + They link via `implements:` / `implemented_by:`. + +| User intent | Skill | +|---|---| +| Map or refresh a `src/` repo into wiki entities | `ckb-code-map` | +| Write, sync, or bridge specs (either level) | `ckb-spec` | + +Module-contributed page types: `repository`, `component`, `spec`. Additional +optional frontmatter: `repo`, `commit`, `spec_id`, `implements`, `implemented_by`. diff --git a/.agents/modules/software/fragments/gitignore.snippet b/.agents/modules/software/fragments/gitignore.snippet new file mode 100644 index 0000000..f6cc9ff --- /dev/null +++ b/.agents/modules/software/fragments/gitignore.snippet @@ -0,0 +1,7 @@ +# Source repos are independent git clones with their own remotes — never part of +# this KB's history. Knowledge about them lives in wiki/entities/ instead. +src/* +!src/.gitadd +!src/README.md +# KB-root cross-cutting specs ARE tracked — they are knowledge, not code. +!openspec/ diff --git a/.agents/modules/software/module.yaml b/.agents/modules/software/module.yaml new file mode 100644 index 0000000..85c9682 --- /dev/null +++ b/.agents/modules/software/module.yaml @@ -0,0 +1,59 @@ +# Cascade KB module manifest — read by `ckb-module` on install/uninstall. +# See wiki/decisions/0001-opt-in-file-based-kb-modules.md for why modules are +# files in the repo rather than native agent plugins. +name: software +title: Software / source-code KB +version: 1.0.0 +requires_kb_schema: "1.5" +summary: > + Turns this knowledge base into one that documents software you are building: + source repos live as gitignored plain clones in src/, and OpenSpec drives + iterative development at both KB-root and per-repo level. + +# Skills copied into .agents/skills/ on install, removed on uninstall. +# .claude/skills is a symlink to .agents/skills, so there is no second copy. +skills: + - ckb-code-map + - ckb-spec + +# Directories created on install. Never removed on uninstall — they may hold +# the user's clones and specs. +scaffold: + - path: src/ + from: scaffold/src-README.md + as: src/README.md + note: Drop zone for source repos, one clone per subdirectory. + - path: openspec/ + from: scaffold/openspec/ + note: KB-root, cross-cutting specs spanning multiple src/ repos. + +# Appended to AGENTS.md between the module markers, removed on uninstall. +agents_fragment: fragments/agents-routing.md + +# Appended to .gitignore between the module markers, removed on uninstall. +gitignore_fragment: fragments/gitignore.snippet + +# Frontmatter this module contributes to the page schema. Additive: the base +# schema tolerates these whether or not the module is installed. +schema_additions: + types: + - repository # one src/ repo: remote, branch, language, build, owner + - component # a module/service/package inside a repo + - spec # a capability spec, KB-root or repo-level + fields: + - repo # /wiki/entities/.md this page belongs to + - commit # commit hash the page was generated from + - spec_id # OpenSpec capability id + - implements # repo-level spec -> the KB-root spec it implements + - implemented_by # KB-root spec -> repo-level specs implementing it + +# External dependency. The module reports its absence rather than substituting +# its own workflow — see wiki/decisions/0002-software-module-design.md. +depends_on: + - name: openspec + scope: src-repo-level-only + check: "command -v openspec" + optional: true + note: > + Required only for per-repo specs. The KB-root spec layer is served by + ckb-spec itself and works without the CLI. diff --git a/.agents/modules/software/scaffold/openspec/README.md b/.agents/modules/software/scaffold/openspec/README.md new file mode 100644 index 0000000..edc71b4 --- /dev/null +++ b/.agents/modules/software/scaffold/openspec/README.md @@ -0,0 +1,17 @@ +# KB-root specs + +Cross-cutting capability specs — the ones that span several `src/` repos and that +no single repo owns. Managed by the `ckb-spec` skill. + +* `specs/.md` — current truth. What the system, as a whole, does. +* `changes//` — a proposed delta, not yet true. +* `changes/archive/` — applied or rejected changes. Immutable; often worth a + matching decision record under `wiki/decisions/`. + +Specs for how *one* repo implements a capability belong in that repo, at +`src//openspec/`, where OpenSpec's own tooling manages them and they travel +with the code. Link the two with `implements:` / `implemented_by:` — both sides, +always. + +Unlike `src/`, this directory **is** tracked in the KB's git history: it is +knowledge, not code. diff --git a/.agents/modules/software/scaffold/openspec/changes/.gitadd b/.agents/modules/software/scaffold/openspec/changes/.gitadd new file mode 100644 index 0000000..e69de29 diff --git a/.agents/modules/software/scaffold/openspec/specs/.gitadd b/.agents/modules/software/scaffold/openspec/specs/.gitadd new file mode 100644 index 0000000..e69de29 diff --git a/.agents/modules/software/scaffold/src-README.md b/.agents/modules/software/scaffold/src-README.md new file mode 100644 index 0000000..cac0849 --- /dev/null +++ b/.agents/modules/software/scaffold/src-README.md @@ -0,0 +1,15 @@ +# `src/` + +Source repositories for the software this knowledge base documents. One clone +per subdirectory, each an independent git repo with its own remote. + +**Everything here except this file is gitignored.** Clones are never committed to +the KB. A fresh clone of this KB will have an empty `src/` — that is expected. + +What survives is the knowledge: every repo has a `type: repository` page under +`wiki/entities/` recording its remote, default branch, language, build command +and owner, so you can re-clone from the wiki alone. Run `ckb-code-map` after +adding a repo here to create or refresh that page. + +Per-repo specs live in `src//openspec/` and travel with that repo, not with +this KB. Cross-cutting specs live in the KB root's `openspec/`. diff --git a/.agents/modules/software/scaffold/src-gitadd b/.agents/modules/software/scaffold/src-gitadd new file mode 100644 index 0000000..e69de29 diff --git a/.agents/modules/software/skills/ckb-code-map/SKILL.md b/.agents/modules/software/skills/ckb-code-map/SKILL.md new file mode 100644 index 0000000..950b810 --- /dev/null +++ b/.agents/modules/software/skills/ckb-code-map/SKILL.md @@ -0,0 +1,174 @@ +--- +name: ckb-code-map +description: Read a source repository under src/ and write what it IS into wiki/entities/ — a `type: repository` page (remote, default branch, language, build and test commands, owner) plus `type: component` pages for its significant modules/services, cross-linked into the graph and stamped with the commit they were generated from so staleness is detectable. Use when the user says "map the code", "map src/", "refresh the code map", "index the repo", "add this repo to the wiki", or after cloning a new repo into src/. Distinct from `ckb-ingest` (which processes raw/inbox/ material and never reads code) and from reading code to answer a question (that is `ckb-retrieve` using src/ as evidence). Part of the opt-in `software` module. +--- + +# Code map skill + +## Purpose + +`src/` clones are gitignored: they are not in this KB's history and may be +absent entirely from a fresh checkout. So the *knowledge* about a repository +has to live in `wiki/`, or it doesn't survive. + +This skill produces that knowledge. It is deliberately **not** a code-to-prose +dump — a wiki page restating what any reader could get by opening the file is +pure liability, because it goes stale silently. What this skill records is what +you cannot get by reading one file: how to obtain the repo, how to build and +test it, what its pieces are, who owns it, and how those pieces connect to +entities the wiki already knows about. + +## Trigger phrases + +- "map the code" / "map `src/`" / "index the repo" +- "refresh the code map" / "the code map is stale" +- "add this repo to the wiki" / "I cloned a new repo into src" + +## Scope rule + +Reads `src/`. Writes only `wiki/`. Never writes, commits, or pushes anything +inside `src/` — those are independent repos with their own remotes. + +## How to run this skill + +### Step 0 — Confirm the module is installed and the repo exists + +Check `ckb.yaml` lists the `software` module. If `src/` is empty or the named +repo isn't there, say so and stop — don't guess which repo was meant when +several are present, ask. + +### Step 1 — Gather the facts that don't come from reading code + +From inside the repo, cheaply: + +```bash +git -C src/ remote -v +git -C src/ rev-parse --abbrev-ref HEAD +git -C src/ rev-parse --short HEAD +git -C src/ log -1 --format=%cI +git -C src/ status --short +``` + +Then read the manifest and entry docs — `README`, `package.json`, `pyproject.toml`, +`go.mod`, `Cargo.toml`, `Makefile`, CI config. Build and test commands come from +here, not from inference. + +**Do not run the build, the tests, or any script from the repo** to find out what +it does. Mapping is a read-only activity. + +### Step 2 — Identify components, and be ruthless about what counts + +A component is a part of the system a person would name in conversation: a +service, a CLI, a published package, a long-lived subsystem. A directory is not +automatically a component. **Ten honest component pages beat a hundred mirroring +the folder tree** — the second kind makes the wiki look thorough while making it +useless to search. + +If you cannot write a one-sentence `tldr` for a candidate that says what it *does* +(not where it lives), it isn't a component. Leave it out. + +### Step 3 — Consult the cascade before creating anything + +Per the cascade rule, check whether pages already exist for this repo or its +components — in `wiki/` first, then `linked/`, then `libs/`. Refreshing an +existing page is the normal case, not the exception: update it, keep its history, +and don't renumber or re-slug it just because a directory was renamed. + +### Step 4 — Write the repository page + +`wiki/entities/.md`: + +```markdown +--- +type: repository +tldr: One sentence on what this software does — not "the repo for X". +resource: https://git.example.com/me/thing +repo: thing +commit: a1b2c3d +confidence: 0.9 +quality: 0.8 +last_updated: YYYY-MM-DD +freshness_window_days: 90 +retention: high +--- + +# thing + +**Remote:** `git@git.example.com:me/thing.git` · **Default branch:** `main` +· **Local path:** `src/thing` · **Mapped at:** `a1b2c3d` (YYYY-MM-DD) + +## What it is + +Two or three sentences. What problem it solves and for whom. + +## Getting it + + git clone git@git.example.com:me/thing.git src/thing + +## Build and test + + + +## Components + +* [[thing-api]] / [thing-api](/wiki/entities/thing-api.md) — + +## Specs + +KB-root specs this repo implements, and the repo-level specs that implement them. +Written by `ckb-spec`; leave the section here even when empty. + +## Sources + +`src/thing` at `a1b2c3d`, mapped YYYY-MM-DD. README, `pyproject.toml`, CI config. +``` + +The `commit` field and the **Mapped at** line are what make this page auditable — +they let a reader and `ckb-lint` tell how far the page has drifted from the code. +Never write them from memory; take them from Step 1. + +### Step 5 — Write component pages + +Same shape, `type: component`, with `repo: ` pointing home. Keep them +thin and link upward to the repository page and sideways to whatever the wiki +already knows — a component that talks to a system with an existing entity page +should link to it rather than re-describing it. + +### Step 6 — Graph, indexes, log + +- `wiki/graph/edges.json` — `part_of` (component → repository), `depends_on` + (repo/component → an external library or a system that has a page), `owns` + (person → repo, **only** on stated ownership, never inferred from commit counts). +- `wiki/entities/index.md` — add or refresh a row per page. +- `wiki/log.md` — one entry per run, per Rule B, naming the repo and commit. + +### Step 7 — Report + +State the repo and commit mapped, pages created vs. refreshed, components +deliberately skipped and why, anything you couldn't determine (no build command +in the manifest — say so rather than inventing one), and whether the working tree +was dirty at map time (a map taken from uncommitted work is fine, but should be +labelled as such). Close with the standard reminder: on disk, not committed. + +## Edge cases + +- **Dirty working tree** — map it, but record the commit *plus* a note that + uncommitted changes were present. Don't refuse, and don't silently pretend the + tree was clean. +- **Repo with no remote** (local-only) — record `resource:` as absent and say + plainly in **Getting it** that this repo exists only locally. That's a real + finding: a gitignored, remote-less repo is one disk failure from gone. +- **Monorepo** — one repository page, components per package. Don't create a + repository page per package. +- **Several repos, user said "map the code"** — ask which, or offer to do all; + don't pick one. +- **Repo that's mostly vendored/generated code** — map what's authored here. Note + the vendored portion once, on the repository page. +- **A component page already exists as `type: concept`** from an earlier ingest — + don't create a duplicate. Update the existing page and change its type, noting + the change in the log entry. + +--- + +*Licensed under the Apache License, Version 2.0 — see [LICENSE](../../../../LICENSE) +at the repository root, or .* diff --git a/.agents/modules/software/skills/ckb-spec/SKILL.md b/.agents/modules/software/skills/ckb-spec/SKILL.md new file mode 100644 index 0000000..3aaa9ba --- /dev/null +++ b/.agents/modules/software/skills/ckb-spec/SKILL.md @@ -0,0 +1,192 @@ +--- +name: ckb-spec +description: Own the KB-root `openspec/` layer (cross-cutting capability specs spanning several src/ repos), delegate per-repo specs to OpenSpec's own installed workflow inside src//openspec/, and bridge both into wiki/ — archived change proposals become numbered decision records, current specs become `type: spec` entity pages, and the two levels link via implements/implemented_by. Use when the user says "write a spec", "propose a change", "what specs do we have", "archive this change", "sync the specs", "which spec covers X", or "wire OpenSpec into the wiki". Part of the opt-in `software` module. Distinct from `ckb-decide` (records decisions directly; this skill feeds it from archived specs) and `ckb-code-map` (records what the code IS; this skill records what it SHOULD DO). +--- + +# Spec skill + +## Purpose + +A code map says what the software *is*. A spec says what it is *supposed to do* — +and a change proposal says what should become true next. This skill owns that +axis, across two levels that deliberately differ: + +| Level | Holds | Owned by | +|---|---|---| +| `openspec/` at the KB root | Cross-cutting capabilities and contracts spanning several `src/` repos. The *what* and *why*. | **This skill.** A root `openspec/` has no code beneath it and no single repo governing it, so OpenSpec's own repo-shaped workflow doesn't serve it. | +| `src//openspec/` | How one repo implements those capabilities. The *how*. | **OpenSpec itself.** This is its native case: specs travel with the code and ride along in the repo's own PRs. | + +The split is the point, and so is the risk it creates: two places a statement can +live is two places it can diverge. The `implements` / `implemented_by` links +below exist so divergence becomes a **lint finding** rather than a silent second +source of truth. Maintaining those links is not optional bookkeeping — it is the +reason the two-level arrangement is safe. + +## Trigger phrases + +- "write a spec" / "add a capability" / "what specs do we have" / "which spec covers X" +- "propose a change" / "draft a change proposal" / "archive this change" +- "sync the specs" / "wire OpenSpec into the wiki" / "are the specs in sync" + +## Scope rule + +Writes `openspec/` at the KB root, and `wiki/`. Inside `src//` it reads +freely and writes **only** through OpenSpec's own workflow, on the user's +explicit instruction. It never commits or pushes a `src/` repo. + +## KB-root specs + +### Layout + +``` +openspec/ +├── README.md # what this layer is for +├── specs/ +│ └── .md # one capability, current truth +└── changes/ + ├── / # proposed delta, not yet true + └── archive/ # applied changes, immutable +``` + +### A KB-root capability spec + +```markdown +--- +type: spec +spec_id: billing-invoicing +tldr: One sentence stating the capability, in the present tense, as a contract. +status: active +implemented_by: /src/billing/openspec/specs/invoicing.md, /src/portal/openspec/specs/invoice-view.md +affects: /wiki/entities/billing.md +confidence: 0.9 +quality: 0.8 +last_updated: YYYY-MM-DD +freshness_window_days: 180 +retention: high +--- +``` + +Body: **Purpose** (why this capability exists), **Requirements** (each one +testable — "the system SHALL ..." beats "the system should be fast"), +**Out of scope**, **Implementations** (which repos, dual-linked), **Sources**. + +Write requirements a reader can disprove. A requirement nobody can fail is not a +requirement, and a spec full of them reads as thorough while constraining nothing. + +### Writing one + +1. Check `openspec/specs/` for an existing capability on the subject. Extend it + rather than creating a near-duplicate — two overlapping specs is the failure + this layer exists to prevent. +2. Check the cascade (`wiki/` → `linked/` → `libs/`) for what the KB already + knows about the subject, and link to it rather than restating it. +3. Write the spec, then a `type: spec` mirror page under `wiki/entities/` (or + link the spec file directly from the relevant entity page — prefer one home + plus links over two copies of the text). +4. Log it per Rule B and update `wiki/entities/index.md`. + +## Per-repo specs + +**Delegate.** If `src//openspec/` exists, follow the instructions OpenSpec +installed there — do not substitute a workflow of your own, and do not "improve" +its file format to match this KB's conventions. That repo's specs are governed by +OpenSpec upstream; divergence there breaks its tooling and its PR flow. + +### Never run `openspec init` at the KB root + +`openspec init` writes tool-integration files into `.claude/skills/` and adds +marker blocks to `AGENTS.md` / `CLAUDE.md`. At the KB root both are load-bearing: +`.claude/skills` is a symlink to `.agents/skills` (so OpenSpec's files would join +this KB's skill set), and `CLAUDE.md` is a symlink to `AGENTS.md`, the KB's own +system prompt. + +Run it **only** inside `src//`, where the repo gets its own `.claude/` and +its own `AGENTS.md`. The KB-root `openspec/` is not an OpenSpec install and never +needs `init`. If the user asks for `init` at the root, explain this and offer the +KB-root spec layer instead — don't run it and don't clean up afterwards. + +Install is `npm install -g @fission-ai/openspec@latest` (Node 20.19.0+), then +`openspec init` in the repo; `openspec update` after a CLI upgrade. See +[OPENSPEC.md](../../../../OPENSPEC.md) for the user-facing guide. + +If OpenSpec is not installed (`command -v openspec` fails, or the repo has no +`openspec/`), **say so plainly and stop** rather than improvising: + +> "This repo has no OpenSpec setup, and the `openspec` CLI isn't on PATH. Per-repo +> specs are OpenSpec's own workflow — install it and run `openspec init` in +> `src/`, and I'll take it from there. I can write this as a KB-root +> cross-cutting spec instead if it isn't repo-specific." + +That offer is genuine, not a consolation: a requirement that spans repos belongs +at the root anyway. + +## The bridge + +Three directions, all owned here. + +### 1. Archived change → decision record + +An applied-and-archived OpenSpec change is a decision that was made and acted on. +When the user archives a change (either level), offer to record it via +`ckb-decide`: the change's *why* becomes **Context** and **Rationale**, the delta +becomes **Decision**, and rejected options in the proposal become +**Alternatives considered**. + +Cite the change id and its path in the decision's `## Sources`. Do not +auto-record without asking — not every archived change is a decision worth a +permanent numbered record, and a decisions log padded with routine changes loses +the property that makes it worth reading. + +Both artifacts are append-only, which makes them a natural pair: neither is ever +rewritten when the thinking changes later. + +### 2. Spec → entity page + +Current KB-root specs surface in `wiki/entities/` as `type: spec` pages so +`ckb-retrieve` can answer "what is this supposed to do" without opening the spec +tree. Keep these thin and pointer-style: `tldr`, `spec_id`, status, links. The +spec file stays the source of truth — a full copy in `wiki/` is a second thing +to keep in sync, and it will lose. + +### 3. Level linking — the drift rule + +- A KB-root spec lists every repo-level spec implementing it in `implemented_by`. +- A repo-level spec names its parent in `implements`. +- Both become graph edges (`implements`) in `wiki/graph/edges.json`. + +Set **both sides**, every time. A one-sided link is a lint finding, exactly as a +one-sided decision supersession is. + +### Sync check + +On "sync the specs" / "are the specs in sync", report: + +1. KB-root specs with empty `implemented_by` — *specified but nobody builds it.* +2. Repo-level specs with `implements` pointing at a missing or archived root spec + — *building against something no longer true.* +3. One-sided links, either direction. +4. Root specs whose `last_updated` is older than the mapped commit of every repo + implementing them — *possible drift; verify, don't auto-fix.* + +Report all four. **Fix none of them automatically** — each is a statement about +intent, and only the user knows which side is right. `ckb-lint` runs the same +four checks as part of its sweep when this module is installed. + +## Edge cases + +- **`src/` is empty** — the KB-root layer still works. Cross-cutting specs can + precede any code; that's often the point. +- **A spec that's really a decision** ("we'll use Postgres") — that's `ckb-decide`. + A spec states a standing contract; a decision records a choice at a point in + time. If it doesn't constrain future behaviour, it isn't a spec. +- **A capability implemented by exactly one repo, forever** — it probably belongs + in that repo, not at the root. Say so; don't silently promote it. +- **OpenSpec's format changes upstream** — for per-repo specs, follow upstream. + This skill's formats govern the KB-root layer only. +- **A change proposal that was rejected** — it still archives, and it is still + worth a decision record with `status: rejected`. The reasoning is the value. + +--- + +*Licensed under the Apache License, Version 2.0 — see [LICENSE](../../../../LICENSE) +at the repository root, or .* diff --git a/.agents/skills/ckb-init/SKILL.md b/.agents/skills/ckb-init/SKILL.md index 9621be7..4bd424c 100644 --- a/.agents/skills/ckb-init/SKILL.md +++ b/.agents/skills/ckb-init/SKILL.md @@ -323,6 +323,14 @@ from Step 4, plus anything explicitly added. Then create `.claude/skills` in the target as a symlink to `../.agents/skills`, matching this repo's convention - do this once, after copying the whole set, not per-skill. +Also copy `.agents/modules/` wholesale. Modules are inert until installed, +so a new KB carries the full catalogue at zero context cost, and the user +can enable one later with `ckb-module` instead of re-deriving it. Do **not** +install any module into the new KB, and do not create a `ckb.yaml`: an +absent manifest correctly means "nothing installed". If the user has said +the new KB is for software they are building, mention the `software` module +and offer to install it after Step 11 — offer, don't assume. + ### Step 11 - Initialize the new KB's own git history (ask first) The target is now a complete KB but has no history of its own - and if the diff --git a/.agents/skills/ckb-lint/SKILL.md b/.agents/skills/ckb-lint/SKILL.md index 821ff69..c6a4833 100644 --- a/.agents/skills/ckb-lint/SKILL.md +++ b/.agents/skills/ckb-lint/SKILL.md @@ -199,6 +199,28 @@ a gap to report or fix. The script follows the same rule: it reads that file only to label each connector `access: read-only` / `access: write` in its report. +### 11 — Installed module checks + +If `ckb.yaml` lists installed modules, run whatever extra checks those +modules define, and skip this step entirely when the file is absent or +empty. Modules are optional by design: their absence is never a finding. + +For the `software` module specifically: + +- **Stale code maps** — a `type: repository` page whose `commit` is behind + the current `HEAD` of its `src/` clone. Report how far behind; suggest + `ckb-code-map`. A missing clone is **not** a finding — `src/` is + gitignored and expected to be empty on a fresh checkout. +- **Spec drift** — the four checks `ckb-spec` defines: root specs with + empty `implemented_by`, repo-level specs implementing a missing or + archived parent, one-sided `implements`/`implemented_by` links, and root + specs older than the mapped commit of every repo implementing them. +- **Remote-less repos** — a mapped repository page with no `resource:`, + meaning a gitignored clone that exists nowhere else. + +All report-only. Never auto-fix any of these: each is a statement about +intent, and only the user knows which side is correct. + ### Auto-fix vs. report Auto-fix what can be done safely and mechanically: broken links, missing diff --git a/.agents/skills/ckb-module/SKILL.md b/.agents/skills/ckb-module/SKILL.md new file mode 100644 index 0000000..f5598a4 --- /dev/null +++ b/.agents/skills/ckb-module/SKILL.md @@ -0,0 +1,164 @@ +--- +name: ckb-module +description: Install, list, or uninstall an optional Cascade KB module from .agents/modules// — 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 module", "what modules are available", "which modules are installed", "uninstall the 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//` — 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 `` module" / "add the `` module" / "enable ``" +- "what modules are available" / "which modules are installed" +- "uninstall the `` module" / "remove ``" / "disable ``" +- "make this KB handle source code" (→ offer the `software` module) + +## The manifest + +Installed modules are recorded in `ckb.yaml` at the repo root: + +```yaml +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. + +If `ckb.yaml` doesn't exist, no modules are installed; create it on first install. + +## Installing + +### Step 1 — Resolve and read the module + +Find `.agents/modules//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//skills/ .agents/skills/ +``` + +`.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: + +``` + +...fragment... + +``` + +- **`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/` for each skill the manifest lists — **but + first diff it against `.agents/modules//skills/`.** 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 .* diff --git a/.agents/skills/ckb-reset/SKILL.md b/.agents/skills/ckb-reset/SKILL.md new file mode 100644 index 0000000..5125a29 --- /dev/null +++ b/.agents/skills/ckb-reset/SKILL.md @@ -0,0 +1,198 @@ +--- +name: ckb-reset +description: DESTRUCTIVE — empty this knowledge base back to a clean template, deleting every accumulated wiki page, decision record, graph edge, log entry, workload summary and (on request) raw/outputs material, then restoring the empty scaffold that `ckb-init` would create. Use when the user says "reset the wiki", "empty the wiki", "clean this KB out", "make this a clean template", "wipe the knowledge base", or wants to turn a working KB back into a distributable template. Always inventories what would be destroyed and takes explicit confirmation before deleting anything. Never touches the template layer (AGENTS.md, skills, modules, docs) or `src/`. +--- + +# Reset skill + +## Purpose + +A KB that also serves as the template for other KBs accumulates content that +shouldn't ship with it — decisions made about this project, workload summaries, +entity pages, graph edges. This skill returns it to the shape `ckb-init` creates: +same structure, same schema, no knowledge. + +It is the only skill in this KB that deletes knowledge on purpose. Everything +below is written on the assumption that **getting this wrong destroys work that +took a long time to accumulate**, and that "the user asked for it" is not enough +on its own — people ask for this in the wrong repo. + +## Trigger phrases + +- "reset the wiki" / "empty the wiki" / "wipe the knowledge base" +- "clean this KB out" / "make this a clean template" +- "turn this back into a template" / "strip the content but keep the structure" + +## Non-negotiable safety rules + +1. **Never delete without an inventory shown first and an explicit confirmation + after it.** Not "proceed?" before you know the scale — the count is the thing + that makes the answer meaningful. +2. **Never touch the template layer.** `AGENTS.md`, `CLAUDE.md`, `.agents/`, + `.claude/`, `LICENSE`, `VERSION`, `README*`, `MANUAL*`, `OPENSPEC*`, + `.gitignore`, `ckb.yaml`, `.git/`. Those *are* the template. +3. **Never touch `src/`.** Those are independent repositories holding code this + skill has no business deleting. Not even with confirmation — tell the user to + delete them with `rm -rf` themselves if that's really what they want. +4. **Never run when the working tree is dirty**, unless the user overrides after + being told why. Uncommitted work is unrecoverable once deleted; committed work + is always recoverable from git. +5. **Never guess the scope.** If the user says "reset" without saying how far, + ask — don't assume the widest or the narrowest reading. + +## How to run this skill + +### Step 0 — Establish that git can undo this + +Run `git status --short` and `git log --oneline -1`. + +- **Dirty tree** — stop and report exactly what's uncommitted. Offer to commit + first ("Let me commit this as a restore point, then reset"), and only proceed + without committing if the user explicitly says the uncommitted work is + disposable. This is the single highest-value check in the skill: after a reset, + committed content is a `git checkout` away and uncommitted content is gone. +- **Not a git repository at all** — say so plainly and require a much more + explicit confirmation, because nothing here is recoverable. Recommend the user + copy the folder somewhere safe first. +- **Clean tree** — note the commit hash and tell the user it's the restore point. + Offer to tag it (`git tag pre-reset-`), since a hash in a chat log is + easy to lose. + +### Step 1 — Agree the scope + +Present the tiers and let the user choose. Default to **Tier 1 only** if they +just said "reset the wiki" — the narrowest reading that satisfies the request. + +| Tier | Contents | Default | +|---|---|---| +| **1 — Wiki knowledge** | Every page under `wiki/entities/`, `wiki/projects/`, `wiki/decisions/` (the `NNNN-*.md` records), `wiki/graph/edges.json` entries, and all log/overview/query-gap/error-book *entries* | **Yes** | +| **2 — Workload history** | Every `workload/*_summary.md` | Ask | +| **3 — Source material** | `raw/inbox/*`, `raw/archive/*` | Ask — this is the user's original material and may exist nowhere else | +| **4 — Generated artifacts** | `outputs/*` | Ask — cheap to regenerate, usually safe | +| **5 — External sources** | `libs/*`, `linked/*` | Ask — **default no.** `linked/` holds symlinks to *other people's* KBs, and deleting a symlink target by accident is a real risk | +| **6 — Installed modules** | `ckb.yaml` + module-installed skills + the marked blocks in `AGENTS.md`/`.gitignore` | Ask — **default no.** That's `ckb-module uninstall`'s job, not this skill's | + +For a template being prepared for distribution, tiers 1–4 are the usual answer. + +**Say what each tier means in files, not just in names.** "Tier 3 deletes 48 +files in `raw/archive/` including the original meeting recordings" is a sentence +that changes answers. + +### Step 2 — Build and show the inventory + +Count, don't estimate. For the chosen tiers: + +```bash +find wiki/entities wiki/projects -name '*.md' ! -name 'index.md' | wc -l +ls wiki/decisions/[0-9]*.md 2>/dev/null | wc -l +python3 -c "import json;print(len(json.load(open('wiki/graph/edges.json'))['edges']))" +ls workload/*_summary.md 2>/dev/null | wc -l +find raw/inbox raw/archive -type f 2>/dev/null | wc -l +``` + +Present it as a table: what, how many, and — for anything irreplaceable — where +it came from. Call out explicitly: + +- **Decision records**, by number and title. These are append-only by design and + represent reasoning that cannot be reconstructed; losing them is the most + expensive part of any reset. +- **`raw/archive/` material with no upstream**, if tier 3 is selected. +- **Anything with `retention: high`** in its frontmatter — the wiki's own signal + that it was meant to be kept. + +Then state what will *survive*, in one line. That's as reassuring as the deletion +list is alarming, and it's what tells the user whether you understood the task. + +### Step 3 — Take the confirmation + +Ask for a typed phrase, not a yes: + +> This will permanently delete **47 wiki pages, 12 decision records, 9 workload +> summaries and 128 graph edges**. Restore point: `491ca8a` (clean tree). +> Type **`reset the wiki`** to proceed, or anything else to cancel. + +Accept only that phrase. A "yes", a "go ahead", or silence is **not** consent +here — the typed phrase exists precisely so the action can't be taken by reflex +or by an agent misreading agreement to something else in the conversation. + +If the user modifies the scope in their reply, go back to Step 2 and re-inventory. +Never carry a confirmation across a scope change: they confirmed a number, and +the number moved. + +### Step 4 — Delete, then restore the scaffold + +Delete the agreed tiers. Then restore the empty scaffold **exactly as `ckb-init` +Step 8 defines it** — that skill is the single source of truth for what a clean +`wiki/` looks like, so read it rather than reconstructing the files from memory: + +- `wiki/index.md` — routing table, infrastructure rows only, no entity rows. + **Keep `kb_schema_version` at its current value.** A reset empties content; it + does not roll back the schema contract. +- `wiki/overview.md` — the generic version, `last_updated` today. +- `wiki/log.md`, `wiki/decisions/log.md` — headers and explanation, no entries. +- `wiki/error-book.md`, `wiki/query-gaps.md` — headers, no entries. +- `wiki/entities/index.md`, `wiki/projects/index.md`, `wiki/graph/index.md` — + headers plus placeholder notes. +- `wiki/decisions/index.md` — header, placeholder, and the status-vocabulary + table **verbatim** (`ckb-decide` and `ckb-lint` both validate against it). +- `wiki/graph/edges.json` — `{"version": 1, "last_updated": "", "edges": []}`. +- `.gitadd` placeholder files in any directory that would otherwise be empty, so + the structure survives in git. + +Preserve directories even when empty. A reset KB must have the same shape as a +fresh one, or the next ingest starts by rebuilding scaffolding. + +### Step 5 — Verify before reporting success + +Do not report completion until you've checked it: + +```bash +ls wiki/entities/ wiki/decisions/ wiki/projects/ +python3 .agents/skills/ckb-lint/scripts/lint_report.py +git status --short +``` + +Lint should come back clean on a fresh scaffold. If it doesn't, the scaffold is +wrong — say so and fix it rather than declaring done. A reset that leaves a +malformed wiki is worse than no reset, because the damage is already unrecoverable +and now the structure is broken too. + +### Step 6 — Report + +State: tiers reset, counts deleted per tier, scaffold files restored, the restore +point hash (and tag, if one was made), lint result, and what was deliberately left +alone (`src/`, modules, template layer). + +**Do not append a workload summary.** Rule D's session note would be the first +entry in a workload directory this skill just emptied, which defeats the purpose. +Say so in the report instead — this is a deliberate, one-off exception to Rule D, +and worth naming so it doesn't read as an oversight. + +Finish with: the reset is on disk but not committed. `git checkout .` still undoes +everything until it is. That sentence is the last safety net, so don't omit it. + +## Edge cases + +- **Already clean** — say so and change nothing. Don't rewrite identical scaffold + files to look busy. +- **Run in a KB that is not a template** — this skill can't tell the difference, + so if the wiki holds substantial content (say, 50+ pages or any decision + records), name that in the confirmation: "This KB has 12 decision records — + templates don't usually have those. Are you in the right repository?" Ask once; + don't refuse if they confirm. +- **`linked/` symlinks** — never follow them when deleting. `rm -rf linked/foo` + where `foo` is a symlink to another KB is catastrophic and silent. Remove the + *link*, never its target, and prefer leaving tier 5 alone. +- **Partial failure mid-delete** — stop, report exactly what was and wasn't + deleted, and point at the restore point. Don't continue on the theory that + finishing is tidier. +- **User asks to reset "everything including the skills"** — that's not a reset, + it's deleting the KB. Say so and point at `ckb-init` for a fresh one elsewhere. +- **Module installed** — module-created page types (`repository`, `component`, + `spec`) are wiki content and reset with tier 1. The module itself stays + installed unless tier 6 was chosen. + +--- + +*Licensed under the Apache License, Version 2.0 — see [LICENSE](../../../LICENSE) +at the repository root, or .* diff --git a/.agents/skills/ckb-sync-changes/SKILL.md b/.agents/skills/ckb-sync-changes/SKILL.md index 9e8dfcd..6d09de3 100644 --- a/.agents/skills/ckb-sync-changes/SKILL.md +++ b/.agents/skills/ckb-sync-changes/SKILL.md @@ -63,6 +63,23 @@ ask the user via `AskUserQuestion` whether to include or skip each one *before* staging anything in Step 3 — never silently commit or silently drop a flagged file. +### Step 1b — Nested source repos (`software` module only) + +If `ckb.yaml` lists the `software` module and `src/` holds clones, those are +**independent repositories with their own remotes**. This skill syncs *this* +repo only. + +- Never `git add` anything under `src/`, and never `git commit`, `git push`, + or `git checkout` inside one. They are gitignored; if `git status` shows + something there, treat it as a `.gitignore` defect to report, not content + to stage. +- Do report each clone's state — current branch, dirty or clean, ahead or + behind its own remote — so uncommitted work isn't silently forgotten while + the KB itself gets pushed. Reporting is the whole contribution here; + acting on it is the user's call, in that repo. + +Skip this step entirely when the module isn't installed or `src/` is empty. + ### Step 2 — Ensure `origin` is configured ```bash diff --git a/.agents/skills/ckb-upgrade/SKILL.md b/.agents/skills/ckb-upgrade/SKILL.md index b7466f0..e83ad8a 100644 --- a/.agents/skills/ckb-upgrade/SKILL.md +++ b/.agents/skills/ckb-upgrade/SKILL.md @@ -153,6 +153,13 @@ The template layer is exactly these paths — never anything under `wiki/`, exist upstream (an older local KB may not have some of these yet) - `.agents/skills//**` for every skill folder present in `tmp/ckb-upgrade-src/.agents/skills/` +- `.agents/modules//**` for every optional module present upstream + (see `ckb-module`). Upgrade the module *payload* freely — it is inert + template content. But **never delete a skill under `.agents/skills/` + just because it is absent upstream**: it may be a module-installed copy + that this KB deliberately enabled. Check `ckb.yaml` before treating any + skill as removed upstream. When an installed module's payload changes, + say so and suggest reinstalling it — the installed copies are now stale. - The base ignore rules in `.gitignore` (`libs/`, `linked/`, `tmp/`, regenerated `outputs/` subfolders, `.env`, etc.) — merged, never replaced wholesale (see Step 6) diff --git a/AGENTS.md b/AGENTS.md index 1f411d3..a265b10 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,6 +14,7 @@ should be loaded only when their trigger applies. Maintain this root layout: ``` +├── .agents/modules/ # Optional modules, inert until installed ├── libs/ # Read-only external sources: │ └── / # - git-copy clone/ZIP: immutable, never write here │ # - connector source: has user-authored source.yaml @@ -38,6 +39,17 @@ Maintain this root layout: └── YYYY-MM-DD_summary.md ``` +### Optional Modules +Capabilities not every KB needs ship in `.agents/modules//` and are +inert until installed. Installing copies the module's skills into +`.agents/skills/`, creates its scaffold, appends a marked block to this +file and `.gitignore`, and records it in the root `ckb.yaml`. `ckb-module` +owns that; read `ckb.yaml` to see what is installed. A module may add +directories (such as `src/`) and optional page types — always additively. + +`CLAUDE.md` is a symlink to this file and `.claude/skills` a symlink to +`.agents/skills`. Write the `.agents`-side path only; never duplicate. + ### Cascade Priority When searching for any entity, concept, or file, use first match wins: @@ -94,9 +106,11 @@ append-only: never rewrite a decision's substance to match a later change of mind — record a new decision that supersedes it, and set both `supersedes` and `superseded_by`. `ckb-decide` owns the format. -`wiki/index.md` alone also carries `kb_schema_version`, currently `"1.4"`. -Detailed schema migration and version-bump policy belongs in -`ckb-upgrade`. +`wiki/index.md` alone also carries `kb_schema_version`, currently `"1.4"` +for the base contract. An installed module may raise it additively by +declaring `requires_kb_schema` and contributing optional types and fields; +`ckb-module` applies that bump at install time. Detailed schema migration +and version-bump policy belongs in `ckb-upgrade`. --- @@ -114,6 +128,8 @@ file. | Sync this repo with `origin` | `ckb-sync-changes` | | Upgrade template or wiki schema | `ckb-upgrade` | | Bootstrap a new empty KB (from local files or a fresh clone of the template repo) | `ckb-init` | +| Install, list, or uninstall an optional module | `ckb-module` | +| Empty the wiki back to a clean template (destructive) | `ckb-reset` | | Export OKF or Starlight artifacts | `ckb-export-okf`, `ckb-export-starlight` | | Generate a project overview | `ckb-project-summary` | | Teach, quiz, or onboard from the wiki | `ckb-teach-me`, `ckb-quiz`, `ckb-onboard-me` | @@ -136,6 +152,13 @@ Short routing rules: use `ckb-sync-changes`, not ingest. - For "upgrade the wiki" or "check for a newer template version", use `ckb-upgrade`. +- For "install/uninstall the `` module", "what modules are + available", or a request for a capability the base KB lacks (such as + handling source code), use `ckb-module`. +- For "reset the wiki", "empty the wiki", or "make this a clean template", + use `ckb-reset`. It deletes accumulated knowledge, so it always shows an + inventory and takes a typed confirmation first, and never touches the + template layer or `src/`. --- diff --git a/MANUAL.md b/MANUAL.md index df857cf..dfad0f3 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -284,6 +284,52 @@ safely can on its own, and reports the rest for you to decide. Like Ingest, it f Implemented by the `ckb-lint` skill — `.agents/skills/ckb-lint/SKILL.md`. +### Starting over: resetting to a clean template + +Sometimes you want the *shape* of a knowledge base without its contents — +typically because this repo doubles as the template you hand to other +people, and it has accumulated decisions, workload summaries and entity +pages that shouldn't ship with it. + +> "Reset the wiki." / "Make this a clean template." + +This is the one command in this repo that **deletes knowledge on purpose**, +so it is built to be hard to trigger by accident: + +1. **It looks for a restore point first.** If your working tree is dirty it + stops and offers to commit, because after a reset anything committed is a + `git checkout` away and anything uncommitted is simply gone. It can also + tag the commit (`pre-reset-`) so you don't have to keep a hash in + your head. +2. **It asks how far to go.** Six tiers, chosen individually: wiki knowledge, + workload history, `raw/` source material, `outputs/`, external sources, + and installed modules. Only the first is on by default. `libs/`, + `linked/` and modules default to *no* — `linked/` holds symlinks into + other people's knowledge bases, and it will remove a link but never + follow one. +3. **It counts before it asks.** You get an inventory — how many pages, how + many decision records (listed by number and title), how many graph edges, + plus anything marked `retention: high` — and one line on what survives. +4. **It wants a typed phrase**, not a "yes". And if you change the scope in + your reply, it re-counts and asks again, because you agreed to a number + and the number moved. +5. **It verifies afterwards**, running lint before telling you it worked. + +What it restores is exactly what `ckb-init` would create: same directories, +same scaffold files, same `kb_schema_version`. Emptying the content doesn't +roll back the schema. + +What it never touches, with or without confirmation: the template layer +(`AGENTS.md`, `.agents/`, `LICENSE`, `VERSION`, the docs) and `src/`, which +holds independent code repositories this command has no business deleting. + +One deliberate quirk: unlike every other skill, this one does **not** write a +`workload/` session note — that entry would be the first thing in a directory +it has just emptied. It tells you so in its report. + +Implemented by the `ckb-reset` skill — +`.agents/skills/ckb-reset/SKILL.md`. + --- ## 4. Syncing — with yourself, and with other people @@ -677,6 +723,7 @@ graph stay in sync with what you changed. | "Record a decision: ..." / "we decided ..." | Writes a numbered decision record under `wiki/decisions/` | `ckb-decide` | | "What did we decide about X" / "who decided X" / "what's still open" | Answers from the decision records, with who/when/status attached | `ckb-decide` | | "Lint" | Health-checks the wiki, auto-fixes what it safely can | `ckb-lint` | +| "Reset the wiki" / "Make this a clean template" | **Destructive.** Deletes accumulated knowledge and restores the empty scaffold, after an inventory and a typed confirmation | `ckb-reset` | | "Sync changes" / "Sync with git" | Commits, pulls, resolves conflicts, pushes to `origin` | `ckb-sync-changes` | | "Quiz me on X" | One-off scored knowledge test | `ckb-quiz` | | "Teach me the wiki" / "Teach me about X" | Plans and runs a spaced-out course with progress tracking | `ckb-teach-me` | diff --git a/MANUAL.pl.md b/MANUAL.pl.md index 96af378..2e13c6b 100644 --- a/MANUAL.pl.md +++ b/MANUAL.pl.md @@ -296,6 +296,55 @@ zrobić bezpiecznie, a resztę zgłasza do twojej decyzji. Podobnie jak Ingest, synchronizacji. Zaimplementowane przez skill `ckb-lint` — `.agents/skills/ckb-lint/SKILL.md`. +### Zaczynanie od zera: reset do czystego szablonu + +Czasem chcesz zachować *kształt* bazy wiedzy bez jej zawartości — zwykle +dlatego, że to repozytorium pełni też rolę szablonu przekazywanego innym, a +zdążyło zebrać decyzje, podsumowania sesji i strony encji, które nie powinny +z nim wędrować. + +> „Zresetuj wiki.” / „Zrób z tego czysty szablon.” + +To jedyne polecenie w tym repozytorium, które **celowo usuwa wiedzę**, więc +jest zbudowane tak, żeby trudno było je uruchomić przez przypadek: + +1. **Najpierw szuka punktu przywracania.** Jeśli drzewo robocze jest + „brudne”, zatrzymuje się i proponuje commit — po resecie wszystko, co + zacommitowane, jest o jedno `git checkout` stąd, a wszystko + niezacommitowane po prostu znika. Może też otagować commit + (`pre-reset-`), żebyś nie musiał trzymać hasha w głowie. +2. **Pyta, jak daleko sięgnąć.** Sześć poziomów wybieranych osobno: wiedza w + wiki, historia `workload/`, materiał źródłowy w `raw/`, `outputs/`, + źródła zewnętrzne i zainstalowane moduły. Domyślnie włączony jest tylko + pierwszy. `libs/`, `linked/` i moduły domyślnie na *nie* — `linked/` + zawiera dowiązania do cudzych baz wiedzy, więc usuwa dowiązanie, ale + nigdy nie podąża za nim. +3. **Liczy, zanim zapyta.** Dostajesz inwentarz — ile stron, ile rekordów + decyzji (wymienionych z numerem i tytułem), ile krawędzi grafu, plus + wszystko oznaczone `retention: high` — i jedną linijkę o tym, co + przetrwa. +4. **Wymaga wpisania frazy**, nie „tak”. A jeśli w odpowiedzi zmienisz + zakres, przeliczy wszystko i zapyta ponownie, bo zgodziłeś się na + konkretną liczbę, a liczba się zmieniła. +5. **Weryfikuje po wszystkim**, uruchamiając lint, zanim powie, że się + udało. + +Odtwarza dokładnie to, co utworzyłby `ckb-init`: te same katalogi, te same +pliki szkieletu, ten sam `kb_schema_version`. Opróżnienie treści nie cofa +wersji schematu. + +Czego nie rusza nigdy, z potwierdzeniem czy bez: warstwy szablonu +(`AGENTS.md`, `.agents/`, `LICENSE`, `VERSION`, dokumentacja) oraz `src/`, +gdzie leżą niezależne repozytoria kodu, do których usuwania to polecenie nie +ma żadnego tytułu. + +Jedna celowa osobliwość: w odróżnieniu od każdego innego skilla ten **nie** +zapisuje notatki sesji w `workload/` — byłby to pierwszy wpis w katalogu, +który właśnie opróżnił. Informuje o tym w raporcie. + +Zaimplementowane przez skill `ckb-reset` — +`.agents/skills/ckb-reset/SKILL.md`. + --- ## 4. Synchronizacja — z samym sobą i z innymi ludźmi @@ -711,6 +760,7 @@ zmieniłeś. | „Zapisz decyzję: ...” / „zdecydowaliśmy ...” | Zapisuje numerowany rekord decyzji pod `wiki/decisions/` | `ckb-decide` | | „Co zdecydowaliśmy w sprawie X” / „kto zdecydował X” / „co jest otwarte” | Odpowiada z zapisów decyzji, z autorem, datą i statusem | `ckb-decide` | | „Lint” | Sprawdza kondycję wiki, automatycznie naprawia to, co bezpiecznie może | `ckb-lint` | +| „Zresetuj wiki” / „Zrób z tego czysty szablon” | **Destrukcyjne.** Usuwa zgromadzoną wiedzę i odtwarza pusty szkielet, po inwentarzu i potwierdzeniu wpisaną frazą | `ckb-reset` | | „Sync changes” / „Sync with git” | Commituje, pobiera, rozwiązuje konflikty, wypycha do `origin` | `ckb-sync-changes` | | „Quiz me on X” | Jednorazowy, punktowany sprawdzian wiedzy | `ckb-quiz` | | „Teach me the wiki” / „Teach me about X” | Planuje i prowadzi rozłożony w czasie kurs ze śledzeniem postępu | `ckb-teach-me` | diff --git a/OPENSPEC.md b/OPENSPEC.md new file mode 100644 index 0000000..db9ac04 --- /dev/null +++ b/OPENSPEC.md @@ -0,0 +1,202 @@ +# OpenSpec in this knowledge base + +*Read this in: **English** | [Polski](OPENSPEC.pl.md)* + +How to add [OpenSpec](https://openspec.dev) to a Cascade KB that documents +software you're building, and how it fits alongside the wiki. + +This is a human guide. The agent's own rules live in the `software` module — +[.agents/modules/software/](.agents/modules/software/README.md) — which must be +installed before any of this applies. Say **"install the software module"**. + +--- + +## Contents + +1. [What OpenSpec is for here](#1-what-openspec-is-for-here) +2. [Read this before you run `openspec init`](#2-read-this-before-you-run-openspec-init) +3. [Installing](#3-installing) +4. [The two spec levels](#4-the-two-spec-levels) +5. [Daily workflow](#5-daily-workflow) +6. [How specs reach the wiki](#6-how-specs-reach-the-wiki) +7. [Keeping the levels honest](#7-keeping-the-levels-honest) +8. [Quick reference](#8-quick-reference) + +--- + +## 1. What OpenSpec is for here + +The wiki records three different things about software, and it's worth keeping +them apart: + +| Question | Where it lives | Who writes it | +|---|---|---| +| What *is* the code? | `wiki/entities/` — `repository` and `component` pages | `ckb-code-map` | +| What *should* it do? | `openspec/specs/` | `ckb-spec` + OpenSpec | +| What did we *choose*, and why? | `wiki/decisions/` | `ckb-decide` | + +OpenSpec owns the middle row: a spec states a standing contract, and a change +proposal states what should become true next. You write the spec before the +code, the agent implements against it, and the archived change becomes part of +the permanent record. + +If something doesn't constrain future behaviour, it isn't a spec — it's a +decision. Say "record a decision" instead. + +## 2. Read this before you run `openspec init` + +**Never run `openspec init` in the knowledge base root.** Run it inside +`src//`. + +This isn't stylistic caution. `openspec init` writes tool integration files into +`.claude/skills/`, and it adds marker blocks to `AGENTS.md` / `CLAUDE.md`. In +this repository both of those are load-bearing: + +- `.claude/skills` is a **symlink** to `.agents/skills`. Anything OpenSpec writes + there lands in your KB's own skill set. +- `CLAUDE.md` is a **symlink** to `AGENTS.md` — the KB's system prompt. They are + one file, so a marker block written to "both" is written twice to the same + place. + +Run it at the root and you get OpenSpec's per-repo workflow instructions mixed +into the rules governing your whole knowledge base. Run it in `src//` and +everything stays where it belongs: the repo gets its own `.claude/`, its own +`AGENTS.md`, and its specs travel with its code. + +The KB root's `openspec/` directory is **not** an OpenSpec install (§4), so it +never needs `init`. + +## 3. Installing + +Needs **Node.js 20.19.0+**. + +```bash +npm install -g @fission-ai/openspec@latest # or pnpm / yarn / bun +openspec --version +``` + +Then, per repository: + +```bash +cd src/ +openspec init +``` + +After upgrading the CLI later, run `openspec update` in each repo to refresh its +generated instruction files. + +**Uninstalling from a repo** means removing its `openspec/` directory, its +generated tool files, and the OpenSpec marker blocks from that repo's +`AGENTS.md` / `CLAUDE.md` by hand — the CLI doesn't unwind those for you. + +## 4. The two spec levels + +Specs live in two places on purpose. + +**KB root — `openspec/`** — cross-cutting capabilities that span several `src/` +repos. The *what* and *why* that no single repo owns. + +This layer is managed by the `ckb-spec` skill, **not** by the OpenSpec CLI. +There's no code beneath it and no repo for it to govern, so OpenSpec's +repo-shaped workflow doesn't apply. It's tracked in the KB's git history, like +every other piece of knowledge here. + +**Per repo — `src//openspec/`** — how that repo implements those +capabilities. The *how*. This is OpenSpec's native case: managed by the CLI and +its own instructions, travelling with the code and riding along in that repo's +pull requests. + +The agent defers to OpenSpec here and won't substitute a workflow of its own. If +the CLI isn't installed it says so rather than improvising. + +## 5. Daily workflow + +From inside a repo that's been initialized, the loop is +**propose → apply → archive**: + +| Step | Say / run | What happens | +|---|---|---| +| Propose | `/opsx:propose ` | Proposal, spec delta, design and tasks written as Markdown under `openspec/changes//` | +| Review | `openspec show `, `openspec validate ` | Read the delta; validation checks structure and checks modified requirements against the specs they'd replace | +| Apply | `/opsx:apply` | The agent implements against the spec | +| Archive | `/opsx:archive` or `openspec archive ` | The change merges into the main specs and moves to `changes/archive/` | + +Useful alongside: `openspec list`, `openspec status`, `openspec view` (an +interactive dashboard). + +For the KB-root layer there's no CLI — just say **"write a cross-cutting spec +for X"** and `ckb-spec` handles it. + +## 6. How specs reach the wiki + +Three bridges, all handled by `ckb-spec`. This is what stops OpenSpec from being +a parallel universe next to your knowledge base. + +**Archived change → decision record.** An applied-and-archived change is a +decision that was made and acted on. The agent *offers* to record it under +`wiki/decisions/` — the proposal's reasoning becomes Context and Rationale, the +delta becomes the Decision, rejected options become Alternatives considered. + +It offers rather than doing it automatically, deliberately. Not every routine +change deserves a permanent numbered record, and a decisions log padded with +them stops being worth reading. + +**Spec → entity page.** Current KB-root specs surface in `wiki/entities/` as thin +`type: spec` pages, so questions like "what is this supposed to do?" get answered +from the index without opening the spec tree. The spec file stays the source of +truth — the wiki page is a pointer, not a copy. + +**Level → level.** Root specs and repo specs link to each other (§7). + +## 7. Keeping the levels honest + +Two spec levels means two places a statement can live, and therefore two places +it can quietly diverge. One rule prevents that: + +> A root spec lists every repo spec implementing it in `implemented_by:`. +> A repo spec names its parent in `implements:`. +> **Always set both sides.** + +Those links become graph edges, which turns divergence into a visible finding +rather than a silent second source of truth. + +Say **"sync the specs"** (or run `lint`) and you get four checks: + +1. Root specs with no implementer — *specified, but nobody's building it.* +2. Repo specs whose parent is missing or archived — *building against something + that's no longer true.* +3. One-sided links, either direction. +4. Root specs older than the mapped commit of every repo implementing them — + *possible drift, worth a look.* + +None of these are auto-fixed. Each is a statement about intent, and only you know +which side is right. + +## 8. Quick reference + +| You want to | Say / run | +|---|---| +| Enable all of this | "install the software module" | +| Add OpenSpec to a repo | `cd src/ && openspec init` | +| Map a repo into the wiki | "map `src/`" | +| Write a cross-cutting spec | "write a cross-cutting spec for X" | +| Propose a change in a repo | `/opsx:propose ` | +| Check spec health | "sync the specs" | +| Turn an archived change into a decision | "record this change as a decision" | + +**Never:** run `openspec init` at the KB root · `git add` anything under `src/` · +edit a repo's OpenSpec files to match this KB's conventions. + +--- + +## Sources + +- [OpenSpec documentation](https://openspec.dev/docs/installation) · + [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec) · + [@fission-ai/openspec on npm](https://www.npmjs.com/package/@fission-ai/openspec) +- Design records: [D-0001](wiki/decisions/0001-opt-in-file-based-kb-modules.md), + [D-0002](wiki/decisions/0002-software-module-design.md) + +--- + +*Licensed under the Apache License, Version 2.0 — see [LICENSE](LICENSE).* diff --git a/OPENSPEC.pl.md b/OPENSPEC.pl.md new file mode 100644 index 0000000..69434d9 --- /dev/null +++ b/OPENSPEC.pl.md @@ -0,0 +1,209 @@ +# OpenSpec w tej bazie wiedzy + +*Read this in: [English](OPENSPEC.md) | **Polski*** + +Jak dodać [OpenSpec](https://openspec.dev) do Cascade KB, które dokumentuje +tworzone przez Ciebie oprogramowanie, i jak to współgra z wiki. + +To przewodnik dla człowieka. Zasady dla samego agenta są w module `software` — +[.agents/modules/software/](.agents/modules/software/README.md) — który musi być +zainstalowany, zanim cokolwiek z poniższych zacznie obowiązywać. Powiedz: +**„zainstaluj moduł software”**. + +--- + +## Spis treści + +1. [Po co tu OpenSpec](#1-po-co-tu-openspec) +2. [Przeczytaj to, zanim uruchomisz `openspec init`](#2-przeczytaj-to-zanim-uruchomisz-openspec-init) +3. [Instalacja](#3-instalacja) +4. [Dwa poziomy specyfikacji](#4-dwa-poziomy-specyfikacji) +5. [Codzienna praca](#5-codzienna-praca) +6. [Jak specyfikacje trafiają do wiki](#6-jak-specyfikacje-trafiają-do-wiki) +7. [Pilnowanie spójności poziomów](#7-pilnowanie-spójności-poziomów) +8. [Szybki przegląd](#8-szybki-przegląd) + +--- + +## 1. Po co tu OpenSpec + +Wiki zapisuje o oprogramowaniu trzy różne rzeczy i warto trzymać je osobno: + +| Pytanie | Gdzie mieszka | Kto zapisuje | +|---|---|---| +| Czym *jest* kod? | `wiki/entities/` — strony `repository` i `component` | `ckb-code-map` | +| Co *powinien* robić? | `openspec/specs/` | `ckb-spec` + OpenSpec | +| Co *wybraliśmy* i dlaczego? | `wiki/decisions/` | `ckb-decide` | + +OpenSpec odpowiada za środkowy wiersz: specyfikacja opisuje obowiązujący +kontrakt, a propozycja zmiany — co ma stać się prawdą w następnej kolejności. +Piszesz specyfikację przed kodem, agent implementuje pod nią, a zarchiwizowana +zmiana staje się częścią trwałego zapisu. + +Jeśli coś nie ogranicza przyszłego zachowania, to nie jest specyfikacja, tylko +decyzja. Powiedz wtedy „zapisz decyzję”. + +## 2. Przeczytaj to, zanim uruchomisz `openspec init` + +**Nigdy nie uruchamiaj `openspec init` w katalogu głównym bazy wiedzy.** +Uruchamiaj go w `src//`. + +To nie jest ostrożność na wszelki wypadek. `openspec init` zapisuje pliki +integracji z narzędziami w `.claude/skills/` oraz dodaje bloki znacznikowe do +`AGENTS.md` / `CLAUDE.md`. W tym repozytorium oba te miejsca są nośne: + +- `.claude/skills` to **dowiązanie symboliczne** do `.agents/skills`. Cokolwiek + OpenSpec tam zapisze, ląduje w zestawie skilli Twojej bazy wiedzy. +- `CLAUDE.md` to **dowiązanie symboliczne** do `AGENTS.md` — systemowego prompta + bazy. To jeden i ten sam plik, więc blok zapisany „do obu” zapisuje się + dwukrotnie w to samo miejsce. + +Uruchomienie w katalogu głównym wmiesza instrukcje OpenSpec dla pojedynczego +repozytorium w reguły rządzące całą bazą wiedzy. Uruchomienie w `src//` +zostawia wszystko na swoim miejscu: repozytorium dostaje własne `.claude/`, +własny `AGENTS.md`, a jego specyfikacje podróżują razem z kodem. + +Katalog `openspec/` w korzeniu bazy **nie jest** instalacją OpenSpec (§4), więc +nigdy nie wymaga `init`. + +## 3. Instalacja + +Wymaga **Node.js 20.19.0 lub nowszego**. + +```bash +npm install -g @fission-ai/openspec@latest # albo pnpm / yarn / bun +openspec --version +``` + +Następnie, dla każdego repozytorium: + +```bash +cd src/ +openspec init +``` + +Po późniejszej aktualizacji CLI uruchom w każdym repozytorium `openspec update`, +żeby odświeżyć wygenerowane pliki instrukcji. + +**Odinstalowanie z repozytorium** oznacza ręczne usunięcie katalogu `openspec/`, +wygenerowanych plików narzędziowych oraz bloków znacznikowych OpenSpec z +`AGENTS.md` / `CLAUDE.md` tego repozytorium — CLI tego za Ciebie nie cofa. + +## 4. Dwa poziomy specyfikacji + +Specyfikacje mieszkają w dwóch miejscach i jest to zamierzone. + +**Korzeń bazy — `openspec/`** — przekrojowe zdolności obejmujące kilka +repozytoriów w `src/`. To *co* i *dlaczego*, którego nie posiada żadne pojedyncze +repozytorium. + +Tą warstwą zarządza skill `ckb-spec`, a **nie** CLI OpenSpec. Nie ma pod nią +kodu ani repozytorium, którym miałaby rządzić, więc workflow OpenSpec — skrojony +pod repozytorium — tu nie pasuje. Warstwa ta jest śledzona w historii gita bazy, +tak jak każda inna wiedza. + +**Per repozytorium — `src//openspec/`** — jak to repozytorium realizuje te +zdolności. To *jak*. Rodzimy przypadek OpenSpec: zarządzany przez CLI i jego +własne instrukcje, podróżujący z kodem i biorący udział w pull requestach tego +repozytorium. + +Agent oddaje tu pole OpenSpec i nie podstawia własnego workflow. Jeśli CLI nie +jest zainstalowane, powie to wprost, zamiast improwizować. + +## 5. Codzienna praca + +W zainicjalizowanym repozytorium pętla wygląda tak: +**propose → apply → archive**. + +| Krok | Powiedz / uruchom | Co się dzieje | +|---|---|---| +| Propozycja | `/opsx:propose ` | Propozycja, delta specyfikacji, projekt i zadania zapisane jako Markdown w `openspec/changes//` | +| Przegląd | `openspec show `, `openspec validate ` | Czytasz deltę; walidacja sprawdza strukturę oraz zmodyfikowane wymagania wobec specyfikacji, które mają zastąpić | +| Wdrożenie | `/opsx:apply` | Agent implementuje pod specyfikację | +| Archiwizacja | `/opsx:archive` lub `openspec archive ` | Zmiana scala się z główną specyfikacją i trafia do `changes/archive/` | + +Przydatne obok: `openspec list`, `openspec status`, `openspec view` +(interaktywny pulpit). + +Dla warstwy w korzeniu bazy nie ma CLI — po prostu powiedz **„napisz przekrojową +specyfikację dla X”**, a zajmie się tym `ckb-spec`. + +## 6. Jak specyfikacje trafiają do wiki + +Trzy mostki, wszystkie obsługiwane przez `ckb-spec`. To one sprawiają, że +OpenSpec nie staje się równoległym światem obok bazy wiedzy. + +**Zarchiwizowana zmiana → rekord decyzji.** Wdrożona i zarchiwizowana zmiana to +decyzja, którą podjęto i wykonano. Agent *proponuje* zapisanie jej w +`wiki/decisions/` — uzasadnienie z propozycji staje się Kontekstem i Uzasadnieniem, +delta staje się Decyzją, a odrzucone opcje — Rozważanymi alternatywami. + +Proponuje, a nie robi tego automatycznie, i jest to celowe. Nie każda rutynowa +zmiana zasługuje na trwały, numerowany rekord, a dziennik decyzji zapchany nimi +przestaje być wart czytania. + +**Specyfikacja → strona encji.** Aktualne specyfikacje z korzenia bazy pojawiają +się w `wiki/entities/` jako cienkie strony `type: spec`, dzięki czemu pytania w +rodzaju „co to ma robić?” da się odpowiedzieć z indeksu, bez otwierania drzewa +specyfikacji. Źródłem prawdy pozostaje plik specyfikacji — strona wiki jest +wskaźnikiem, nie kopią. + +**Poziom → poziom.** Specyfikacje z korzenia i z repozytoriów linkują się +nawzajem (§7). + +## 7. Pilnowanie spójności poziomów + +Dwa poziomy specyfikacji to dwa miejsca, w których może mieszkać to samo +stwierdzenie — a więc i dwa, w których może się po cichu rozjechać. Zapobiega +temu jedna zasada: + +> Specyfikacja z korzenia wymienia każdą implementującą ją specyfikację +> repozytorium w `implemented_by:`. +> Specyfikacja repozytorium wskazuje rodzica w `implements:`. +> **Zawsze ustawiaj obie strony.** + +Te odnośniki stają się krawędziami grafu, co zamienia rozjazd w widoczne +znalezisko, zamiast w cichy drugi ośrodek prawdy. + +Powiedz **„zsynchronizuj specyfikacje”** (albo uruchom `lint`), a dostaniesz +cztery kontrole: + +1. Specyfikacje z korzenia bez implementacji — *opisane, ale nikt tego nie buduje.* +2. Specyfikacje repozytorium, których rodzic zniknął lub trafił do archiwum — + *budujesz pod coś, co przestało obowiązywać.* +3. Jednostronne odnośniki, w dowolnym kierunku. +4. Specyfikacje z korzenia starsze niż zmapowany commit każdego repozytorium, + które je implementuje — *możliwy rozjazd, wart sprawdzenia.* + +Żadna z tych rzeczy nie jest naprawiana automatycznie. Każda jest stwierdzeniem +o intencji, a tylko Ty wiesz, która strona ma rację. + +## 8. Szybki przegląd + +| Chcesz | Powiedz / uruchom | +|---|---| +| Włączyć to wszystko | „zainstaluj moduł software” | +| Dodać OpenSpec do repozytorium | `cd src/ && openspec init` | +| Zmapować repozytorium do wiki | „zmapuj `src/`” | +| Napisać przekrojową specyfikację | „napisz przekrojową specyfikację dla X” | +| Zaproponować zmianę w repozytorium | `/opsx:propose ` | +| Sprawdzić stan specyfikacji | „zsynchronizuj specyfikacje” | +| Zamienić zarchiwizowaną zmianę w decyzję | „zapisz tę zmianę jako decyzję” | + +**Nigdy:** nie uruchamiaj `openspec init` w korzeniu bazy · nie rób `git add` +niczego w `src/` · nie przerabiaj plików OpenSpec repozytorium pod konwencje tej +bazy. + +--- + +## Źródła + +- [Dokumentacja OpenSpec](https://openspec.dev/docs/installation) · + [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec) · + [@fission-ai/openspec na npm](https://www.npmjs.com/package/@fission-ai/openspec) +- Rekordy projektowe: [D-0001](wiki/decisions/0001-opt-in-file-based-kb-modules.md), + [D-0002](wiki/decisions/0002-software-module-design.md) + +--- + +*Udostępniane na licencji Apache License 2.0 — zobacz [LICENSE](LICENSE).* diff --git a/README.md b/README.md index 039daee..98fb2de 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ how to create a wiki, add knowledge, keep it tidy, sync with others, and worked examples for every use case — see [MANUAL.md](MANUAL.md) ([Polski](MANUAL.pl.md)). +If this KB documents software you're building, the optional `software` module +adds `src/` repositories and spec-driven development — see +[OPENSPEC.md](OPENSPEC.md) ([Polski](OPENSPEC.pl.md)). + --- ## Directory Structure diff --git a/README.pl.md b/README.pl.md index ff5694b..95f8a4d 100644 --- a/README.pl.md +++ b/README.pl.md @@ -15,6 +15,10 @@ przewodnik — jak stworzyć wiki, dodawać wiedzę, utrzymywać porządek, synchronizować się z innymi i przykłady dla każdego przypadku użycia — znajdziesz w [MANUAL.pl.md](MANUAL.pl.md) ([English](MANUAL.md)). +Jeśli ta baza dokumentuje tworzone przez Ciebie oprogramowanie, opcjonalny moduł +`software` dodaje repozytoria w `src/` i pracę sterowaną specyfikacją — zobacz +[OPENSPEC.pl.md](OPENSPEC.pl.md) ([English](OPENSPEC.md)). + --- ## Struktura katalogów diff --git a/VERSION b/VERSION index 9c6d629..bd8bf88 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.1 +1.7.0 diff --git a/wiki/decisions/0001-opt-in-file-based-kb-modules.md b/wiki/decisions/0001-opt-in-file-based-kb-modules.md new file mode 100644 index 0000000..98b97de --- /dev/null +++ b/wiki/decisions/0001-opt-in-file-based-kb-modules.md @@ -0,0 +1,78 @@ +--- +type: decision +tldr: Optional KB capabilities ship as file-based modules under `.agents/modules//`, installed into the KB on request, rather than as native Claude Code plugins. +status: accepted +decided_on: 2026-09-20 +decided_by: Michał Kopeć +affects: /wiki/index.md +confidence: 0.9 +quality: 0.8 +last_updated: 2026-09-20 +freshness_window_days: 365 +retention: high +--- + +# D-0001 — Optional KB capabilities ship as file-based modules, not native plugins + +**Status:** Accepted · **Decided:** 2026-09-20 · **Deciders:** Michał Kopeć + +## Context + +The base KB ships fourteen `ckb-*` skills, all always loaded. Some capabilities +are only useful to *some* knowledge bases — the first concrete case being a KB +that documents software the user is building (see +[[D-0002]] / [D-0002](/wiki/decisions/0002-software-module-design.md)). Adding +those skills unconditionally would grow the always-loaded skill-description +budget for every KB, including ones that will never need them. + +Three mechanisms were on the table for making a capability opt-in. The KB is +deliberately agent-agnostic: `AGENTS.md` is the source of truth and `CLAUDE.md` +is a symlink to it (git mode `120000`), as is `.claude/skills` → `.agents/skills`. +That symlink arrangement is a confirmed preference, and it means anything written +to `.agents/skills/` is visible to Claude Code for free. + +## Decision + +Optional capabilities are packaged as **file-based modules** stored in +`.agents/modules//` and installed into the KB on explicit request. A +module may contribute skills (into `.agents/skills/`), directory scaffold, a +routing block appended to `AGENTS.md`, and `.gitignore` rules. Installation is +recorded in a root manifest listing the installed modules and their config; +uninstalling reverses it. + +## Rationale + +A module is a property of *the knowledge base*, not of the machine or the agent +reading it. File-based modules travel with a clone, so a cloned KB stays +self-describing, and they work for any agent that reads `AGENTS.md` — not only +Claude Code. Shipping module content outside `.agents/skills/` until install +keeps the always-loaded skill budget flat for KBs that don't opt in. + +## Consequences + +- A `ckb-module`-style install/uninstall path is needed. +- `ckb-init` should offer modules at bootstrap; `ckb-upgrade` must not delete + module-installed skills it doesn't recognise upstream, and must also upgrade + `.agents/modules/`. +- `ckb-lint` gains validation of the module manifest. +- Module skills are authored so they could *also* be published as a native + Claude Code plugin later without a rewrite — this decision doesn't foreclose + that, it just declines to make it the primary mechanism. +- Because `.claude/skills` is a symlink, an installer writes `.agents/skills/` + only; no duplicate copy to keep in sync. + +## Alternatives considered + +- **Always-shipped skills that self-gate on a flag** — no install step and + trivially upgradeable, but every skill description stays in context for every + KB regardless of relevance. Rejected: that budget degrades quietly. +- **Native Claude Code plugin** (`.claude-plugin/plugin.json` + marketplace) — + real enable/disable and no file copying, but serves only Claude Code, breaking + the dual-headed `AGENTS.md`/`CLAUDE.md` contract, and installs per-machine + rather than per-KB. Rejected as the primary mechanism, not ruled out as an + additional distribution channel. + +## Sources + +Chat conversation, 2026-09-20 — design evaluation of a source-code/software KB +mode. See `workload/2026-09-20_summary.md`. diff --git a/wiki/decisions/0002-software-module-design.md b/wiki/decisions/0002-software-module-design.md new file mode 100644 index 0000000..c4569ae --- /dev/null +++ b/wiki/decisions/0002-software-module-design.md @@ -0,0 +1,113 @@ +--- +type: decision +tldr: The `software` module keeps code as gitignored plain clones in `src/`, runs OpenSpec at both KB-root and per-repo level with a hybrid vendor/depend split, and links the two spec levels with `implements`/`implemented_by`. +status: accepted +decided_on: 2026-09-20 +decided_by: Michał Kopeć +affects: /wiki/decisions/0001-opt-in-file-based-kb-modules.md, /wiki/index.md +confidence: 0.85 +quality: 0.8 +last_updated: 2026-09-20 +freshness_window_days: 365 +retention: high +--- + +# D-0002 — Design of the opt-in `software` module + +**Status:** Accepted · **Decided:** 2026-09-20 · **Deciders:** Michał Kopeć + +## Context + +Some knowledge bases document software the user is actively building. In that +case the source code lives in `src/`, usually as one or more *independent* git +repositories with their own remotes — a git repo inside a git repo. The user +also wants OpenSpec-driven iterative development available in that mode. + +This is the first concrete module under +[[D-0001]] / [D-0001](/wiki/decisions/0001-opt-in-file-based-kb-modules.md), +and four sub-questions had to be settled: how code is hosted, where specs live, +whether OpenSpec's own workflow instructions are vendored or depended on, and +how two spec levels avoid becoming two sources of truth. + +## Decision + +**Code hosting.** `src//` holds plain clones, gitignored (`src/*`, as +`libs/*` already is). No submodules. Because the code may be absent from a +fresh clone, each repo also gets a durable `type: repository` entity page in +`wiki/` recording its remote URL, default branch, language, build command, +`src/` path, and owner — that page, not the clone, is the durable artifact. + +**`src/` is not a cascade layer.** It is primary evidence, like `raw/archive/`: +`ckb-retrieve` may open and cite it when verifying a claim, but it never answers +"what is entity X", and `ckb-ingest` does not treat code as inbox material. + +**Spec location — both levels.** OpenSpec runs at the KB root (cross-cutting +capabilities spanning multiple `src/` repos) *and* inside each `src//` +(implementation specs that travel with the code in its own repo). + +**Vendoring — hybrid.** The KB-root spec layer is served by a module-owned +skill, because a KB-root `openspec/` is not a normal OpenSpec repo install (no +code beneath it, no single repo it governs) and the module must own instructions +for it regardless. The per-`src`-repo layer delegates to OpenSpec's own native +install and instructions, and the module reports plainly when OpenSpec is +missing rather than substituting its own workflow. The module additionally owns +the bridge in both directions: an archived OpenSpec change becomes a +`wiki/decisions/NNNN-*.md` record, and current specs sync into `type: spec` +entity pages. + +**Drift rule.** KB-level specs state *what* and *why* across repos; `src`-level +specs state *how* a given repo implements it. The two are linked by +`implements:` / `implemented_by:` frontmatter, which becomes graph edges. +`ckb-lint` gains checks for KB-level specs with no implementer and `src`-level +specs whose parent was archived or superseded. + +## Rationale + +Gitignored clones avoid embedded-repo warnings and keep code out of KB history, +while each repo keeps pushing to its own origin; submodules would pin commits +that go stale against daily work in `src/`. Specs at both levels reflect a real +distinction — cross-repo contracts genuinely differ from per-repo implementation +— and the hybrid vendoring split follows from that same distinction rather than +splitting the difference: only the level OpenSpec doesn't natively serve is +owned locally. The `implements`/`implemented_by` link exists specifically so the +two-level arrangement produces a lint signal when the levels disagree, instead +of two silently divergent truths. + +## Consequences + +- `.gitignore` gains `src/*` rules. +- New frontmatter types `repository`, `component`, `spec`, and optional `repo:`, + `commit:`, `spec_id:`, `implements:`, `implemented_by:` fields — a + `kb_schema_version` bump to `1.5`, additive only. +- Module skills needed: a code-mapping skill (`src/` → entity pages, with + a recorded commit hash so staleness is detectable) and a KB-root OpenSpec + + bridge skill. +- `ckb-sync-changes` must never `git add` under `src/`, and should report each + `src/` repo's dirty/ahead state separately. +- `ckb-retrieve` gains code as a verification source; `ckb-lint` gains the src + and spec-drift checks; OKF and Starlight exports exclude `src/`. +- The module is unusable at the `src/` level until OpenSpec is installed + separately — it is not on PATH as of this decision. + +## Alternatives considered + +- **Git submodules for `src/`** — code travels with the KB and is pinned to a + commit, which is genuinely attractive for "what did the wiki describe at that + point". Rejected for submodule friction on every sync and pins going stale. +- **Specs only inside each `src/` repo** — OpenSpec's native case, nothing to + own locally, but no home for contracts spanning several repos. +- **Specs only at KB root** — one place to look, but specs stop travelling with + the code they govern and fall out of the repo's own PR flow. +- **Vendoring OpenSpec's workflow wholesale** — self-contained, works with + nothing installed, tailorable to KB conventions. Rejected: it means + maintaining a fork of an external workflow, and `ckb-upgrade` would have two + upstreams to track. +- **Depending on OpenSpec at both levels** — nothing to maintain, but leaves the + KB-root layer with no instructions at all, since OpenSpec doesn't serve that + case. + +## Sources + +Chat conversation, 2026-09-20 — design evaluation of a source-code/software KB +mode, including the user's explicit choices on mechanism, code hosting, spec +location, and vendoring. See `workload/2026-09-20_summary.md`. diff --git a/wiki/decisions/index.md b/wiki/decisions/index.md index da5c1b7..87541ee 100644 --- a/wiki/decisions/index.md +++ b/wiki/decisions/index.md @@ -7,7 +7,8 @@ Filenames are `NNNN-short-slug.md`, numbered sequentially from `0001`, and numbers are never reused: a decision that is reversed or superseded keeps its number and its page, and the newer decision points back at it. -*(No decisions recorded yet — say "record a decision" to add the first one.)* +* **[Accepted]** [D-0001 — Optional KB capabilities ship as file-based modules, not native plugins](0001-opt-in-file-based-kb-modules.md) — Optional KB capabilities ship as file-based modules under `.agents/modules//`, installed into the KB on request, rather than as native Claude Code plugins. +* **[Accepted]** [D-0002 — Design of the opt-in `software` module](0002-software-module-design.md) — The `software` module keeps code as gitignored plain clones in `src/`, runs OpenSpec at both KB-root and per-repo level with a hybrid vendor/depend split, and links the two spec levels with `implements`/`implemented_by`. ## Status vocabulary diff --git a/wiki/decisions/log.md b/wiki/decisions/log.md index 54d1229..f28e053 100644 --- a/wiki/decisions/log.md +++ b/wiki/decisions/log.md @@ -9,6 +9,12 @@ Reverse chronological order, most recent first. --- +## [2026-09-20 00:00] - [CREATE] +- **File Affected:** `wiki/decisions/0001-opt-in-file-based-kb-modules.md`, `wiki/decisions/0002-software-module-design.md`, `wiki/decisions/index.md` +- **Description:** Recorded the first two decision records. D-0001 settles the mechanism for optional KB capabilities: file-based modules under `.agents/modules//`, installed on request, rather than native Claude Code plugins. D-0002 settles the design of the first such module (`software`): gitignored plain clones in `src/`, `src/` as evidence rather than a cascade layer, OpenSpec at both KB-root and per-repo levels, hybrid vendoring (own the KB-root layer, depend on OpenSpec per repo, own the bridge), and `implements`/`implemented_by` linking the two spec levels for drift detection. Both indexed; no `decided_by` entity page exists for Michał Kopeć yet. +- **Source:** Chat conversation, 2026-09-20 — `ckb-decide`. +--- + ## [2026-09-01 21:05] - [CREATE] - **File Affected:** `wiki/decisions/index.md`, `wiki/decisions/log.md` - **Description:** Created the decision-log scaffold: an index listing every decision by number with its status and one-line summary, the status vocabulary (proposed / accepted / rejected / superseded / reversed), and this log. No decisions recorded yet. diff --git a/wiki/graph/edges.json b/wiki/graph/edges.json new file mode 100644 index 0000000..b283ec2 --- /dev/null +++ b/wiki/graph/edges.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "last_updated": "2026-09-20", + "edges": [ + { + "from": "/wiki/decisions/0002-software-module-design.md", + "to": "/wiki/decisions/0001-opt-in-file-based-kb-modules.md", + "type": "affects", + "note": "D-0002 is the first concrete module defined under D-0001's mechanism." + } + ] +} diff --git a/wiki/log.md b/wiki/log.md index 94b46e2..53f22a4 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -1,5 +1,11 @@ # Wiki Change Log +## [2026-09-20 00:00] - [CREATE] +- **File Affected:** `wiki/decisions/` (D-0001, D-0002), `wiki/graph/edges.json` +- **Description:** See `wiki/decisions/log.md` for decision-record changes on this date. Also created `wiki/graph/edges.json` with its first edge (D-0002 → D-0001, `affects`). +- **Source:** Chat conversation, 2026-09-20 — `ckb-decide`. +--- + ## [2026-09-01 21:05] - [CREATE] - **File Affected:** `wiki/decisions/` (directory) - **Description:** Created the decision-records directory — one numbered, append-only page per decision, recorded and queried by the new `ckb-decide` skill. Its own contents are logged in `wiki/decisions/log.md`. diff --git a/workload/2026-09-02_summary.md b/workload/2026-09-02_summary.md new file mode 100644 index 0000000..956f61a --- /dev/null +++ b/workload/2026-09-02_summary.md @@ -0,0 +1,16 @@ +## 2026-09-02 — Research: can Plane (plane.so) replace Vikunja? + +- User asked whether Plane could replace Vikunja, motivated by (a) preferring Plane's UI and (b) Plane bundling a wiki useful for requirements work. +- KB had no prior content on either tool (`grep` over `wiki/ raw/ workload/ linked/ libs/` found nothing) — answered from external web research only, not from the cascade. +- Key finding: the self-hosted **Community Edition** is a separate AGPL-3.0 codebase at ~parity with Cloud's *Free* tier, with **no Pro/Business features at all**. The features that motivate the switch are paid: + - Workspace **Wiki** → Pro ($6/seat/mo) + - **Nested pages** → Business ($13/seat/mo) + - Work-item mentions in pages / convert text → work item → Business + - **Recurring work items** → Business (Vikunja has these free) + - Importers incl. CSV → Cloud/Commercial only (no migration path into CE) + - Epics/initiatives, workflows/approvals, custom work-item types, SSO → paid +- CE does include project-level Pages (unlimited), five layouts, cycles, modules, intake, estimates, REST API, webhooks, no seat limit. +- Vikunja capabilities Plane lacks at any tier found: CalDAV (VTODO) two-way sync, Quick Add Magic. +- Ops delta: Vikunja = single Go binary + SQLite, ~1 GB RAM. Plane = ~13 containers, 4 GB RAM minimum / 8 GB recommended, ~1.8 GB idle; CE has no auto-upgrade and documented upgrade breakage (makeplane/plane#8708) plus contradictory seat-limit docs (#9086). +- Recommendation given: CE does not deliver the stated wiki benefit and is a net regression for personal task use; if the wiki is the real driver, either pay for Pro/Business, or keep Vikunja and pair it with a dedicated docs layer (this CKB, Outline, or BookStack). +- No `wiki/` writes made — offered to record this as a decision (`ckb-decide`) or ingest it as entity pages if the user wants it durable. diff --git a/workload/2026-09-20_summary.md b/workload/2026-09-20_summary.md new file mode 100644 index 0000000..2a73af0 --- /dev/null +++ b/workload/2026-09-20_summary.md @@ -0,0 +1,114 @@ + +## [2026-09-20] - Design evaluation: software/source-code KB module + +- **Activity:** Evaluated options for making this KB optionally "about software + I'm building" — `src/` holding one or more independent code repos, plus + OpenSpec-driven iterative development, packaged as an opt-in module. +- **Scope:** Read-only inspection of repo layout, `.agents/skills/`, `.gitignore`, + `wiki/index.md`, `ckb-init`/`ckb-upgrade`/`ckb-lint`. No files changed. +- **User decisions made this turn:** + - Module mechanism: files-in-repo module (`.agents/modules//`), installed + on request — not a native Claude Code plugin. + - `src/` repos: plain clones, gitignored. No submodules. + - Spec location: OpenSpec at *both* levels — KB root (cross-cutting, spans + multiple `src/` repos) and inside each `src/` (travels with the code). + - Confirmed preference: `CLAUDE.md` stays a symlink to `AGENTS.md`, and + `.claude/skills` stays a symlink to `.agents/skills` (both already correct, + tracked as git mode 120000). +- **Still open:** whether the module vendors OpenSpec's own workflow skills or + depends on an external OpenSpec install (hybrid recommended); schema bump to + 1.5 for `repository`/`component`/`spec` types. +- **Housekeeping:** `workload/2026-09-02_summary.md` still untracked — suggest + `ckb-sync-changes`. + +## [2026-09-20] - Decisions D-0001 and D-0002 recorded + +- **Activity:** Ran `ckb-decide`. Recorded the settled design as two decision + records rather than one, so the module *mechanism* can be superseded + independently of the *software module's* design (e.g. a later switch to + submodules touches only D-0002). +- **Files:** `wiki/decisions/0001-opt-in-file-based-kb-modules.md`, + `wiki/decisions/0002-software-module-design.md`, `wiki/decisions/index.md`, + `wiki/decisions/log.md`, `wiki/log.md`, `wiki/graph/edges.json` (created). +- **Open:** `kb_schema_version` bump 1.4 → 1.5 not yet applied — it belongs with + the module build, not the decision. No entity page exists for Michał Kopeć, + so `decided_by` is plain text on both records. +- **Not committed.** Say "sync changes" to push. + +## [2026-09-20] - Built the module mechanism and the `software` module + +- **Activity:** Implemented D-0001 and D-0002. +- **New — core (always loaded):** `.agents/skills/ckb-module/SKILL.md` — install, + list, uninstall. Owns the root `ckb.yaml` manifest, marker-wrapped patches to + `AGENTS.md` and `.gitignore`, and the additive `kb_schema_version` bump. +- **New — module payload (inert until installed):** `.agents/modules/software/` + with `module.yaml`, `README.md`, `fragments/` (AGENTS routing block, gitignore + snippet), `scaffold/` (src README, KB-root `openspec/`), and two skills — + `ckb-code-map` (repo → `type: repository`/`component` pages, commit-stamped) + and `ckb-spec` (KB-root specs, delegation to OpenSpec per repo, bridge to + decisions/entities, four-part drift check). +- **Edited core skills for module awareness:** `ckb-lint` (new check 11: stale + code maps, spec drift, remote-less repos — report-only, skipped when no + module installed), `ckb-sync-changes` (new Step 1b: never stage under `src/`, + but do report each clone's state), `ckb-upgrade` (upgrade `.agents/modules/`; + never delete a skill absent upstream without checking `ckb.yaml`), `ckb-init` + (copy the module catalogue, install nothing). +- **`AGENTS.md`:** new "Optional Modules" subsection in §1, module-schema note + in §2, `ckb-module` routing row + rule in §3. `CLAUDE.md` inherits via symlink. +- **`VERSION`:** 1.6.1 → 1.7.0 (template/tooling). `kb_schema_version` stays + `1.4` — deliberately: 1.5 arrives only when a module requiring it is installed. +- **Verified:** `.claude/skills` lists 15 skills including `ckb-module` and + *excluding* `ckb-code-map`/`ckb-spec` — the opt-in isolation works. `ckb.yaml` + absent = nothing installed. Lint clean apart from a pre-existing + `query-gaps.md` freshness finding. +- **Not done:** the `software` module is built but **not installed** here. +- **Not committed.** Say "sync changes" to push. + +## [2026-09-20] - OpenSpec user guides (EN + PL) + +- **New:** `OPENSPEC.md` and `OPENSPEC.pl.md` — human-facing guides to adding + OpenSpec and using it with this wiki, matching the existing + README/MANUAL `.md` + `.pl.md` convention and cross-linked both ways. +- **Verified against upstream docs, not written from memory:** Node 20.19.0+, + `npm install -g @fission-ai/openspec@latest`, `openspec init/update/list/show/ + validate/archive/status/view`, and the `/opsx:propose|apply|archive` loop. +- **Key finding worth the research:** `openspec init` writes into + `.claude/skills/` and adds marker blocks to `AGENTS.md`/`CLAUDE.md`. In this + repo `.claude/skills` → `.agents/skills` and `CLAUDE.md` → `AGENTS.md` are + symlinks, so running `init` at the KB root would inject OpenSpec's per-repo + files into the KB's own skill set and system prompt. Documented as a hard + "never" in both guides *and* added as a rule inside `ckb-spec`, so the agent + refuses it rather than running and cleaning up. +- **Also:** README.md / README.pl.md now point at the guides; module README links + them too. +- **Not committed.** Say "sync changes" to push. + +## [2026-09-20] - Added `ckb-reset` (destructive template reset) + +- **New:** `.agents/skills/ckb-reset/SKILL.md` — empties the KB back to the + scaffold `ckb-init` Step 8 defines, so a working KB can be turned back into a + distributable template. Routed in `AGENTS.md` §3. Invocable as `/ckb-reset`. +- **Safety design (the point of the skill):** git restore-point check first and a + refusal to run on a dirty tree without override; six opt-in scope tiers with + `linked/`, `libs/` and installed modules defaulting to *no*; a counted + inventory shown *before* asking; a typed-phrase confirmation that is + re-requested whenever scope changes; post-reset lint verification before + reporting success; `src/` excluded unconditionally, even with confirmation. +- **Deliberate exception to Rule D:** `ckb-reset` does not append a workload + summary — it would be the first entry in a directory it just emptied. The skill + says so in its report so it doesn't read as a bug. +- **Fixed while here:** `wiki/graph/edges.json` was missing the `version` and + `last_updated` keys the `ckb-init` scaffold specifies. Now conformant. +- **Not committed.** Say "sync changes" to push. + +## [2026-09-20] - Documented `ckb-reset` in both manuals + +- **`MANUAL.md` / `MANUAL.pl.md`:** new subsection in §3 ("Starting over: + resetting to a clean template" / "Zaczynanie od zera: reset do czystego + szablonu") covering the five-stage safety flow, the six scope tiers, what is + restored, what is never touched (`src/`, template layer), and the deliberate + Rule D exception. Plus a row in each §8 quick-reference table, marked + destructive. +- **Placement rationale:** §3 "Keeping it tidy" rather than §1, because reset is + a maintenance operation on an existing KB; §1 is about creating one. +- **Not committed.** Say "sync changes" to push.