The template repo now keeps three branches with fixed meanings — main is
stable, test is the release candidate, experimental is development — and
ckb-init/ckb-upgrade can source from any of them instead of only main.
Selection is per-invocation, in words the user already uses ("initialize
from the test branch", "check experimental for updates", "switch back to
stable"), and sticky: the resolved repo and branch are written to a
template: block in ckb.yaml. Without persistence, a KB bootstrapped from
experimental would be silently pulled back to main by its next upgrade.
A missing file or missing block both mean main, so every KB predating
this convention behaves exactly as before.
One consequence needed explicit handling. A KB tracking test or
experimental can sit on a VERSION main has not released yet, so comparing
it against main finds nothing newer — which the version check would have
reported as "up to date". That is true and misleading. ckb-upgrade now
reports it as "ahead", and treats a move back to main as a downgrade:
explicitly confirmed, with the specific losses named, and blocked
outright where kb_schema_version would drop below what local pages are
already written against.
ckb-module is told not to clobber the template: block — a module install
that silently reset a KB's channel would change what its next upgrade
pulls, which is not a module's business.
Documented in both READMEs, both MANUALs and both CHANGELOGs. VERSION
1.8.0 -> 1.9.0; kb_schema_version stays 1.5, since this is tooling rather
than a content contract.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
602 lines
31 KiB
Markdown
602 lines
31 KiB
Markdown
# Cascade Knowledge Base
|
||
|
||
*Read this in: **English** | [Polski](README.pl.md)*
|
||
|
||
**Source repo (always the most up-to-date version):**
|
||
[git.wierzbowa.cloud/michal/ckb](https://git.wierzbowa.cloud/michal/ckb)
|
||
|
||
A layered, agent-managed wiki where local content overlays read-only upstream
|
||
sources. Built on Karpathy's LLM Wiki pattern with extensions for scaling,
|
||
lifecycle management, and multi-agent support.
|
||
|
||
This document is a technical feature overview. For a task-oriented guide —
|
||
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)).
|
||
|
||
For the page schema in full, and for how both version numbers got where they
|
||
are, see [CHANGELOG.md](CHANGELOG.md) ([Polski](CHANGELOG.pl.md)).
|
||
|
||
### Release channels
|
||
|
||
The template repo keeps three branches. They are not interchangeable:
|
||
|
||
| Branch | What it is | Who should track it |
|
||
|---|---|---|
|
||
| `main` | **Stable** — the released template | Everyone, by default |
|
||
| `test` | **Release candidate** — validated before merging to `main` | Anyone helping validate a release, or needing a landed-but-unshipped fix |
|
||
| `experimental` | **Development** — active work, may be broken or reverted | People developing the template itself |
|
||
|
||
Both `ckb-init` and `ckb-upgrade` default to `main`. To use another channel,
|
||
just say which: *"initialize from the test branch"*, *"check experimental for
|
||
updates"*, *"switch this KB back to the stable channel"*. The branch a KB
|
||
tracks is recorded in `ckb.yaml`:
|
||
|
||
```yaml
|
||
template:
|
||
repo: https://git.wierzbowa.cloud/michal/ckb.git
|
||
branch: main
|
||
```
|
||
|
||
A KB with no `ckb.yaml` (or no `template:` block) is treated as tracking
|
||
`main`, which is what every KB predating this convention was doing anyway.
|
||
|
||
---
|
||
|
||
## Directory Structure
|
||
|
||
```
|
||
├── libs/ # Read-only external sources — git-copy clones (gitignored) OR
|
||
│ # connector configs (source.yaml) with a self-contained generated index
|
||
├── linked/ # Read-only upstream KBs mounted as symlinks
|
||
├── outputs/ # Generated artifacts, exports, compiled files
|
||
├── raw/ # User-provided source material
|
||
│ └── inbox/ # Drop zone: unprocessed material
|
||
├── tmp/ # Temporary files, caches (gitignored)
|
||
├── wiki/ # Local structured markdown wiki (agent-managed)
|
||
│ ├── index.md # Routing table with "Use when" triggers + kb_schema_version
|
||
│ ├── overview.md # High-level map
|
||
│ ├── log.md # Root rollup change log
|
||
│ ├── error-book.md # Compilation errors & derived constraints
|
||
│ ├── query-gaps.md # Failed or missing-answer questions for future ingest
|
||
│ ├── projects/ # Optional local query scopes
|
||
│ ├── decisions/ # Numbered, append-only decision records + own index.md & log.md
|
||
│ ├── entities/ # Typed entity pages (people, projects, concepts) + own index.md
|
||
│ └── graph/ # Edge lists and relationship data + own index.md
|
||
└── workload/ # Session summaries & decisions
|
||
└── YYYY-MM-DD_summary.md
|
||
```
|
||
|
||
---
|
||
|
||
## Cascade Priority
|
||
|
||
When searching, layers are checked in order — first match wins:
|
||
|
||
```
|
||
wiki/ (highest) ← agent writes here, always wins
|
||
linked/A/ (medium) ← symlinked upstream KBs
|
||
linked/B/ (low) ← symlinked upstream KBs
|
||
libs/A/ (lowest) ← git-managed external KB copies, or a connector's own generated index
|
||
```
|
||
|
||
The agent never writes to `linked/` or a git-copy `libs/<name>/`. To correct
|
||
upstream content, write the right version in `wiki/` — it takes precedence
|
||
automatically. The one exception is a connector-backed `libs/<name>/` (see
|
||
"External Source Connectors & Indexing" below) — the agent owns and
|
||
maintains its generated index exactly as it would `wiki/`.
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
### Inbox-Driven Workflow
|
||
Drop any raw material (notes, articles, links) into `raw/inbox/` without
|
||
organizing. On "Ingest" (or "Sync the wiki" / "Update the wiki"), the agent
|
||
processes the inbox — extracts knowledge, files it into `wiki/`, and
|
||
archives processed items to `raw/` — then reminds you to review the result
|
||
and run "sync changes" to push it to `origin` once you're happy with it.
|
||
Implemented as a Claude Code Skill — see
|
||
`.agents/skills/ckb-ingest/SKILL.md` — rather than baked into
|
||
`CLAUDE.md`/`AGENTS.md`, so the full procedure only loads into context when
|
||
actually invoked. Distinct from the `ckb-sync-changes` skill, which is a
|
||
pure git-level operation with no wiki synthesis.
|
||
|
||
For long conversations, meeting notes, transcripts, or chat exports, ingest
|
||
uses a structured distillation rather than treating the whole file as one
|
||
undifferentiated blob: searchable question, short summary, resolution or
|
||
decision, systems/code references, people involved, and high-signal excerpts
|
||
that deserve to stay findable on their own.
|
||
|
||
"High-signal" is an explicit test, not a judgment call, or every excerpt
|
||
looks worth keeping and the page becomes a second copy of the transcript.
|
||
An excerpt earns its own retrievable section only if it carries a term rare
|
||
across the wiki (checked with `rg -c` — a distinguishing search handle, not
|
||
a word already on twenty pages), runs to roughly 200 characters or more, and
|
||
is corroborated by something later in the material agreeing with, acting on,
|
||
or correcting it. Fail any one and the content still lands in the page, just
|
||
inside the summary rather than as its own unit. Promoted excerpts carry
|
||
their parent heading or thread question with them, so they read
|
||
unambiguously alone.
|
||
|
||
### Lazy-Loading Index with "Use When" Triggers
|
||
`wiki/index.md` is a routing table. Each entry has a **Use when** column
|
||
listing trigger keywords. The agent reads the index first (stays in context),
|
||
matches keywords against the task, and only loads matching pages. This
|
||
drops context overhead from ~12K to ~3.2K tokens per task.
|
||
|
||
### TLDR-First Query Layer
|
||
Every page carries a one-sentence `tldr` in frontmatter. When querying, the
|
||
agent reads TLDRs first. If the TLDR already answers the question, the full
|
||
body is never loaded. Fallback chain: TLDR → body → raw source.
|
||
|
||
### Local Project Scopes
|
||
For recurring teams, clients, systems, or initiatives, the wiki can keep
|
||
plain Markdown scope pages under `wiki/projects/`. A scope page lists the
|
||
wiki pages, entities, raw/archive sources, connector-backed libs, outputs,
|
||
and graph areas that should be searched first for that project. This gives
|
||
the same practical benefit as a project workspace in a larger retrieval
|
||
system while staying local, transparent, and editable with any text editor.
|
||
|
||
Scopes only narrow the first pass. If the scoped search does not answer the
|
||
question, the agent falls back to the full cascade.
|
||
|
||
### Local Hybrid Retrieval
|
||
When index/TLDR routing is not enough, the agent can combine several local
|
||
signals before answering:
|
||
- exact text search with `rg` for error strings, commands, flags, filenames,
|
||
hostnames, ticket IDs, and other literal tokens — including across
|
||
`raw/inbox/`, so material dropped an hour ago and not yet ingested can
|
||
still answer a question (and flags that an ingest is overdue)
|
||
- semantic/entity matches from page titles, TLDRs, project scopes, and graph
|
||
relationships
|
||
- freshness and confidence metadata, so stale or weak pages are treated with
|
||
care
|
||
- context expansion around a matched section, so answers are grounded in the
|
||
neighboring headings and paragraphs rather than a lone snippet
|
||
|
||
Each signal produces its own ranked list, and the lists are then fused
|
||
rather than resolved by picking a favourite: every candidate scores
|
||
`weight / (k + rank)` summed across the lists it appears in, so a page
|
||
ranked third by three signals beats one ranked first by a single signal.
|
||
`k` is 10, deliberately smaller than the 60 rank fusion is usually quoted
|
||
with — 60 is tuned for retrievers returning hundreds of candidates and
|
||
flattens all scores into near-identical values against the dozen a local
|
||
wiki produces. Literal-token queries up-weight the exact-match list, since
|
||
no amount of title similarity should outrank a match on the exact string
|
||
someone pasted.
|
||
|
||
Fused candidates are then deduplicated by claim — a wiki page, the
|
||
`raw/archive/` file it cites, and a connector page pointing back at it are
|
||
three hits for one fact, not three sources — and reranked 0–10 on how well
|
||
each answers the literal question rather than how well it matches the
|
||
question's wording. Same agent, deliberate second pass, no separate model.
|
||
|
||
The result is normalized internally as an evidence packet: source path,
|
||
matched claim, date/freshness, confidence/quality, relationship or scope
|
||
hints, and which signals each candidate was fused from. No server, vector
|
||
database, or dedicated client is required.
|
||
|
||
### Answer Caveats
|
||
Metadata the wiki already tracks is stated in the answer itself, not just
|
||
consulted while building it. When a page grounding an answer is past its
|
||
`freshness_window_days`, carries low `confidence`/`quality`, rests on
|
||
un-ingested `raw/inbox/` material, or was checked against a cached
|
||
connector index rather than a live re-fetch, the answer says so next to
|
||
the claim it qualifies. Conflicts between two live pages are surfaced the
|
||
same way even when neither carries `superseded_by` yet. The failure mode
|
||
this closes is answering confidently *from* a stale page without passing
|
||
that on.
|
||
|
||
### Expertise & Ownership Lookups
|
||
"Who knows about X" and "who owns X" are direct graph lookups rather than
|
||
full-text guesses. Ingest records `has_expertise_in` edges when someone
|
||
demonstrably answers questions or explains decisions on a topic, and
|
||
`owns` edges for declared responsibility over a system, area, or decision
|
||
— both from demonstrated evidence only, never inferred from meeting
|
||
attendance or job title. Where no edge exists yet, retrieval falls back to
|
||
authorship evidence and says which of the two grounded the answer, since
|
||
an inferred expert is a weaker claim than a recorded one.
|
||
|
||
### Decision Records
|
||
`wiki/decisions/` holds one numbered page per decision (`NNNN-slug.md`):
|
||
what was decided, `decided_by` whom, `decided_on` what date, why, the
|
||
alternatives that lost, and what it `affects`. A `status` field
|
||
(`proposed`/`accepted`/`rejected`/`superseded`/`reversed`) says whether it is
|
||
actually in force, and an optional `review_on` date marks it for revisiting.
|
||
|
||
Decision pages are **append-only**. When the choice changes, a *new* decision
|
||
supersedes the old one — `supersedes`/`superseded_by` are set on both sides,
|
||
the old page's status becomes `superseded` or `reversed`, and its original
|
||
context and rationale stay untouched. That is what makes "why is it like
|
||
this?" answerable years later, and what turns "we use Postgres" into "we use
|
||
Postgres, and before that MySQL, changed in September because of reporting".
|
||
`decided_by` and `affects` also become graph edges, so "who decided X" and
|
||
"what decisions touch Y" are direct lookups. The `ckb-decide` skill records
|
||
decisions and answers questions about them; `ckb-lint` checks their structure
|
||
(status vocabulary, required dates, two-sided supersession, unique numbers,
|
||
overdue reviews).
|
||
|
||
### Query Gaps
|
||
If the cascade cannot answer a question, the agent records or proposes a
|
||
short entry in `wiki/query-gaps.md`: what was asked, where it looked, and the
|
||
smallest source or page that would close the gap. This makes failed searches
|
||
useful demand signals for the next ingest instead of disappearing into chat
|
||
history.
|
||
|
||
### Page Frontmatter Schema
|
||
Every wiki page uses YAML frontmatter. `type` is required; the rest are optional:
|
||
|
||
```yaml
|
||
---
|
||
type: concept # REQUIRED. Open string: person, project, concept, library, decision, playbook, ...
|
||
resource: https://... # Canonical URI to the authoritative external source this page describes
|
||
tldr: One-sentence summary optimised for LLM reading
|
||
confidence: 0.0–1.0 # Source corroboration score
|
||
quality: 0.0–1.0 # Self-evaluation (below 0.7 → flagged)
|
||
supersedes: path/to/old.md
|
||
superseded_by: path/to/new.md
|
||
last_updated: YYYY-MM-DD
|
||
freshness_window_days: 90 # Days before considered stale
|
||
retention: high|medium|low
|
||
source_fingerprint: sha256:3f9a2c1e # digest of the source this page was built from
|
||
source_checked: YYYY-MM-DD # when that digest was last verified
|
||
---
|
||
```
|
||
|
||
- **type** — required; unregistered string, new values always valid, readers tolerate unrecognized ones
|
||
- **resource** — optional pointer to the live/authoritative source, kept separate from the wiki's own commentary
|
||
- **confidence** — set on write, decays with time, reinforced by new sources
|
||
- **quality** — self-scored on write, pages below 0.7 flagged for review
|
||
- **supersedes / superseded_by** — when new info replaces old, link them
|
||
- **freshness_window_days** — pages older than this get flagged during lint
|
||
- **retention** — low pages are archived after 2× freshness window
|
||
- **source_fingerprint / source_checked** — a digest of the material the page
|
||
was synthesized from, plus when it was last confirmed. A freshness window is
|
||
a guess that a source *might* have moved; a fingerprint is a fact about
|
||
whether it *did*, and lint checks it mechanically.
|
||
|
||
#### Reserved body sections
|
||
Four `##` headings mean something specific everywhere in the KB:
|
||
|
||
| Section | What it holds |
|
||
|---|---|
|
||
| `## Sources` | one bullet per source, each with a fingerprint |
|
||
| `## Crux` | verbatim quotes from those sources — evidence, never paraphrase |
|
||
| `## Notes` | human-authored and **protected**: no skill rewrites it, ever |
|
||
|
||
`## Crux` is what lets a question be answered from the page instead of from
|
||
the archive: a summary can drift silently, a quote either still matches its
|
||
source or it doesn't. `## Notes` is the inverse guarantee — on pages the agent
|
||
regenerates (connector indexes, code maps), it is the one place an annotation
|
||
survives the next rebuild.
|
||
|
||
`wiki/index.md` alone also carries `kb_schema_version` (currently `"1.5"`), declaring
|
||
which revision of this schema the wiki was authored against — bump minor for
|
||
additive optional fields, major for breaking changes.
|
||
|
||
### Entity Extraction & Knowledge Graph
|
||
During ingest, the agent extracts typed entities (people, projects, libraries,
|
||
concepts, systems) and stores them as pages in `wiki/entities/`. Typed
|
||
relationships are recorded in `wiki/graph/edges.json`, using a closed
|
||
vocabulary where each verb is defined by the question it answers (see
|
||
`wiki/graph/index.md`) — structural ones (`part_of`, `uses`, `depends_on`,
|
||
`produces`, `configures`, `validates`, `implements`, `caused`, `contradicts`,
|
||
`supersedes`) plus people-to-topic ones (`has_expertise_in`, `owns`). Queries can walk the
|
||
graph to discover connected pages (e.g. "what depends on Redis?") or to
|
||
answer "who knows about X" directly.
|
||
|
||
### Recursive Index & Log Convention
|
||
Any `wiki/` subdirectory that groups multiple pages (`entities/`, `graph/`,
|
||
future topic folders) keeps its own `index.md` — a plain link list, no
|
||
frontmatter — so subdirectory navigation stays lazy instead of requiring a
|
||
full scan. A subdirectory can also keep its own `log.md` once it has enough
|
||
independent history; `wiki/log.md` stays the root-level rollup and never
|
||
duplicates a change a subdirectory log already recorded.
|
||
|
||
### External Source Connectors & Indexing (on demand)
|
||
A `libs/<name>/` folder supports a second population mode alongside the
|
||
existing git-copy one: a small user-authored `libs/<name>/source.yaml`
|
||
declaring a *live* external source — a SharePoint folder, a Google Drive
|
||
folder, a plain URL, or another connector — that you don't want to fully
|
||
mirror locally:
|
||
```yaml
|
||
connector: sharepoint
|
||
location: "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Reports"
|
||
description: "Finance team's shared reports folder"
|
||
refresh_interval_days: 7 # optional, defaults to 30
|
||
```
|
||
`refresh_interval_days` tunes cadence per source — a folder that churns
|
||
daily deserves a shorter window than a quarterly archive that barely moves
|
||
— and sets the `freshness_window_days` stamped on that source's generated
|
||
pages. Both "index external sources" and "Lint" report a source that's
|
||
overdue against it, and say by how much, so a read-only user knows which
|
||
admin to chase rather than quietly trusting a copy three weeks past due.
|
||
|
||
Say "index external sources" and the agent walks it, resolving `connector`
|
||
to whatever live tool is available that session (a connected Microsoft
|
||
365/Google Drive MCP tool, or `WebFetch` for a plain URL), and builds a
|
||
self-contained generated index inside that same `libs/<name>/` —
|
||
`index.md`/`entities/`/`graph/`/`log.md`, mirroring `wiki/`'s own shape via
|
||
the Recursive Index & Log Convention above, but scoped entirely to that one
|
||
connector. This is a deliberate design choice: the index is **not** blended
|
||
into the main `wiki/entities/`/`wiki/graph/edges.json` — it stays separated
|
||
at the `libs/` cascade layer, the same way a git-cloned KB's own files
|
||
already are. `source.yaml` itself stays user-only, never written by the
|
||
agent.
|
||
|
||
Two refinements on top of that:
|
||
|
||
- **Shared, pre-built indexes.** `source.yaml` can add an optional `index:`
|
||
block declaring *where the already-built index lives* — a git repo, or a
|
||
shared resource such as a network path or another connector-reachable
|
||
location:
|
||
```yaml
|
||
index:
|
||
store: git # git | shared
|
||
location: "https://github.com/org/finance-index-cache.git"
|
||
ref: main # optional — branch, tag, or subpath hint within that store
|
||
```
|
||
Every run checks that location: if it already has an index, fetch it —
|
||
most people just read what's already there instead of building it
|
||
themselves. If it doesn't yet, that's the normal first-time state, not an
|
||
error: a write-access user's very next run is what creates and publishes
|
||
it there, with no separate "initialize" step.
|
||
- **Read vs. write, per user, per source.** Whether *this* user can
|
||
actually rebuild an index (versus only read a fetched/published one) is a
|
||
separate, local, gitignored `libs/<name>/source.local.yaml` — read-only
|
||
by default. Setting `access: write` there opts a given machine/user in as
|
||
that source's admin, so a team can designate one or two people to
|
||
maintain a source while everyone else just reads the result — no
|
||
redundant rebuilding, no need for every user to have their own connector
|
||
authorization.
|
||
|
||
Implemented as a Claude Code Skill — see
|
||
`.agents/skills/ckb-index-external/SKILL.md`.
|
||
|
||
### Dual-Linking (Wikilinks + Markdown)
|
||
Every cross-reference uses both `[[Wikilinks]]` (Obsidian-compatible) and
|
||
standard `[markdown](path.md)` links. Works in Obsidian graph view, GitHub
|
||
rendering, and CLI tools. Upstream references use full relative paths:
|
||
`linked/<name>/...` or `libs/<name>/...`. Intra-wiki references prefer
|
||
project-root-absolute paths (`/wiki/entities/foo.md`) over relative ones,
|
||
so links survive later file moves.
|
||
|
||
### Self-Healing Lint
|
||
Periodically (or on demand), the agent health-checks the wiki:
|
||
- **Conformance** — flags any page missing parseable frontmatter or a `type` field
|
||
- **Freshness** — flags pages past their `freshness_window_days`
|
||
- **Confidence decay** — reduces confidence on unreinforced pages
|
||
- **Retention sweep** — archives `retention: low` pages past 2× window
|
||
- **Supersession detection** — finds contradictions, links old→new
|
||
- **Orphan detection** — finds pages with no inbound links
|
||
- **Graph consistency** — verifies all edges point to existing entities
|
||
- **Index/log consistency** — verifies every subdirectory has an index.md and no change is double-logged
|
||
- **Source fingerprints** — recomputes each cited source's digest and flags pages whose evidence has actually changed, not merely aged
|
||
- **Crux verbatimness** — flags a quoted excerpt that no longer appears in the source it cites
|
||
- **Connector cadence** — flags a connector-backed source whose generated index is overdue against its `refresh_interval_days`, and by how much
|
||
- **Error Book** — records systemic issues with root cause and fix
|
||
|
||
Auto-fixes what it can (broken links, missing backlinks, stale flags), and
|
||
reminds you to review the result and run "sync changes" to push it to
|
||
`origin` once you're happy with it. Implemented as a Claude Code Skill —
|
||
see `.agents/skills/ckb-lint/SKILL.md` — rather than baked into
|
||
`CLAUDE.md`/`AGENTS.md`, so the full checklist only loads into context when
|
||
actually invoked.
|
||
|
||
### Conflict Resolution (Supersession)
|
||
When new information contradicts an existing page, the agent adds
|
||
`supersedes` / `superseded_by` links. The old page is preserved but
|
||
marked stale. Version control for knowledge, not just files.
|
||
|
||
### Quality Scoring
|
||
Every page gets a quality score (0.0–1.0) on write, based on structure,
|
||
source citations, and consistency with the rest of the wiki. Pages below
|
||
0.7 are flagged for review or rewritten in the next lint pass.
|
||
|
||
### Error Book
|
||
Systematic errors (orphan links, formatting issues, cross-page contradictions)
|
||
are recorded in `wiki/error-book.md` with root cause, applied fix, and a
|
||
reusable constraint to prevent recurrence. Two-layer repair:
|
||
- **Layer 1** — deterministic auto-fix for structural issues
|
||
- **Layer 2** — agent reasoning pass for semantic/cross-page issues
|
||
|
||
### Automation Hooks
|
||
- **New source** → auto-ingest on next "Ingest" command
|
||
- **Session start** → load index + latest workload summary; check for
|
||
unsynchronized changes (uncommitted work, or ahead/behind `origin`) and
|
||
suggest `ckb-sync-changes` if any are found
|
||
- **Session end** → compress observations into workload/; re-check for
|
||
unsynchronized changes (including anything the session itself just
|
||
created) and suggest `ckb-sync-changes` if needed
|
||
- **Query** → file back valuable answers as wiki pages
|
||
- **Memory write** → check contradictions, trigger supersession
|
||
- **Schedule** → periodic lint, consolidation, retention decay
|
||
|
||
### Demand-Driven Context (DDC)
|
||
The wiki grows based on actual agent failures rather than upfront curation:
|
||
1. Agent can't answer → identifies missing knowledge
|
||
2. Proposes minimal entity/page to fill the gap
|
||
3. User approves or provides source material
|
||
4. Next ingest incorporates it
|
||
|
||
Converges to a stable KB after ~20–30 cycles.
|
||
|
||
### Session Summaries
|
||
After every conversational action, the agent appends to
|
||
`workload/YYYY-MM-DD_summary.md`. This provides continuity between sessions
|
||
and a browsable history of how the KB evolved. The agent reads the latest
|
||
summary on session start to pick up where it left off.
|
||
|
||
### Change Log
|
||
Every wiki modification is immediately logged in `wiki/log.md` in reverse
|
||
chronological order (most recent first), recording what changed, why, and
|
||
the source.
|
||
|
||
### OKF Export (on demand)
|
||
The wiki can be exported as an [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
|
||
v0.1-conformant bundle at `outputs/okf/`, consumable by any generic OKF tool
|
||
(e.g. Google's reference graph visualizer) without disturbing the richer
|
||
internal schema (`confidence`/`quality`/`retention`/`supersedes`/dual-linking)
|
||
that OKF doesn't natively understand. Implemented as a Claude Code Skill —
|
||
see `.agents/skills/ckb-export-okf/SKILL.md` — rather than baked into
|
||
`CLAUDE.md`/`AGENTS.md`, so the mapping ruleset only loads into context when
|
||
actually invoked. A deterministic Python script
|
||
(`scripts/export_okf.py`) does the whole transform — frontmatter remapping,
|
||
link rewriting, index and log regeneration, and an OKF conformance pass over
|
||
its own output — so the export is reproducible rather than re-reasoned page
|
||
by page; the agent runs it and relays the report. `outputs/okf/` is
|
||
gitignored — it's a fully-regenerated build artifact, so each machine/tool
|
||
regenerates it on demand rather than carrying it in git history.
|
||
|
||
### Starlight Export (on demand)
|
||
The wiki can also be exported into an Astro + Starlight-consumable form at
|
||
`outputs/starlight/`, producing a human-readable documentation website —
|
||
unlike the OKF export, which targets machine/tool consumption. A
|
||
deterministic Python script (`scripts/export_starlight.py`) handles
|
||
frontmatter remapping, dual-link collapsing, wikilink resolution, asset
|
||
copying, and sidebar generation; the agent's job is just to ask the two
|
||
setup questions (export scope: full runnable scaffold vs. content-only;
|
||
whether to include the log/error-book meta pages) and relay the script's
|
||
report. Also on-demand and skill-only — see
|
||
`.agents/skills/ckb-export-starlight/SKILL.md`. Like `outputs/okf/`,
|
||
`outputs/starlight/` is gitignored as a regenerated build artifact.
|
||
|
||
### Decision Log (on demand)
|
||
Say "record a decision: ..." (or just "we decided ...") to file a numbered
|
||
decision record; ask "what did we decide about X", "who decided that",
|
||
"which decisions are still proposed", or "what superseded decision 3" to get
|
||
it back with the who, when, and status attached. Recording gathers the
|
||
missing fields in a single round rather than an interview, wires the
|
||
supersession links in both directions, adds `decided_by`/`affects` graph
|
||
edges, and logs to `wiki/decisions/log.md`. See
|
||
`.agents/skills/ckb-decide/SKILL.md`.
|
||
|
||
### Guided Onboarding Tours (on demand)
|
||
Ask "onboard me on X" (or "where do I start with X", "mini tour of X") to get
|
||
a short, read-only guided reading order: an overview paragraph plus an
|
||
ordered list of wiki pages to read, built by walking the knowledge graph
|
||
outward from the best-matching page (foundations first, then the topic
|
||
itself, then what builds on it). Never writes to `wiki/`. See
|
||
`.agents/skills/ckb-onboard-me/SKILL.md`.
|
||
|
||
### Project Summary (on demand)
|
||
Ask for "a project summary" (or "where do things stand", "catch me up on the
|
||
project") to regenerate `PROJECT-OVERVIEW.md` at the repo root — a
|
||
one-to-two-page snapshot (overview, project state, actions & status, risks,
|
||
assumptions) synthesized entirely from the current `wiki/` contents and its
|
||
knowledge graph. Always overwritten in full on re-run, never hand-appended
|
||
to. See `.agents/skills/ckb-project-summary/SKILL.md`.
|
||
|
||
### Git Sync (on demand)
|
||
This repo's own git history can be reconciled with its `origin` remote on
|
||
demand: local changes get committed, remote changes get pulled and merged,
|
||
any conflicts are presented to the user file-by-file to resolve, then the
|
||
result is pushed automatically. Say "sync changes" to trigger it. Also
|
||
implemented as a Claude Code Skill — see
|
||
`.claude/skills/ckb-sync-changes/SKILL.md` — and deliberately distinct from the
|
||
content-level "Sync the wiki" / "Ingest" workflow, which processes
|
||
`raw/inbox/` into structured `wiki/` pages and has nothing to do with git.
|
||
|
||
### Quiz Mode (on demand)
|
||
Ask to be quizzed on the wiki ("quiz me on X", "test my knowledge") for a
|
||
one-off, scored knowledge check: the agent reads the relevant pages,
|
||
generates open or multiple-choice questions grounded in specific wiki
|
||
facts, runs them one at a time with immediate feedback and a running
|
||
score, and closes with a verdict. Stateless — nothing is saved between
|
||
runs. See `.agents/skills/ckb-quiz/SKILL.md`.
|
||
|
||
### Guided Teaching Curriculum (on demand)
|
||
Ask to be taught the wiki ("teach me the wiki", "teach me about X", "run a
|
||
teaching session") for a stateful course rather than a one-off quiz. First
|
||
call plans it: scopes the material (optionally supplementing thin spots
|
||
from the web, clearly marked as non-authoritative), asks whether it should
|
||
be one session or a spaced series (duration, frequency, optional calendar
|
||
`.ics` reminders), chunks the content into session-sized portions —
|
||
preferring an extra session over cramming — and saves the accepted plan
|
||
and a progress tracker to `outputs/teaching/<topic>/`. Later calls compare
|
||
plan against progress, teach the next portion using a different technique
|
||
each time (Socratic questioning, analogies, worked examples, teach-back,
|
||
mnemonics, ...), spot-check retention, and re-teach weak spots before
|
||
advancing. Never writes to `wiki/`. See
|
||
`.agents/skills/ckb-teach-me/SKILL.md`.
|
||
|
||
---
|
||
|
||
## Quick Start
|
||
|
||
1. **Mount upstream KBs:**
|
||
```bash
|
||
ln -s /path/to/other-kb ./linked/my-upstream
|
||
git clone https://github.com/org/external-kb ./libs/external-kb
|
||
```
|
||
Or, for a live source you don't want to fully mirror, drop a
|
||
`libs/<name>/source.yaml` instead (see "External Source Connectors &
|
||
Indexing" above) and say "index external sources."
|
||
|
||
2. **Drop raw material** into `raw/inbox/` (notes, links, articles).
|
||
|
||
3. **Tell an agent to "Ingest"** — it processes the inbox, consults the
|
||
cascade, extracts entities, and writes structured markdown into `wiki/`.
|
||
|
||
4. **Ask questions** — the agent uses the index for routing, TLDRs for
|
||
quick answers, and the graph for relationship discovery.
|
||
|
||
5. **Periodically ask to "Lint"** — the agent health-checks everything,
|
||
auto-fixes what it can, and reports issues.
|
||
|
||
---
|
||
|
||
## Agent Instruction Files
|
||
|
||
| File | Purpose |
|
||
|------|---------|
|
||
| `AGENTS.md` | Full instruction for any AI coding agent |
|
||
| `CLAUDE.md` | Symlink to `AGENTS.md`, auto-detected by Claude Code |
|
||
|
||
Skills live in one shared location, `.agents/skills/`, so any agent tooling
|
||
that reads that convention picks them up. `.claude/skills` is a symlink to
|
||
`.agents/skills` — Claude Code sees the same skill set without a second
|
||
copy to keep in sync.
|
||
|
||
---
|
||
|
||
## Tips
|
||
|
||
- Upstream KBs (`linked/` and git-copy `libs/`) are **never modified** by
|
||
agents. A connector-backed `libs/<name>/` (one with a `source.yaml`) is
|
||
the one exception — the agent owns and maintains its generated index,
|
||
but only for a user who's opted themselves into `access: write` locally
|
||
(see the next point); everyone else's copy stays read-only.
|
||
- To correct upstream content, write the correct version in `wiki/` — it wins.
|
||
- Use `raw/inbox/` for anything unprocessed; the agent clears it on ingest.
|
||
- The `wiki/index.md` routing table is the most important file — keep it current.
|
||
- Confidence, quality, and freshness let you trust the right content and
|
||
flag the rest for review.
|
||
- The `tmp/` directory is gitignored, and so is most of `libs/` — but not
|
||
all of it: a git-copy `libs/<name>/`'s cloned content stays gitignored as
|
||
before, while a connector-backed `libs/<name>/`'s `source.yaml` and its
|
||
generated `index.md`/`entities/`/`graph/`/`log.md` are tracked, since
|
||
they're synthesized knowledge worth sharing via "sync changes," not a
|
||
disposable build artifact. `libs/<name>/source.local.yaml` (per-user
|
||
read/write setting) is the one exception that stays gitignored right
|
||
alongside them — it's personal machine state, never meant to sync.
|
||
`outputs/` itself is
|
||
tracked, but its regenerated build subdirectories, `outputs/okf/` and
|
||
`outputs/starlight/`, are gitignored — each is fully reproducible from
|
||
`wiki/` on demand, so there's nothing to reconcile by carrying it in git
|
||
history. `outputs/teaching/` (per-user learning plans and session
|
||
progress from the teaching skill) is also gitignored, since it's
|
||
personal session state rather than shared KB content. Commit other,
|
||
hand-maintained artifacts under `outputs/` as normal.
|
||
|
||
---
|
||
|
||
## Version & License
|
||
|
||
Current template version: [VERSION](VERSION). Licensed under the
|
||
[Apache License 2.0](LICENSE).
|