Sync: local changes as of 2026-08-06T08:40:06+02:00
This commit is contained in:
parent
f4cabdaeab
commit
6dd8a30f3b
14 changed files with 519 additions and 43 deletions
|
|
@ -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.3–0.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.3–0.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
|
||||
---
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 0–10 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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
53
MANUAL.md
53
MANUAL.md
|
|
@ -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` |
|
||||
|
|
|
|||
88
MANUAL.pl.md
88
MANUAL.pl.md
|
|
@ -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` |
|
||||
|
|
|
|||
77
README.md
77
README.md
|
|
@ -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 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, 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
|
||||
|
|
|
|||
121
README.pl.md
121
README.pl.md
|
|
@ -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 0–10 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ą
|
||||
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.2.1
|
||||
1.3.0
|
||||
|
|
|
|||
|
|
@ -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.)*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
kb_schema_version: "1.2"
|
||||
kb_schema_version: "1.3"
|
||||
---
|
||||
|
||||
# Knowledge Base Index
|
||||
|
|
|
|||
12
wiki/log.md
12
wiki/log.md
|
|
@ -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.
|
||||
|
|
|
|||
29
workload/2026-07-30_summary.md
Normal file
29
workload/2026-07-30_summary.md
Normal 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 0–10 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 4–6 to 5–7.
|
||||
- `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.
|
||||
Loading…
Add table
Reference in a new issue