refactor(reflect): route reflection-pass through loadPrompt in extension
Move the loadPrompt("reflection-pass") call site from headless-reflect.ts
into a new renderReflectionPrompt helper in reflection.js. gap-audit
greps EXTENSION_SRC for loadPrompt call sites; without a hit there it
flagged the prompt as orphan even though the headless surface was using
it (sf-mp4warqc-y1u0b3).
Side benefits: fragment composition + variable validation now run via
the canonical path instead of the prior raw fs.readFile + string
substitution.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
639dcde717
commit
48e793c003
2 changed files with 35 additions and 20 deletions
|
|
@ -91,6 +91,10 @@ export async function handleReflect(
|
|||
let mod: {
|
||||
assembleReflectionCorpus: (basePath: string) => unknown;
|
||||
renderReflectionCorpusBrief: (corpus: unknown) => string;
|
||||
renderReflectionPrompt: (
|
||||
corpus: unknown,
|
||||
options?: { workingDirectory?: string },
|
||||
) => Promise<string>;
|
||||
writeReflectionReport: (basePath: string, content: string) => string | null;
|
||||
runGeminiReflection: (
|
||||
prompt: string,
|
||||
|
|
@ -138,32 +142,21 @@ export async function handleReflect(
|
|||
return { exitCode: 0 };
|
||||
}
|
||||
|
||||
let promptTemplate: string;
|
||||
// renderReflectionPrompt routes through reflection.js → loadPrompt so the
|
||||
// gap-audit detector sees the call site in EXTENSION_SRC and won't flag
|
||||
// the prompt as orphan (sf-mp4warqc-y1u0b3). It also picks up fragment
|
||||
// composition + variable validation for free.
|
||||
let rendered: string;
|
||||
try {
|
||||
const fs = await import("node:fs/promises");
|
||||
const templatePath = useAgentDir
|
||||
? join(agentExtensionsDir, "prompts", "reflection-pass.md")
|
||||
: resolveBundledSourceResource(
|
||||
import.meta.url,
|
||||
"extensions",
|
||||
"sf",
|
||||
"prompts",
|
||||
"reflection-pass.md",
|
||||
);
|
||||
promptTemplate = await fs.readFile(templatePath, "utf-8");
|
||||
rendered = await mod.renderReflectionPrompt(corpus, {
|
||||
workingDirectory: cwd,
|
||||
});
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
process.stderr.write(`[reflect] prompt template load failed: ${msg}\n`);
|
||||
process.stderr.write(`[reflect] prompt render failed: ${msg}\n`);
|
||||
return { exitCode: 1 };
|
||||
}
|
||||
|
||||
const brief = mod.renderReflectionCorpusBrief(corpus);
|
||||
// Inline-replace {{corpus}} in the template. We do NOT run the full
|
||||
// loadPrompt fragment-resolver here — the operator just needs a clean
|
||||
// rendered prompt to pipe into a model. The full template path runs
|
||||
// inside SF when reflection-pass becomes a real unit type.
|
||||
const rendered = promptTemplate.replace("{{corpus}}", brief);
|
||||
|
||||
if (!options.run) {
|
||||
process.stdout.write(`${rendered}\n`);
|
||||
return { exitCode: 0 };
|
||||
|
|
|
|||
|
|
@ -347,6 +347,28 @@ export function writeReflectionReport(basePath, content) {
|
|||
|
||||
const REFLECTION_TERMINATOR = "REFLECTION_COMPLETE";
|
||||
|
||||
/**
|
||||
* Render the reflection-pass prompt template with a corpus brief.
|
||||
*
|
||||
* Routes through the canonical loadPrompt path so:
|
||||
* - fragment composition ({{include:working-directory}}) resolves
|
||||
* - variable validation catches missing values at render time
|
||||
* - the gap-audit detector sees a real loadPrompt("reflection-pass")
|
||||
* call site in extension source (sf-mp4warqc-y1u0b3 — orphan flag
|
||||
* would otherwise fire because grep only scans EXTENSION_SRC).
|
||||
*
|
||||
* Consumer: headless-reflect operator surface; future autonomous-loop
|
||||
* reflection unit handler.
|
||||
*/
|
||||
export async function renderReflectionPrompt(corpus, options = {}) {
|
||||
const brief = renderReflectionCorpusBrief(corpus);
|
||||
const { loadPrompt } = await import("./prompt-loader.js");
|
||||
return loadPrompt("reflection-pass", {
|
||||
corpus: brief,
|
||||
workingDirectory: options.workingDirectory ?? process.cwd(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Default provider/model used when --model is not supplied. This is the
|
||||
* single point of model defaulting — the rest of runReflection is
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue