knowledge

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package knowledge defines the card model and parses the canonical file store. Files are the source of truth; everything here must parse permissively — one bad card is logged and skipped, never fatal.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Commit

func Commit(kdir, message string) error

Commit records the current state of the knowledge dir as one git commit with a structured message — the governance trail: `git log` answers when a card appeared, which pipeline wrote it, and why it changed. Automated commits are authored as "culi" so they are distinguishable from the user's own edits, and they work even without a global git identity.

Best-effort by contract: callers must never fail a pipeline over history. A knowledge dir that is not a git repo returns an error the caller logs and moves on; a clean tree commits nothing and returns nil. The .import staging area is excluded — staged-but-unreviewed content is not knowledge yet (C4's review gate would be meaningless if staging were archived as if applied).

func EstimateTokens

func EstimateTokens(s string) int

EstimateTokens approximates token count without a tokenizer dependency: chars/4 for ASCII-heavy text, runes/1.8 when >20% multibyte (Vietnamese is token-denser). ±15% accuracy is fine — this drives budgets, not billing.

func Render

func Render(c Card) ([]byte, error)

Render serializes a Card back to file bytes: YAML frontmatter + body. yaml.Marshal handles quoting, so summaries containing ": " or quotes can never produce an unparseable card (a hand-rolled writer once did). Round-tripping through Parse loses nothing culi reads, but drops unknown frontmatter keys — Render is for cards culi authors (import, learning), never for rewriting hand-edited files.

func ShortID

func ShortID(cardID string) string

ShortID returns a stable 4-hex-char pointer ID derived from the card ID. Collisions are resolved at index time (store.uniqueShortID appends a decimal suffix deterministically).

func SplitFrontmatter

func SplitFrontmatter(raw []byte) (fm, body []byte, err error)

SplitFrontmatter separates a leading "---" YAML block from the body of any markdown file (cards, but also Claude Code agent/skill files during import). A file without frontmatter returns nil fm and the full raw as body.

func UpdateFile

func UpdateFile(knowledgeDir, relPath string, mutate func(*Card)) error

UpdateFile parses one card file, applies mutate, and rewrites it atomically (temp + rename). ONLY for culi-authored cards — Render drops frontmatter keys culi does not model, so a hand-edited file must never pass through here (C4). Callers gate on Provenance.Source before calling.

Types

type Card

type Card struct {
	ID       string // derived from path: "rules/go-error-wrapping"
	Path     string // relative to the knowledge dir
	Type     string // rule|skill|lesson|style|pattern|agent
	Title    string
	Summary  string
	Body     string
	Scopes   []string // global | lang:<x> | repo:<name> | branch:<repo>@<glob> | dir:<hash>
	Key      string   // optional shadowing key: narrowest scope wins among cards sharing it
	Triggers Triggers
	Aliases  []string // extra FTS keywords (e.g. Vietnamese terms)
	Baseline bool     // part of the SessionStart baseline for its scope
	Status   string   // ""/confirmed | candidate | retired (learning lifecycle)

	// Learning lifecycle (Phase 4): a mined card starts as a candidate with
	// Observations 1 and confirms at 2 (re-learning reinforces instead of
	// duplicating). Supersedes names the card ID this one replaces; the old
	// card is retired when this one confirms.
	Observations int
	Supersedes   string

	ContentHash string // sha256 of raw file content
	TokSummary  int    // estimated tokens, computed at parse time
	TokBody     int

	// Export links a card back to a generated ~/.claude artifact; nil for
	// cards that are knowledge-only. Provenance records where imported or
	// learned content came from. Neither is stored in the SQLite index —
	// files are truth, and only `culi import`/`culi export` read them.
	Export     *ExportMeta
	Provenance *Provenance
}

Card is one atomic unit of knowledge (a rule, lesson, style note, pattern, skill, or agent definition) with three granularities: HookLine (~15 tok), Summary (~60 tok), Body (full markdown).

func Parse

func Parse(relPath string, raw []byte) (Card, error)

Parse builds a Card from raw file bytes. relPath is the path relative to the knowledge dir (it derives the default ID and type). Errors are returned for the caller to log-and-skip — a bad card must never fail an index run.

func ReadCard

func ReadCard(dir, relPath string) (Card, error)

ReadCard loads and parses one card file.

func (Card) NarrowestScopeRank

func (c Card) NarrowestScopeRank(allowed map[string]bool) int

NarrowestScopeRank returns the precedence rank of the card's narrowest in-scope scope: branch(3) > repo(2) > lang(1) > global/dir(0). Used for key-shadowing resolution.

type ExportMeta

type ExportMeta struct {
	Kind        string   `yaml:"kind"` // agent | skill
	Name        string   `yaml:"name"` // basename in ~/.claude/agents or ~/.claude/skills
	Frontmatter string   `yaml:"frontmatter,omitempty"`
	Attachments []string `yaml:"attachments,omitempty"` // skill sibling files, dir-relative
}

ExportMeta describes how `culi export` regenerates a Claude Code agent or skill file from this card. Frontmatter is the verbatim YAML block of the original artifact (without --- delimiters) so exports round-trip exactly.

type FileInfo

type FileInfo struct {
	RelPath string
	MTime   int64
	Size    int64
}

FileInfo describes one card file on disk, cheap enough to stat the whole store per index run (100s–1000s of files).

func Walk

func Walk(dir string) ([]FileInfo, error)

Walk lists every card file under dir. Card files are *.md, excluding dot dirs (.git, .import, .drafts — staging areas are not indexed). For skills, only SKILL.md is a card; sibling files are attachments (Phase 3).

type Provenance

type Provenance struct {
	Source     string   `yaml:"source,omitempty"`      // import | learn | mcp | gen | manual
	MergedFrom []string `yaml:"merged_from,omitempty"` // contributing repo names
	Model      string   `yaml:"model,omitempty"`       // LLM used, if any
	// SourceHash fingerprints the deterministic input a generated card
	// derives from (gitfacts hash) — unchanged input ⇒ regen skips the card.
	SourceHash string `yaml:"source_hash,omitempty"`
}

Provenance records the origin of imported or learned content.

type Triggers

type Triggers struct {
	Keywords []string `yaml:"keywords,omitempty"`
	Globs    []string `yaml:"globs,omitempty"`
}

Triggers pin a card to the top of the ranked list when matched (max 2 pins per injection, enforced by the retriever).

func (Triggers) IsZero

func (t Triggers) IsZero() bool

IsZero lets yaml omitempty drop an empty triggers block when rendering.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL