{"record":{"id":"1c946cae86fd5903","repo":"EveryInc/compound-engineering-plugin","slug":"context-collectionpath-points-outside-a-compoun","errorCode":null,"errorMessage":"${context.collectionPath} points outside a Compound Engineering checkout; refusing to overwrite it","messagePattern":"(.+?) points outside a Compound Engineering checkout; refusing to overwrite it","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/dev/codex-dev.ts","lineNumber":269,"sourceCode":"    if (path.basename(resolvedTarget) !== \"skills\") {\n      return { kind: \"unrelated\", target, resolvedTarget }\n    }\n    return { kind: \"valid\", target, resolvedTarget }\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { kind: \"broken\", target }\n    throw error\n  }\n}\n\nexport async function activateLocalCollection(context: CodexDevContext): Promise<void> {\n  await fs.mkdir(path.dirname(context.collectionPath), { recursive: true })\n  const desiredTarget = await fs.realpath(context.skillsRoot)\n  const state = await inspectLocalCollection(context)\n  if (state.kind === \"collision\") {\n    throw new Error(`${context.collectionPath} exists and is not a symlink; refusing to overwrite it`)\n  }\n  if (state.kind === \"unrelated\") {\n    throw new Error(`${context.collectionPath} points outside a Compound Engineering checkout; refusing to overwrite it`)\n  }\n  if (state.kind === \"broken\") {\n    throw new Error(`${context.collectionPath} is a broken symlink; refusing to overwrite it`)\n  }\n  if (state.kind === \"valid\" && state.resolvedTarget === desiredTarget) return\n\n  await replaceManagedCollectionLink(context.collectionPath, desiredTarget, state)\n}\n\nexport type ManagedCollectionLinkExpectation =\n  | { kind: \"absent\" }\n  | { kind: \"valid\"; target: string }\n\nexport async function removeManagedCollectionLink(\n  collectionPath: string,\n  expectedTarget: string,\n  options: {\n    ignoreChanges?: boolean","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/EveryInc/compound-engineering-plugin/blob/c9c10f8c75412c7232cb2bd663e5fd1cea98d84e/src/dev/codex-dev.ts#L251-L287","documentation":"When the collection path is a symlink, the library verifies it resolves inside the current Compound Engineering checkout (to <repoRoot>/skills). A symlink pointing somewhere else is kind \"unrelated\": overwriting could destroy a link the user or another tool owns, so activateLocalCollection refuses. This is a deliberate path-safety guard on user-level Codex state.","triggerScenarios":"inspectLocalCollection finds a symlink at <codexHome>/skills/compound-engineering-local whose realpath is not the current checkout's skillsRoot — e.g. it was created from a different clone, worktree, or an entirely unrelated project (src/dev/codex-dev.ts:269).","commonSituations":"Switching between two clones of the repo on one machine; the previous checkout was deleted and a new clone lives at a different path (resolvedTarget no longer matches); another project set up its own compound-engineering-local link.","solutions":["Check where it points: readlink ~/.codex/skills/compound-engineering-local and confirm the target path.","If the target is a deleted or abandoned checkout, remove just the link: rm ~/.codex/skills/compound-engineering-local, then re-run local mode.","Run the workflow from the checkout the link should point at (bun run codex:dev -- local from the new clone) — the link is only rewritten from the owning checkout.","If two checkouts must coexist, remove the link each time before switching, or keep one canonical checkout for local mode."],"exampleFix":"// before\n~/.codex/skills/compound-engineering-local -> /old/path/compound-engineering/skills  // deleted clone\n// after\nrm ~/.codex/skills/compound-engineering-local\ncd ~/src/compound-engineering && bun run codex:dev -- local\n# link now -> ~/src/compound-engineering/skills","handlingStrategy":"validation","validationCode":"import { lstat, realpath } from \"node:fs/promises\"\nimport path from \"node:path\"\nconst p = path.join(process.env.CODEX_HOME || path.join(process.env.HOME!, \".codex\"), \"skills\", \"compound-engineering-local\")\ntry {\n  const target = await realpath(p)\n  const here = await realpath(\"skills\")\n  if (target !== here) console.warn(`Link points to ${target}, not this checkout; rm the link before switching checkouts`)\n} catch { /* absent or dangling: fine */ }","typeGuard":null,"tryCatchPattern":"try {\n  await activateLocalCollection(ctx)\n} catch (error) {\n  if ((error as Error).message.includes(\"points outside a Compound Engineering checkout\")) {\n    console.error(`rm ${ctx.collectionPath} (stale link from another checkout) and retry`)\n  } else throw error\n}","preventionTips":["Keep one canonical checkout for local mode; don't alternate between clones.","After deleting or moving a checkout, rm the stale ~/.codex/skills/compound-engineering-local link.","readlink the collection path when switching machines, clones, or worktrees."],"tags":["symlink","safety","paths"],"backgroundTag":"symlink-points-outside-expected-target","analyzedSha":"c9c10f8c75412c7232cb2bd663e5fd1cea98d84e","analyzedAt":"2026-08-31T15:18:07.959Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}