contextpack

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package contextpack assembles a bounded, budget-capped "context pack" of the most relevant GTD/decision/knowledge/memory items for a given objective, so an agent (or a human) can be handed a compact brief instead of re-reading the whole workspace.

Index

Constants

View Source
const (
	TypeTask       = "task"
	TypeProject    = "project"
	TypeDecision   = "decision"
	TypeKnowledge  = "knowledge"
	TypeAtom       = "atom"
	TypeProcedure  = "procedure"
	TypeSkill      = "skill"
	TypeOutcome    = "outcome"
	TypeReflection = "reflection"
	TypeRule       = "rule"
	TypeSession    = "session"
)

Item.Type vocabulary. These are the only values retrieve()'s itemFromX helpers ever emit; scorer.go's typeCap and retrieval.go's IncludeTypes mapping key off these consts (not string literals) so the two can never silently drift apart again (P1 review finding B: typeCap used to key on "gtd"/"procedural"/"behaviorRule", none of which matched what retrieve() actually emitted).

Variables

This section is empty.

Functions

This section is empty.

Types

type Assembler

type Assembler struct {
	// contains filtered or unexported fields
}

Assembler holds the domain read ports needed to retrieve, score, and trim context pack candidates. It is backend-agnostic: every field is a narrow, consumer-owned read port (see ports.go) implemented structurally by the same Postgres/SQLite stores that satisfy the full domain StoreIface — no adapter type is needed to narrow them.

func NewAssembler

func NewAssembler(
	gtdStore TaskProjectReadPort,
	decisionStore DecisionReadPort,
	knowledgeStore KnowledgeReadPort,
	atomStore AtomReadPort,
	proceduralStore ProceduralReadPort,
	skillStore SkillReadPort,
	outcomeStore OutcomeReadPort,
	reflectionStore ReflectionReadPort,
	behaviorRuleStore BehaviorRuleReadPort,
	sessionStore SessionReadPort,
	workSessionStore WorkSessionReadPort,
) (*Assembler, error)

NewAssembler wires the domain read ports an Assembler needs. All arguments are required — a nil store would panic on first use deep inside retrieve() (internal/contextpack/retrieval.go), so NewAssembler rejects nil up front instead of leaving the invariant unenforced.

func (*Assembler) Assemble

func (a *Assembler) Assemble(ctx context.Context, req Request) (*Pack, error)

Assemble retrieves candidate items, scores and caps them, trims to the requested character budget, and returns the resulting Pack.

Stale/proposed exclusion is retrieve()'s responsibility, not this orchestration's.

type AtomReadPort

type AtomReadPort interface {
	Search(ctx context.Context, workspaceID *uuid.UUID, query string, limit int) ([]atom.Atom, error)
}

AtomReadPort is the subset of atom.StoreIface that retrieveAtoms (retrieval.go) calls.

type BehaviorRuleReadPort

type BehaviorRuleReadPort interface {
	List(ctx context.Context, p behaviorrule.ListParams) ([]*behaviorrule.BehaviorRule, error)
}

BehaviorRuleReadPort is the subset of behaviorrule.StoreIface that retrieveBehaviorRules (retrieval.go) calls.

type DecisionReadPort

type DecisionReadPort interface {
	ByRepo(ctx context.Context, repoName string, limit int32) ([]db.Decision, error)
	ByProject(ctx context.Context, projectID uuid.UUID, limit int32) ([]db.Decision, error)
	ByTask(ctx context.Context, taskID uuid.UUID, limit int32) ([]db.Decision, error)
	// All returns the most recent decisions across every repo/project/task —
	// used only when req has no scope signal at all (RepoName == "" &&
	// ProjectID == nil && TaskID == nil). The session-start hook (A5a) is one
	// caller that hits this: it has no current-repo signal to pass — see
	// retrieveDecisions and backend-security-design.md-adjacent dispatch
	// notes on why deriveRepoSlug is deliberately not used to manufacture
	// one. It is NOT the only caller: assemble_context's MCP tool schema
	// (internal/mcp/tools_contextpack.go) marks repo_name/project_id/task_id
	// Optional — only objective is Required — so any MCP client that omits
	// all three (e.g. a bare "what have we decided" query) reaches this
	// branch too, returning workspace-wide decisions instead of the empty
	// set a caller of the pre-A5a code path would have seen. Both All()
	// implementations (Postgres and SQLite) still filter to the caller's own
	// workspace, so this is a scope-widening within one tenant, not a
	// cross-tenant leak — see TestHandleAssembleContext_UnscopedRequestReachesDecisionAll
	// (internal/mcp/tools_contextpack_test.go) for the locked-in contract.
	All(ctx context.Context, limit int32) ([]db.Decision, error)
}

DecisionReadPort is the subset of decision.StoreIface that retrieveDecisions (retrieval.go) calls.

type Item

type Item struct {
	Type        string            `json:"type"`
	ID          uuid.UUID         `json:"id"`
	SourceTable string            `json:"source_table"`
	Summary     string            `json:"summary"`
	Score       float64           `json:"score"`
	Reasons     []string          `json:"reasons"`
	Provenance  map[string]string `json:"provenance"`
}

Item is a single candidate (task, decision, knowledge row, memory atom, etc.) pulled in from one of the domain stores, scored and annotated for inclusion in a Pack.

type KnowledgeReadPort

type KnowledgeReadPort interface {
	SearchReadOnly(ctx context.Context, query string, limit int) ([]db.KnowledgeItem, error)
}

KnowledgeReadPort is the subset of knowledge.StoreIface that retrieveKnowledge (retrieval.go) calls. Deliberately SearchReadOnly only — never Search — so assemble_context stays genuinely read-only.

type Omitted

type Omitted struct {
	Type   string `json:"type"`
	Count  int    `json:"count"`
	Reason string `json:"reason"`
}

Omitted records that items of a given Type were dropped (and why) while trimming the candidate set to fit the budget.

type OutcomeReadPort

type OutcomeReadPort interface {
	ListFailedOutcomes(ctx context.Context, workspaceID *uuid.UUID, limit int) ([]outcome.Outcome, error)
}

OutcomeReadPort is the subset of outcome.StoreIface that retrieveOutcomes (retrieval.go) calls.

type Pack

type Pack struct {
	PackID      *uuid.UUID `json:"pack_id"`
	Objective   string     `json:"objective"`
	BudgetChars int        `json:"budget_chars"`
	UsedChars   int        `json:"used_chars"`
	Items       []Item     `json:"items"`
	Warnings    []Warning  `json:"warnings"`
	Omitted     []Omitted  `json:"omitted"`
}

Pack is the assembled, budget-capped result handed back to the caller. The json tags here are the wire contract documented at docs/wayneblacktea-2.0-development-prompt.md:265-291 — snake_case at every level, including nested Item/Warning/Omitted.

type ProceduralReadPort

type ProceduralReadPort interface {
	Query(ctx context.Context, f procedural.QueryFilter) ([]procedural.ProceduralMemory, error)
}

ProceduralReadPort is the subset of procedural.StoreIface that retrieveProcedural (retrieval.go) calls.

type ReflectionReadPort

type ReflectionReadPort interface {
	RecentWithPatterns(ctx context.Context, workspaceID *uuid.UUID, since time.Time, limit int) ([]*reflection.Reflection, error)
}

ReflectionReadPort is the subset of reflection.StoreIface that retrieveReflections (retrieval.go) calls.

type Request

type Request struct {
	Objective    string
	RepoName     string
	ProjectID    *uuid.UUID
	TaskID       *uuid.UUID
	BranchName   string
	FilesTouched []string
	BudgetChars  int
	IncludeTypes []string
	Persist      bool
}

Request describes what the caller wants a context pack assembled for.

type SessionReadPort

type SessionReadPort interface {
	LatestHandoff(ctx context.Context) (*db.SessionHandoff, error)
}

SessionReadPort is the subset of session.StoreIface that retrieveSession (retrieval.go) calls.

type SkillReadPort

type SkillReadPort interface {
	Search(ctx context.Context, f skill.SearchFilter) ([]*skill.Skill, error)
}

SkillReadPort is the subset of skill.StoreIface that retrieveSkills (retrieval.go) calls.

type TaskProjectReadPort

type TaskProjectReadPort interface {
	GetTaskByID(ctx context.Context, id uuid.UUID) (*db.Task, error)
	GetProjectByID(ctx context.Context, id uuid.UUID) (*db.Project, error)
	ProjectsByRepoName(ctx context.Context, repoName string) ([]db.Project, error)
	WorkspaceID() pgtype.UUID
}

TaskProjectReadPort is the subset of gtd.StoreIface that retrieveCurrentTaskProject and workspaceID() (retrieval.go) call.

type Warning

type Warning struct {
	Type    string `json:"type"`
	Summary string `json:"summary"`
}

Warning surfaces a non-fatal issue encountered while assembling the pack (e.g. a store call failed and was skipped).

type WorkSessionReadPort

type WorkSessionReadPort interface {
	GetActive(ctx context.Context, workspaceID uuid.UUID, repoName string) (*worksession.ActiveSessionResult, error)
}

WorkSessionReadPort is the subset of worksession.StoreIface that retrieveCurrentTaskProject (retrieval.go) calls.

Jump to

Keyboard shortcuts

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