Documentation
¶
Overview ¶
Package ctxindex is the per-repo context index a card cutter reads so a worker starts from the spec paragraph, the guarding test and the file list instead of exploring for them (nova-tools#2498 S2: an OK card cost 39k-108k input tokens, almost all exploration).
Three indices, each a directory of hash buckets, so a lookup reads the one bucket its key hashes to and never scans (Glenn 2026-09-23: "no linear scans"):
<head>/spec/<b>.json spec ID -> the paragraph it names, where, and its guarding tests <head>/test/<b>.json test (<dir>.<TestName>) -> where it is and the files it covers <head>/symbol/<b>.json symbol (<dir>.<Name> or <dir>.<Type>.<Method>) -> definition and guarding tests
The bucket count per index is sized at build time to keep a bucket near BucketSize entries and is written into <head>/HEAD, so a bucket stays small however the repo grows. One file per key was measured first and rejected: 30k files took minutes to write on a loaded Studio, where the buckets are a few hundred files.
A spec ID is the backticked kebab-case name at a numbered item of a tracked Markdown file (6. `cut-line1-is-contract`: every card ...), and a test guards it when its doc comment opens with that name and a colon (// cut-line1-is-contract: ...), the convention the repo's specs and tests already follow.
Build is run at each landing, on a clone at the landed tip. Each head is built into its own directory <out>/<head>/, every bucket written whole (temp file then rename), and the one-line <out>/CURRENT file naming the head is renamed into place last. That rename is the swap: a reader opens CURRENT and reads only that head's directory, so a cut during a build, or after a build that failed partway, reads the previous complete index whole, never a mix. Build never deletes: older head directories stay until the caller prunes them. A bucket that is missing or carries another head inside the CURRENT directory is a damaged index, and the lookup returns an error so the cut is refused instead of carrying no CONTEXT.
Index ¶
Constants ¶
const MaxCardSpecs = 5
MaxCardSpecs caps the spec IDs one card carries context for.
const MaxParagraph = 2000
MaxParagraph caps one spec paragraph; a numbered item longer than this is cut.
const MaxSymbolTests = 20
MaxSymbolTests caps the guarding tests one symbol entry lists.
Variables ¶
var BucketSize = 64
BucketSize is the entry count a bucket is sized for; an index of n entries gets the power of two at or above n/BucketSize buckets.
var ErrNoIndex = errors.New("no CURRENT: the index was never built (run nova-pulse index --repo <clone> --out <dir>)")
ErrNoIndex is an index directory with no CURRENT: no build ever completed.
Functions ¶
Types ¶
type Index ¶
type Index struct {
Head string
// contains filtered or unexported fields
}
Index is an opened index: the head CURRENT names and each index's bucket count.
func Open ¶
Open reads CURRENT, the head of the last complete build, then that head's HEAD line: the sha and each index's bucket count.
func (*Index) Context ¶
Context is the block a card carries for the spec IDs text names: per ID its paragraph, its guarding tests, and the files those tests cover. It is empty when text names none.
type Spec ¶
type Spec struct {
ID string `json:"id"`
File string `json:"file"`
Line int `json:"line"`
Paragraph string `json:"paragraph"`
Tests []string `json:"tests"` // test keys, sorted
}
Spec is one spec ID's entry.
type Stats ¶
type Stats struct {
Head string
Specs int
Tests int
Symbols int
Guarded int // spec IDs with at least one guarding test
}
Stats is what one Build wrote.