From 8012f375a3f3b3308fe774a0cd5e24c7c484d98b Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 17 Apr 2026 00:32:04 -0500 Subject: [PATCH] Fix workspace bootstrap prompt routing --- src/agents/bootstrap-files.test.ts | 12 +++++ src/agents/bootstrap-files.ts | 3 ++ .../run/attempt.context-engine-helpers.ts | 2 + ....spawn-workspace.context-injection.test.ts | 21 +++++++++ src/agents/pi-embedded-runner/run/attempt.ts | 14 +++++- src/agents/system-prompt.test.ts | 25 ++++++++++ src/agents/system-prompt.ts | 10 ++++ src/agents/workspace.test.ts | 46 +++++++++++++++++++ src/agents/workspace.ts | 33 +++++++++++++ src/auto-reply/reply/get-reply-run.ts | 18 ++++++-- .../reply/session-reset-prompt.test.ts | 21 +++++++-- src/auto-reply/reply/session-reset-prompt.ts | 16 ++++++- 12 files changed, 212 insertions(+), 9 deletions(-) diff --git a/src/agents/bootstrap-files.test.ts b/src/agents/bootstrap-files.test.ts index 711c4771939..23e023d87c5 100644 --- a/src/agents/bootstrap-files.test.ts +++ b/src/agents/bootstrap-files.test.ts @@ -107,6 +107,18 @@ describe("resolveBootstrapContextForRun", () => { expect(extra?.content).toBe("extra"); }); + it("keeps BOOTSTRAP.md available in shared injected context for non-attempt consumers", async () => { + const workspaceDir = await makeTempWorkspace("openclaw-bootstrap-"); + await fs.writeFile(path.join(workspaceDir, "BOOTSTRAP.md"), "ritual", "utf8"); + await fs.writeFile(path.join(workspaceDir, "AGENTS.md"), "rules", "utf8"); + + const result = await resolveBootstrapContextForRun({ workspaceDir }); + + expect(result.bootstrapFiles.some((file) => file.name === "BOOTSTRAP.md")).toBe(true); + expect(result.contextFiles.some((file) => file.path.endsWith("BOOTSTRAP.md"))).toBe(true); + expect(result.contextFiles.some((file) => file.path.endsWith("AGENTS.md"))).toBe(true); + }); + it("uses heartbeat-only bootstrap files in lightweight heartbeat mode", async () => { const workspaceDir = await makeTempWorkspace("openclaw-bootstrap-"); await fs.writeFile(path.join(workspaceDir, "HEARTBEAT.md"), "check inbox", "utf8"); diff --git a/src/agents/bootstrap-files.ts b/src/agents/bootstrap-files.ts index 5a3b7c8abe4..c4957881068 100644 --- a/src/agents/bootstrap-files.ts +++ b/src/agents/bootstrap-files.ts @@ -15,6 +15,7 @@ import { import { DEFAULT_HEARTBEAT_FILENAME, filterBootstrapFilesForSession, + isWorkspaceBootstrapPending, loadWorkspaceBootstrapFiles, type WorkspaceBootstrapFile, } from "./workspace.js"; @@ -272,3 +273,5 @@ export async function resolveBootstrapContextForRun(params: { }); return { bootstrapFiles, contextFiles }; } + +export { isWorkspaceBootstrapPending }; diff --git a/src/agents/pi-embedded-runner/run/attempt.context-engine-helpers.ts b/src/agents/pi-embedded-runner/run/attempt.context-engine-helpers.ts index 7e95d6c0951..f8ed0e257b2 100644 --- a/src/agents/pi-embedded-runner/run/attempt.context-engine-helpers.ts +++ b/src/agents/pi-embedded-runner/run/attempt.context-engine-helpers.ts @@ -19,6 +19,7 @@ export async function resolveAttemptBootstrapContext< contextInjectionMode: "always" | "continuation-skip"; bootstrapContextMode?: string; bootstrapContextRunKind?: string; + workspaceBootstrapPending?: boolean; sessionFile: string; hasCompletedBootstrapTurn: (sessionFile: string) => Promise; resolveBootstrapContextForRun: () => Promise; @@ -29,6 +30,7 @@ export async function resolveAttemptBootstrapContext< } > { const isContinuationTurn = + !params.workspaceBootstrapPending && params.contextInjectionMode === "continuation-skip" && params.bootstrapContextRunKind !== "heartbeat" && (await params.hasCompletedBootstrapTurn(params.sessionFile)); diff --git a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.context-injection.test.ts b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.context-injection.test.ts index 1444cf8d7b8..999fb8d1e5e 100644 --- a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.context-injection.test.ts +++ b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.context-injection.test.ts @@ -15,6 +15,7 @@ async function resolveBootstrapContext(params: { contextInjectionMode?: "always" | "continuation-skip"; bootstrapContextMode?: string; bootstrapContextRunKind?: string; + workspaceBootstrapPending?: boolean; completed?: boolean; resolver?: () => Promise<{ bootstrapFiles: unknown[]; contextFiles: unknown[] }>; }) { @@ -30,6 +31,7 @@ async function resolveBootstrapContext(params: { contextInjectionMode: params.contextInjectionMode ?? "always", bootstrapContextMode: params.bootstrapContextMode ?? "full", bootstrapContextRunKind: params.bootstrapContextRunKind ?? "default", + workspaceBootstrapPending: params.workspaceBootstrapPending ?? false, sessionFile: "/tmp/session.jsonl", hasCompletedBootstrapTurn, resolveBootstrapContextForRun, @@ -75,6 +77,25 @@ describe("embedded attempt context injection", () => { expect(resolver).toHaveBeenCalledTimes(1); }); + it("does not let stale session markers suppress pending workspace bootstrap", async () => { + const resolver = vi.fn(async () => ({ + bootstrapFiles: [{ name: "AGENTS.md" }, { name: "BOOTSTRAP.md" }], + contextFiles: [{ path: "AGENTS.md" }], + })); + + const { result, hasCompletedBootstrapTurn } = await resolveBootstrapContext({ + contextInjectionMode: "continuation-skip", + workspaceBootstrapPending: true, + completed: true, + resolver, + }); + + expect(result.isContinuationTurn).toBe(false); + expect(hasCompletedBootstrapTurn).not.toHaveBeenCalled(); + expect(result.bootstrapFiles).toEqual([{ name: "AGENTS.md" }, { name: "BOOTSTRAP.md" }]); + expect(resolver).toHaveBeenCalledTimes(1); + }); + it("forwards senderIsOwner into embedded message-action discovery", async () => { const input = buildEmbeddedMessageActionDiscoveryInput({ cfg: {}, diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index bdf9d9ed00e..339c0a6e03a 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -49,6 +49,7 @@ import { import { FULL_BOOTSTRAP_COMPLETED_CUSTOM_TYPE, hasCompletedBootstrapTurn, + isWorkspaceBootstrapPending, makeBootstrapWarn, resolveBootstrapContextForRun, resolveContextInjectionMode, @@ -441,14 +442,16 @@ export async function runEmbeddedAttempt( const sessionLabel = params.sessionKey ?? params.sessionId; const contextInjectionMode = resolveContextInjectionMode(params.config); + const workspaceBootstrapPending = await isWorkspaceBootstrapPending(effectiveWorkspace); const { bootstrapFiles: hookAdjustedBootstrapFiles, - contextFiles, + contextFiles: resolvedContextFiles, shouldRecordCompletedBootstrapTurn, } = await resolveAttemptBootstrapContext({ contextInjectionMode, bootstrapContextMode: params.bootstrapContextMode, bootstrapContextRunKind: params.bootstrapContextRunKind, + workspaceBootstrapPending, sessionFile: params.sessionFile, hasCompletedBootstrapTurn, resolveBootstrapContextForRun: async () => @@ -466,11 +469,17 @@ export async function runEmbeddedAttempt( runKind: params.bootstrapContextRunKind, }), }); + const contextFiles = resolvedContextFiles.filter( + (file) => !/(^|[\\/])BOOTSTRAP\.md$/iu.test(file.path.trim()), + ); + const bootstrapFilesForInjectionStats = hookAdjustedBootstrapFiles.filter( + (file) => file.name !== DEFAULT_BOOTSTRAP_FILENAME, + ); const bootstrapMaxChars = resolveBootstrapMaxChars(params.config); const bootstrapTotalMaxChars = resolveBootstrapTotalMaxChars(params.config); const bootstrapAnalysis = analyzeBootstrapBudget({ files: buildBootstrapInjectionStats({ - bootstrapFiles: hookAdjustedBootstrapFiles, + bootstrapFiles: bootstrapFilesForInjectionStats, injectedFiles: contextFiles, }), bootstrapMaxChars, @@ -869,6 +878,7 @@ export async function runEmbeddedAttempt( toolNames: effectiveTools.map((tool) => tool.name), memoryCitationsMode: params.config?.memory?.citations, contextFiles, + bootstrapPending: workspaceBootstrapPending, routing: promptChannelRouting, }); const privilegedPromptState: { diff --git a/src/agents/system-prompt.test.ts b/src/agents/system-prompt.test.ts index 6b318cdc59a..426a6069a75 100644 --- a/src/agents/system-prompt.test.ts +++ b/src/agents/system-prompt.test.ts @@ -74,6 +74,31 @@ describe("buildAgentSystemPrompt", () => { expect(promptPrefix).toBeUndefined(); }); + it("keeps bootstrap instructions out of the privileged prompt when bootstrap is pending", () => { + const channels = buildAgentPromptChannels({ + workspaceDir: "/tmp/openclaw", + bootstrapPending: true, + }); + + expect(channels.systemPrompt).not.toContain("## Bootstrap"); + expect(channels.systemPrompt).not.toContain("Bootstrap is pending for this workspace."); + }); + + it("adds bootstrap-specific prelude text to the user prompt prefix when bootstrap is pending", () => { + const promptPrefix = buildAgentUserPromptPrefix({ bootstrapPending: true }); + + expect(promptPrefix).toContain("[Bootstrap pending]"); + expect(promptPrefix).toContain( + "Before producing any user-visible reply, you MUST read BOOTSTRAP.md from the workspace", + ); + expect(promptPrefix).toContain( + "Do not greet the user, offer help, answer the message, or reply normally", + ); + expect(promptPrefix).toContain( + "Your first user-visible reply for a bootstrap-pending workspace must follow BOOTSTRAP.md", + ); + }); + it("routes developer and user context when a routing contribution is applied", () => { registerMemoryPromptSection(() => ["## Memory Recall", "Use memory carefully.", ""]); const channels = buildAgentPromptChannels({ diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index ca12e6603ed..bfa3c40a994 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -258,6 +258,7 @@ export function buildAgentUserPromptPrefix(params: { toolNames?: string[]; memoryCitationsMode?: MemoryCitationsMode; contextFiles?: EmbeddedContextFile[]; + bootstrapPending?: boolean; routing?: PromptChannelRoutingResult; }): string | undefined { const promptMode = params.promptMode ?? "full"; @@ -279,6 +280,15 @@ export function buildAgentUserPromptPrefix(params: { (file) => routeMap[normalizeContextFilePath(file.path)] === "user", ); const text = [ + ...(params.bootstrapPending + ? [ + "[Bootstrap pending]", + "Before producing any user-visible reply, you MUST read BOOTSTRAP.md from the workspace and follow it.", + "Do not greet the user, offer help, answer the message, or reply normally until after you have read and are following BOOTSTRAP.md.", + "Your first user-visible reply for a bootstrap-pending workspace must follow BOOTSTRAP.md, not a generic greeting.", + "", + ] + : []), ...splitPromptAdditionLines(params.routing?.userAdditions), ...memorySection, ...buildUserContextSection(userContextFiles), diff --git a/src/agents/workspace.test.ts b/src/agents/workspace.test.ts index 07f1d292002..b6e90c0c16a 100644 --- a/src/agents/workspace.test.ts +++ b/src/agents/workspace.test.ts @@ -14,7 +14,9 @@ import { DEFAULT_USER_FILENAME, ensureAgentWorkspace, filterBootstrapFilesForSession, + isWorkspaceBootstrapPending, loadWorkspaceBootstrapFiles, + resolveWorkspaceBootstrapStatus, resolveDefaultAgentWorkspaceDir, type WorkspaceBootstrapFile, } from "./workspace.js"; @@ -174,6 +176,50 @@ describe("ensureAgentWorkspace", () => { expect(persisted).toContain('"setupCompletedAt": "2026-03-15T02:30:00.000Z"'); }); + it("reports bootstrap pending while BOOTSTRAP.md exists and completion is unset", async () => { + const tempDir = await makeTempWorkspace("openclaw-workspace-"); + + await ensureAgentWorkspace({ dir: tempDir, ensureBootstrapFiles: true }); + + await expect(isWorkspaceBootstrapPending(tempDir)).resolves.toBe(true); + await expect(resolveWorkspaceBootstrapStatus(tempDir)).resolves.toMatchObject({ + phase: "pending", + bootstrapExists: true, + }); + }); + + it("reports bootstrap complete after BOOTSTRAP.md deletion sets setupCompletedAt", async () => { + const tempDir = await makeTempWorkspace("openclaw-workspace-"); + + await ensureAgentWorkspace({ dir: tempDir, ensureBootstrapFiles: true }); + await fs.unlink(path.join(tempDir, DEFAULT_BOOTSTRAP_FILENAME)); + await ensureAgentWorkspace({ dir: tempDir, ensureBootstrapFiles: true }); + + await expect(isWorkspaceBootstrapPending(tempDir)).resolves.toBe(false); + await expect(resolveWorkspaceBootstrapStatus(tempDir)).resolves.toMatchObject({ + phase: "complete", + bootstrapExists: false, + }); + }); + + it("does not reopen bootstrap when BOOTSTRAP.md is restored after completion", async () => { + const tempDir = await makeTempWorkspace("openclaw-workspace-"); + + await ensureAgentWorkspace({ dir: tempDir, ensureBootstrapFiles: true }); + await fs.unlink(path.join(tempDir, DEFAULT_BOOTSTRAP_FILENAME)); + await ensureAgentWorkspace({ dir: tempDir, ensureBootstrapFiles: true }); + await writeWorkspaceFile({ + dir: tempDir, + name: DEFAULT_BOOTSTRAP_FILENAME, + content: "# restored bootstrap", + }); + + await expect(resolveWorkspaceBootstrapStatus(tempDir)).resolves.toMatchObject({ + phase: "complete", + bootstrapExists: true, + }); + }); + it("writes the current fenced HEARTBEAT template body into new workspaces", async () => { const tempDir = await makeTempWorkspace("openclaw-workspace-"); diff --git a/src/agents/workspace.ts b/src/agents/workspace.ts index e23334d89b8..69e69351c52 100644 --- a/src/agents/workspace.ts +++ b/src/agents/workspace.ts @@ -166,6 +166,15 @@ type WorkspaceSetupState = { setupCompletedAt?: string; }; +export type WorkspaceBootstrapPhase = "pending" | "complete"; + +export type WorkspaceBootstrapStatus = { + phase: WorkspaceBootstrapPhase; + bootstrapExists: boolean; + bootstrapSeededAt?: string; + setupCompletedAt?: string; +}; + /** Set of recognized bootstrap filenames for runtime validation */ const VALID_BOOTSTRAP_NAMES: ReadonlySet = new Set([ DEFAULT_AGENTS_FILENAME, @@ -263,6 +272,30 @@ export async function isWorkspaceSetupCompleted(dir: string): Promise { return typeof state.setupCompletedAt === "string" && state.setupCompletedAt.trim().length > 0; } +export async function resolveWorkspaceBootstrapStatus( + dir: string, +): Promise { + const resolvedDir = resolveUserPath(dir); + const [state, bootstrapExists] = await Promise.all([ + readWorkspaceSetupStateForDir(resolvedDir), + fileExists(path.join(resolvedDir, DEFAULT_BOOTSTRAP_FILENAME)), + ]); + const setupCompletedAt = + typeof state.setupCompletedAt === "string" && state.setupCompletedAt.trim().length > 0 + ? state.setupCompletedAt + : undefined; + return { + phase: setupCompletedAt ? "complete" : bootstrapExists ? "pending" : "complete", + bootstrapExists, + bootstrapSeededAt: state.bootstrapSeededAt, + setupCompletedAt, + }; +} + +export async function isWorkspaceBootstrapPending(dir: string): Promise { + return (await resolveWorkspaceBootstrapStatus(dir)).phase === "pending"; +} + async function writeWorkspaceSetupState( statePath: string, state: WorkspaceSetupState, diff --git a/src/auto-reply/reply/get-reply-run.ts b/src/auto-reply/reply/get-reply-run.ts index 01406e5970e..e5e417d2db3 100644 --- a/src/auto-reply/reply/get-reply-run.ts +++ b/src/auto-reply/reply/get-reply-run.ts @@ -4,6 +4,7 @@ import type { ExecToolDefaults } from "../../agents/bash-tools.js"; import { resolveFastModeState } from "../../agents/fast-mode.js"; import { resolveEmbeddedFullAccessState } from "../../agents/pi-embedded-runner/sandbox-info.js"; import type { EmbeddedFullAccessBlockedReason } from "../../agents/pi-embedded-runner/types.js"; +import { isWorkspaceBootstrapPending } from "../../agents/workspace.js"; import { resolveGroupSessionKey } from "../../config/sessions/group.js"; import { resolveSessionFilePath, @@ -43,7 +44,10 @@ import { resolveOriginMessageProvider } from "./origin-routing.js"; import { buildReplyPromptBodies } from "./prompt-prelude.js"; import { resolveActiveRunQueueAction } from "./queue-policy.js"; import { resolveQueueSettings } from "./queue/settings-runtime.js"; -import { buildBareSessionResetPrompt } from "./session-reset-prompt.js"; +import { + buildBareSessionResetBootstrapPendingPrompt, + buildBareSessionResetPrompt, +} from "./session-reset-prompt.js"; import { drainFormattedSystemEvents } from "./session-system-events.js"; import { buildSessionStartupContextPrelude, shouldApplyStartupContext } from "./startup-context.js"; import { resolveTypingMode } from "./typing-mode.js"; @@ -320,15 +324,23 @@ export async function runPreparedReply( isNewSession && ((baseBodyTrimmedRaw.length === 0 && rawBodyTrimmed.length > 0) || isBareNewOrReset); const startupAction = /^\/reset(?:\s|$)/.test(normalizedCommandBody) ? "reset" : "new"; + const workspaceBootstrapPending = + isBareSessionReset || isFirstTurnInSession + ? await isWorkspaceBootstrapPending(workspaceDir) + : false; const startupContextPrelude = - isBareSessionReset && shouldApplyStartupContext({ cfg, action: startupAction }) + isBareSessionReset && + !workspaceBootstrapPending && + shouldApplyStartupContext({ cfg, action: startupAction }) ? await buildSessionStartupContextPrelude({ workspaceDir, cfg, }) : null; const baseBodyFinal = isBareSessionReset - ? buildBareSessionResetPrompt(cfg) + ? workspaceBootstrapPending + ? buildBareSessionResetBootstrapPendingPrompt(cfg) + : buildBareSessionResetPrompt(cfg) : stripPromptThinkingDirectives(baseBody); const envelopeOptions = resolveEnvelopeFormatOptions(cfg); const inboundUserContext = buildInboundUserContextPrefix( diff --git a/src/auto-reply/reply/session-reset-prompt.test.ts b/src/auto-reply/reply/session-reset-prompt.test.ts index fe4d757bc2e..95b3f92523c 100644 --- a/src/auto-reply/reply/session-reset-prompt.test.ts +++ b/src/auto-reply/reply/session-reset-prompt.test.ts @@ -1,19 +1,34 @@ import { describe, it, expect } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; -import { buildBareSessionResetPrompt } from "./session-reset-prompt.js"; +import { + buildBareSessionResetBootstrapPendingPrompt, + buildBareSessionResetPrompt, +} from "./session-reset-prompt.js"; describe("buildBareSessionResetPrompt", () => { it("includes the explicit Session Startup instruction for bare /new and /reset", () => { const prompt = buildBareSessionResetPrompt(); expect(prompt).toContain("Execute your Session Startup sequence now"); expect(prompt).toContain("read the required files before responding to the user"); - expect(prompt).toContain("If BOOTSTRAP.md exists in the provided Project Context"); - expect(prompt).toContain("read it and follow its instructions first"); + expect(prompt).toContain("If bootstrap is still pending for this workspace"); + expect(prompt).toContain("read BOOTSTRAP.md from the workspace"); expect(prompt).not.toContain( "If runtime-provided startup context is included for this first turn", ); }); + it("builds a bootstrap-pending reset prompt that suppresses the normal first greeting", () => { + const prompt = buildBareSessionResetBootstrapPendingPrompt(); + expect(prompt).toContain("while bootstrap is still pending for this workspace"); + expect(prompt).toContain( + "Before producing any user-visible reply, you MUST read BOOTSTRAP.md from the workspace now", + ); + expect(prompt).toContain( + "Do not greet the user, offer help, answer the message, or reply normally", + ); + expect(prompt).toContain("Your first user-visible reply must follow BOOTSTRAP.md"); + }); + it("appends current time line so agents know the date", () => { const cfg = { agents: { defaults: { userTimezone: "America/New_York", timeFormat: "12" } }, diff --git a/src/auto-reply/reply/session-reset-prompt.ts b/src/auto-reply/reply/session-reset-prompt.ts index a0c89c4afce..832cc5a2cf6 100644 --- a/src/auto-reply/reply/session-reset-prompt.ts +++ b/src/auto-reply/reply/session-reset-prompt.ts @@ -2,7 +2,10 @@ import { appendCronStyleCurrentTimeLine } from "../../agents/current-time.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; const BARE_SESSION_RESET_PROMPT_BASE = - "A new session was started via /new or /reset. Execute your Session Startup sequence now - read the required files before responding to the user. If BOOTSTRAP.md exists in the provided Project Context, read it and follow its instructions first. Then greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning."; + "A new session was started via /new or /reset. Execute your Session Startup sequence now - read the required files before responding to the user. If bootstrap is still pending for this workspace, then before producing any user-visible reply you MUST read BOOTSTRAP.md from the workspace and follow it. Do not greet the user, offer help, answer the message, or reply normally until after you have read and are following BOOTSTRAP.md. Only once bootstrap is complete should you greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning."; + +const BARE_SESSION_RESET_BOOTSTRAP_PENDING_PROMPT_BASE = + "A new session was started via /new or /reset while bootstrap is still pending for this workspace. Before producing any user-visible reply, you MUST read BOOTSTRAP.md from the workspace now and follow it. Do not greet the user, offer help, answer the message, or reply normally until after you have read and are following BOOTSTRAP.md. Your first user-visible reply must follow BOOTSTRAP.md, not a generic greeting. If the runtime model differs from default_model in the system prompt, mention the default model only after following BOOTSTRAP.md. Do not mention internal steps, files, tools, or reasoning."; /** * Build the bare session reset prompt, appending the current date/time so agents @@ -17,5 +20,16 @@ export function buildBareSessionResetPrompt(cfg?: OpenClawConfig, nowMs?: number ); } +export function buildBareSessionResetBootstrapPendingPrompt( + cfg?: OpenClawConfig, + nowMs?: number, +): string { + return appendCronStyleCurrentTimeLine( + BARE_SESSION_RESET_BOOTSTRAP_PENDING_PROMPT_BASE, + cfg ?? {}, + nowMs ?? Date.now(), + ); +} + /** @deprecated Use buildBareSessionResetPrompt(cfg) instead */ export const BARE_SESSION_RESET_PROMPT = BARE_SESSION_RESET_PROMPT_BASE;