link

package
v0.0.11 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package link relates a topic's documents to its wiki articles (spec §9): code proposes candidates (mentions, BM25, shared structure, optional semantic neighbours), the decision model judges one request per document, and code writes frontmatter relations and body links under write policy (d). kb only adds links; it never removes one.

Index

Constants

View Source
const (
	// MaxCandidates caps the merged candidate list per document.
	MaxCandidates = 20
	// LexicalTopK is the number of BM25 neighbours kept per document.
	LexicalTopK = 15
	// VectorTopK is the number of optional semantic neighbours asked for.
	VectorTopK = 10
)

Candidate limits (spec §9.1).

View Source
const (
	OriginMention   = "mention"
	OriginStructure = "structure"
	OriginLexical   = "bm25"
	OriginVector    = "vector"
)

Candidate origins, recorded for dry runs and tests.

View Source
const (
	// BankID is the question bank asked by link.
	BankID = "link"
	// CandidatesBank is the state-row bank key holding the candidate hash.
	CandidatesBank = "link_candidates"
	// InsertedLinksFile is the log of every body link kb inserted, under
	// <topic>/.decisions/.
	InsertedLinksFile = "inserted-links.jsonl"
)

State and bank bookkeeping (plan "Bank ids recorded in state rows").

View Source
const (
	SkipUnchanged    = "unchanged"
	SkipNoCandidates = "no-candidates"
	SkipLocked       = "locked"
	SkipChanged      = "changed"
	SkipUserKey      = "user-key"
	SkipQuarantined  = "quarantined"
	SkipNotFound     = "not-found"
)

Skip reasons reported in Report.Skipped.

View Source
const (
	RelationRelated     = "related"
	RelationContradicts = "contradicts"

	// KeyAffects is the source → article relation written from affects_{id}.
	KeyAffects = "affects"
)

Relation names written by link (spec §6, §9.3).

Variables

This section is empty.

Functions

func CandidateHash

func CandidateHash(candidates []Candidate) string

CandidateHash is the hash of the sorted candidate paths recorded in the state row as `link_candidates` (spec §9.4 incremental runs).

func InsertLinks(body string, insertions []Insertion) string

InsertLinks returns body with `[[<form>|<text>]]` at every insertion. Insertions must not overlap; they are applied from the end so offsets stay valid.

func IsHub

func IsHub(topicRel string) bool

IsHub reports whether a topic-relative path is a hub file that is never a link candidate or a linked document (`log.md`, indexes, `CLAUDE.md`, ...).

Types

type Candidate

type Candidate struct {
	// ID is the element name used in question ids (`c1`, `c2`, ...).
	ID        string
	Path      string
	Title     string
	Aliases   []string
	Criterion string
	Summary   string
	Origins   []string
}

Candidate is one article proposed as a link target for a document.

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator proposes link candidates by code only: alias/title mentions, BM25 over articles, shared structure and optional semantic neighbours.

func NewGenerator

func NewGenerator(articles []*corpus.Document, neighbours Neighbours) *Generator

NewGenerator indexes articles (hub files are dropped) for candidate generation. neighbours may be nil.

func (*Generator) Articles

func (g *Generator) Articles() []*corpus.Document

Articles returns the indexed (non-hub) articles.

func (*Generator) Candidates

func (g *Generator) Candidates(ctx context.Context, doc *corpus.Document) []Candidate

Candidates returns at most MaxCandidates articles for doc, never doc itself, merged in this order: mentions (text order), shared structure (existing body links to articles, articles named in `concepts`, articles sharing ≥2 concepts or a `sources` entry), BM25 top 15, semantic neighbours. IDs are assigned in merged order.

func (*Generator) Mentions

func (g *Generator) Mentions(doc *corpus.Document, candidates []Candidate) []corpus.Mention

Mentions returns the mentions in doc's body of the given candidates, in text order.

type Insertion

type Insertion struct {
	Target   string // candidate path
	Form     string
	Relation string
	Text     string
	Start    int
	End      int
	P        float64
	Receipt  string
}

Insertion is one body link kb inserts (apply) or proposes (shadow).

type MentionRef

type MentionRef struct {
	N int
	// Candidate is the candidate ID the mention points to.
	Candidate string
	Start     int
	End       int
	Text      string
	Sentence  string
}

MentionRef is one mention asked about in the judgment: `mention_sense_{N}`.

type Neighbours

type Neighbours interface {
	Neighbours(ctx context.Context, doc *corpus.Document, k int) ([]string, error)
}

Neighbours proposes semantic neighbours of a document (optional qmd vector search, spec §9.1 step 4). It returns topic-relative article paths best first. Scores never enter bands. A nil Neighbours turns the source off.

type Options

type Options struct {
	// Paths limits the run to these topic-relative documents (ingest); empty
	// means every document of the topic.
	Paths []string
	// All relinks documents whose body and candidate set are unchanged.
	All bool
	// DryRun asks (cached) decisions but writes nothing: no files, state
	// rows, queue items or inserted-links rows.
	DryRun bool
	// Neighbours is the optional semantic-neighbour source (nil = off).
	Neighbours Neighbours
}

Options configures Run.

type Outcome

type Outcome struct {
	// Updates are the owned-key writes (relation lists, affects).
	Updates map[string]any
	// Added lists, per key, the targets newly added.
	Added map[string][]string
	// Insertions are the body links to insert (apply mode only).
	Insertions []Insertion
	// Items are review-queue items to add.
	Items          []review.Item
	Proposals      int
	Reviews        int
	Contradictions int
	Demotions      int
	Undecided      int
}

Outcome is the write policy's verdict for one document.

func Decide

func Decide(plan Plan, answers map[string]decisions.Answer, th Thresholds, bodyMode string) Outcome

Decide applies write policy (d) (spec §9.3) to the answers of one judgment. It is pure: nothing is written.

  • should_link ≥ Apply: the target is added to the list of the argmax relation (`none` or relation confidence < 0.5 → `related`) unless the document already lists it under any relation, in both modes; `contradicts` never applies and becomes a contradiction item.
  • an applied target with a mention whose mention_sense ≥ Mention gets one body link at its first qualifying mention: inserted when bodyMode is apply, else proposed as a `link` review item.
  • Review ≤ should_link < Apply: a `link` review item.
  • below Apply, a target kb itself wrote to a relation list becomes a `link` demotion item; nothing is ever removed.
  • affects_{id} ≥ Affects on a source: the target is added to `affects`.

Every answer the policy consumes counts in Undecided when it is missing or undecided (should_link, relation at or above Review, the mention_sense answers read for a body link, affects); the target is then left alone rather than judged "no", and the caller keeps the document retryable.

type Plan

type Plan struct {
	Doc        *corpus.Document
	Candidates []Candidate
	Mentions   []MentionRef
	// Forms maps candidate path → relation target form (stem or vault path).
	Forms map[string]string
	// Relations holds the document's current relation lists (raw entries)
	// for every relation key and `affects`.
	Relations map[string][]string
	// Present maps key → candidate paths already listed under that key.
	Present map[string]map[string]bool
	// KBOwned reports keys whose current value kb wrote (value hash equals
	// the state row's written hash).
	KBOwned map[string]bool
	// BodyLinked lists candidate paths the body already links to.
	BodyLinked map[string]bool
}

Plan is everything the write policy needs about one document, computed by code before the judgment.

type Report

type Report struct {
	DryRun    bool
	BodyMode  string
	Documents int
	Judged    int
	// Applied counts new targets per relation key (and `affects`).
	Applied        map[string]int
	Inserted       int
	Proposals      int
	Reviews        int
	Demotions      int
	Contradictions int
	// Undecided counts undecided answers.
	Undecided int
	// Decided counts judged documents whose every answer was decided.
	Decided int
	// UndecidedDocuments lists, sorted, the judged documents with an
	// undecided answer: they keep no link bookkeeping, so the next run
	// judges them again (through the cache for the decided answers).
	UndecidedDocuments []string
	Skipped            map[string]int
	// Changes lists what was (or, in a dry run, would be) changed.
	Changes []string
}

Report summarizes a link run.

func Reverse

func Reverse(ctx context.Context, s *session.Session, articlePath string) (Report, error)

Reverse is the backlink audit of spec §9.4: every document mentioning the article's title or aliases is judged with that article as its only candidate. It does not touch the incremental link bookkeeping.

func ReverseAll

func ReverseAll(ctx context.Context, s *session.Session, articlePaths []string) (Report, error)

ReverseAll runs the reverse pass for each article in turn (spec §9.4: an article was created or gained aliases) and merges the reports. The corpus is reloaded between articles so a document written for one article is read fresh for the next.

func Run

func Run(ctx context.Context, s *session.Session, opts Options) (Report, error)

Run links the topic's documents (spec §9.4): new or changed documents by default, every document with All, only Paths when set.

func (Report) Lines

func (r Report) Lines() []string

Lines renders the report for the terminal.

type Targets

type Targets struct {
	// contains filtered or unexported fields
}

Targets renders relation targets and resolves existing link targets for one topic against the vault index (spec §6, plan "Relation target form").

func NewTargets

func NewTargets(index *resolve.Index, files []resolve.File, topicPrefix string) *Targets

NewTargets builds the target helper over the vault index files. topicPrefix is the vault-relative slash path of the topic root.

func (*Targets) Form

func (t *Targets) Form(topicRel string) string

Form returns the relation target of the topic document at topicRel: its file stem, or its vault-relative path without `.md` when the stem is ambiguous across the vault. Callers wrap it as `[[<form>]]`.

func (*Targets) Resolve

func (t *Targets) Resolve(fromTopicRel, target string) string

Resolve returns the topic-relative path a link target written in the document at fromTopicRel points to, or "" when it resolves to nothing in the topic.

func (t *Targets) Wikilink(topicRel string) string

Wikilink returns the quoted-list entry for a relation target: `[[<form>]]`.

type Thresholds

type Thresholds struct {
	Apply   float64 // link_apply
	Review  float64 // link_review
	Mention float64 // mention_sense
	Affects float64 // affects
}

Thresholds are the named gates of the write policy.

func ThresholdsFrom

func ThresholdsFrom(s *session.Session) Thresholds

ThresholdsFrom reads the link thresholds of a session.

Jump to

Keyboard shortcuts

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