Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 62 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ Retrieval is bounded. The high-level `kb search` and `KnowledgeBaseSession.searc

Each note owns its outbound typed relationships in frontmatter. KB derives backlinks, inverse edges, and bounded traversal at read time, so parallel agents do not contend on one generated fact file. `kb percolate <note>` reports recurring concepts and missing-link candidates with inspectable support but writes nothing. An agent reads the cited notes before creating a reusable concept or relationship. Semantic similarity never creates an edge automatically.

Percolation Result V2 presents a missing relationship as an unordered pair of
notes with a required predicate. It does not choose the source, direction, or a
`related-to` fallback. Recommended authored predicates include `synthesizes`,
`evidenced-by`, `informed-by`, `supersedes`, and `contradicts`; they are an
advisory vocabulary, so a vault can use another canonical predicate when its
prose and evidence define the claim. KB never infers reciprocal, inverse,
transitive, or similarity-derived relationships.

Git provenance is opt-in. A search without `--history` performs no Git indexing. `--history` requests best-effort provenance, while `--require-history` rejects unavailable history or incomplete provenance for the selected notes. If one commit exceeds the 2,000-path detail limit, KB retains its identity and vault-local note associations, marks its co-change detail incomplete, and continues through later commits. Best-effort search reports that requested lane as partial.

Local attachment checks cover Markdown and Obsidian references to images, PDFs, and editable tldraw sources. They reject missing or escaping files while leaving external URLs alone. A source-inbox view separately lists recent captures that have no inbound disposition from maintained knowledge. It is an advisory, not an automatic backlink requirement: a saved source may intentionally remain a leaf.
Expand All @@ -187,6 +195,39 @@ The same mixed-cache, single-run test recorded p95 latencies of 44.345 milliseco

Search finds candidates. Similarity does not establish that a passage is current, correct, or supported by its sources. The Markdown, cited captures, explicit relationships, and requested Git history supply the material a reader must inspect.

### Customize through an approved proposal

The Agent Skill routes setup and evolution requests before it prepares a
runtime. It inspects the proposed location without mutation, interviews the
user about the memory questions the KB should answer, and presents exact read
and write targets. Only the approved targets may be scaffolded. A changed path,
repository, account, integration, or companion skill requires renewed
approval.

The standard router may be enough. A recurring ritual can instead receive a
companion skill with explicit inputs, authority, durable outputs, idempotence,
failure behavior, and verification. These skills are inert instructions. They
do not create a plugin runtime, execute vault metadata, inherit ambient account
access, or couple application code to the KB. An exact repeat is a no-op;
divergence, path escape, symbolic links, partial writes, and unapproved
external surfaces stop the workflow.

The repository's fake-capability suite exercises those transitions. It is a
tested contract example, not proof that every agent or host integration
complies.

This workflow builds on Frank Chen's public notes about [designing a personal
knowledge base with an
agent](https://gist.github.com/fxchen/773397095d7a6bffda621e4237da0da9)
and [extending it with
skills](https://gist.github.com/fxchen/09cb410b22c9c5256d80243ee925b57e).

KB ships no `kb_role` metadata, lifecycle resolver or API, lifecycle CLI,
compatibility diagnostic, or metadata migration. A frozen Phase 0 value gate
must show that those surfaces improve deterministic agent decisions before they
are introduced. Current and historical plan routing remains derived from
existing type, path, and status conventions.

### Adopt the smallest useful split

Start with a short inherited `AGENTS.md` path for rules whose omission would make an edit wrong. A small knowledge base may need only Markdown, Git, an index page, and ordinary file search. Add source capture when evidence keeps disappearing. Add repository scopes when agents need to recover current memory from code paths. Add metadata or hybrid search when file search stops answering the repository's questions. Add links and graph views only when the relationships themselves help people make decisions.
Expand All @@ -205,6 +246,11 @@ bytes with status `prepared`, and has no vault, Git, Oh-store, or promotion
capability. KB pins `@hraness/oh` v0.2.0 and delegates closure integrity to its
official store verifier.

The release also adds interview-first setup guidance, a companion-skill
contract, and Percolation Result V2. V2 requires an explicit predicate instead
of inventing `related-to`, while the V1 parser remains available for historical
results throughout the 0.18 release line.

## Upgrade to v0.17.3

Version 0.17.3 restructures the README around an inspectable first task,
Expand Down Expand Up @@ -507,7 +553,12 @@ Predicates use lower-kebab-case. Local targets use exact vault-root IDs without
`.md`; cross-vault targets use canonical stable `kb://` URIs. `kb graph`, `kb backlinks`, `kb relation list`, and `kb links` derive
inverse edges and bounded paths without injecting reciprocal or inferred facts into notes.
`kb percolate` proposes reusable concepts and missing connections with explicit
support; an agent reviews the cited prose before authoring anything.
support; an agent reviews the cited prose before authoring anything. In its V2
result, a missing relationship is an unordered endpoint pair with a required
predicate, never an executable directed assertion or an automatic
`related-to`. Common reviewed claims use `synthesizes`, `evidenced-by`,
`informed-by`, `supersedes`, or `contradicts`; other canonical custom predicates
remain valid when their meaning is supported.

Within a portfolio, a note can target a stable cross-vault identity such as
`kb://hraness/sleepyland/sound-wellness-expansion`. The target vault must be
Expand Down Expand Up @@ -580,8 +631,10 @@ diffs, and the explicit local job ledger are available from
The repository ships one reusable `kb` Agent Skill under `skills/kb/`. Its
intent router loads focused references only when a task needs them: querying
repository context and agent memory, capturing URLs or PDFs, writing durable
plans, promoting concepts and typed relationships, or refreshing and checking
a vault. The package smoke test keeps future tagged packages byte-identical to
plans, promoting concepts and typed relationships, refreshing and checking a
vault, or designing a setup through an interview and approved proposal. An
approved setup may scaffold a bounded companion skill for a distinct recurring
ritual. The package smoke test keeps future tagged packages byte-identical to
that source tree.

```sh
Expand All @@ -591,9 +644,11 @@ bunx skills add hraness/kb#v0.18.0
```

The skill invokes the installed `kb` command without depending on a repository
checkout. Its runtime setup installs the pinned CLI only when the command is
missing, and it never initializes or mutates a vault as an installation side
effect. The repository's phase-orchestration skill remains available to local
repository agents but is marked internal, so public skill discovery omits it.
checkout. It routes setup and evolution before runtime preparation. For
execution workflows, runtime setup installs the pinned CLI only when the
command is missing, and it never initializes or mutates a vault as an
installation side effect. The repository's phase-orchestration skill remains
available to local repository agents but is marked internal, so public skill
discovery omits it.

See [Design](docs/design.md), [Portfolio federation](docs/portfolio.md), [Agent workflow](docs/agent-workflow.md), [PDF capture](docs/pdf.md), and [Contributing](CONTRIBUTING.md) for the durable contracts and development gate. hraness/kb is available under the [MIT License](LICENSE).
4 changes: 2 additions & 2 deletions dist/authoring.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import {
normalizeRelationPredicate,
noteRevision,
removeNoteRelation
} from "./index-01jj6rbv.js";
} from "./index-gxr0fctd.js";
import"./index-3rm7cz6h.js";
import"./index-cxfrakt7.js";
import"./index-ekpwvbra.js";
export {
removeNoteRelation,
noteRevision,
Expand Down
6 changes: 3 additions & 3 deletions dist/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import {
createSyntheticRankFusionFixture,
evaluateRanking,
evaluateRetrievalBenchmark
} from "./index-s2gw5aw9.js";
import"./index-cv6fh7z5.js";
} from "./index-qwgsmtsz.js";
import"./index-gm9t95d9.js";
import"./index-d13v9ckt.js";
import"./index-48pz4jpc.js";
import"./index-06c9ctr6.js";
import"./index-5vwpzb5a.js";
import"./index-cxfrakt7.js";
import"./index-ekpwvbra.js";
export {
evaluateRetrievalBenchmark,
evaluateRanking,
Expand Down
28 changes: 16 additions & 12 deletions dist/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
loadPortfolioRegistry,
openKnowledgePortfolio,
snapshotPortfolioRegistry
} from "./index-jsmvyyvf.js";
} from "./index-ey46z1zf.js";
import {
diffCaptureBundle
} from "./index-j4zgmzjr.js";
Expand All @@ -34,19 +34,19 @@ import {
MAX_PERCOLATION_NOTES,
MAX_SCOPED_PERCOLATION_MENTION_PAIRS,
percolateVault
} from "./index-dyqwejk5.js";
} from "./index-f9fy4w1n.js";
import {
knowledgeBaseEvaluationRetrieverIds,
openKnowledgeBaseEvaluation
} from "./index-n5dd7r0v.js";
} from "./index-xw9ac71d.js";
import {
DEFAULT_SEARCH_RESULTS,
MAX_SEARCH_CANDIDATES,
MAX_SEARCH_NOTE_REFERENCE_BYTES,
MAX_SEARCH_RELATED_SEEDS,
MAX_SEARCH_RESULTS,
openKnowledgeBase
} from "./index-zzhgcwyt.js";
} from "./index-vxmf14m1.js";
import {
MAX_SEARCH_RULE_CONFIG_BYTES,
parseSearchRules
Expand All @@ -59,7 +59,7 @@ import {
refreshVault,
scanVault,
sha256EmbeddingModelFile
} from "./index-zxdy5pby.js";
} from "./index-5m2ydj5q.js";
import"./index-4j3tt0c3.js";
import"./index-1gwbassd.js";
import {
Expand All @@ -79,11 +79,11 @@ import {
addNoteRelation,
createNote,
removeNoteRelation
} from "./index-01jj6rbv.js";
} from "./index-gxr0fctd.js";
import"./index-3rm7cz6h.js";
import {
validateSearchQuery
} from "./index-cv6fh7z5.js";
} from "./index-gm9t95d9.js";
import {
navigateLinks
} from "./index-d13v9ckt.js";
Expand Down Expand Up @@ -111,7 +111,7 @@ import {
lookupNote,
parseVaultKey,
renderCatalog
} from "./index-cxfrakt7.js";
} from "./index-ekpwvbra.js";
import {
main
} from "./index-0kavxzqj.js";
Expand Down Expand Up @@ -2885,7 +2885,7 @@ function renderPercolation(result, note) {
if (candidate.kind === "missing-concept") {
lines.push(` concept #${safe(candidate.tag)} \u2192 ${safe(candidate.suggestedId)} (${candidate.support} supporting notes)` + (candidate.collidesWith === null ? "" : `; natural ID is occupied by ${safe(candidate.collidesWith)}`));
} else if (candidate.kind === "missing-relation") {
lines.push(` relation ${safe(candidate.source)} ${safe(candidate.suggestedPredicate)} ${safe(candidate.target)} (${candidate.support} shared signals)`);
lines.push(` relation pair {${safe(candidate.source)}, ${safe(candidate.target)}} (predicate required; ${candidate.support} shared signals)`);
} else if (candidate.kind === "unlinked-mention") {
lines.push(` mention ${safe(candidate.source)} \u2192 ${safe(candidate.target)} (${candidate.support})`);
} else {
Expand Down Expand Up @@ -2927,12 +2927,16 @@ async function runPercolate(command, output, dependencies) {
minSupport: command.minSupport,
limit: command.limit
});
output.stdout(command.json ? terminalSafeJson({
const jsonOutput = {
root: snapshot.root,
note: command.note ?? null,
minSupport: command.minSupport,
...result
}) : sanitizeTerminalText(renderPercolation(result, command.note)));
limit: command.limit,
schemaVersion: result.schemaVersion,
candidates: result.candidates,
truncated: result.truncated
};
output.stdout(command.json ? terminalSafeJson(jsonOutput) : sanitizeTerminalText(renderPercolation(result, command.note)));
return 0;
}
async function runList(command, output, dependencies) {
Expand Down
10 changes: 5 additions & 5 deletions dist/evaluation-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import {
knowledgeBaseEvaluationRetrieverIds,
openKnowledgeBaseEvaluation,
verifyFrozenEvaluationSnapshot
} from "./index-n5dd7r0v.js";
import"./index-zzhgcwyt.js";
} from "./index-xw9ac71d.js";
import"./index-vxmf14m1.js";
import"./index-adx6khj5.js";
import {
indexSemanticVault,
recommendedEmbeddingModel,
recommendedEmbeddingModelSha256,
scanVault
} from "./index-zxdy5pby.js";
} from "./index-5m2ydj5q.js";
import"./index-4j3tt0c3.js";
import {
runGitCommand
Expand All @@ -22,12 +22,12 @@ import {
MAX_EVALUATION_EVIDENCE_BYTES,
MAX_EVALUATION_RESULTS_PER_QUERY
} from "./index-b88v3vtm.js";
import"./index-cv6fh7z5.js";
import"./index-gm9t95d9.js";
import"./index-d13v9ckt.js";
import"./index-48pz4jpc.js";
import"./index-06c9ctr6.js";
import"./index-5vwpzb5a.js";
import"./index-cxfrakt7.js";
import"./index-ekpwvbra.js";
import"./index-1xxnjn0d.js";

// src/evaluation-builder.ts
Expand Down
10 changes: 5 additions & 5 deletions dist/evaluation-kb.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import {
knowledgeBaseEvaluationRetrieverIds,
openKnowledgeBaseEvaluation,
verifyFrozenEvaluationSnapshot
} from "./index-n5dd7r0v.js";
import"./index-zzhgcwyt.js";
} from "./index-xw9ac71d.js";
import"./index-vxmf14m1.js";
import"./index-adx6khj5.js";
import"./index-zxdy5pby.js";
import"./index-5m2ydj5q.js";
import"./index-4j3tt0c3.js";
import"./index-1gwbassd.js";
import"./index-b88v3vtm.js";
import"./index-cv6fh7z5.js";
import"./index-gm9t95d9.js";
import"./index-d13v9ckt.js";
import"./index-48pz4jpc.js";
import"./index-06c9ctr6.js";
import"./index-5vwpzb5a.js";
import"./index-cxfrakt7.js";
import"./index-ekpwvbra.js";
import"./index-1xxnjn0d.js";
export {
verifyFrozenEvaluationSnapshot,
Expand Down
4 changes: 3 additions & 1 deletion dist/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
catalogEnd,
catalogStart,
isCanonicalNoteId,
isCanonicalRelationPredicate,
lookupNote,
metadataValueFromUnknown,
normalizeVaultPath,
Expand All @@ -17,7 +18,7 @@ import {
replaceCatalog,
searchableMarkdown,
wikiLinks
} from "./index-cxfrakt7.js";
} from "./index-ekpwvbra.js";
export {
wikiLinks,
searchableMarkdown,
Expand All @@ -27,6 +28,7 @@ export {
normalizeVaultPath,
metadataValueFromUnknown,
lookupNote,
isCanonicalRelationPredicate,
isCanonicalNoteId,
catalogStart,
catalogEnd,
Expand Down
4 changes: 2 additions & 2 deletions dist/index-zxdy5pby.js → dist/index-5m2ydj5q.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {
fuseRankedCandidates,
validateSearchQuery
} from "./index-cv6fh7z5.js";
} from "./index-gm9t95d9.js";
import {
MAX_ANALYZED_NOTES,
analyzeVault,
Expand All @@ -12,7 +12,7 @@ import {
parseNote,
renderCatalog,
replaceCatalog
} from "./index-cxfrakt7.js";
} from "./index-ekpwvbra.js";

// src/semantic.ts
import { createHash as createHash2 } from "crypto";
Expand Down
Loading