{"version":3,"file":"index.mjs","names":["loadDoomConfigLenient"],"sources":["../../../../src/cli/commands/sync/index.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigDirectory } from '@agimon-ai/doompi-config/config';\nimport { loadDomains } from '@agimon-ai/doompi-config/domains';\nimport { filterHookDisabledLayers, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { loadMajorModesConfig, loadMajorModesConfigLenient } from '@agimon-ai/doompi-config/majorModes';\nimport type { ConfigDiagnostic } from '@agimon-ai/doompi-config/types';\nimport { DOOM_MCP_BUNDLE_FILE } from '@agimon-ai/doompi-core/mcp-facet';\nimport {\n  mergePiSettings,\n  piAgentDirectory,\n  piThemeDirectory,\n  readPiSettings,\n  serializePiSettings,\n} from '@agimon-ai/doompi-core/runtime-pi-settings';\nimport { DOOM_SERVER_BUNDLE_FILE } from '@agimon-ai/doompi-core/server-facet';\nimport {\n  acquireSyncLocationLock,\n  resolveSyncLocation,\n  syncGenerationDirectory,\n} from '@agimon-ai/doompi-core/sync-location';\nimport {\n  DOOMPI_API_VERSION,\n  publishSyncRegistration,\n  readSyncRegistration,\n  SYNC_REGISTRATION_VERSION,\n  syncStateSha256,\n  type SyncPackageRegistration,\n} from '@agimon-ai/doompi-core/sync-registration';\nimport { DEFAULT_THEME, DEFAULT_THEME_NAME } from '@agimon-ai/doompi-ui/theme';\n\nimport { buildSyncedRuntime } from '../../../builders/cli';\nimport { readBootstrapStatus } from '../../../builders/cli/bootstrapLocator';\nimport {\n  createLayerResolvers,\n  type ExtensionComposition,\n  PERSONA_ENTRY,\n  resolveExtensionComposition,\n} from '../../../builders/cli/extensionAssembler';\nimport { buildHarnessContext } from '../../../builders/cli/harnessContext';\nimport {\n  doomPiPackageRoot,\n  piExtensionAliasIsCurrent,\n  writePiExtensionAlias,\n} from '../../../builders/cli/piExtensionAlias';\nimport { piExtensionDispatcherIsUpgradeable } from '../../../builders/cli/piExtensionDispatcher';\nimport {\n  DUPLICATE_REGISTRATION_DRIFT,\n  projectRegistersDoom,\n  writeProjectPiSettings,\n} from '../../../builders/cli/projectSettings';\nimport { syncServerBundle } from '../../../builders/server';\nimport { syncMcpBundle } from '../../../builders/server/mcpBundle';\nimport { syncWebBundle } from '../../../builders/web';\nimport { HARNESS_STATE_POINTER, loadHarnessState } from '../../../composition/harnessState';\nimport { ensureLayerPackages, missingLayerPackageSpecifiers } from '../../../composition/layerPackageInstaller';\nimport { loadDoomConfigLenient } from '../../../composition/projectTrust';\nimport { resolveDoomConfigurationRoot } from '../../../composition/repository';\nimport { readSyncDrift, type SyncDriftReason } from '../../../composition/syncDrift';\nimport {\n  computeInputsHash,\n  computeMcpSourcesHash,\n  computeServerSourcesHash,\n  computeWebSourcesHash,\n  readLocatedSyncState,\n  readMcpServerNames,\n  recordResolvedEntries,\n  SYNC_STATE_VERSION,\n  type SyncSelection,\n  type SyncState,\n  syncStateRootMatches,\n  writeSyncState,\n} from '../../../composition/syncState';\nimport type { HarnessOptions } from '../../../composition/types/harness';\nimport { DOOMPI_DOMAINS_ENV, DOOMPI_MAJOR_MODE_ENV, DOOMPI_PROFILE_ENV } from '../../matrixOptions';\nimport { parseHarnessArgs } from '../../options';\nimport { SyncProgress, type SyncProgressOutput } from './presenter';\n\n/**\n * `doom-pi sync`: resolve the matrix once and write it where plain Pi finds it.\n *\n * The doom-emacs split. Everything that needs a real Node process (module\n * resolution, staging skills and agents, generating the MCP config) happens\n * here, and the doom-pi extension then only reads what this produced. The\n * launcher is untouched and keeps resolving the same matrix per run.\n */\n\nconst SYNC_COMMAND = 'sync';\nconst CHECK_OPTION = '--check';\n/** Republishes even when nothing drifted, for a generation suspected of being damaged. */\nconst FORCE_OPTION = '--force';\nconst GLOBAL_OPTION = '--global';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\nconst PERSONA_FILE_ENV = 'DOOMPI_PERSONA_FILE';\nconst HOOK_EMITTER = path.join('tools', 'harness', 'emit-hooks.mjs');\nconst NONE = '(none)';\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst SYNC_LABEL = 'sync';\nconst RUNTIME_LABEL = 'runtime';\nconst WEB_LABEL = 'web';\nconst API_LABEL = 'api';\n\nexport interface SyncRoots {\n  globalOnly: boolean;\n  globalRoot: string;\n  sourceRoot: string;\n  targetRoot: string;\n}\n\n/** Resolves the configuration source and publication destination for one sync. */\nexport function resolveSyncRoots(\n  args: readonly string[],\n  environment: NodeJS.ProcessEnv = process.env,\n  currentDirectory = process.cwd(),\n  homeDirectory = environment.HOME ?? os.homedir(),\n): SyncRoots {\n  const globalRoot = globalDoomConfigDirectory(homeDirectory);\n  const inheritedRoot = environment[HARNESS_ROOT_ENV];\n  const sourceRoot = inheritedRoot\n    ? path.resolve(inheritedRoot)\n    : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n  const globalOnly = args.includes(GLOBAL_OPTION);\n  return { globalOnly, globalRoot, sourceRoot, targetRoot: globalOnly ? globalRoot : sourceRoot };\n}\n\nconst GLOBAL_SCOPE_INHERITED_KEYS = [\n  HARNESS_ROOT_ENV,\n  HARNESS_STATE_POINTER,\n  DOOMPI_MAJOR_MODE_ENV,\n  DOOMPI_DOMAINS_ENV,\n  DOOMPI_PROFILE_ENV,\n] as const;\n\n/** Removes workspace-only state before a global runtime is resolved. */\nexport function environmentForSyncScope(environment: NodeJS.ProcessEnv, globalOnly: boolean): NodeJS.ProcessEnv {\n  if (!globalOnly) return environment;\n  const scoped = { ...environment };\n  for (const key of GLOBAL_SCOPE_INHERITED_KEYS) delete scoped[key];\n  return scoped;\n}\n\n/**\n * Harness variables worth recording, by prefix or exact name.\n *\n * An allowlist rather than the whole environment: the state file is a snapshot\n * of resolved configuration, and dumping `process.env` into it would write\n * every credential the sync happened to run with onto disk.\n */\nconst RECORDED_PREFIXES = ['DOOMPI_'];\nconst RECORDED_KEYS = ['CLAUDE_PROJECT_DIR', 'CODEX_REPO_ROOT', 'ORIGINAL_REPO_PATH', 'MCP_UI_VIEWER'];\n/**\n * Launcher-only values a synced session must not inherit.\n *\n * The child extension list is recomposed on every load, and the subagent binary\n * points at `pi.sh`, which a session started as plain `pi` should not shell out\n * to: Doom Team resolves Pi's own CLI when the variable is absent.\n */\nconst EXCLUDED_KEYS = new Set([\n  'DOOMPI_CHILD_EXTENSIONS',\n  'DOOMPI_COMPOSED',\n  'DOOMPI_MUTE',\n  'DOOMPI_TEMP_DIR',\n  // A pointer to the syncing process's own state file. Recording it would hand\n  // every later session a path to a state that died with this one.\n  HARNESS_STATE_POINTER,\n  'PI_SUBAGENT_PI_BINARY',\n]);\n\ntype SyncOutput = SyncProgressOutput;\n\nexport type SyncSettingsMode = 'persisted' | 'embedded';\n\nexport interface SyncCommandOptions {\n  settingsMode?: SyncSettingsMode;\n  /** Test/embedding override; normal CLI execution uses the process home. */\n  homeDirectory?: string;\n  /** Internal pipeline seam when the caller owns the worktree lock. */\n  lockHeld?: boolean;\n}\n\nexport interface SyncResult {\n  statePath: string;\n  /** Omitted when DPI supplies the integration as a process-local overlay. */\n  settingsPath?: string;\n  /** Set only when the repository still carried its own DoomPi registration. */\n  projectSettingsPath?: string;\n  selection: SyncSelection;\n  mcpServers: string[];\n  skillCount: number;\n  agentCount: number;\n}\n\nexport function recordedEnvironment(environment: NodeJS.ProcessEnv): Record<string, string> {\n  const recorded: Record<string, string> = {};\n  for (const [key, value] of Object.entries(environment)) {\n    if (value === undefined || EXCLUDED_KEYS.has(key)) continue;\n    if (RECORDED_KEYS.includes(key) || RECORDED_PREFIXES.some((prefix) => key.startsWith(prefix))) {\n      recorded[key] = value;\n    }\n  }\n  return recorded;\n}\n\n/**\n * Reports the config keys sync chose to ignore.\n *\n * Never fatal. A key nobody recognises is usually a config written for another\n * version of a layer, and refusing to build over it is worse than proceeding\n * without it. The strict check lives in `doompi doctor`.\n */\nfunction writeConfigDiagnostics(diagnostics: readonly ConfigDiagnostic[], output: SyncOutput): void {\n  if (diagnostics.length === 0) return;\n  const lines = diagnostics.map((entry) => `  ${entry.filePath}: ${entry.path}`).join('\\n');\n  output.write(\n    `config:   ignored ${String(diagnostics.length)} unsupported key(s); run doompi doctor for the strict check\\n${lines}\\n`,\n  );\n}\n/**\n * Layers the repository's declared selection under the usual resolution.\n *\n * `.doom/config.yaml` holds what the repository selects by default, the way\n * init.el does for doom-emacs. Seeding the environment the parser reads keeps\n * the precedence the launcher already documents: an explicit flag wins, then an\n * exported variable, then the declared default.\n */\nexport function selectionEnvironment(\n  repoRoot: string,\n  environment: NodeJS.ProcessEnv,\n  homeDirectory?: string,\n): NodeJS.ProcessEnv {\n  const { selection } = loadDoomConfigLenient(repoRoot, homeDirectory).config;\n  if (!selection) return environment;\n  return {\n    ...environment,\n    ...(selection.majorMode && !environment[DOOMPI_MAJOR_MODE_ENV]\n      ? { [DOOMPI_MAJOR_MODE_ENV]: selection.majorMode }\n      : {}),\n    ...(selection.profile && !environment[DOOMPI_PROFILE_ENV] ? { [DOOMPI_PROFILE_ENV]: selection.profile } : {}),\n    ...(selection.domains && environment[DOOMPI_DOMAINS_ENV] === undefined\n      ? { [DOOMPI_DOMAINS_ENV]: selection.domains.join(',') }\n      : {}),\n  };\n}\n\nexport function toSelection(\n  options: Pick<HarnessOptions, 'majorMode' | 'domains' | 'profile' | 'preset'>,\n): SyncSelection {\n  return {\n    majorMode: options.majorMode,\n    domains: options.domains,\n    profile: options.profile,\n    preset: options.preset,\n  };\n}\n\nexport function selectionCompositionFingerprint(\n  repoRoot: string,\n  options: Pick<HarnessOptions, 'agents' | 'hooks' | 'majorMode' | 'mcp' | 'preset'>,\n  homeDirectory: string = os.homedir(),\n): string {\n  const majorModesConfig = loadMajorModesConfig(repoRoot, homeDirectory);\n  const resolvers = createLayerResolvers(repoRoot);\n  return resolveExtensionComposition({\n    agents: options.agents,\n    autoStop: false,\n    mute: false,\n    preset: options.preset,\n    personaEntry: resolvers.packageEntry(PERSONA_ENTRY),\n    majorMode: options.majorMode,\n    layers: filterHookDisabledLayers(\n      majorModesConfig,\n      resolveLayers(majorModesConfig, options.majorMode),\n      options.hooks,\n    ),\n    majorModesConfig,\n    resolvers,\n  }).fingerprint;\n}\n\n/** Settings, dispatcher and theme differences an init would fix, independent of sync state. */\nfunction piIntegrationDrift(agentDirectory: string): string[] {\n  const drift: string[] = [];\n  const themePath = path.join(piThemeDirectory(agentDirectory), `${DEFAULT_THEME_NAME}.json`);\n  const settings = readPiSettings(agentDirectory);\n  const merged = mergePiSettings(settings, agentDirectory, { themePath, themeName: DEFAULT_THEME_NAME });\n  if (serializePiSettings(merged) !== serializePiSettings(settings)) {\n    drift.push('Pi user settings are out of date; run doompi init');\n  }\n  if (!piExtensionAliasIsCurrent(agentDirectory)) drift.push('Pi user dispatcher is out of date; run doompi init');\n  const expectedTheme = `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`;\n  if (!fs.existsSync(themePath) || fs.readFileSync(themePath, 'utf8') !== expectedTheme) {\n    drift.push('Pi user theme is out of date; run doompi init');\n  }\n  return drift;\n}\n\n/** Differences between what a sync would produce and what is on disk. */\nexport function collectDrift(\n  repoRoot: string,\n  selection: SyncSelection,\n  state: SyncState | undefined,\n  environment: NodeJS.ProcessEnv = process.env,\n  settingsMode: SyncSettingsMode = 'persisted',\n  expectedCompositionFingerprint?: string,\n): string[] {\n  if (!state) return ['no sync state: run doompi sync'];\n  const drift: string[] = [];\n  if (syncRegistrationNeedsApiMigration(repoRoot, environment.HOME ?? os.homedir())) {\n    drift.push('DoomPi registration needs API migration');\n  }\n  if (!syncStateRootMatches(repoRoot, state.root)) drift.push('sync state belongs to a different repository');\n  const recorded = state.selection;\n  if (\n    recorded.majorMode !== selection.majorMode ||\n    recorded.profile !== selection.profile ||\n    recorded.preset !== selection.preset ||\n    recorded.domains.join(',') !== selection.domains.join(',')\n  ) {\n    drift.push('selection changed since the last sync');\n  }\n  // Hashed against the recorded selection, not the requested one, so a\n  // selection change is reported once rather than as two findings.\n  if (computeInputsHash(repoRoot, recorded, environment.HOME ?? os.homedir()) !== state.inputsHash) {\n    drift.push('.doom configuration changed');\n  }\n  // Re-resolving is what catches a dependency upgrade moving a package, which\n  // the inputs hash deliberately does not read.\n  if (\n    JSON.stringify(\n      recordResolvedEntries(\n        loadMajorModesConfig(repoRoot, environment.HOME ?? os.homedir()),\n        createLayerResolvers(repoRoot),\n      ),\n    ) !== JSON.stringify(state.resolved)\n  ) {\n    drift.push('resolved extension paths changed');\n  }\n  if (expectedCompositionFingerprint && state.compositionFingerprint !== expectedCompositionFingerprint) {\n    drift.push('extension composition changed');\n  }\n  try {\n    if (!readBootstrapStatus(repoRoot, undefined, environment.HOME ?? os.homedir()).fresh) {\n      drift.push('precompiled runtime is missing or stale');\n    }\n  } catch {\n    drift.push('precompiled runtime is missing or stale');\n  }\n\n  if (settingsMode === 'persisted') {\n    const agentDirectory = piAgentDirectory(environment);\n    const themePath = path.join(piThemeDirectory(agentDirectory), `${DEFAULT_THEME_NAME}.json`);\n    drift.push(...piIntegrationDrift(agentDirectory));\n    if (projectRegistersDoom(repoRoot)) drift.push(DUPLICATE_REGISTRATION_DRIFT);\n    if (state.baseline.themePath !== themePath || state.baseline.themeName !== DEFAULT_THEME_NAME) {\n      drift.push('synced theme location is out of date');\n    }\n  }\n  const sharedDrift = readSyncDrift({ repoRoot, homeDirectory: environment.HOME ?? os.homedir() });\n  const sharedMessages: Partial<Record<SyncDriftReason, string>> = {\n    'never-synced': 'sync registration is missing or invalid',\n    'code-changed': 'cockpit sources changed since the last sync',\n    'cockpit-bundle-missing': 'cockpit bundle is missing',\n    'package-apis-missing': 'package API routes are missing',\n    'server-bundle-stale': 'server bundle is missing or stale',\n    'mcp-bundle-stale': 'MCP bundle is missing or stale',\n  };\n  for (const reason of sharedDrift.reasons) {\n    const message = sharedMessages[reason];\n    if (message) drift.push(message);\n  }\n  return drift;\n}\n\n/** Regenerates the hook files the other frontends read before any harness code runs. */\nfunction emitFrontendHooks(repoRoot: string, output: SyncOutput): void {\n  const emitter = path.join(repoRoot, HOOK_EMITTER);\n  if (!fs.existsSync(emitter)) return;\n  const result = spawnSync(process.execPath, [emitter, '--write'], { cwd: repoRoot, encoding: 'utf8' });\n  if (result.status === 0) {\n    output.write('hooks:    regenerated for Claude Code and Codex\\n');\n    return;\n  }\n  output.write(`hooks:    emit-hooks failed (${result.stderr?.trim() || `exit ${String(result.status)}`})\\n`);\n}\n\nexport function formatSyncResult(result: SyncResult, runner = 'pi'): string {\n  const { selection } = result;\n  return [\n    `mode:     ${selection.majorMode}`,\n    `domains:  ${selection.domains.join(', ') || NONE}`,\n    `profile:  ${selection.profile ?? NONE}`,\n    `skills:   ${result.skillCount}`,\n    `agents:   ${result.agentCount}`,\n    `mcp:      ${result.mcpServers.join(', ') || NONE}`,\n    `state:    ${result.statePath}`,\n    ...(result.settingsPath ? [`settings: ${result.settingsPath}`] : []),\n    ...(result.projectSettingsPath\n      ? [`project:  removed duplicate registration from ${result.projectSettingsPath}`]\n      : []),\n    '',\n    `Run ${runner} from the repository root to use it.`,\n    '',\n  ].join('\\n');\n}\n\n/**\n * The DoomPi that produced this generation, which is the one that can load it.\n *\n * Always the executing package, never another copy the repository happens to\n * install. A generation is not portable between two installations: the bundles\n * are compiled from the building package's own extension entries, the recorded\n * compiler inputs are its files, and the state names its bootstrap entry. Naming\n * a second copy here publishes a registration whose package disagrees with the\n * state it points at, and Pi's dispatcher then loads a harness that rejects the\n * bootstrap as stale on every session, with no sync able to fix it.\n *\n * A repository that wants its own copy to own its sessions runs sync with that\n * copy's CLI, which makes it the executing package.\n */\nfunction packageRegistrationFor(): SyncPackageRegistration {\n  const root = fs.realpathSync(doomPiPackageRoot());\n  const manifestPath = path.join(root, 'package.json');\n  const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {\n    version?: unknown;\n    doompiApiVersion?: unknown;\n    pi?: { extensions?: unknown };\n  };\n  const version = manifest.version;\n  const apiVersion = manifest.doompiApiVersion;\n  const extensions = manifest.pi?.extensions;\n  const extension = Array.isArray(extensions) ? extensions.find((value) => typeof value === 'string') : undefined;\n  if (\n    typeof version !== 'string' ||\n    typeof apiVersion !== 'number' ||\n    !Number.isSafeInteger(apiVersion) ||\n    apiVersion < 1 ||\n    apiVersion !== DOOMPI_API_VERSION ||\n    typeof extension !== 'string'\n  ) {\n    throw new Error(`Installed DoomPi package at ${root} has no supported API-versioned Pi extension entry`);\n  }\n  return {\n    root,\n    version,\n    apiVersion: apiVersion as number,\n    manifestPath,\n    entry: fs.realpathSync(path.resolve(root, extension)),\n  };\n}\n\n/** Returns true when a valid legacy registration must be republished with API metadata. */\nexport function syncRegistrationNeedsApiMigration(repoRoot: string, homeDirectory: string): boolean {\n  try {\n    const registration = readSyncRegistration(repoRoot, homeDirectory);\n    return (\n      registration !== undefined &&\n      (registration.version !== SYNC_REGISTRATION_VERSION || registration.package.apiVersion === undefined)\n    );\n  } catch {\n    return false;\n  }\n}\n\n/** Resolves the matrix, stages it into home-scoped worktree storage, and publishes one generation. */\nexport async function synchronize(\n  args: string[],\n  environment: NodeJS.ProcessEnv = process.env,\n  currentDirectory = process.cwd(),\n  output: SyncOutput = process.stdout,\n  commandOptions: SyncCommandOptions = {},\n): Promise<number> {\n  const check = args.includes(CHECK_OPTION);\n  const force = args.includes(FORCE_OPTION);\n  const rest = args.slice(1).filter((argument) => ![CHECK_OPTION, FORCE_OPTION, GLOBAL_OPTION].includes(argument));\n  const homeDirectory = commandOptions.homeDirectory ?? environment.HOME ?? os.homedir();\n  const roots = resolveSyncRoots(args, environment, currentDirectory, homeDirectory);\n  const { globalOnly, globalRoot, targetRoot: repoRoot } = roots;\n  const scopedEnvironment = environmentForSyncScope(environment, globalOnly);\n  if (globalOnly && !check) fs.mkdirSync(globalRoot, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });\n  // Sync tolerates keys it does not recognise so a config written against a\n  // different version cannot break a build. `doompi doctor` reports them.\n  const modes = loadMajorModesConfigLenient(repoRoot, homeDirectory);\n  const configDiagnostics = [...loadDoomConfigLenient(repoRoot, homeDirectory).diagnostics, ...modes.diagnostics];\n  const defaultMajorMode = modes.config.defaultMajorMode;\n  const defaultDomains = loadDomains(repoRoot, homeDirectory).defaultDomains;\n  const parsed = parseHarnessArgs(\n    rest,\n    selectionEnvironment(repoRoot, scopedEnvironment, homeDirectory),\n    globalOnly ? globalRoot : currentDirectory,\n    defaultMajorMode,\n    defaultDomains,\n  );\n  const selection = toSelection(parsed.options);\n  const agentDirectory = piAgentDirectory(scopedEnvironment, homeDirectory);\n  if ((commandOptions.settingsMode ?? 'persisted') === 'persisted' && !check) {\n    if (piExtensionDispatcherIsUpgradeable(agentDirectory)) {\n      writePiExtensionAlias(agentDirectory);\n      output.write('repair:   refreshed Pi user dispatcher\\n');\n    }\n    const drift = piIntegrationDrift(agentDirectory);\n    if (drift.length > 0) {\n      throw new Error(`DoomPi Pi integration is not ready:\\n${drift.map((entry) => `  ${entry}`).join('\\n')}`);\n    }\n  }\n  writeConfigDiagnostics(configDiagnostics, output);\n  if (check) {\n    const majorModesConfig = modes.config;\n    const missingPackages = missingLayerPackageSpecifiers(\n      majorModesConfig,\n      Object.keys(majorModesConfig.layers),\n      createLayerResolvers(repoRoot),\n    );\n    if (missingPackages.length > 0) {\n      output.write(\n        `doompi sync is out of date:\\n${missingPackages\n          .map((specifier) => `  configured package is not installed: ${specifier}`)\n          .join('\\n')}\\n`,\n      );\n      return 1;\n    }\n    let located: ReturnType<typeof readLocatedSyncState>;\n    try {\n      located = readLocatedSyncState(repoRoot, homeDirectory);\n    } catch (error) {\n      const detail = error instanceof Error ? error.message : String(error);\n      output.write(`doompi sync is out of date:\\n  ${detail}\\n`);\n      return 1;\n    }\n    const expectedCompositionFingerprint = selectionCompositionFingerprint(repoRoot, parsed.options, homeDirectory);\n    const drift = collectDrift(\n      repoRoot,\n      selection,\n      located?.state,\n      scopedEnvironment,\n      commandOptions.settingsMode ?? 'persisted',\n      expectedCompositionFingerprint,\n    );\n    if (drift.length === 0) {\n      output.write('doompi sync is up to date\\n');\n      return 0;\n    }\n    output.write(`doompi sync is out of date:\\n${drift.map((entry) => `  ${entry}`).join('\\n')}\\n`);\n    return 1;\n  }\n\n  // Publishing an identical generation is not a no-op: it moves the\n  // registration, so every attached cockpit reloads and the previous\n  // generation becomes garbage. Same inputs, same published result.\n  const driftOptions = {\n    repoRoot,\n    homeDirectory,\n    requireWebBundle: Boolean(environment.DOOMPI_WEB_PACKAGE_ROOT),\n  };\n  const registrationNeedsMigration = syncRegistrationNeedsApiMigration(repoRoot, homeDirectory);\n  if (!force && !registrationNeedsMigration && readSyncDrift(driftOptions).fresh) {\n    output.write('doompi sync is already up to date\\n');\n    return 0;\n  }\n\n  const progress = new SyncProgress(output);\n  const releaseLock = commandOptions.lockHeld\n    ? undefined\n    : await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n  let result: SyncResult;\n  try {\n    // A concurrent publisher may have resolved the drift while this command\n    // waited for the lock. Avoid moving the registration for no change.\n    const registrationNeedsMigration = syncRegistrationNeedsApiMigration(repoRoot, homeDirectory);\n    if (!force && !registrationNeedsMigration && readSyncDrift(driftOptions).fresh) {\n      output.write('doompi sync is already up to date\\n');\n      return 0;\n    }\n    result = await stageSync(repoRoot, parsed.options, scopedEnvironment, homeDirectory, progress, commandOptions);\n  } finally {\n    await releaseLock?.();\n  }\n  emitFrontendHooks(repoRoot, output);\n  output.write(formatSyncResult(result, (commandOptions.settingsMode ?? 'persisted') === 'embedded' ? 'dpi' : 'pi'));\n  return 0;\n}\n\nasync function stageSync(\n  repoRoot: string,\n  options: Omit<HarnessOptions, 'repoRoot'>,\n  environment: NodeJS.ProcessEnv,\n  homeDirectory: string,\n  progress: SyncProgress,\n  commandOptions: SyncCommandOptions = {},\n): Promise<SyncResult> {\n  const location = resolveSyncLocation(repoRoot, homeDirectory);\n  const generation = `${Date.now().toString(36)}-${crypto.randomUUID()}`;\n  const directory = syncGenerationDirectory(location, generation);\n  await fs.promises.mkdir(location.generationsDirectory, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });\n  // The leaf is created without `recursive`, so an existing path is an error\n  // rather than something to adopt: the cockpit signs and serves whatever the\n  // published generation holds, and sync must only ever publish bytes it\n  // wrote itself into a directory it just created.\n  await fs.promises.mkdir(directory, { mode: PRIVATE_DIRECTORY_MODE });\n\n  try {\n    const staged = progress.start(SYNC_LABEL, 'resolving the matrix and staging resources');\n    const context = await buildHarnessContext({\n      ...options,\n      repoRoot: location.root,\n      homeDirectory,\n      cwd: location.root,\n      resourceDirectory: directory,\n    });\n    await ensureLayerPackages({\n      repoRoot: location.root,\n      config: context.majorModesConfig,\n      layers: Object.keys(context.majorModesConfig.layers),\n      environment,\n    });\n    staged(`${String(context.resources.skillCount)} skills, ${String(context.resources.agentCount)} agents`);\n    const selection = toSelection(options);\n    const resolvers = createLayerResolvers(location.root);\n    const resolved = recordResolvedEntries(context.majorModesConfig, resolvers);\n    const compositionFingerprint = selectionCompositionFingerprint(location.root, options, homeDirectory);\n    const agentDirectory = piAgentDirectory(environment, homeDirectory);\n    const persistedThemePath = path.join(piThemeDirectory(agentDirectory), `${DEFAULT_THEME_NAME}.json`);\n    const themePath =\n      (commandOptions.settingsMode ?? 'persisted') === 'persisted' ? persistedThemePath : context.defaultThemePath;\n    const state: SyncState = {\n      version: SYNC_STATE_VERSION,\n      root: location.root,\n      identity: location.identity,\n      inputsHash: computeInputsHash(location.root, selection, homeDirectory),\n      webSourcesHash: computeWebSourcesHash(resolved),\n      compositionFingerprint,\n      selection,\n      env: recordedEnvironment(context.environment),\n      fileState: {\n        profileEnvironment: loadHarnessState(context.environment).state.profileEnvironment,\n        pluginHooks: context.resources.pluginHooks,\n        mcpProjection: context.resources.mcpProjection,\n      },\n      resolved,\n      baseline: {\n        mcpConfigPath: context.resources.mcpConfigPath,\n        personaFile: context.environment[PERSONA_FILE_ENV],\n        themePath,\n        themeName: DEFAULT_THEME_NAME,\n      },\n    };\n\n    // Runtime compilation writes the package dist files consumed by both the web\n    // and server bundlers. Finish it first so a package clean cannot race either\n    // consumer, then run the independent web and server builds together.\n    let resolveCompositions!: (compositions: readonly ExtensionComposition[]) => void;\n    let rejectCompositions!: (reason?: unknown) => void;\n    const compositionsReady = new Promise<readonly ExtensionComposition[]>((resolve, reject) => {\n      resolveCompositions = resolve;\n      rejectCompositions = reject;\n    });\n    const runtimeProgress = progress.start(RUNTIME_LABEL, 'precompiling the mode bundles');\n    const runtimeBuild = buildSyncedRuntime(location.root, environment, homeDirectory, {\n      state,\n      directory,\n      onCompositionsResolved: resolveCompositions,\n    }).then((synced) => {\n      runtimeProgress(`${String(Object.keys(synced.bundles).length)} mode bundles`);\n      return synced;\n    });\n    void runtimeBuild.catch(rejectCompositions);\n    const webBuild = (async () => {\n      await runtimeBuild;\n      const webProgress = progress.start(WEB_LABEL, 'bundling the web cockpit plugins');\n      const web = await syncWebBundle({\n        repoRoot: location.root,\n        resolvedEntries: state.resolved,\n        environment,\n        outputDirectory: path.join(directory, 'web-bundle'),\n        onNotice: (message) => progress.line(WEB_LABEL, message),\n      });\n      if (web.status === 'failed') throw new Error(`Cockpit bundle failed: ${web.reason}`);\n      webProgress(web.status === 'bundled' ? `cockpit bundled with plugins: ${web.pluginIds.join(', ')}` : web.reason);\n      return web;\n    })();\n    const serverBuild = (async () => {\n      const compositions = await compositionsReady;\n      await runtimeBuild;\n      const apiProgress = progress.start(API_LABEL, 'compiling the server bundle');\n      const apiDirectory = path.join(directory, 'api');\n      const fingerprint = crypto\n        .createHash('sha256')\n        .update(JSON.stringify([...new Set(compositions.map((composition) => composition.fingerprint))]))\n        .digest('hex');\n      const [server, mcp] = await Promise.all([\n        syncServerBundle({\n          repositoryRoot: location.root,\n          generation,\n          fingerprint,\n          compositions,\n          outputDirectory: apiDirectory,\n          cacheDirectory: path.join(directory, 'cache'),\n          sharedCacheDirectory: location.sharedCacheDirectory,\n        }),\n        syncMcpBundle({\n          repositoryRoot: location.root,\n          generation,\n          fingerprint,\n          compositions,\n          outputDirectory: path.join(directory, 'mcp'),\n          cacheDirectory: path.join(directory, 'cache'),\n          sharedCacheDirectory: location.sharedCacheDirectory,\n        }),\n      ]);\n      apiProgress(\n        `${server.descriptor.entries.length} server facet(s), ${mcp.descriptor.entries.length} MCP plugin(s) compiled`,\n      );\n      for (const gap of server.contractGaps) progress.line(API_LABEL, `API contract incomplete: ${gap}`);\n      return { server, mcp, fingerprint, apiDirectory };\n    })();\n    const [runtimeResult, webResult, serverResult] = await Promise.allSettled([runtimeBuild, webBuild, serverBuild]);\n    if (runtimeResult.status === 'rejected') throw runtimeResult.reason;\n    if (webResult.status === 'rejected') throw webResult.reason;\n    if (serverResult.status === 'rejected') throw serverResult.reason;\n    const synced = runtimeResult.value;\n    const web = webResult.value;\n    const { server, mcp, fingerprint, apiDirectory } = serverResult.value;\n    const descriptorPath = path.join(apiDirectory, DOOM_SERVER_BUNDLE_FILE);\n    const mcpDescriptorPath = path.join(directory, 'mcp', DOOM_MCP_BUNDLE_FILE);\n    const finalState: SyncState = {\n      ...synced.state,\n      serverBundle: {\n        descriptorPath,\n        fingerprint,\n        compilerManifests: server.compilerManifests,\n        sourcesHash: computeServerSourcesHash(synced.state.resolved),\n      },\n      mcpBundle: {\n        descriptorPath: mcpDescriptorPath,\n        fingerprint,\n        compilerManifests: mcp.compilerManifests,\n        sourcesHash: computeMcpSourcesHash(synced.state.resolved),\n      },\n    };\n    const statePath = await writeSyncState(\n      location.root,\n      finalState,\n      homeDirectory,\n      path.join(directory, 'state.json'),\n    );\n    const projectSettingsPath =\n      (commandOptions.settingsMode ?? 'persisted') === 'persisted'\n        ? writeProjectPiSettings(location.root, homeDirectory)\n        : undefined;\n    const result: SyncResult = {\n      statePath,\n      ...(projectSettingsPath ? { projectSettingsPath } : {}),\n      selection,\n      mcpServers: synced.state.baseline.mcpConfigPath ? readMcpServerNames(synced.state.baseline.mcpConfigPath) : [],\n      skillCount: context.resources.skillCount,\n      agentCount: context.resources.agentCount,\n    };\n    publishSyncRegistration(\n      location.root,\n      {\n        version: SYNC_REGISTRATION_VERSION,\n        root: location.root,\n        identity: location.identity,\n        generation,\n        generationRoot: directory,\n        statePath,\n        stateSha256: syncStateSha256(statePath),\n        webDirectory: web.status === 'bundled' ? web.assetsDir : null,\n        apiDirectory,\n        serverBundle: { path: descriptorPath, fingerprint, sha256: syncStateSha256(descriptorPath) },\n        mcpBundle: { path: mcpDescriptorPath, fingerprint, sha256: syncStateSha256(mcpDescriptorPath) },\n        package: packageRegistrationFor(),\n      },\n      homeDirectory,\n    );\n    // ponytail: retain generations until host-owned drain evidence can prove no session uses them.\n    // Directory age and an open-file check cannot establish that a lazy import is finished.\n    return result;\n  } catch (error) {\n    await fs.promises.rm(directory, { recursive: true, force: true });\n    throw error;\n  }\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class SyncCommand {\n  readonly name = SYNC_COMMAND;\n  private readonly settingsMode: SyncSettingsMode;\n  private readonly homeDirectory: string | undefined;\n  private readonly lockHeld: boolean;\n\n  constructor(options: SyncCommandOptions = {}) {\n    this.settingsMode = options.settingsMode ?? 'persisted';\n    this.homeDirectory = options.homeDirectory;\n    this.lockHeld = options.lockHeld ?? false;\n  }\n\n  matches(args: string[]): boolean {\n    return args[0] === this.name;\n  }\n\n  async execute(\n    args: string[],\n    environment: NodeJS.ProcessEnv = process.env,\n    currentDirectory = process.cwd(),\n    output: SyncOutput = process.stdout,\n  ): Promise<number> {\n    return synchronize(args, environment, currentDirectory, output, {\n      settingsMode: this.settingsMode,\n      homeDirectory: this.homeDirectory,\n      lockHeld: this.lockHeld,\n    });\n  }\n}\n"],"mappings":"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"}