Sync: local changes as of 2026-08-06T08:40:06+02:00

This commit is contained in:
Michał Kopeć 2026-08-06 08:40:06 +02:00
parent f4cabdaeab
commit 6dd8a30f3b
14 changed files with 519 additions and 43 deletions

View file

@ -94,6 +94,12 @@ connector: sharepoint # sharepoint | google_drive | web | custom — open
location: "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Reports"
description: "Finance team's shared reports folder" # optional
refresh_interval_days: 7 # optional — how often a write-access run should rebuild this source,
# and the freshness_window_days stamped on its generated pages.
# Omit to use the default of 30. Tune per source: a busy folder
# that changes daily deserves a shorter window than a quarterly
# reports archive that barely moves.
index: # optional — omit entirely for the original default: the index lives only
# here, in this repo, tracked by this repo's own git (nothing to fetch/publish)
store: git # git | shared — open string, where the built index is published to / fetched from
@ -183,6 +189,15 @@ This is the one place access level actually changes behavior:
from here on; Step 8 is what actually creates the remote copy either
way.
Either way, compare the existing index's newest `last_updated` against
this source's `refresh_interval_days` (default 30) and say where it
stands. A read-only user needs to know they're reading a copy that's three
weeks past due so they can go ask the admin rather than quietly trusting
it; a write-access user is about to rebuild anyway, but "this was 40 days
stale" is worth saying, because a source that's routinely overdue is
either configured with too tight an interval or has nobody actually
maintaining it. Both are worth surfacing rather than silently correcting.
### Step 5 — Resolve the connector and enumerate/summarize documents
Resolve `connector` to whatever live tool is actually available this
@ -215,7 +230,8 @@ tldr: ...
confidence: 0.30.9 # per the rule above
quality: ...
last_updated: YYYY-MM-DD
freshness_window_days: 30 # shorter than a typical wiki page — external sources change without notice
freshness_window_days: 30 # this source's refresh_interval_days, or 30 if unset — shorter than a
# typical wiki page, because external sources change without notice
retention: medium
---
```
@ -253,7 +269,7 @@ tldr: One sentence — who/what this is, and what these documents specifically s
confidence: 0.30.9
quality: ...
last_updated: YYYY-MM-DD
freshness_window_days: 30
freshness_window_days: 30 # or this source's refresh_interval_days, if set
retention: medium
---
```

View file

@ -63,6 +63,17 @@ libraries, concepts, systems. Create entity pages at
relationships between entities — `uses`, `depends_on`, `caused`,
`contradicts`, `supersedes` — as edge data in `wiki/graph/edges.json`.
Also record `has_expertise_in` and `owns` edges when the material actually
evidences them: `has_expertise_in` when a person demonstrably answers
questions or explains decisions on a topic, `owns` when they hold
declared responsibility for a system, area, or decision. These are what
make "who knows about X" and "who owns X" answerable as a direct graph
lookup instead of a full-text guess (see `ckb-retrieve` Step 3). Record
them only from demonstrated evidence — someone being present in a meeting
or cc'd on a thread is not expertise, and don't infer ownership from job
title alone. Both are optional, like every other edge type; an absent
edge is better than a fabricated one.
For recurring teams, clients, systems, or initiatives, consider whether a
plain project scope page under `wiki/projects/<name>.md` would make future
queries easier to route. A scope page should list when to use it, included
@ -95,9 +106,30 @@ structured distillation before writing the final page:
- `High-signal excerpts` for dense technical paragraphs or consecutive
messages that would be lost in a single summary.
If a high-signal excerpt is substantial enough to answer future questions
on its own, keep it as its own section or linked page rather than burying
it inside a broad transcript summary.
"High-signal" needs an acceptance test, or every excerpt looks worth
keeping and the page becomes a second copy of the transcript. Promote a
run of text to its own section or linked page only when it clears all
three:
- **It carries a rare term.** Something specific enough that a future
search would use it — a config flag, an error string, a hostname, a
contract clause, a version number. Check with `rg -c` across `wiki/`:
if the term already appears on many pages it isn't a distinguishing
handle, and the excerpt adds no findability the summary doesn't have.
- **It's substantial.** Roughly 200 characters or more, or a few
consecutive paragraphs/messages from one author. A one-line "yes, do
that" is a resolution to fold into `Resolution`, not an excerpt.
- **Something corroborates it.** It was agreed with, acted on, corrected,
or referred back to later in the material. An unanswered assertion is a
claim, not a settled fact — keep it in the summary with that ambiguity
intact rather than promoting it.
Fail any one of the three and the content still belongs in the page, just
inside `Summary`/`Resolution` rather than as its own retrievable unit.
When you do promote an excerpt, carry its parent topic with it — the
thread question or section heading it sat under. An excerpt that reads
unambiguously on its own is the entire point; one that needs the
surrounding transcript to make sense hasn't been extracted, only moved.
### Step 5 — Link and cross-reference

View file

@ -124,9 +124,20 @@ doesn't need an Error Book entry — this is for patterns, not incidents.
For each `libs/<name>/source.yaml`, verify it has a non-empty `connector`
and `location` — report only, this file is never edited by any skill. If
an `index:` block is present, verify it has a non-empty `store` and
`location` too. Also flag (report only) a `libs/<name>/` that ambiguously
has both real content files and a `source.yaml` — that's a configuration
conflict for the user to resolve, not something to guess at.
`location` too. If `refresh_interval_days` is present, verify it's a
positive integer. Also flag (report only) a `libs/<name>/` that
ambiguously has both real content files and a `source.yaml` — that's a
configuration conflict for the user to resolve, not something to guess at.
Report any connector-backed source whose generated index is overdue:
newest `last_updated` in `libs/<name>/` older than its
`refresh_interval_days` (default 30). Report it the same way whether or
not this user has write access — a read-only user can't fix it, but
knowing which source to chase the admin about is the actionable part. Name
how overdue it is rather than just "stale," since a source two days past a
7-day interval is a different situation from one six months past a 30-day
one. Never re-index here; that's `ckb-index-external`'s job, and suggesting
it is as far as this check goes.
Don't flag a missing `libs/<name>/source.local.yaml` as an issue — its
absence is the correct, read-only default (see `ckb-index-external`), not

View file

@ -87,11 +87,20 @@ its Sources. Keep the shortlist to what's plausibly relevant; this isn't
If index/TLDR matching is not enough, run a local hybrid pass before
giving up: use `rg` for exact tokens across `wiki/`, `raw/archive/`,
`outputs/`, and readable upstream indexes; combine those hits with
project-scope matches, entity/title/TLDR matches, graph proximity,
freshness, confidence, and quality. Prefer exact text matches for error
strings, commands, flags, filenames, hostnames, IDs, and other literals;
prefer entity/semantic matches for paraphrased questions.
`outputs/`, `raw/inbox/`, and readable upstream indexes; combine those
hits with project-scope matches, entity/title/TLDR matches, graph
proximity, freshness, confidence, and quality. Prefer exact text matches
for error strings, commands, flags, filenames, hostnames, IDs, and other
literals; prefer entity/semantic matches for paraphrased questions.
Sweep `raw/inbox/` even though nothing there has been ingested yet.
Material dropped an hour ago can already hold the answer, and finding it
there is also the clearest possible signal that an `ckb-ingest` run is
overdue — mention that. Say plainly when an answer rests on un-ingested
inbox material rather than on a synthesized page.
Keep each signal's hits as its own ranked list rather than merging them by
eye as you go. Step 4 needs the separate orderings.
### Step 3 — Walk the graph for anything the shortlist missed
@ -100,22 +109,70 @@ connector's own `graph/edges.json`), follow `depends_on`/`uses`/`caused`
edges one hop out to catch a connected page the index text match alone
wouldn't have surfaced.
### Step 4 — Expand local context and build an evidence packet
For "who knows about X" and "who owns X" questions — both advertised in
the trigger phrases above — the graph is the primary lookup rather than a
fallback. Read the `has_expertise_in` and `owns` edges pointing at the
topic entity and answer from the people or teams on the other end,
ordered by how many distinct sources evidence each edge. Where no such
edge exists yet, fall back to authorship evidence: who the `## Sources`
material actually shows answering questions on that topic. Say which of
the two grounded the answer, since an inferred expert is a weaker claim
than a recorded one.
For every result that might ground the answer, keep a small evidence
packet with:
### Step 4 — Fuse the signals, dedupe, then rerank
Signals disagree, and none of them is trustworthy alone: an exact `rg` hit
can sit in a page that answers a different question, and a confident TLDR
match can be a loose paraphrase of something stale. Don't settle that by
picking a favourite signal — fuse the ranked lists from Step 2.
**Fuse.** For every candidate, sum `weight / (k + rank)` across each list
it appears in, where `rank` is its 1-based position in that list. Use
`k = 10` and a default `weight` of 1.0. A page ranked third in three
different lists beats one ranked first in a single list; consensus is the
whole point.
`k = 10` is deliberately smaller than the `k = 60` rank fusion is usually
quoted with. 60 is tuned for retrievers returning hundreds of candidates,
and against the dozen-or-so a local wiki produces it flattens every score
into near-identical values. Raise a list's weight when the question
warrants it — for a pasted error string, command, flag, or ID, weight the
exact-match list around 2.0, because no amount of title/TLDR similarity
should outrank a literal match on the token the user actually pasted.
**Dedupe.** Collapse candidates carrying the *same claim* into one entry
before ranking further. Step 6 actively manufactures these: a `wiki/`
page, the `raw/archive/` file it cites, and a connector-index page whose
`resource:` points back at that same wiki page are three hits for one
fact. Keep whichever sits closest to the primary material and record the
others as corroboration, not as independent evidence. Three views of one
claim are not three sources.
**Rerank.** Score each surviving candidate 010 on how well it answers
*the literal question asked*, not on how well it matches the query's
vocabulary, then keep the best handful and drop the rest. This is the same
agent making a deliberate second pass, not a separate model. The point is
that relevance judgment happens explicitly, over the shortlist, in one
place — rather than being folded silently into how the final answer gets
drafted.
### Step 5 — Expand local context and build an evidence packet
For every result that survived Step 4, keep a small evidence packet with:
- source path or connector resource
- matched claim or short excerpt
- source date or `last_updated`
- freshness/confidence/quality signals, when available
- project-scope or graph relationship hints, when relevant
- which signals it was fused from, its rerank score, and anything it
absorbed during dedupe — this is what Step 7 draws caveats from
When a match is a section, heading, or snippet inside a larger Markdown
file, include nearby headings/paragraphs before deciding what it means.
Avoid answering from an isolated fragment when the neighboring context
changes the interpretation.
### Step 5 — Follow every page on the shortlist to its source before answering from it
### Step 6 — Follow every page on the shortlist to its source before answering from it
This is the step this skill exists to enforce. For each page on the
shortlist that will actually ground part of the answer:
@ -148,7 +205,7 @@ deck doesn't need a full read every time, just enough (search for the
name/topic, read the surrounding context) to confirm the point actually
being used.
### Step 6 — Reconcile and answer
### Step 7 — Reconcile and answer
If the source confirms the index, answer normally — but note what
grounded it (e.g. "per the kickoff transcript cited in
@ -162,6 +219,17 @@ exist to eventually catch, so mention it's worth a lint pass if the gap
looks like more than a one-off, but don't rewrite the wiki page yourself
mid-answer unless the user asks for that separately.
State caveats in the answer itself, not only in the metadata you read to
build it. When a page grounding the answer is past its
`freshness_window_days`, carries a low `confidence` or `quality`, rests on
un-ingested `raw/inbox/` material, or was checked against a cached
connector index rather than a live re-fetch, say so in a short clause next
to the claim it qualifies. Surface a conflict between two live pages the
same way, even when neither is marked `superseded_by` yet. The metadata
already exists and Step 4 already put it in front of you; the failure mode
is answering confidently *from* a stale or contested page without passing
that on, which leaves the reader no way to weigh it.
If no page anywhere is even plausibly relevant, say so — don't verify
against a source that has nothing to do with the question just to appear
thorough, and don't fabricate an answer either. For durable missing
@ -172,6 +240,11 @@ that would close the gap. If you edit `wiki/query-gaps.md`, update
## Edge cases
- **Only one signal returned anything** — fusion is a no-op, so don't run
the arithmetic for show. The rerank still applies (it's the check that
the one list actually answers the question rather than merely matching
its wording), and dedupe still applies as soon as Step 6 pulls in a
page's own cited source.
- **A cited source file no longer exists** (moved, renamed, or cleaned
up) — say so plainly rather than silently falling back to the `tldr` as
if it had been verified. Flag it as a likely `ckb-lint` finding (a

View file

@ -86,7 +86,7 @@ retention: high|medium|low
---
```
`wiki/index.md` alone also carries `kb_schema_version`, currently `"1.2"`.
`wiki/index.md` alone also carries `kb_schema_version`, currently `"1.3"`.
Detailed schema migration and version-bump policy belongs in
`ckb-upgrade`.
@ -112,7 +112,9 @@ file.
Short routing rules:
- For questions, use `ckb-retrieve`; it owns project scopes, hybrid local
search, evidence packets, source verification, and query-gap capture.
search, rank fusion across signals, dedupe/rerank, expertise and
ownership lookups, evidence packets, source verification, answer
caveats, and query-gap capture.
- For "Ingest", "Sync the wiki", or "Update the wiki", use `ckb-ingest`.
- For "Index external sources", "index libs", or "refresh the external
index", use `ckb-index-external`.

View file

@ -105,6 +105,13 @@ which stay entirely read-only. There are three ways to mount one:
committed, never seen by anyone else). This is deliberate: it lets one
or two people maintain a source for the whole team instead of everyone
redundantly re-scanning it.
- **You can set how often it should be refreshed.** Add an optional
`refresh_interval_days: 7` to `source.yaml` (it defaults to 30). A
folder that churns daily wants a shorter window than a quarterly
archive nobody touches. Both "index external sources" and "Lint" then
tell you when a source is overdue and by how much — which matters most
if you're read-only for it, since knowing *which* source has gone
stale is what lets you go ask the person who maintains it.
Either way, once it's mounted, just ask questions normally — the agent
checks your local `wiki/` first, then walks `linked/`, then `libs/`, and
@ -143,6 +150,17 @@ Example:
> reminding you to review the result and say "sync changes" once you're
> happy with it.
For a long transcript, the agent doesn't just write one summary page. It
pulls out the searchable question, the summary, the resolution, the systems
and people involved — and promotes individual passages to their own
findable sections when they'd otherwise be lost inside a summary. That last
part has a deliberate bar: a passage has to contain a genuinely specific
term (a flag, an error string, a clause, a version), run to a couple of
sentences at least, and be corroborated by something later in the material.
Otherwise it stays folded into the summary. Without that bar every
paragraph looks quotable and the wiki page ends up being the transcript
again, which defeats the point of ingesting it.
If `raw/inbox/` is empty, the agent scans `raw/` directly instead (still
skipping `raw/archive/`, which is already-processed history).
@ -206,6 +224,9 @@ This runs a health check across the whole wiki:
- orphaned pages (nothing links to them) get backlinked or archived
- broken graph edges get fixed or removed
- missing/duplicate index and log entries get corrected
- connector-backed sources whose index is overdue for a refresh get
flagged, with how overdue they are — useful even if you're read-only for
that source, since it tells you who to chase
- recurring systemic issues get written into `wiki/error-book.md`
It fixes what it safely can on its own, and reports the rest for you to
@ -369,6 +390,32 @@ knowledge graph for connected facts, and falls back to `linked/`/`libs/` if
the local wiki has nothing. You get an answer grounded in what's actually
written down, not a guess.
Two things about that worth knowing as a user:
- **It searches `raw/inbox/` too.** Something you dropped in this morning
and haven't ingested yet can still answer your question. The agent will
tell you when an answer came from un-ingested material, which doubles as
a nudge that "Ingest" is overdue.
- **Answers carry their own caveats.** If the page behind an answer is past
its freshness window, scored low on confidence, or was read from a cached
connector index instead of a live check, the answer says so next to the
claim. If two pages disagree and neither has been marked superseded yet,
you'll hear about that too. The point is that you never have to go read
the frontmatter yourself to know how much to trust what you just got.
### Ask who knows something
> "Who knows about the checkpoint restore path?" / "Who owns the billing
> service?"
These are answered from the knowledge graph directly rather than by
keyword-searching for names. Ingest records an expertise or ownership edge
when the source material actually shows someone answering questions on a
topic or holding declared responsibility for it — not from having attended
a meeting or from a job title. If nobody has a recorded edge yet, the agent
falls back to who the archived sources show answering that kind of question
and tells you it's inferring rather than reporting.
When there is still no answer, the agent should tell you what is missing
and either add/propose a short entry in `wiki/query-gaps.md` or suggest the
smallest source to drop into `raw/inbox/`.
@ -471,6 +518,7 @@ Example:
> connector: sharepoint
> location: "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Reports"
> description: "Finance team's shared reports folder"
> refresh_interval_days: 7
> ```
> *then say "Index external sources."*
>
@ -554,7 +602,7 @@ graph stay in sync with what you changed.
| `raw/archive/<date>/` | Agent | Auto-filed copy of what you dropped in `raw/inbox/`, organised by ingestion date. Don't hand-file here — let Ingest do it, so the date and pairing with the log entry stay accurate. |
| `linked/<name>/` | **You** (you create the symlink) | Points at another KB's real files, which live and get edited *in that other repo* — never here. The agent must never write inside `linked/`. |
| `libs/<name>/` (git-copy, no `source.yaml`) | **You** (you `git clone`) | A frozen copy of an external KB. Update it by re-pulling that repo yourself, not by hand-editing files here. The agent must never write inside it. |
| `libs/<name>/source.yaml` (connector) | **You, only** | Declares the connector, location, and optionally where a shared/pre-built index lives (`index:`). The agent reads it but never writes it — same as anything else upstream. |
| `libs/<name>/source.yaml` (connector) | **You, only** | Declares the connector, location, optionally how often it should be refreshed (`refresh_interval_days:`), and optionally where a shared/pre-built index lives (`index:`). The agent reads it but never writes it — same as anything else upstream. |
| `libs/<name>/source.local.yaml` (connector) | **You** (or the agent, only when you explicitly ask to become/stop being that source's admin) | Per-person, per-machine `access: write`/`read` setting — never committed, never seen by anyone else. Absent = read-only, the default. |
| `libs/<name>/{index.md,entities/,graph/,log.md}` (connector) | Agent-generated, **you can freely edit** | The agent's own index of that one connector's source, built/refreshed by "Index external sources" — but only if you have `access: write` locally; read-only users just get a fetched copy. Structurally the same deal as the main `wiki/` row below — feel free to correct an entry by hand, then run "Lint" (it now also checks connector-backed indexes, respecting the same read/write split). Scoped entirely to that connector; never blended into `wiki/`. |
| `wiki/` (pages, `index.md`, `overview.md`, `log.md`, `error-book.md`, `entities/`, `graph/`) | Agent-generated, **you can freely edit** | This is the one place the agent both writes and expects you might too. Feel free to correct a page by hand — just keep the frontmatter fields intact (or update `last_updated`), and run Lint afterward if you touched something the index/graph/log reference. |
@ -584,4 +632,5 @@ graph stay in sync with what you changed.
| "Export the wiki to Starlight" | Human-readable docs site at `outputs/starlight/` | `ckb-export-starlight` |
| "Upgrade the wiki" / "Check for a newer template version" | Checks template + wiki schema versions against the canonical repo, upgrades what you accept | `ckb-upgrade` |
| "Index external sources" / "Index libs" | Builds/refreshes a self-contained index for each connector-backed `libs/<name>/` | `ckb-index-external` |
| Just ask a question | Answers from the wiki, using the index/TLDR/graph cascade | — (core query workflow) |
| Just ask a question | Answers from the wiki, using the index/TLDR/graph cascade, with caveats when a source is stale or contested | `ckb-retrieve` |
| "Who knows about X" / "Who owns X" | Answers from expertise/ownership edges in the graph | `ckb-retrieve` |

View file

@ -110,6 +110,14 @@ podpięcia:
niewidoczny dla współpracowników). To celowe: pozwala jednej lub dwóm
osobom utrzymywać źródło dla całego zespołu, zamiast żeby każdy
redundantnie je skanował.
- **Możesz ustawić, jak często ma być odświeżane.** Dodaj opcjonalne
`refresh_interval_days: 7` do `source.yaml` (domyślnie 30). Folder
zmieniający się codziennie potrzebuje krótszego okna niż kwartalne
archiwum, którego nikt nie tyka. Wtedy zarówno „index external
sources", jak i „Lint" powiedzą ci, kiedy źródło jest zaległe i o ile —
co ma największe znaczenie, jeśli masz do niego dostęp tylko do
odczytu, bo wiedza o tym, *które* źródło się przedawniło, pozwala
zapytać osobę, która je utrzymuje.
Niezależnie od sposobu, po podpięciu wystarczy normalnie zadawać pytania —
agent sprawdza najpierw twoją lokalną `wiki/`, potem przechodzi przez
@ -149,6 +157,17 @@ Przykład:
> `raw/archive/2026-07-10/`. Na koniec przypomina o przejrzeniu wyniku i
> powiedzeniu „sync changes”, gdy będziesz zadowolony.
Przy długim transkrypcie agent nie pisze po prostu jednej strony
podsumowania. Wyciąga wyszukiwalne pytanie, podsumowanie, rozwiązanie oraz
zaangażowane systemy i osoby — a pojedyncze fragmenty awansuje do własnych
znajdowalnych sekcji, jeśli inaczej przepadłyby wewnątrz podsumowania. Ta
ostatnia część ma celowy próg: fragment musi zawierać naprawdę konkretny
termin (flagę, komunikat błędu, klauzulę, numer wersji), mieć co najmniej
kilka zdań i być potwierdzony przez coś dalej w materiale. W przeciwnym razie
zostaje wtopiony w podsumowanie. Bez tego progu każdy akapit wygląda na wart
zacytowania, a strona wiki znów staje się transkryptem — co przekreśla sens
jego zingestowania.
Jeśli `raw/inbox/` jest puste, agent skanuje bezpośrednio `raw/` (nadal
pomijając `raw/archive/`, które zawiera już przetworzoną historię).
@ -179,6 +198,21 @@ ingest to wchłonie. Dzięki temu wiki pozostaje napędzana zapotrzebowaniem:
rośnie wokół tego, o co faktycznie pytasz, a nie wokół wszystkiego, co
teoretycznie dałoby się spisać.
Trwałe braki można też śledzić w `wiki/query-gaps.md`. Dobry wpis o luce jest
maleńki: pytanie, gdzie agent szukał i jakie najmniejsze źródło lub strona
sprawiłaby, że odpowiedź będzie dostępna następnym razem.
### D. Utwórz lokalny zakres projektu
Gdy jakiś temat, klient, system lub inicjatywa wraca często, poproś:
> „Utwórz zakres projektu dla integracji płatności."
Agent utworzy lub zaktualizuje zwykłą stronę Markdown pod `wiki/projects/`,
wymieniającą strony, encje, pliki z `raw/archive/`, indeksy konektorów i
obszary grafu, które należy przeszukać najpierw dla tego zakresu. Nadal masz
jedną lokalną wiki; to tylko daje powracającym pytaniom lepszy punkt startowy.
---
## 3. Utrzymanie porządku
@ -201,6 +235,9 @@ To uruchamia przegląd kondycji całej wiki:
albo są archiwizowane
- uszkodzone krawędzie grafu są naprawiane lub usuwane
- brakujące/podwójne wpisy w indeksie i dzienniku są poprawiane
- konektorowe źródła, których indeks jest zaległy do odświeżenia, zostają
oflagowane wraz z informacją o ile — przydatne nawet jeśli masz do tego
źródła dostęp tylko do odczytu, bo mówi ci, kogo dopytać
- powtarzające się problemy systemowe trafiają do `wiki/error-book.md`
Naprawia samodzielnie to, co może zrobić bezpiecznie, a resztę zgłasza do
@ -363,11 +400,46 @@ Po prostu zapytaj, zwykłym językiem:
> „Co wiemy o ryzyku migracji w Q3?”
Agent najpierw czyta `wiki/index.md`, żeby znaleźć odpowiednie strony,
sprawdza ich jednolinijkowy `tldr` przed załadowaniem pełnej strony,
przechodzi po grafie wiedzy w poszukiwaniu powiązanych faktów i sięga do
`linked/`/`libs/`, jeśli lokalna wiki nic nie ma. Dostajesz odpowiedź
opartą na tym, co faktycznie zostało spisane, a nie na domysłach.
Agent najpierw czyta `wiki/index.md`, żeby znaleźć odpowiednie strony. Jeśli
istnieje pasujący zakres projektu pod `wiki/projects/`, przeszukuje najpierw
ten zakres. Potem sprawdza jednolinijkowe pola `tldr`, w razie potrzeby
uruchamia dokładne wyszukiwanie lokalne dla literalnych tokenów, rozszerza
kontekst wokół dopasowanych sekcji, przechodzi po grafie wiedzy w poszukiwaniu
powiązanych faktów i sięga do `linked/`/`libs/`, jeśli lokalna wiki nic nie ma.
Dostajesz odpowiedź opartą na tym, co faktycznie zostało spisane, a nie na
domysłach.
Dwie rzeczy warte wiedzenia jako użytkownik:
- **Przeszukuje też `raw/inbox/`.** Coś, co wrzuciłeś dziś rano i czego jeszcze
nie zingestowałeś, nadal może odpowiedzieć na twoje pytanie. Agent powie ci,
kiedy odpowiedź pochodzi z niezingestowanego materiału, co jednocześnie
sygnalizuje, że „Ingest" jest zaległy.
- **Odpowiedzi noszą własne zastrzeżenia.** Jeśli strona stojąca za odpowiedzią
przekroczyła okno świeżości, ma niską pewność albo została przeczytana z
zapisanego indeksu konektora zamiast z żywego źródła, odpowiedź mówi o tym
obok danego twierdzenia. Jeśli dwie strony są ze sobą sprzeczne, a żadna nie
została jeszcze oznaczona jako zastąpiona, też o tym usłyszysz. Chodzi o to,
żebyś nigdy nie musiał sam czytać frontmatteru, by wiedzieć, na ile zaufać
temu, co właśnie dostałeś.
Gdy nadal nie ma odpowiedzi, agent powinien powiedzieć, czego brakuje, i albo
dodać/zaproponować krótki wpis w `wiki/query-gaps.md`, albo zasugerować
najmniejsze źródło do wrzucenia do `raw/inbox/`.
### Pytanie, kto się na czymś zna
> „Kto zna się na ścieżce przywracania checkpointów?" / „Kto jest właścicielem
> usługi billingowej?"
Na te pytania odpowiada bezpośrednio graf wiedzy, a nie wyszukiwanie nazwisk po
słowach kluczowych. Ingest zapisuje krawędź eksperctwa lub własności, gdy
materiał źródłowy faktycznie pokazuje, że ktoś odpowiada na pytania w danym
temacie albo ma zadeklarowaną odpowiedzialność za niego — a nie na podstawie
obecności na spotkaniu czy nazwy stanowiska. Jeśli nikt nie ma jeszcze
zapisanej krawędzi, agent wraca do tego, kogo zarchiwizowane źródła pokazują
jako odpowiadającego na tego rodzaju pytania, i mówi ci, że wnioskuje, a nie
raportuje.
### Nauka z wiki
@ -472,6 +544,7 @@ Przykład:
> connector: sharepoint
> location: "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Reports"
> description: "Wspólny folder raportów zespołu finansowego"
> refresh_interval_days: 7
> ```
> *potem mówisz „Index external sources.”*
>
@ -562,7 +635,7 @@ zmieniłeś.
| `raw/archive/<data>/` | Agent | Automatycznie zarchiwizowana kopia tego, co wrzuciłeś do `raw/inbox/`, uporządkowana według daty ingestu. Nie umieszczaj tu plików ręcznie — pozwól, żeby zrobił to Ingest, tak by data i powiązanie z wpisem w dzienniku były poprawne. |
| `linked/<name>/` | **Ty** (tworzysz dowiązanie symboliczne) | Wskazuje na rzeczywiste pliki innej KB, które żyją i są edytowane *w tamtym repozytorium* — nigdy tutaj. Agent nigdy nie może zapisywać wewnątrz `linked/`. |
| `libs/<name>/` (kopia git, bez `source.yaml`) | **Ty** (robisz `git clone`) | Zamrożona kopia zewnętrznej KB. Aktualizujesz ją, ponownie pobierając to repozytorium samodzielnie, a nie ręcznie edytując pliki tutaj. Agent nigdy nie może zapisywać wewnątrz niej. |
| `libs/<name>/source.yaml` (konektor) | **Tylko ty** | Deklaruje konektor, lokalizację i opcjonalnie gdzie znajduje się współdzielony/wcześniej zbudowany indeks (`index:`). Agent go czyta, ale nigdy nie zapisuje — tak jak wszystko inne nadrzędne. |
| `libs/<name>/source.yaml` (konektor) | **Tylko ty** | Deklaruje konektor, lokalizację, opcjonalnie jak często ma być odświeżany (`refresh_interval_days:`) i opcjonalnie gdzie znajduje się współdzielony/wcześniej zbudowany indeks (`index:`). Agent go czyta, ale nigdy nie zapisuje — tak jak wszystko inne nadrzędne. |
| `libs/<name>/source.local.yaml` (konektor) | **Ty** (albo agent, tylko gdy wyraźnie poprosisz o zostanie/przestanie bycia administratorem tego źródła) | Osobiste, per-komputer ustawienie `access: write`/`read` — nigdy niecommitowane, nigdy niewidoczne dla innych. Brak = tylko do odczytu, domyślnie. |
| `libs/<name>/{index.md,entities/,graph/,log.md}` (konektor) | Generowane przez agenta, **możesz swobodnie edytować** | Własny indeks agenta dla tego jednego źródła konektora, budowany/odświeżany przez „Index external sources” — ale tylko jeśli masz lokalnie `access: write`; użytkownicy tylko-do-odczytu dostają po prostu pobraną kopię. Strukturalnie ta sama zasada jak przy wierszu `wiki/` poniżej — śmiało popraw wpis ręcznie, a potem uruchom „Lint” (teraz sprawdza też indeksy oparte na konektorach, respektując ten sam podział odczyt/zapis). Ograniczone wyłącznie do tego konektora; nigdy nie wmieszane w `wiki/`. |
| `wiki/` (strony, `index.md`, `overview.md`, `log.md`, `error-book.md`, `entities/`, `graph/`) | Generowane przez agenta, **możesz swobodnie edytować** | To jedyne miejsce, w którym zarówno agent zapisuje, jak i spodziewa się, że ty też możesz. Śmiało popraw stronę ręcznie — zachowaj tylko pola frontmatteru (lub zaktualizuj `last_updated`) i uruchom potem Lint, jeśli dotknąłeś czegoś, do czego odwołuje się indeks/graf/dziennik. |
@ -592,4 +665,5 @@ zmieniłeś.
| „Export the wiki to Starlight” | Czytelna dla człowieka strona dokumentacji w `outputs/starlight/` | `ckb-export-starlight` |
| „Upgrade the wiki” / „Check for a newer template version” | Sprawdza wersje szablonu i schematu wiki względem kanonicznego repozytorium, aktualizuje to, co zaakceptujesz | `ckb-upgrade` |
| „Index external sources” / „Index libs” | Buduje/odświeża samodzielny indeks dla każdego `libs/<name>/` opartego na konektorze | `ckb-index-external` |
| Po prostu zadaj pytanie | Odpowiedź z wiki, przy użyciu kaskady indeks/TLDR/graf | — (podstawowy przepływ zapytań) |
| Po prostu zadaj pytanie | Odpowiedź z wiki, przy użyciu kaskady indeks/TLDR/graf, z zastrzeżeniami gdy źródło jest nieaktualne lub sprzeczne | `ckb-retrieve` |
| „Kto wie o X" / „Kto jest właścicielem X" | Odpowiedź z krawędzi eksperctwa/własności w grafie | `ckb-retrieve` |

View file

@ -80,6 +80,17 @@ 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),
@ -106,7 +117,9 @@ question, the agent falls back to the full cascade.
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
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
@ -114,9 +127,48 @@ signals before answering:
- 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 010 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, and relationship or scope
hints. No server, vector database, or dedicated client is required.
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.
### Query Gaps
If the cascade cannot answer a question, the agent records or proposes a
@ -151,16 +203,18 @@ retention: high|medium|low
- **freshness_window_days** — pages older than this get flagged during lint
- **retention** — low pages are archived after 2× freshness window
`wiki/index.md` alone also carries `kb_schema_version` (e.g. `"1.2"`), declaring
`wiki/index.md` alone also carries `kb_schema_version` (e.g. `"1.3"`), 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 (`uses`, `depends_on`, `caused`, `contradicts`, `supersedes`)
are recorded in `wiki/graph/edges.json`. Queries can walk the graph to
discover connected pages (e.g. "what depends on Redis?").
relationships are recorded in `wiki/graph/edges.json` — structural ones
(`uses`, `depends_on`, `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/`,
@ -180,7 +234,15 @@ mirror locally:
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
@ -240,6 +302,7 @@ Periodically (or on demand), the agent health-checks the wiki:
- **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
- **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

View file

@ -75,6 +75,25 @@ się do kontekstu tylko wtedy, gdy jest faktycznie wywoływana. Odrębne od
skilla `ckb-sync-changes`, który jest czysto operacją na poziomie gita, bez
syntezy wiki.
Dla długich rozmów, notatek ze spotkań, transkryptów lub eksportów czatu
ingest używa strukturalnej destylacji, zamiast traktować cały plik jako jedną
niezróżnicowaną bryłę: wyszukiwalne pytanie, krótkie podsumowanie,
rozwiązanie lub decyzja, odniesienia do systemów/kodu, zaangażowane osoby
oraz fragmenty o wysokiej wartości, które zasługują na to, by pozostać
znajdowalne samodzielnie.
„Wysoka wartość" to jawny test, a nie ocena uznaniowa — inaczej każdy
fragment wygląda na wart zachowania, a strona staje się drugą kopią
transkryptu. Fragment zasługuje na własną wyszukiwalną sekcję tylko wtedy,
gdy zawiera termin rzadki w całej wiki (sprawdzane przez `rg -c` — wyróżniający
uchwyt wyszukiwania, a nie słowo już obecne na dwudziestu stronach), ma około
200 znaków lub więcej i jest potwierdzony przez coś dalej w materiale, co się
z nim zgadza, działa na jego podstawie lub go koryguje. Niespełnienie choćby
jednego warunku oznacza, że treść nadal trafia na stronę, tylko wewnątrz
podsumowania, a nie jako osobna jednostka. Awansowane fragmenty zabierają ze
sobą nagłówek nadrzędny lub pytanie wątku, żeby dały się jednoznacznie
czytać samodzielnie.
### Leniwie ładowany indeks z wyzwalaczami „Use When"
`wiki/index.md` to tabela routingu. Każdy wpis ma kolumnę **Use when** z
listą słów kluczowych wyzwalających. Agent najpierw czyta indeks (pozostaje
@ -87,6 +106,86 @@ Podczas zapytania agent najpierw czyta TLDR-y. Jeśli TLDR już odpowiada na
pytanie, pełna treść nigdy nie jest ładowana. Łańcuch odwoławczy: TLDR →
treść → surowe źródło.
### Lokalne zakresy projektów
Dla powracających zespołów, klientów, systemów lub inicjatyw wiki może
trzymać zwykłe strony zakresów w formacie Markdown pod `wiki/projects/`.
Strona zakresu wymienia strony wiki, encje, źródła z `raw/archive/`,
konektorowe `libs/`, wyjścia i obszary grafu, które należy przeszukać
najpierw dla danego projektu. Daje to tę samą praktyczną korzyść co
przestrzeń robocza projektu w większym systemie wyszukiwania, pozostając
lokalnym, przejrzystym i edytowalnym w dowolnym edytorze tekstu.
Zakresy zawężają tylko pierwsze przejście. Jeśli wyszukiwanie w zakresie nie
odpowiada na pytanie, agent wraca do pełnej kaskady.
### Lokalne wyszukiwanie hybrydowe
Gdy routing po indeksie/TLDR nie wystarcza, agent może połączyć kilka
lokalnych sygnałów przed odpowiedzią:
- dokładne wyszukiwanie tekstu przez `rg` dla komunikatów błędów, komend,
flag, nazw plików, nazw hostów, identyfikatorów zgłoszeń i innych
literalnych tokenów — również w `raw/inbox/`, więc materiał wrzucony
godzinę temu i jeszcze nie zingestowany nadal może odpowiedzieć na pytanie
(i sygnalizuje, że ingest jest zaległy)
- dopasowania semantyczne/encyjne z tytułów stron, TLDR-ów, zakresów
projektów i relacji w grafie
- metadane świeżości i pewności, dzięki którym nieaktualne lub słabe strony
są traktowane ostrożnie
- rozszerzenie kontekstu wokół dopasowanej sekcji, aby odpowiedzi były
osadzone w sąsiadujących nagłówkach i akapitach, a nie w samotnym urywku
Każdy sygnał tworzy własną listę rankingową, a listy są następnie łączone,
zamiast rozstrzygania przez wybór ulubionego sygnału: każdy kandydat zbiera
`weight / (k + rank)` zsumowane po listach, na których występuje, więc strona
na trzecim miejscu w trzech listach wygrywa ze stroną pierwszą w jednej.
`k` wynosi 10, celowo mniej niż zwykle cytowane 60 — 60 jest dostrojone do
wyszukiwarek zwracających setki kandydatów i spłaszcza wszystkie wyniki do
niemal identycznych wartości przy kilkunastu, które daje lokalna wiki.
Zapytania o literalne tokeny podnoszą wagę listy dokładnych dopasowań,
ponieważ żadne podobieństwo tytułu nie powinno wyprzedzić trafienia w dokładny
ciąg, który ktoś wklejił.
Połączeni kandydaci są następnie deduplikowani według twierdzenia — strona
wiki, plik z `raw/archive/`, który cytuje, i strona konektora wskazująca na
nią to trzy trafienia dla jednego faktu, nie trzy źródła — i przerankowani w
skali 010 według tego, jak dobrze odpowiadają na dosłownie zadane pytanie, a
nie jak dobrze pasują do jego sformułowania. Ten sam agent, świadome drugie
przejście, bez osobnego modelu.
Wynik jest wewnętrznie normalizowany jako pakiet dowodowy: ścieżka źródła,
dopasowane twierdzenie, data/świeżość, pewność/jakość, wskazówki o relacjach
lub zakresie oraz informacja, z których sygnałów każdy kandydat został
połączony. Nie jest wymagany żaden serwer, baza wektorowa ani dedykowany
klient.
### Zastrzeżenia w odpowiedziach
Metadane, które wiki już śledzi, są podawane w samej odpowiedzi, a nie tylko
sprawdzane przy jej budowaniu. Gdy strona stanowiąca podstawę odpowiedzi
przekroczyła `freshness_window_days`, ma niską `confidence`/`quality`, opiera
się na niezingestowanym materiale z `raw/inbox/` lub została sprawdzona
względem zapisanego w pamięci indeksu konektora, a nie żywego źródła —
odpowiedź mówi o tym obok twierdzenia, którego to dotyczy. Konflikty między
dwiema aktywnymi stronami są ujawniane tak samo, nawet jeśli żadna nie ma
jeszcze `superseded_by`. Zamyka to tryb awarii polegający na pewnej
odpowiedzi *z* nieaktualnej strony bez przekazania tej informacji dalej.
### Wyszukiwanie ekspertów i właścicieli
„Kto wie o X" i „kto jest właścicielem X" to bezpośrednie zapytania do grafu,
a nie zgadywanie po pełnym tekście. Ingest zapisuje krawędzie
`has_expertise_in`, gdy ktoś wykazuje się odpowiadaniem na pytania lub
wyjaśnianiem decyzji w danym temacie, oraz krawędzie `owns` dla zadeklarowanej
odpowiedzialności za system, obszar lub decyzję — oba wyłącznie na podstawie
wykazanych dowodów, nigdy wnioskowane z obecności na spotkaniu czy ze
stanowiska. Gdy krawędzi jeszcze nie ma, wyszukiwanie wraca do dowodów
autorstwa i mówi, które z dwóch stanowiło podstawę odpowiedzi, bo domniemany
ekspert to słabsze twierdzenie niż zapisany.
### Luki w zapytaniach
Jeśli kaskada nie potrafi odpowiedzieć na pytanie, agent zapisuje lub proponuje
krótki wpis w `wiki/query-gaps.md`: o co pytano, gdzie szukał i jakie
najmniejsze źródło lub strona zamknęłaby lukę. Dzięki temu nieudane
wyszukiwania stają się użytecznym sygnałem zapotrzebowania dla następnego
ingestu, zamiast przepadać w historii czatu.
### Schemat frontmatteru strony
Każda strona wiki używa frontmatteru YAML. Pole `type` jest wymagane; reszta
jest opcjonalna:
@ -121,7 +220,7 @@ retention: high|medium|low
- **retention** — strony o niskim priorytecie są archiwizowane po 2× oknie
świeżości
Sam `wiki/index.md` dodatkowo zawiera `kb_schema_version` (np. `"1.1"`),
Sam `wiki/index.md` dodatkowo zawiera `kb_schema_version` (np. `"1.3"`),
deklarujący, według której wersji tego schematu wiki została napisana —
zwiększaj wersję pomniejszą dla dodatkowych opcjonalnych pól, główną dla
zmian łamiących kompatybilność.
@ -129,9 +228,11 @@ zmian łamiących kompatybilność.
### Ekstrakcja encji i graf wiedzy
Podczas ingestu agent wydobywa typowane encje (osoby, projekty, biblioteki,
koncepcje, systemy) i zapisuje je jako strony w `wiki/entities/`. Typowane
relacje (`uses`, `depends_on`, `caused`, `contradicts`, `supersedes`) są
zapisywane w `wiki/graph/edges.json`. Zapytania mogą przechodzić po grafie,
aby odkrywać powiązane strony (np. „co zależy od Redis?").
relacje są zapisywane w `wiki/graph/edges.json` — strukturalne (`uses`,
`depends_on`, `caused`, `contradicts`, `supersedes`) oraz łączące osoby z
tematami (`has_expertise_in`, `owns`). Zapytania mogą przechodzić po grafie,
aby odkrywać powiązane strony (np. „co zależy od Redis?") albo bezpośrednio
odpowiadać na „kto wie o X".
### Rekurencyjna konwencja indeksu i dziennika
Każdy podkatalog `wiki/`, który grupuje wiele stron (`entities/`, `graph/`,
@ -151,7 +252,16 @@ URL albo inny konektor — którego nie chcesz w pełni kopiować lokalnie:
connector: sharepoint
location: "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Reports"
description: "Wspólny folder raportów zespołu finansowego"
refresh_interval_days: 7 # opcjonalne, domyślnie 30
```
`refresh_interval_days` dostraja częstotliwość per źródło — folder zmieniający
się codziennie zasługuje na krótsze okno niż kwartalne archiwum, które prawie
nie drgnie — i ustawia `freshness_window_days` nadawane generowanym stronom
tego źródła. Zarówno „index external sources", jak i „Lint" raportują źródło
zaległe względem tej wartości i mówią o ile, żeby użytkownik z dostępem tylko
do odczytu wiedział, kogo zapytać, zamiast po cichu polegać na kopii sprzed
trzech tygodni.
Powiedz „index external sources", a agent go przeskanuje, dopasowując
`connector` do dowolnego żywego narzędzia dostępnego w danej sesji
(połączonego narzędzia MCP do Microsoft 365/Google Drive, albo `WebFetch`
@ -219,6 +329,9 @@ Okresowo (lub na żądanie) agent sprawdza kondycję wiki:
istniejące encje
- **Spójność indeksu/dziennika** — weryfikuje, czy każdy podkatalog ma
index.md i czy żadna zmiana nie jest podwójnie logowana
- **Częstotliwość konektorów** — oznacza konektorowe źródło, którego
generowany indeks jest zaległy względem `refresh_interval_days`, wraz z
informacją o ile
- **Księga błędów (Error Book)** — zapisuje systemowe problemy wraz z
przyczyną i naprawą

View file

@ -1 +1 @@
1.2.1
1.3.0

View file

@ -2,6 +2,8 @@
Edge list and relationship data for the knowledge graph, keyed by entity page.
* `edges.json` - Typed relationships (`uses`, `depends_on`, `caused`, `contradicts`, `supersedes`) between entity pages. Created on the first ingest that extracts entities.
* `edges.json` - Typed relationships between entity pages. Created on the first ingest that extracts entities.
* Structural: `uses`, `depends_on`, `caused`, `contradicts`, `supersedes`.
* People-to-topic: `has_expertise_in` (demonstrated ability to answer questions on a topic) and `owns` (declared responsibility for a system, area, or decision). These make "who knows about X" and "who owns X" a direct graph lookup rather than a full-text guess. Recorded only from demonstrated evidence, never inferred from attendance or job title.
*(No edges recorded yet — populated on the next ingest.)*

View file

@ -1,5 +1,5 @@
---
kb_schema_version: "1.2"
kb_schema_version: "1.3"
---
# Knowledge Base Index

View file

@ -1,5 +1,17 @@
# Wiki Change Log
## [2026-07-30 08:40] - [UPDATE]
- **File Affected:** `wiki/index.md`
- **Description:** Bumped `kb_schema_version` from `1.2` to `1.3` — a minor bump for the additive `has_expertise_in`/`owns` graph edge types. No existing field or convention changed meaning.
- **Source:** Chat conversation implementing eight ideas drawn from Cerebras' "How We Built Our Knowledge Base".
---
## [2026-07-30 08:38] - [UPDATE]
- **File Affected:** `wiki/graph/index.md`
- **Description:** Documented two new optional edge types, `has_expertise_in` and `owns`, alongside the existing structural ones, so "who knows about X" / "who owns X" become direct graph lookups. Both are evidence-only — never inferred from meeting attendance or job title.
- **Source:** Chat conversation implementing eight ideas drawn from Cerebras' "How We Built Our Knowledge Base".
---
## [2026-07-29 22:47] - [UPDATE]
- **File Affected:** `wiki/index.md`
- **Description:** Bumped `kb_schema_version` from `1.1` to `1.2` for the new optional project-scope and query-gap scaffold conventions.

View file

@ -0,0 +1,29 @@
## 2026-07-30 08:05 CEST
- User pointed at a local copy of the Cerebras article saved to `tmp/How Cerebras Built Its Enterprise Knowledge Base.html` after two direct `WebFetch` attempts returned HTTP 500.
- Converted it to plain text via `lynx -dump` into the session scratchpad and re-derived the concept list from the primary source, correcting details taken from secondary write-ups in the previous turn.
- Re-listed the ideas not covered by this KB but compatible with a local, file-based, no-install design; excluded the pgvector/HNSW embeddings table, Socket Mode ingestion, CocoIndex chunking, and the hosted cross-encoder reranker as out of scope.
## 2026-07-30 08:20 CEST
- User asked which of those ideas could actually be implemented in the current wiki.
- Read `.agents/skills/ckb-retrieve/SKILL.md` and `.agents/skills/ckb-ingest/SKILL.md` in full, plus the `source.yaml` schema in `ckb-index-external`, the graph edge-type vocabulary, and `.gitignore`'s per-user local-state precedent.
- Found three items from the previous turn's list were already partly covered by the skills (high-signal excerpts in ingest Step 4, `rg` over `raw/archive/` in retrieve Step 2, contradiction-surfacing in retrieve Step 6) and narrowed those claims accordingly.
- Concluded all ten are implementable without dedicated software: seven as prose-only edits to existing skills, three needing one new convention each (an expertise edge type, a `source.yaml` cadence field, a gitignored default-scope file). No implementation performed — assessment only.
## 2026-07-30 09:05 CEST
- User asked to implement the list, then chose all ten minus #5 (planning pass) and #10 (per-user default scope) — the two I'd advised against on value grounds. Eight items implemented.
- `ckb-retrieve`: added `raw/inbox/` to the exact-token sweep, a new Step 4 (RRF-style fusion at `k = 10`, claim-level dedupe, explicit 010 rerank), an expertise/ownership graph lookup in Step 3, caveat surfacing in Step 7, and an edge case for the single-signal case. Renumbered old Steps 46 to 57.
- `ckb-ingest`: replaced the loose "high-signal excerpt" guidance with a three-part acceptance test (rare term via `rg -c`, ~200 chars, corroborated later in the material) plus a rule to carry the parent heading; added `has_expertise_in`/`owns` edge recording, evidence-only.
- `ckb-index-external`: added optional `refresh_interval_days` to `source.yaml` (default 30), wired it into the generated pages' `freshness_window_days` and into Step 4's overdue reporting for both access levels.
- `ckb-lint`: validates `refresh_interval_days` and reports overdue connector indexes with how overdue, regardless of the user's access level; never re-indexes.
- Chose `k = 10` rather than the usual `k = 60` for fusion, since 60 is tuned for hundreds of candidates and flattens scores at local-wiki scale. Recorded the reasoning inline in the skill so it isn't mistaken for a transcription error.
- Bumped `kb_schema_version` 1.2 → 1.3 (additive edge types) and `VERSION` 1.2.1 → 1.3.0; logged both wiki changes in `wiki/log.md` per Rule B.
- Found `README.pl.md`/`MANUAL.pl.md` were behind by more than the version string: five README sections and two MANUAL sections from the 2026-07-29 session had never been translated. Caught both up rather than layering today's changes onto an incoherent base. EN/PL section parity now 28/28 and 15/15.
## 2026-07-30 09:30 CEST
- User asked the reverse comparison: what this KB has that the Cerebras system does not.
- Verified claimed absences by grepping the saved article text rather than asserting from memory — no hits for version/history/supersede/contradict/retention/archive/quality/confidence/entity/ontology/curate/stale/conflict; "graph" only as the HNSW citation, "decay" only as query-time age decay, "audit" once with no detail.
- Framed the answer around the root asymmetry: Cerebras Knowledge is a read path over systems of record it doesn't own, while this KB is itself a system of record that authors and curates content. Noted honestly that the article is a blog post rather than a spec, and that several of this KB's curation features are only tractable at small scale.