feat(prompts): fragment infrastructure + RFC #4782 stub manifests
Phase 1 — Fragment infrastructure:
- Add {{include:fragment-name}} support to prompt-loader.js
- fragmentsDir registered alongside promptsDir/templatesDir
- warmCache() now reads prompts/fragments/*.md with 'frg:' prefix
- Pre-resolution pass in loadPrompt() resolves {{include:}} before
the {{var}} validator (colon is outside validator regex [a-zA-Z0-9_],
so unresolved includes are caught as parse errors)
- Lazy-load fallback for fragments mirrors existing prompt lazy-load
- Create prompts/fragments/working-directory.md (Variant A: full
contract including 'Do NOT cd to any other directory')
- Create prompts/fragments/working-directory-ops.md (Variant B:
ops prompts, no cd restriction)
- Replace duplicated 3-line Working Directory boilerplate in 17 prompts
with {{include:working-directory}} (12 files) or
{{include:working-directory-ops}} (5 ops files)
- One fix to Working Directory wording now propagates to all 17 prompts
Phase 2 — RFC #4782 stub manifests:
- Add deploy, smoke-production, release, rollback, challenge to
KNOWN_UNIT_TYPES and UNIT_MANIFESTS in unit-context-manifest.js
- All 5 builders already called composeInlinedContext() but returned ""
because resolveManifest() found no entry; now they return live content
- All 26 unit types now have manifests (resolveManifest returns non-null
for every type in KNOWN_UNIT_TYPES)
Tests:
- 5 new tests in prompt-loader-fragments.test.mjs (include resolution,
lazy-load fallback, unknown fragment error, nested var inheritance,
variant-B fragment)
- Full unit suite: 427 files passed, 4476 tests passed, 0 regressions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
55229f6604
commit
ca5d869e34
22 changed files with 253 additions and 51 deletions
|
|
@ -43,6 +43,7 @@ function resolveExtensionDir() {
|
|||
}
|
||||
const __extensionDir = resolveExtensionDir();
|
||||
const promptsDir = join(__extensionDir, "prompts");
|
||||
const fragmentsDir = join(__extensionDir, "prompts", "fragments");
|
||||
const templatesDir = join(__extensionDir, "templates");
|
||||
/**
|
||||
* Return the resolved templates directory path for use in prompts.
|
||||
|
|
@ -95,6 +96,26 @@ function warmCache() {
|
|||
);
|
||||
}
|
||||
}
|
||||
try {
|
||||
for (const file of readdirSync(fragmentsDir)) {
|
||||
if (!file.endsWith(".md")) continue;
|
||||
const cacheKey = `frg:${file.slice(0, -3)}`;
|
||||
if (!templateCache.has(cacheKey)) {
|
||||
templateCache.set(
|
||||
cacheKey,
|
||||
readFileSync(join(fragmentsDir, file), "utf-8"),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// fragments/ may not exist in test environments or older installs.
|
||||
if (!process.env.VITEST && !process.env.NODE_TEST) {
|
||||
logWarning(
|
||||
"prompt",
|
||||
`warmCache: fragments dir not found: ${fragmentsDir}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Snapshot all templates at module load time
|
||||
warmCache();
|
||||
|
|
@ -116,6 +137,29 @@ export function loadPrompt(name, vars = {}) {
|
|||
"If a `SF Skill Preferences` block is present in system context, use it and the `<available_skills>` catalog in your system prompt to decide which skills to load and follow for this unit, without relaxing required verification or artifact rules.",
|
||||
...vars,
|
||||
};
|
||||
// Resolve {{include:fragment-name}} directives before variable validation.
|
||||
// Fragment content can itself declare {{varName}} placeholders, which become
|
||||
// visible to the validator below and are substituted in the normal pass.
|
||||
// The include pattern uses ":" which is outside the validator regex [a-zA-Z0-9_],
|
||||
// so unresolved includes never accidentally pass validation.
|
||||
content = content.replace(/\{\{include:([a-zA-Z][a-zA-Z0-9_-]*)\}\}/g, (_, fragName) => {
|
||||
let frag = templateCache.get(`frg:${fragName}`);
|
||||
if (frag === undefined) {
|
||||
// Lazy-load fallback (mirrors the prompt lazy-load path): allows fragments
|
||||
// added after warmCache() ran (e.g. in test environments) to be resolved.
|
||||
try {
|
||||
frag = readFileSync(join(fragmentsDir, `${fragName}.md`), "utf-8");
|
||||
templateCache.set(`frg:${fragName}`, frag);
|
||||
} catch {
|
||||
throw new SFError(
|
||||
SF_PARSE_ERROR,
|
||||
`loadPrompt("${name}"): unknown fragment "{{include:${fragName}}}". ` +
|
||||
`Create prompts/fragments/${fragName}.md and rebuild.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return frag;
|
||||
});
|
||||
// Check BEFORE substitution: find all {{varName}} placeholders the template
|
||||
// declares and verify every one has a value in vars. Checking after substitution
|
||||
// would also flag {{...}} patterns injected by inlined content (e.g. template
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Challenge (Adversarial Review) — {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
{{include:working-directory-ops}}
|
||||
|
||||
{{inlinedContext}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Complete Milestone {{milestoneId}} ("{{milestoneTitle}}")
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
## Your Role in the Pipeline
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Complete Slice {{sliceId}} ("{{sliceTitle}}") — Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
## Your Role in the Pipeline
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Deploy — {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
{{include:working-directory-ops}}
|
||||
|
||||
{{inlinedContext}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Execute Task {{taskId}} ("{{taskTitle}}") — Slice {{sliceId}} ("{{sliceTitle}}"), Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
A researcher explored the codebase and a planner decomposed the work — you are the executor. The task plan below is your authoritative contract for the slice goal and verification bar, but it is not a substitute for local reality. Verify the referenced files and surrounding code before changing them. Do not do broad re-research or spontaneous re-planning. Small factual corrections, file-path fixes, and local implementation adaptations are part of execution. Escalate to `blocker_discovered: true` only when the slice contract or downstream task graph no longer holds.
|
||||
|
||||
|
|
@ -38,6 +36,7 @@ Then:
|
|||
0. Narrate step transitions, key implementation decisions, and verification outcomes as you work. Keep it terse — one line between tool-call clusters, not between every call — but write complete sentences in user-facing prose, not shorthand notes or scratchpad fragments.
|
||||
0a. **Batch independent tool calls in parallel.** When the next step needs to read or grep multiple files/paths that don't depend on each other's results, issue them in a single tool-call message (multiple tool uses in one assistant turn) rather than one-at-a-time. Examples: reading the handler + the test file + the schema file to triangulate a bug; greping for two unrelated symbols. Sequential tool calls are only correct when each call's input genuinely depends on the previous call's output. Talking-then-doing is also dead weight — if the next action is unambiguous, just take it; describe what you found in the result, not what you plan to look at.
|
||||
0b. **Swarm opportunity check.** Before implementation, decide whether this task can be split into a 2-3 worker same-model swarm. Swarm only if the shards have disjoint file/directory ownership, no shared-interface or lockfile edits, shard-local verification, and clear wall-clock savings. If it passes, dispatch `subagent({ tasks: [...] })` with explicit write scopes, expected output files, and verification per worker; then inspect `git status --short`, synthesize results, resolve conflicts, and run final task verification yourself. If it does not pass, continue single-agent execution without ceremony.
|
||||
0c. **Rubber-duck check (non-trivial tasks only).** If the task touches more than two files, introduces a new abstraction, changes an API boundary, or has a non-obvious failure mode — dispatch a `rubber-duck` subagent with the task plan and any relevant existing code as context. Summarise its verdict in one line. If it returns a **Blocking** finding, address it before writing code. Skip this step for simple edits, test fixes, or renaming tasks.
|
||||
1. {{skillActivation}} Follow any activated skills before writing code. If no skills match this task, skip this step.
|
||||
2. **Verify file existence before editing.** The task plan references specific files. Before reading or editing any file mentioned in the plan, confirm it exists with `ls`, `find`, or `existsSync`. If a referenced file does NOT exist, stop immediately — do not attempt to create it based on the plan's description of what "should" be there. The file may have been deleted, renamed, or moved. Escalate as `blocker_discovered: true` with a clear description of which file is missing and what the plan expected to find. This prevents phantom work on stale file paths.
|
||||
3. Execute the steps in the inlined task plan, adapting minor local mismatches when the surrounding code differs from the planner's snapshot
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Plan Milestone {{milestoneId}} ("{{milestoneTitle}}")
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
All relevant context has been preloaded below - start working immediately without re-reading these files.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Plan Slice {{sliceId}} ("{{sliceTitle}}") — Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
All relevant context has been preloaded below — start working immediately without re-reading these files.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Reassess Roadmap — Milestone {{milestoneId}} after {{completedSliceId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
## Your Role in the Pipeline
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Refine Slice {{sliceId}} ("{{sliceTitle}}") — Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
This unit **expands an approved sketch into a full plan**. It is not a blank-sheet planning pass — the sketch's scope is the authoritative boundary, and the prior slice's real outcomes are the authoritative context. Your job is to produce a detailed plan that fits inside the sketch while reflecting what actually shipped in earlier slices.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Release — {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
{{include:working-directory-ops}}
|
||||
|
||||
{{inlinedContext}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Replan Slice {{sliceId}} ("{{sliceTitle}}") — Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
A completed task reported `blocker_discovered: true`, meaning the current slice plan cannot be executed as-is. Your job is to rewrite the remaining tasks in the slice plan to address the blocker while preserving all completed work.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Research Milestone {{milestoneId}} ("{{milestoneTitle}}")
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
All relevant context has been preloaded below — start working immediately without re-reading these files.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Research Slice {{sliceId}} ("{{sliceTitle}}") — Milestone {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
All relevant context has been preloaded below — start working immediately without re-reading these files.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Rollback — {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
{{include:working-directory-ops}}
|
||||
|
||||
{{inlinedContext}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Run UAT — {{milestoneId}}/{{sliceId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
All relevant context has been preloaded below. Start working immediately without re-reading these files.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ You are executing SF autonomous mode.
|
|||
|
||||
## UNIT: Smoke Test Production — {{milestoneId}}
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory.
|
||||
{{include:working-directory-ops}}
|
||||
|
||||
{{inlinedContext}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
You are the validation orchestrator for **{{milestoneId}} — {{milestoneTitle}}**.
|
||||
|
||||
## Working Directory
|
||||
|
||||
Your working directory is `{{workingDirectory}}`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT `cd` to any other directory.
|
||||
{{include:working-directory}}
|
||||
|
||||
## Mission
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* prompt-loader-fragments.test.mjs — fragment include resolution contracts.
|
||||
*
|
||||
* Purpose: verify that {{include:name}} directives in prompt templates are
|
||||
* resolved before variable validation so fragment-provided placeholder text
|
||||
* participates in normal {{var}} substitution.
|
||||
*
|
||||
* Consumer: prompt-loader.js warmCache + loadPrompt.
|
||||
*/
|
||||
import { rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, test } from "vitest";
|
||||
import { loadPrompt } from "../prompt-loader.js";
|
||||
|
||||
const promptsDir = join(import.meta.dirname, "..", "prompts");
|
||||
const fragmentsDir = join(promptsDir, "fragments");
|
||||
|
||||
// Temp fixture files written during tests — cleaned up in afterEach.
|
||||
const tempFiles = [];
|
||||
|
||||
function writeFixturePrompt(name, content) {
|
||||
const path = join(promptsDir, `${name}.md`);
|
||||
writeFileSync(path, content);
|
||||
tempFiles.push(path);
|
||||
return name;
|
||||
}
|
||||
|
||||
function writeFixtureFragment(name, content) {
|
||||
const path = join(fragmentsDir, `${name}.md`);
|
||||
writeFileSync(path, content);
|
||||
tempFiles.push(path);
|
||||
return name;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
for (const p of tempFiles.splice(0)) rmSync(p, { force: true });
|
||||
});
|
||||
|
||||
describe("fragment include resolution", () => {
|
||||
test("fragment_resolved_and_var_substituted_in_one_pass", () => {
|
||||
// Write a minimal fragment and a minimal prompt that includes it.
|
||||
writeFixtureFragment("testfrag-wd-simple", "## WD\n\nPath: `{{workingDirectory}}`.");
|
||||
writeFixturePrompt("testprompt-include-simple", "{{include:testfrag-wd-simple}}\n");
|
||||
|
||||
const result = loadPrompt("testprompt-include-simple", {
|
||||
workingDirectory: "/my/project",
|
||||
});
|
||||
|
||||
expect(result).toContain("## WD");
|
||||
expect(result).toContain("`/my/project`");
|
||||
});
|
||||
|
||||
test("working_directory_fragment_resolves_in_real_prompt", () => {
|
||||
// Use a real migrated prompt that includes {{include:working-directory}}.
|
||||
// Write a minimal wrapper prompt so we control the exact var set.
|
||||
writeFixturePrompt(
|
||||
"testprompt-wd-real",
|
||||
"# Header\n\n{{include:working-directory}}\n",
|
||||
);
|
||||
|
||||
const result = loadPrompt("testprompt-wd-real", {
|
||||
workingDirectory: "/real/path",
|
||||
});
|
||||
|
||||
expect(result).toContain("## Working Directory");
|
||||
expect(result).toContain("`/real/path`");
|
||||
expect(result).toContain("Do NOT `cd` to any other directory");
|
||||
});
|
||||
|
||||
test("ops_fragment_omits_no_cd_restriction", () => {
|
||||
writeFixturePrompt(
|
||||
"testprompt-wd-ops",
|
||||
"# Header\n\n{{include:working-directory-ops}}\n",
|
||||
);
|
||||
|
||||
const result = loadPrompt("testprompt-wd-ops", {
|
||||
workingDirectory: "/ops/path",
|
||||
});
|
||||
|
||||
expect(result).toContain("## Working Directory");
|
||||
expect(result).toContain("`/ops/path`");
|
||||
expect(result).not.toContain("Do NOT `cd`");
|
||||
});
|
||||
|
||||
test("unknown_fragment_throws_parse_error", () => {
|
||||
writeFixturePrompt(
|
||||
"testprompt-unknown-frag",
|
||||
"{{include:this-fragment-does-not-exist-xyzzy}}\n",
|
||||
);
|
||||
|
||||
expect(() => loadPrompt("testprompt-unknown-frag", {})).toThrow(
|
||||
/unknown fragment.*this-fragment-does-not-exist-xyzzy/,
|
||||
);
|
||||
});
|
||||
|
||||
test("prompts_without_includes_unaffected", () => {
|
||||
// A plain template with no {{include:}} must still load and substitute cleanly.
|
||||
writeFixturePrompt(
|
||||
"testprompt-no-include",
|
||||
"# Plain\n\nValue: {{someVar}}.\n",
|
||||
);
|
||||
|
||||
const result = loadPrompt("testprompt-no-include", { someVar: "hello" });
|
||||
|
||||
expect(result).toBe("# Plain\n\nValue: hello.");
|
||||
expect(result).not.toContain("{{include:");
|
||||
});
|
||||
});
|
||||
|
|
@ -116,6 +116,12 @@ export const KNOWN_UNIT_TYPES = [
|
|||
"discuss-requirements",
|
||||
"research-project",
|
||||
"workflow-preferences",
|
||||
// ─── Ops / deployment pipeline ────────────────────────────────────────
|
||||
"deploy",
|
||||
"smoke-production",
|
||||
"release",
|
||||
"rollback",
|
||||
"challenge",
|
||||
];
|
||||
export const UNIT_MANIFESTS = {
|
||||
// ─── Milestone-scoped ────────────────────────────────────────────────
|
||||
|
|
@ -508,6 +514,77 @@ export const UNIT_MANIFESTS = {
|
|||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
||||
},
|
||||
// ─── Ops / deployment pipeline ────────────────────────────────────────
|
||||
"deploy": {
|
||||
skills: { mode: "all" },
|
||||
knowledge: "critical-only",
|
||||
memory: "critical-only",
|
||||
codebaseMap: false,
|
||||
preferences: "active-only",
|
||||
tools: TOOLS_ALL,
|
||||
artifacts: {
|
||||
inline: ["project"],
|
||||
excerpt: [],
|
||||
onDemand: [],
|
||||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
||||
},
|
||||
"smoke-production": {
|
||||
skills: { mode: "all" },
|
||||
knowledge: "critical-only",
|
||||
memory: "critical-only",
|
||||
codebaseMap: false,
|
||||
preferences: "active-only",
|
||||
tools: TOOLS_ALL,
|
||||
artifacts: {
|
||||
inline: ["project"],
|
||||
excerpt: [],
|
||||
onDemand: [],
|
||||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
||||
},
|
||||
"release": {
|
||||
skills: { mode: "all" },
|
||||
knowledge: "critical-only",
|
||||
memory: "critical-only",
|
||||
codebaseMap: false,
|
||||
preferences: "active-only",
|
||||
tools: TOOLS_ALL,
|
||||
artifacts: {
|
||||
inline: ["project"],
|
||||
excerpt: [],
|
||||
onDemand: [],
|
||||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
||||
},
|
||||
"rollback": {
|
||||
skills: { mode: "all" },
|
||||
knowledge: "critical-only",
|
||||
memory: "critical-only",
|
||||
codebaseMap: false,
|
||||
preferences: "active-only",
|
||||
tools: TOOLS_ALL,
|
||||
artifacts: {
|
||||
inline: ["project"],
|
||||
excerpt: [],
|
||||
onDemand: [],
|
||||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
||||
},
|
||||
"challenge": {
|
||||
skills: { mode: "all" },
|
||||
knowledge: "critical-only",
|
||||
memory: "critical-only",
|
||||
codebaseMap: false,
|
||||
preferences: "active-only",
|
||||
tools: TOOLS_ALL,
|
||||
artifacts: {
|
||||
inline: ["project"],
|
||||
excerpt: [],
|
||||
onDemand: [],
|
||||
},
|
||||
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
||||
},
|
||||
};
|
||||
// ─── Lookup helper ────────────────────────────────────────────────────────
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue