refactor: consolidate DB-fallback inline functions in auto-prompts (#1276)
* refactor: consolidate DB-fallback inline functions in auto-prompts Extract shared inlineFromDbOrFile() helper that encapsulates the repeated pattern of checking DB availability, dynamically importing context-store, running a query, formatting results, and falling back to the filesystem. The three public functions (inlineDecisionsFromDb, inlineRequirementsFromDb, inlineProjectFromDb) become thin wrappers that pass only the differing query/format logic as a callback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update source-level test to match refactored DB-fallback function name The context-compression test greps auto-prompts.ts source for `inlineGsdRootFile(base, "project.md"` which was replaced by `inlineProjectFromDb(base)` in the consolidation refactor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8f06a14fb6
commit
922826ba8a
2 changed files with 50 additions and 48 deletions
|
|
@ -188,6 +188,38 @@ export async function inlineGsdRootFile(
|
|||
|
||||
// ─── DB-Aware Inline Helpers ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Shared DB-fallback pattern: attempt a DB query via the context-store, format
|
||||
* the result, and fall back to the filesystem file when the DB is unavailable
|
||||
* or the query yields no results.
|
||||
*
|
||||
* @param base Project root for filesystem fallback
|
||||
* @param label Section heading (e.g. "Decisions")
|
||||
* @param filename Filesystem fallback file (e.g. "decisions.md")
|
||||
* @param queryDb Async callback receiving the dynamically-imported
|
||||
* context-store module. Returns formatted markdown or null.
|
||||
*/
|
||||
async function inlineFromDbOrFile(
|
||||
base: string,
|
||||
label: string,
|
||||
filename: string,
|
||||
queryDb: (cs: typeof import("./context-store.js")) => string | null,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const { isDbAvailable } = await import("./gsd-db.js");
|
||||
if (isDbAvailable()) {
|
||||
const contextStore = await import("./context-store.js");
|
||||
const content = queryDb(contextStore);
|
||||
if (content) {
|
||||
return `### ${label}\nSource: \`.gsd/${filename.toUpperCase().replace(/\.MD$/i, "")}.md\`\n\n${content}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// DB not available — fall through to filesystem
|
||||
}
|
||||
return inlineGsdRootFile(base, filename, label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline decisions with optional milestone scoping from the DB.
|
||||
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
||||
|
|
@ -196,23 +228,13 @@ export async function inlineDecisionsFromDb(
|
|||
base: string, milestoneId?: string, scope?: string, level?: InlineLevel,
|
||||
): Promise<string | null> {
|
||||
const inlineLevel = level ?? resolveInlineLevel();
|
||||
try {
|
||||
const { isDbAvailable } = await import("./gsd-db.js");
|
||||
if (isDbAvailable()) {
|
||||
const { queryDecisions, formatDecisionsForPrompt } = await import("./context-store.js");
|
||||
const decisions = queryDecisions({ milestoneId, scope });
|
||||
if (decisions.length > 0) {
|
||||
// Use compact format for non-full levels to save ~35% tokens
|
||||
const formatted = inlineLevel !== "full"
|
||||
? formatDecisionsCompact(decisions)
|
||||
: formatDecisionsForPrompt(decisions);
|
||||
return `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${formatted}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// DB not available — fall through to filesystem
|
||||
}
|
||||
return inlineGsdRootFile(base, "decisions.md", "Decisions");
|
||||
return inlineFromDbOrFile(base, "Decisions", "decisions.md", (cs) => {
|
||||
const decisions = cs.queryDecisions({ milestoneId, scope });
|
||||
if (decisions.length === 0) return null;
|
||||
return inlineLevel !== "full"
|
||||
? formatDecisionsCompact(decisions)
|
||||
: cs.formatDecisionsForPrompt(decisions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -223,23 +245,13 @@ export async function inlineRequirementsFromDb(
|
|||
base: string, sliceId?: string, level?: InlineLevel,
|
||||
): Promise<string | null> {
|
||||
const inlineLevel = level ?? resolveInlineLevel();
|
||||
try {
|
||||
const { isDbAvailable } = await import("./gsd-db.js");
|
||||
if (isDbAvailable()) {
|
||||
const { queryRequirements, formatRequirementsForPrompt } = await import("./context-store.js");
|
||||
const requirements = queryRequirements({ sliceId });
|
||||
if (requirements.length > 0) {
|
||||
// Use compact format for non-full levels to save ~40% tokens
|
||||
const formatted = inlineLevel !== "full"
|
||||
? formatRequirementsCompact(requirements)
|
||||
: formatRequirementsForPrompt(requirements);
|
||||
return `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// DB not available — fall through to filesystem
|
||||
}
|
||||
return inlineGsdRootFile(base, "requirements.md", "Requirements");
|
||||
return inlineFromDbOrFile(base, "Requirements", "requirements.md", (cs) => {
|
||||
const requirements = cs.queryRequirements({ sliceId });
|
||||
if (requirements.length === 0) return null;
|
||||
return inlineLevel !== "full"
|
||||
? formatRequirementsCompact(requirements)
|
||||
: cs.formatRequirementsForPrompt(requirements);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,19 +261,9 @@ export async function inlineRequirementsFromDb(
|
|||
export async function inlineProjectFromDb(
|
||||
base: string,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const { isDbAvailable } = await import("./gsd-db.js");
|
||||
if (isDbAvailable()) {
|
||||
const { queryProject } = await import("./context-store.js");
|
||||
const content = queryProject();
|
||||
if (content) {
|
||||
return `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${content}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// DB not available — fall through to filesystem
|
||||
}
|
||||
return inlineGsdRootFile(base, "project.md", "Project");
|
||||
return inlineFromDbOrFile(base, "Project", "project.md", (cs) => {
|
||||
return cs.queryProject();
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Skill Discovery ──────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ test("compression: buildPlanMilestonePrompt minimal drops project/requirements/d
|
|||
// The plan-milestone builder should gate root file inlining on inlineLevel
|
||||
assert.ok(
|
||||
promptsSrc.includes('inlineLevel !== "minimal"') &&
|
||||
promptsSrc.includes('inlineGsdRootFile(base, "project.md"'),
|
||||
promptsSrc.includes("inlineProjectFromDb(base)"),
|
||||
"plan-milestone should conditionally include project.md based on level",
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue