{"record":{"id":"d617b8a5c89cac46","repo":"can1357/oh-my-pi","slug":"compact-compactmode-name-does-not-take-focus-i","errorCode":null,"errorMessage":"/compact ${compactMode.name} does not take focus instructions.","messagePattern":"/compact (.+?) does not take focus instructions\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/session/session-maintenance.ts","lineNumber":731,"sourceCode":"\t\tmethodOffset = 0,\n\t\tretryController?: AbortController,\n\t): Promise<CompactionResult> {\n\t\tconst ownsCompactionController = retryController === undefined;\n\t\tif (this.#compactionAbortController && this.#compactionAbortController !== retryController) {\n\t\t\tthrow new Error(\"Compaction already in progress\");\n\t\t}\n\t\t// Resolve the `/compact <mode>` subcommand up front so input validation\n\t\t// runs before we disconnect/abort the active agent operation below.\n\t\tconst compactMode = options?.mode ? findCompactMode(options.mode) : undefined;\n\t\t// Modes that produce no LLM summary (snapcompact) have nothing to focus.\n\t\t// Reject focus text loudly so programmatic callers don't silently lose\n\t\t// instructions (the slash path pre-validates via parseCompactArgs).\n\t\t// `internalGuidance` counts the same way — plan-mode approval never\n\t\t// combines with a rejects-focus mode, but reject early if a caller ever\n\t\t// wires it up so we don't silently drop the directive on the snapcompact\n\t\t// fallback (issue #4359).\n\t\tif (compactMode?.rejectsFocus && (customInstructions || options?.internalGuidance)) {\n\t\t\tthrow new Error(`/compact ${compactMode.name} does not take focus instructions.`);\n\t\t}\n\t\tlet methods: CompactionMethod[] = [];\n\t\tlet selectedMethodIndex = -1;\n\t\tlet compactionCommitted = false;\n\t\tlet methodAttempted = false;\n\t\tconst compactionAbortController = retryController ?? new AbortController();\n\t\tconst manualCompactionCleanup = ownsCompactionController ? Promise.withResolvers<void>() : undefined;\n\t\tif (ownsCompactionController) {\n\t\t\tthis.#compactionAbortController = compactionAbortController;\n\t\t\tthis.#manualCompactionCleanup = manualCompactionCleanup?.promise;\n\t\t}\n\t\t// A manual pass supersedes any background speculation; running both would\n\t\t// double-bill the summarizer and race the commit.\n\t\tthis.cancelSpeculation();\n\n\t\ttry {\n\t\t\tif (ownsCompactionController) {\n\t\t\t\tthis.#host.disconnectFromAgent();","sourceCodeStart":713,"sourceCodeEnd":749,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/session-maintenance.ts#L713-L749","documentation":"Thrown by SessionMaintenance's compaction entrypoint when a compaction mode whose `rejectsFocus` flag is true (only `snapcompact`) is invoked together with focus instructions, either as custom text or via `options.internalGuidance`. snapcompact archives history into bitmap images without producing an LLM summary, so focus text would be silently dropped; the library refuses rather than ignore it. The slash-command path pre-validates via `parseCompactArgs`, so this mainly guards programmatic/SDK callers and the snapcompact fallback path (issue #4359).","triggerScenarios":"Calling the compaction API with `compactMode` set to a mode where `CompactModeDef.rejectsFocus === true` (snapcompact) while passing non-empty `customInstructions` or `options.internalGuidance`. E.g. `session.compact({ mode: 'snapcompact' }, 'focus on the refactor plan')` from an extension or SDK script.","commonSituations":"Extensions that attach `internalGuidance` for plan-mode approval wiring it up for every compaction call; scripts porting a `/compact snapcompact focus text` invocation after the parser began rejecting it; mixing snapcompact with prompt-directive logic written for the soft/remote modes.","solutions":["Remove the custom instructions / internalGuidance when the mode is snapcompact.","Switch the mode to `soft` or `remote` if you actually want directed focus text.","If an extension injects internalGuidance unconditionally, gate it on `!compactMode?.rejectsFocus` before calling."],"exampleFix":"// before\nawait session.compact({ mode: \"snapcompact\" }, \"focus on auth changes\");\n// after\nawait session.compact({ mode: \"snapcompact\" }); // snapcompact takes no focus text","handlingStrategy":"validation","validationCode":"import { findCompactMode } from \"./compact-modes\";\nconst modeDef = compactMode ? findCompactMode(compactMode.name) : undefined;\nif (modeDef?.rejectsFocus && (customInstructions || options?.internalGuidance)) {\n  throw new Error(`${modeDef.name} does not accept focus instructions`);\n}","typeGuard":"function takesFocus(mode?: { name: string; rejectsFocus?: boolean }): boolean {\n  return !mode?.rejectsFocus;\n}","tryCatchPattern":null,"preventionTips":["Check `CompactModeDef.rejectsFocus` before attaching instructions to a compaction call.","Prefer the slash path (`parseCompactArgs`) which pre-validates this combination.","Never wire internalGuidance unconditionally across all compaction modes."],"tags":["compaction","invalid-arguments","snapcompact"],"backgroundTag":"incompatible-option-combination","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}