Documentation
¶
Overview ¶
Package pinned renders persisted pinned-delivery memories into the payload that the UserPromptSubmit hook injects on every agent turn. Unlike bootstrap (loaded once at session start), pinned content is reinjected continuously — so the payload is wrapped in a <system-reminder> tag and framed with a rotated imperative ("violation = task failure") to keep the rules acting as a checklist rather than fading into background.
The output has two layers:
- System layer: meta-rules about working with mememory itself, plus rotated framing texts. Hard-coded in internal/system_rules; not editable through MCP tools.
- User layer: rules stored in Postgres with delivery=pinned, scope=global or scope=project. Rendered as-is on stage 1 (LLM rotation of the user layer is deferred to stage 2).
Both layers are wrapped in a single <system-reminder> block. The block is emitted only when at least one user-layer memory is present — the system layer alone has nothing to anchor and would be reinjected on every turn even for installations that never configured pinned rules.
Index ¶
Constants ¶
const BytesPerToken = 3.5
BytesPerToken matches the ratio used by the bootstrap package — tuned for mixed Cyrillic prose and code. Per-tokenizer accuracy is out of scope.
const SoftBudgetTokens = 5_000
SoftBudgetTokens is the soft ceiling on the pinned-payload size. It is not a hard limit — the user layer is preserved verbatim regardless of length — but exceeding it produces an informational warning. The point is not to save context tokens (the agent runs in a 1M-token window) but to preserve the checklist effect: a payload growing past ~5K tokens becomes harder for the model to treat as a focused list.
Variables ¶
This section is empty.
Functions ¶
func CheckBudget ¶
CheckBudget returns a non-empty informational warning when the rendered pinned payload for the given memories would exceed SoftBudgetTokens. The check is non-blocking — callers store the memory regardless and just surface the warning to the user. Returns an empty string when within budget or when memories is empty.
CheckBudget renders with a fixed seed so its measurement is reproducible — the size variation between rotations of the system layer is small enough that picking one is fine for budget purposes.
func EstimateTokens ¶
EstimateTokens converts a byte count into an approximate token count using BytesPerToken. The estimate is rounded to the nearest integer.
func Format ¶
Format renders a Context into the Markdown payload injected by the UserPromptSubmit hook. Returns an empty string when there are no user-layer memories — the caller should suppress hook output entirely in that case.
func FormatHookJSON ¶
FormatHookJSON wraps Format's output in the hookSpecificOutput envelope that Claude Code's UserPromptSubmit hook recognises. Runners that don't know the schema will print the JSON as plain text — noisy but not destructive. Returns an empty string when there is nothing to inject.
Types ¶
type Context ¶
type Context struct {
Project bootstrap.ProjectInfo
GlobalMems []t.Memory
ProjectMems []t.Memory
// Seed controls the rotation choice for the system layer. Zero means
// "use time.Now().UnixNano()" — production behaviour. Tests pass a
// fixed value to make the output deterministic.
Seed int64
}
Context bundles everything Format needs to render a pinned payload. It is constructed by the CLI (after fetching memories from the admin API) or by the MCP resource handler (after listing memories from the engine).