Documentation
¶
Overview ¶
Package prompt assembles the cache-stable system prompt for the agent.
Cache-stability invariants enforced here:
- The static prefix (StaticBase + InstructionFiles) is never allowed to drift mid-session. Updating the binary's BasePromptV1 constant counts as a release-time bump that intentionally invalidates the prompt cache.
- Per-turn dynamic context (git status, current date, etc.) is placed AFTER the DynamicContextBoundary marker so it never pollutes the cached prefix.
- The boundary marker string itself is a load-bearing constant. Changing it is a release-time bump.
The Build method composes Static prefix → boundary → Dynamic suffix in that exact order. Callers that need only the cached prefix can split on DynamicContextBoundary.
Index ¶
Constants ¶
const BasePromptV1 = baseSection1Identity + "\n" + baseSection2Tools + "\n" + baseSection3Style
BasePromptV1 is the cache-stable static base prompt. The "V1" suffix is load-bearing: any change to this constant is a release-time bump that intentionally invalidates the DeepSeek prompt cache, so downstream tasks (T-102~T-104) own the final content but the name stays. Compose order matches the section comments above.
const DynamicContextBoundary = "\n=== DYNAMIC CONTEXT (per-turn, do not cache) ===\n"
DynamicContextBoundary marks the cut between cache-stable static prompt content and per-turn dynamic context. Everything after this string is regenerated on every turn; everything before it must stay byte-stable across the session.
Variables ¶
This section is empty.
Functions ¶
func RenderProjectContext ¶
func RenderProjectContext(p ProjectContext) string
RenderProjectContext renders the dynamic project context (cwd, git status, git diff) as a string. Exported so the agent can append it after a frozen static prefix without re-building the full prompt.
Types ¶
type InstructionFile ¶
InstructionFile is a loaded whitelist instruction file. Content is already truncated by the loader.
func LoadInstructionFiles ¶
func LoadInstructionFiles(cwd, home string) ([]InstructionFile, error)
LoadInstructionFiles scans cwd and home for whitelist files and returns them in priority order (cwd before home; within each base, declaration order). Same base name in both locations: cwd wins, home copy is skipped.
Hard limits:
- Per file: maxInstructionFileChars (truncated with marker)
- Total: maxTotalInstructionChars (later files dropped when full)
Safety:
- Any base name containing "claude" (case-insensitive) is dropped even if a future edit erroneously adds it to the whitelist. CLAUDE.md MUST NOT load.
- Missing files and read errors return no error — instructions are advisory.
type ProjectContext ¶
type ProjectContext struct {
CWD string
CurrentDate string
GitStatus string
GitDiff string
ActiveBranch string
OSName string
OSVersion string
Shell string
}
ProjectContext is the dynamic per-turn context appended after the DynamicContextBoundary marker. Git fields are refreshed by the agent on each step; the static fields (CWD, OSName, OSVersion, Shell, CurrentDate) are filled once at session start.
func DiscoverProjectContext ¶
func DiscoverProjectContext(cwd string) ProjectContext
DiscoverProjectContext fills the static-per-session fields of a ProjectContext: cwd, current date (UTC), OS name and version, and shell. Git fields are deliberately left empty — they are per-turn and the agent refreshes them via gitctx.
type SystemPromptBuilder ¶
type SystemPromptBuilder struct {
// StaticBase is the binary-versioned base prompt. Empty falls
// back to BasePromptV1.
StaticBase string
// Instructions is the loaded set of whitelist instruction files
// (DEEPSEEK.md, AGENTS.md, .deepseek/instructions.md). Session-once.
Instructions []InstructionFile
// SkillDirectory is the canonical stable skill directory text, exactly
// as produced by skills.Store.PromptIndex() / IndexText() — one line per
// skill in the form
//
// name | short_description | run_mode | version_hash | allowed_tools
//
// It is rendered into the static prefix (before the dynamic boundary) so
// the model-visible bytes carry the body-derived version_hash. Because
// this is the same text that feeds the epoch's skill-dir hash, a skill
// body edit moves the prefix and the epoch hash together. Empty → no
// ## Skills section. Never contains local absolute paths or skill bodies.
SkillDirectory string
// Project carries the dynamic per-turn context (git status, date,
// os). nil disables the dynamic suffix entirely.
Project *ProjectContext
}
SystemPromptBuilder composes the system prompt from a static base, session-once instruction files, and per-turn project context. Hold one per agent.
func (*SystemPromptBuilder) Build ¶
func (b *SystemPromptBuilder) Build() string
Build returns the assembled system prompt:
<StaticBase> <rendered instructions> (omitted if no instructions) <DynamicContextBoundary> <rendered project context> (omitted if Project is nil)
The bytes before DynamicContextBoundary must stay identical across turns within one session — cache invariant.