5.4 KiB
SF Prompt Modularization
Human-readable contract for the manifest-driven prompt context system.
Status
M004 — Phase 3 complete. All builders migrated to composeUnitContext v2.
Overview
Every autonomous unit type (plan-milestone, execute-task, deploy, …) declares
what context it needs in a manifest. The composer reads the manifest and
orchestrates artifact resolution, producing the ## Inlined Context block that
each prompt template receives.
This replaces the pre-Phase-3 approach where each builder hand-wired file reads and DB queries inline.
Two composer APIs
| API | Purpose | When to use |
|---|---|---|
composeInlinedContext(unitType, resolveArtifact) |
v1 — resolves artifacts.inline keys only |
Deprecated. Retained in unit-context-composer.js for external consumers. Do not use in new builders. |
composeUnitContext(unitType, opts) |
v2 — resolves prepend, inline, excerpt, and computed artifacts |
Use for all new builders. All in-tree builders now call this. |
composeUnitContext contract
composeUnitContext(unitType: string, opts: {
base: string; // repo root
resolveArtifact?: (key: string) => Promise<string | null>;
resolveExcerpt?: (key: string) => Promise<string | null>;
computed?: Record<string, { build: (inputs, base) => string | null }>;
}) => Promise<{ prepend: string; inline: string }>
- prepend — computed blocks that should appear before the main inline content.
- inline — the joined context block suitable for
{{inlinedContext}}substitution. - Unknown
unitTypereturns{ prepend: "", inline: "" }— callers fall through to default behavior. - Missing resolvers or registry entries are skipped silently (no error).
Manifest schema
interface UnitManifest {
skills: { mode: "all" | "planning" | string[] };
knowledge: "full" | "scoped" | "critical-only" | "none";
memory: "prompt-relevant" | "critical-only" | "none";
codebaseMap: boolean;
preferences: "active-only" | "none";
tools: string[];
prepend?: string[]; // computed artifact ids (e.g. ["overrides"])
artifacts: {
inline: string[]; // static artifact keys, resolved in order
excerpt: string[]; // excerpt artifact keys
onDemand: string[]; // referenced but not auto-inlined
computed?: string[]; // async computed artifact ids (e.g. ["knowledge", "graph"])
};
maxSystemPromptChars: number;
}
Stable artifact keys (ARTIFACT_KEYS)
Keys are stable identifiers, not paths. The resolver maps a key to its source (file, DB row, computed block).
Milestone-scoped: roadmap, milestone-context, milestone-summary,
milestone-validation, milestone-research, milestone-plan
Slice-scoped: slice-context, slice-research, slice-plan, slice-summary,
slice-summaries, slice-uat, slice-assessment
Task-scoped: task-plan, task-summary, prior-task-summaries,
dependency-summaries, blocker-summaries
Project-scoped: requirements, decisions, project, templates, queue
Validation-scoped: verification-classes, outstanding-items, previous-validation
History-scoped: prior-milestone-summary
Migration decision matrix
| Builder complexity | Recommendation | Example |
|---|---|---|
| Simple (1–3 static artifacts, no knowledge splice) | Full v2 via composeUnitContext |
deploy, release, rollback, challenge |
| Medium (4–6 static artifacts, optional knowledge/graph) | v2 inline + imperative knowledge splice | research-milestone, complete-slice, reassess-roadmap |
| Complex (many artifacts, computed prepend, conditional logic) | v2 with full computed registry | plan-milestone, research-slice, plan-slice, replan-slice |
| Fully imperative (no composer call) | Keep imperative; add manifest for documentation | execute-task, reactive-execute |
Budget and caching
resolvePromptBudgets()computes context-window-scaled budgets once per dispatch tick (1-second TTL). Do not add additional caches.capPreamble()caps inlined context atmin(30K chars, scaled inline budget).- Exceeding
maxSystemPromptCharslogs a telemetry event; the composer does not truncate.
Verification
auto-prompts-phase3.test.mjs— v2 contracts for plan-milestone, replan-slice, validate-milestone, research-slice.auto-prompts-complete-slice.test.mjs— complete-slice closeout contract.auto-prompts-v2-migration.test.mjs— regression guard for all migrated builders (research-milestone, run-uat, deploy, smoke-production, release, rollback, challenge).unit-context-manifest-computed.test.mjs— manifestcomputedkeys match builder behavior.
Adding a new artifact key
- Add the key to
ARTIFACT_KEYSinunit-context-manifest.js. - Add the key to the
inline/excerpt/onDemand/computedlist of every manifest that needs it. - Implement the resolver in the builder's
resolveArtifactfunction. - Add a regression test that asserts the artifact appears in the prompt.
Adding a new computed artifact type
- Define the builder function (e.g.
inlineKnowledgeBudgeted). - Register it in the
computedregistry passed tocomposeUnitContext:computed: { knowledge: { build: (inputs, base) => inlineKnowledgeBudgeted(base, inputs.keywords) } } - Add the id to
manifest.artifacts.computed. - Add a test that asserts the computed block appears in the output.