Documentation
¶
Overview ¶
Package contextpack assembles everything needed to work on something into one bundle.
It sits above the retrieval systems rather than beside them. memory, index, graph, secretary, and session each already answer one question well; what was missing was the thing that decides *which* of them to ask for a given task, in what proportion, and how to spend a fixed token budget across the answers. That judgement does not belong in the MCP server — which should stay an adapter — nor in internal/project, which would have to import half the repo.
The distinction that matters: recall answers "what do you know about X", and this answers "give me what I need to do X". The second is not a longer version of the first. It includes where the last agent stopped, what they ruled out, what is still open, and the actual text of the notes involved — and it leaves things out on purpose, because the consumer has a finite context window.
Index ¶
Constants ¶
const DefaultBudget = 4000
DefaultBudget is roughly a page and a half of context — enough to be useful, small enough that a host can afford to call this on every task.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Budget ¶
type Budget struct {
Limit int `json:"limit"`
Spent int `json:"spent"`
By []Line `json:"by"`
// Overhead is everything rendered that never passed through take or
// spendCheckpoint/spendMemories: headers, the provenance boundary, the
// Sources and Excluded lists, and the footer's own text. It used to be free
// on paper and real on the wire — a pack that reported ~1955 tokens was
// actually costing ~2212, a 13% undercount nobody could see. See
// renderBudget.
Overhead int `json:"overhead"`
}
type Line ¶
type Line struct {
Section string `json:"section"`
Tokens int `json:"tokens"`
Items int `json:"items"`
Dropped int `json:"dropped"`
}
A Line is one section's spend, including what it could not fit.
type Pack ¶
type Pack struct {
Task string `json:"task"`
Hint string `json:"hint"`
Project *project.Project `json:"project,omitempty"`
// Worktree is the linked worktree continuity was read from, if any, and
// Inherited says the checkpoint below came from the project rather than
// from this worktree — a distinction the render has to make out loud.
Worktree string `json:"worktree,omitempty"`
Inherited bool `json:"inherited,omitempty"`
// Checkpoint is where the last agent stopped on this project, and Working is
// what has been recorded since without being committed. Together they are the
// answer to "where were we", which no amount of semantic recall provides.
Checkpoint *session.Checkpoint `json:"checkpoint,omitempty"`
Working []session.Note `json:"working,omitempty"`
// History is earlier checkpoints on the same project. Only their ruled-out
// approaches are used — see Build.
History []session.Checkpoint `json:"history,omitempty"`
// Notes is vault content — the actual prose, not just titles. Hits reached
// through the graph rather than matched directly carry Via.
Notes []index.Hit `json:"notes"`
Preferences []memory.Memory `json:"preferences"`
Related []memory.Memory `json:"related"`
// Pinned holds memories the user marked always-include (see memory.Pin).
// They bypass ranking entirely — see spendMemories — which is the whole
// difference between a pin and simply having high salience.
Pinned []memory.Memory `json:"pinned,omitempty"`
OpenLoops []secretary.Commitment `json:"open_loops"`
// Superseded holds recalled memories a later statement replaced. They are
// kept out of the answer but reported, so the agent knows the value moved
// rather than seeing one figure and assuming it was always so.
Superseded []memory.Memory `json:"superseded,omitempty"`
// Conflicts names sources that disagree and cannot be ordered. Unlike
// supersession this resolves nothing — it says so out loud instead.
Conflicts []string `json:"conflicts,omitempty"`
// Window is the span of time the task asked about, when it asked about one,
// and OutOfWindow counts what was set aside for falling outside it. The
// count is rendered and the contents are not: an item excluded for being the
// wrong date does not become less wrong for being listed, and reprinting it
// would undo the filter. The number is there so the agent knows a filter ran
// and can ask again without one.
Window *when.Window `json:"window,omitempty"`
OutOfWindow int `json:"out_of_window,omitempty"`
// WindowEmpty is set when the window matched nothing dated, in which case the
// filter was abandoned rather than applied and the pack holds everything it
// gathered.
WindowEmpty bool `json:"window_empty,omitempty"`
// WindowInferred says Window came from neither a task phrase nor an
// explicit Since, but from the gap since the last checkpoint — the reader
// gets told this rather than mistaking a guess for something asked for.
WindowInferred bool `json:"window_inferred,omitempty"`
// Sources lists what actually made it into the render, so the consumer can
// cite rather than paraphrase.
Sources []string `json:"sources"`
// Excluded names what the budget dropped. An agent that can see what it did
// not get can ask for more, which is strictly better than not knowing.
Excluded []string `json:"excluded"`
Budget Budget `json:"budget"`
}
A Pack is everything relevant to one task, gathered from every store, ready to be rendered into a model's context window.
func Build ¶
Build gathers candidates from every store. It deliberately over-gathers: what survives is decided at render time by the budget, because how much fits depends on how long each piece turns out to be.
Everything here degrades rather than fails. A vault with no project notes, no embedding model, or no checkpoints still produces a useful pack — a memory layer that errors because you asked about something it doesn't know is worse than useless, it is untrustworthy.
func (Pack) Carried ¶ added in v0.1.3
Carried is a one-line inventory of what this pack actually contains: the receipt a host shows the user so a restore is something they can see happen rather than something they have to take on faith.
It counts and never characterises. "4 memories" is checkable against the text below it; "the important context" is not, and the moment a receipt says something the body does not support, every later receipt is worth less.
Empty when the pack carries nothing, so a caller can tell "restored nothing" from "restored things I did not enumerate" and say the honest one.
func (Pack) Continuity ¶
Continuity is the scope this pack's sessions and checkpoints are filed under: the project, narrowed to the worktree when the agent is standing in a linked one. Exported because a caller that wants to write into the same session — a note saying it resumed, say — has to key it the way the pack read it.
A path segment rather than a joined name, because that is what it becomes in the vault: sessions/kestrel/feature-x/, a folder inside the project's rather than a sibling of it. A worktree is not another project — it is the same repository with a second working tree — and the layout should not claim otherwise. It also means a main checkout is untouched by any of this: its history is the files directly inside sessions/kestrel/, and a listing that skips directories cannot see the worktrees at all.
func (*Pack) Empty ¶ added in v0.2.0
Empty reports that retrieval found nothing at all — not "nothing that answers the task", which renderGaps already says, but nothing whatsoever.
The render is written for the agent that consumes it, and for an agent an empty pack is still a useful answer: it says do not infer, nothing is here. For a person running `brain resume` as their first command after setup, the same output is a page of scaffolding around a void, and it reads like a broken install rather than an empty vault. Callers use this to tell the two audiences apart.
type Request ¶
type Request struct {
Task string
// Hint narrows the scope: a project name, a file path, or a topic. Optional
// — if empty, the task text is matched against known projects.
Hint string
// Worktree is the linked git worktree the agent is standing in, empty in a
// main checkout. It narrows continuity and nothing else: a worktree is the
// same repository and so has the same memory, but its own uncommitted work
// and its own place to have stopped.
Worktree string
// Budget is the approximate token ceiling for the rendered pack. 0 means
// DefaultBudget.
Budget int
// Now is the clock the task's time expressions are resolved against. Zero
// means the wall clock. It exists so "what was I working on last month" is
// testable, and because a benchmark and a replay both need to ask the
// question as of a moment that is not this one.
Now int64
// Since is an explicit time window, for a caller that wants one without
// phrasing it into Task. SinceInferred (the zero value) defers to whatever
// Task's own words parse to, and otherwise to a window inferred from the
// gap since the last checkpoint — never to no window at all, so a cold
// return still gets the history it needs without being asked.
Since Since
}
A Request is what the caller is trying to do. Task is the important field: "continue the MCP implementation" retrieves differently from the project name alone, because it says which corner of the project matters right now.
type Since ¶ added in v0.3.3
type Since string
Since names an explicit time window a caller can ask for directly, instead of relying on a phrase inside Task. It exists because the phrase parser in package when is deliberately narrow — it recognises a fixed set of English shapes and nothing else — and an agent or a UI control needs a knob that always works.
const ( // SinceInferred is the zero value: no explicit window was asked for. Task's // own words still take precedence when they parse to one; failing that, the // pack infers a window from the gap since the last checkpoint. SinceInferred Since = "" SinceDay Since = "day" SinceWeek Since = "week" SinceMonth Since = "month" SinceQuarter Since = "quarter" SinceYear Since = "year" // SinceAll explicitly disables windowing — the override for "no, I really // do want the whole history", which inference alone can never produce. SinceAll Since = "all" )