Documentation
¶
Overview ¶
Package runctx exports the RunContext-population helpers a run-loop driver applies between "task spawned" and "planner.Next" — the code that turns subsystem state (memory, skills, artifacts, the terminal Finish) into what the planner actually sees (Phase 110b — D-195).
Brief 02's contract is that the planner never imports runtime internals: everything it can see arrives through `planner.RunContext`. The projection code that POPULATES RunContext is therefore the runtime's half of the planner contract. Before 110b that half lived as unexported `package main` helpers in `cmd/harbor`, hand-duplicated in `harbortest/devstack` (the D-094 mirror tax — the SDK friction audit found a THIRD drifting copy of the keyword shaper). This package is the promotion that makes the contract real for every caller: `cmd/harbor`, the devstack test kit, and a headless SDK consumer building its own RunSpec all compose the SAME projections.
Import direction (recorded in the phase plan): `internal/runtime/*` may import `planner` / `memory` / `skills` / `artifacts`; `internal/planner` gains NO new imports — in particular no `memory` import.
All five helpers are pure functions (or functions over their explicit dependencies) with no package-level mutable state — they are trivially safe for concurrent use (D-025).
Phase 111d (D-201) executed the D-195 deprecation notice: the `ExtractSkillKeywords` query shaper is DELETED along with the raw-Search `<skills_context>` injection path it served; the Phase-39 `skills.Directory` view (projected via ProjectSkillsDirectory) is the canonical producer.
Index ¶
- func ExtractAssistantAnswer(fin planner.Finish) string
- func ProjectMemoryBlocks(patch memory.LLMContextPatch) *planner.MemoryBlocks
- func ProjectSkillsContext(ranked []skills.RankedSkill) []any
- func ProjectSkillsDirectory(views []skills.SkillView) []any
- func ResolveInputArtifacts(ctx context.Context, store artifacts.ArtifactStore, q identity.Quadruple, ...) []planner.InputArtifactView
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractAssistantAnswer ¶
ExtractAssistantAnswer pulls the planner's natural-language answer out of a terminal Finish for the memory.AddTurn writeback and the `planner.AnswerEnvelope` projection (Phase 83i — D-152; promoted by Phase 110b). The react planner's FinishGoal carries Payload = map[string]any{"answer": "<the LLM's answer>"}. Other planners may shape Payload differently; we accept any string-valued "answer" key and otherwise fall back to a Sprintf so something always lands in memory (matching CLAUDE.md §5 fail-loud — silent "nothing written" would lose the run's outcome).
func ProjectMemoryBlocks ¶
func ProjectMemoryBlocks(patch memory.LLMContextPatch) *planner.MemoryBlocks
ProjectMemoryBlocks shapes a memory.LLMContextPatch into the JSON-encodable map the planner's `<read_only_conversation_memory>` wrapper renders (Phase 83f — D-149; promoted by Phase 110b). Returns nil when the patch is empty — the wrapper is omitted entirely. V1.1 ships only the Conversation tier; the External tier remains nil pending a long-term memory phase.
func ProjectSkillsContext ¶
func ProjectSkillsContext(ranked []skills.RankedSkill) []any
ProjectSkillsContext shapes a []skills.RankedSkill into the []any the planner's `<skills_context>` wrapper renders (Phase 83f — D-149; promoted by Phase 110b). Each element is a small map carrying the body fields the LLM consumes (name / title / description / steps). An empty input returns nil so the wrapper is omitted.
func ProjectSkillsDirectory ¶
ProjectSkillsDirectory shapes a Phase-39 `skills.Directory.View` snapshot into the []any the planner's `<skills_context>` wrapper renders (Phase 111d — D-201, executing the D-195 deprecation notice: the keyword-shaped raw-Search injection path and its `ExtractSkillKeywords` helper are deleted; the Directory's bounded, pinned-then-recent, capability-filtered, redacted browse window is the canonical producer). Each element is the compact `skills.SkillView` projection (name / title / trigger / task_type / pinned) — full skill content stays behind the `skill_get` meta-tool. An empty input returns nil so the wrapper is omitted.
func ResolveInputArtifacts ¶
func ResolveInputArtifacts( ctx context.Context, store artifacts.ArtifactStore, q identity.Quadruple, ids []string, logger *slog.Logger, ) []planner.InputArtifactView
ResolveInputArtifacts pre-fetches the metadata (+ bytes for `image/*`) for every operator-uploaded artifact ID on a task, producing the `planner.InputArtifactView` slice the run loop hands to the planner's first turn (Round-7 F11 / D-166; promoted by Phase 110b). The synchronous pre-resolution keeps the planner's prompt assembly I/O-free.
Failures are bounded:
- Nil artifact store with non-empty IDs → empty slice + Warn log (the LLM still sees a text-only prompt; the operator can re- attach after wiring the store). Avoids a hard fail-loud here because the artifact-store dependency is genuinely optional in some dev postures.
- `GetRef` not-found / errored → skip that ID + Warn (the rest of the slice survives; the artifact may have been GC'd between spawn and run).
- `Get` (bytes fetch) errored on an image/* → keep the entry but leave Bytes nil. The materializer falls back to a stub-text part for missing-bytes images.
The scope on every store call is the run's identity tuple — the artifact store enforces tenant isolation on read. A nil logger defaults to slog.Default() so the Warn paths above stay loud for every caller.
Types ¶
This section is empty.