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
- func CandidateHash(candidates []Candidate) string
- func InsertLinks(body string, insertions []Insertion) string
- func IsHub(topicRel string) bool
- type Candidate
- type Generator
- type Insertion
- type MentionRef
- type Neighbours
- type Options
- type Outcome
- type Plan
- type Report
- type Targets
- type Thresholds
Constants ¶
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).
const ( OriginMention = "mention" OriginStructure = "structure" OriginLexical = "bm25" OriginVector = "vector" )
Candidate origins, recorded for dry runs and tests.
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").
const ( SkipUnchanged = "unchanged" SkipNoCandidates = "no-candidates" SkipLocked = "locked" SkipChanged = "changed" SkipUserKey = "user-key" SkipQuarantined = "quarantined" SkipNotFound = "not-found" )
Skip reasons reported in Report.Skipped.
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 ¶
CandidateHash is the hash of the sorted candidate paths recorded in the state row as `link_candidates` (spec §9.4 incremental runs).
func InsertLinks ¶
InsertLinks returns body with `[[<form>|<text>]]` at every insertion. Insertions must not overlap; they are applied from the end so offsets stay valid.
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) Candidates ¶
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.
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 ¶
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 ¶
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 ¶
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.
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 ¶
NewTargets builds the target helper over the vault index files. topicPrefix is the vault-relative slash path of the topic root.
func (*Targets) Form ¶
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>]]`.
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.