contextpkg

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package contextpkg is the deterministic context engine: the single source of truth for "what to load" across every delivery surface. It is pure — all IO is injected via ContextRequest.ReadArtifact — and depends only on internal/spec (shared value types) and the standard library. It must never import internal/core (the engine is a leaf), and it must never pull in an LLM or a real tokenizer (the No-LLM-in-context invariant).

Index

Constants

View Source
const (
	ManifestVersion = 1

	MinSoftCeiling = 1000
	MaxSoftCeiling = 200000
)

Manifest version and soft-ceiling bounds for the mission context manifest. ManifestVersion, MinSoftCeiling, and MaxSoftCeiling are exported so core's boundary-layer validator (validateMissionContextManifest) can enforce the same bounds the engine emits. missionContextSoftCeiling is the engine's private default ceiling and stays unexported.

Variables

This section is empty.

Functions

func CanonicalSnapshotJSON

func CanonicalSnapshotJSON(snapshot ContextSnapshot) ([]byte, error)

CanonicalSnapshotJSON serializes a snapshot to stable, indented bytes with a trailing newline, mirroring core's CanonicalOrchestrationJSON. LoadedFiles are sorted by path so two snapshots of the same turn are byte-identical regardless of manifest iteration order.

func CoveredRequirements

func CoveredRequirements(reqMd string, ids []int) (slice string, found bool)

CoveredRequirements returns the "## Requirement N" blocks of reqMd whose numbers appear in ids, each running from its header to the next "## " heading or end of input. Blocks are emitted in ascending requirement-number order regardless of the order of ids, separated by a blank line. found is false when none of the ids match a requirement; slice is then empty.

func DesignSection

func DesignSection(designMd string, headings []string) (slice string, found bool)

DesignSection returns the named section blocks of designMd. A heading matches when its text (after the leading #'s, trimmed) equals a requested heading, case-insensitively. A matched section runs from its heading to the next heading of the same or higher level (fewer or equal #'s), or end of input. Sections are emitted in document order, separated by a blank line. found is false when no requested heading matches; slice is then empty.

func EstimateTokens

func EstimateTokens(b []byte) int

EstimateTokens returns a deterministic heuristic estimate of how many model tokens b would occupy.

Heuristic:

  • Baseline ceil(len(b)/4) — ~4 bytes per token for ordinary prose.
  • Markdown surcharge: code fences and table rows are dense in structural symbols (backticks and pipes) that each tend to tokenize on their own and are undercounted by the prose average. Every such symbol adds half a token (ceil), nudging code/table-heavy briefs upward.

Properties (enforced by tests):

  • Pure and total: identical input always yields identical output; never panics.
  • Empty input yields 0.
  • Monotonic in length: appending bytes never decreases the estimate (the baseline grows with length and the surcharge counts only ever increase).

It is intentionally a heuristic, not a tokenizer: estimates must be reproducible and dependency-free, not exact.

func EstimateTokensString

func EstimateTokensString(s string) int

EstimateTokensString is the string-typed convenience wrapper over EstimateTokens. It shares the same heuristic and properties.

func RecentMemory

func RecentMemory(memoryMd string, n int) (slice string, found bool)

RecentMemory returns the most recent n entries of memoryMd. Memory is append-only, so entries later in the file are more recent; this returns the last n "## <key>" blocks in document order. HTML comments (the template scaffolding) are stripped first so doc-only memory files yield no entries. found is false when memoryMd has no entries or n <= 0; slice is then empty.

func StripHTMLComments

func StripHTMLComments(text string) string

StripHTMLComments blanks out HTML comment spans while preserving byte offsets and newlines (so line numbers survive).

func TaskSlice

func TaskSlice(tasksMd, taskID string) (slice string, found bool)

TaskSlice returns the Markdown block for task taskID in tasksMd: the "- [ ] Tn — …" checkbox line plus its indented metadata lines, up to (but not including) the next task line, the next "## Wave N" header, or end of input. found is false when no task with that id exists; slice is then empty.

func ValidateContextSnapshot

func ValidateContextSnapshot(snapshot ContextSnapshot) error

ValidateContextSnapshot rejects structurally malformed snapshots: a bad version, missing turn/task, or a loaded file with an empty path, a non-hex SHA256, or an inverted line range.

Types

type ContextHUD added in v0.2.0

type ContextHUD struct {
	Spec         string    `json:"spec"`
	Mode         string    `json:"mode"`
	Tier         string    `json:"tier,omitempty"`
	Files        []HUDFile `json:"files"`
	Skills       []string  `json:"skills"`
	TotalBytes   int       `json:"totalBytes"`
	ApproxTokens int       `json:"approxTokens"`
}

ContextHUD is the deterministic context heads-up display for a spec: the steering/skill files a host would load, their on-disk byte and approximate token cost, and the active mode/tier. Every field is derived from files on disk and recorded state only — no interpretation, no LLM call — so the same inputs always render the same HUD (invariant 6/7). It is shared by the `specd context --hud` CLI, the SSE `hud` event, and the MCP resource.

func BuildContextHUD added in v0.2.0

func BuildContextHUD(root, spec, mode, tier string, loadFiles, skills []string) ContextHUD

BuildContextHUD measures each load file from disk and totals the byte/token cost. loadFiles are root-relative paths (steering + artifacts + skills); the order is preserved so the HUD reads top-to-bottom like the load list. skills is the deduplicated set of active skill files (a subset of loadFiles), surfaced separately for a host that wants just the skills.

type ContextMode

type ContextMode string

ContextMode selects which delivery surface a manifest is built for. The engine emits the same item shape for every mode; the mode only widens the inputs a surface is expected to supply (e.g. a host budget on a mission).

const (
	ContextModeBriefing ContextMode = "briefing" // specd context (single agent / human)
	ContextModeDispatch ContextMode = "dispatch" // specd dispatch (parallel fan-out)
	ContextModeMission  ContextMode = "mission"  // Brain -> Pinky orchestrated mission
)

type ContextRequest

type ContextRequest struct {
	Slug           string
	Status         spec.SpecStatus // empty => phase inferred from TaskID prefix
	TaskID         string
	Role           string
	Files          []string
	Mode           ContextMode
	HostBudget     int      // MCP-negotiated cap; <=0 means "unset"
	ContextCommand string   // the "specd context <slug>" briefing command, if any
	Requirements   []int    // requirement ids the task covers (for targeted slicing)
	DesignHeadings []string // design sections the task names (for targeted slicing)
	// ReadArtifact injects the only IO the engine performs: it returns the raw
	// markdown for a spec artifact ("requirements.md", "design.md", "tasks.md",
	// "memory.md") and ok=false when absent. A nil reader is valid: the engine
	// then falls back to conservative default token hints and whole-file modes,
	// reproducing the pre-measurement output byte-for-byte.
	ReadArtifact func(name string) (content string, ok bool)
}

ContextRequest is the single input to the shared context engine. It is the superset of what the three context-delivery surfaces need so that "what to load" is derived exactly once. All IO is injected via ReadArtifact, keeping the engine pure and deterministic.

type ContextSelector

type ContextSelector struct {
	TaskID         string   `json:"taskID,omitempty"`
	Requirements   []int    `json:"requirements,omitempty"`
	DesignHeadings []string `json:"designHeadings,omitempty"`
	Artifact       string   `json:"artifact,omitempty"`
}

type ContextSnapshot

type ContextSnapshot struct {
	Version        int                    `json:"version"`
	Turn           int                    `json:"turn"`
	Phase          string                 `json:"phase"`
	Task           string                 `json:"task"`
	Manifest       MissionContextManifest `json:"manifest"`
	LoadedFiles    []LoadedFile           `json:"loadedFiles"`
	SteeringDigest string                 `json:"steeringDigest,omitempty"`
	MemoryDigest   string                 `json:"memoryDigest,omitempty"`
	Timestamp      string                 `json:"timestamp"`
}

ContextSnapshot is the file-level record of exactly what a turn loaded into a worker: the full mission manifest plus, for each loaded file, its content SHA256 and line range, and digests of the steering set and memory.md (R2). On resume a worker diffs the SHAs and reloads only what changed, turning re-contextualization from O(all files) into O(changed files).

func BuildContextSnapshot

func BuildContextSnapshot(root string, turn int, phase, task string, manifest MissionContextManifest, now time.Time) (ContextSnapshot, error)

BuildContextSnapshot hashes every manifest item that names an on-disk file and computes the steering/memory digests, producing the snapshot for one turn. Manifest items without a path (commands) or whose file is missing/unreadable are skipped — only what was actually loadable is recorded. The caller supplies `now` so the timestamp stays a deterministic function of the caller's clock.

type HUDFile added in v0.2.0

type HUDFile struct {
	Path         string `json:"path"`
	Exists       bool   `json:"exists"`
	Bytes        int    `json:"bytes"`
	ApproxTokens int    `json:"approxTokens"`
}

HUDFile is one load-list entry with its measured cost. Missing files are reported with Exists=false and zero cost rather than omitted, so a host can tell an absent steering file from an empty one.

type LoadedFile

type LoadedFile struct {
	Path   string `json:"path"`
	SHA256 string `json:"sha256"`
	Lines  [2]int `json:"lines"`
}

LoadedFile records one file the turn loaded: its repo-relative path, the SHA256 of its content, and the inclusive 1-based line range that was loaded (whole-file loads use [1, lineCount]; an empty file uses [0, 0]).

type MissionContextItem

type MissionContextItem struct {
	Order     int              `json:"order"`
	Kind      string           `json:"kind"`
	Path      string           `json:"path,omitempty"`
	Command   string           `json:"command,omitempty"`
	Mode      string           `json:"mode"`
	Required  bool             `json:"required"`
	TokenHint int              `json:"tokenHint,omitempty"`
	Rationale string           `json:"rationale"`
	Selector  *ContextSelector `json:"selector,omitempty"`
}

type MissionContextManifest

type MissionContextManifest struct {
	Version          int                  `json:"version"`
	SoftTokenCeiling int                  `json:"softTokenCeiling"`
	Strategy         string               `json:"strategy"`
	Role             string               `json:"role"`
	Items            []MissionContextItem `json:"items"`
	// EstimatedTokens and Budget are additive accounting fields (omitempty for
	// wire back-compat at version 1). EstimatedTokens is the sum of required-item
	// hints; Budget is the effective ceiling derived from phase, role, file count
	// and any host-negotiated cap. Omitting them reproduces the pre-feature bytes.
	EstimatedTokens int      `json:"estimatedTokens,omitempty"`
	Budget          int      `json:"budget,omitempty"`
	OverBudget      bool     `json:"overBudget,omitempty"`
	BudgetActions   []string `json:"budgetActions,omitempty"`
}

MissionContextManifest is the deterministic context-engineering contract for a Pinky mission. It names exactly what a host should load, in order, and how aggressively to expand each item under the soft token ceiling. The manifest is advisory context, not completion evidence.

func BuildContextManifest

func BuildContextManifest(req ContextRequest) MissionContextManifest

BuildContextManifest is the single source of truth for "what to load" across every surface. Order: role -> skill -> phase-skill -> spec-context -> scoped files -> phase-filtered source artifacts. Source artifacts are measured (and, where a selector matches, delivered as read-targeted slices) via the injected reader; everything else uses default hints. The engine performs no IO of its own and is total.

type SnapshotDiff

type SnapshotDiff struct {
	Unchanged       []string `json:"unchanged"`
	Changed         []string `json:"changed"`
	SteeringChanged bool     `json:"steeringChanged"`
	MemoryChanged   bool     `json:"memoryChanged"`
}

SnapshotDiff is the per-file changed/unchanged verdict a resuming worker uses to reload only what actually moved (R2, Req 3).

func DiffContextSnapshot

func DiffContextSnapshot(snapshot ContextSnapshot, root string) (SnapshotDiff, error)

DiffContextSnapshot compares a snapshot against the current working tree, returning which loaded files are unchanged (reference, do not reload) versus changed (reload), and whether the steering set or memory.md moved. A file that has since vanished or become unreadable counts as changed: re-contextualizing it is the safe degradation.

Jump to

Keyboard shortcuts

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