@agimon-ai/doompi 0.0.1-alpha.48 → 0.0.1-alpha.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/adapters/composer.cjs +1 -1
- package/dist/src/adapters/composer.cjs.map +1 -1
- package/dist/src/adapters/composer.d.cts.map +1 -1
- package/dist/src/adapters/composer.d.mts.map +1 -1
- package/dist/src/adapters/composer.mjs +1 -1
- package/dist/src/adapters/composer.mjs.map +1 -1
- package/dist/src/adapters/config/harnessState.d.mts +2 -2
- package/dist/src/adapters/piExtensionDispatcher.cjs +1 -1
- package/dist/src/adapters/piExtensionDispatcher.cjs.map +1 -1
- package/dist/src/adapters/piExtensionDispatcher.mjs +1 -1
- package/dist/src/adapters/piExtensionDispatcher.mjs.map +1 -1
- package/dist/src/commands/syncCommand.cjs +7 -6
- package/dist/src/commands/syncCommand.cjs.map +1 -1
- package/dist/src/commands/syncCommand.d.cts.map +1 -1
- package/dist/src/commands/syncCommand.d.mts.map +1 -1
- package/dist/src/commands/syncCommand.mjs +7 -6
- package/dist/src/commands/syncCommand.mjs.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.cjs +1 -1
- package/dist/src/extensions/entries/modeCatalog.cjs.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.d.cts.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.d.mts.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.mjs +1 -1
- package/dist/src/extensions/entries/modeCatalog.mjs.map +1 -1
- package/dist/src/services/contextCatalog.cjs +2 -0
- package/dist/src/services/contextCatalog.cjs.map +1 -0
- package/dist/src/services/contextCatalog.mjs +2 -0
- package/dist/src/services/contextCatalog.mjs.map +1 -0
- package/dist/src/services/contextProjection.cjs +2 -0
- package/dist/src/services/contextProjection.cjs.map +1 -0
- package/dist/src/services/contextProjection.mjs +2 -0
- package/dist/src/services/contextProjection.mjs.map +1 -0
- package/dist/src/services/extensionAssembler.cjs +1 -1
- package/dist/src/services/extensionAssembler.cjs.map +1 -1
- package/dist/src/services/extensionAssembler.d.cts +19 -1
- package/dist/src/services/extensionAssembler.d.cts.map +1 -1
- package/dist/src/services/extensionAssembler.d.mts +19 -1
- package/dist/src/services/extensionAssembler.d.mts.map +1 -1
- package/dist/src/services/extensionAssembler.mjs +1 -1
- package/dist/src/services/extensionAssembler.mjs.map +1 -1
- package/package.json +13 -13
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../adapters/repository/repository.cjs"),n=require("../adapters/doomPackage.cjs"),r=require("../adapters/syncLocation.cjs"),i=require("../adapters/syncRegistration.cjs"),a=require("../services/extensionAssembler.cjs");require("../adapters/syncStateContract.cjs");const o=require("../adapters/syncState.cjs"),s=require("../adapters/bootstrapLocator.cjs"),c=require("./cli/matrixOptions.cjs"),l=require("./cli/options.cjs");require("../adapters/config/harnessState.cjs");const u=require("../adapters/
|
|
2
|
-
`);return}t.write(`hooks: emit-hooks failed (${r.stderr?.trim()||`exit ${String(r.status)}`})\n`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../adapters/repository/repository.cjs"),n=require("../adapters/doomPackage.cjs"),r=require("../adapters/syncLocation.cjs"),i=require("../adapters/syncRegistration.cjs"),a=require("../services/extensionAssembler.cjs");require("../adapters/syncStateContract.cjs");const o=require("../adapters/syncState.cjs"),s=require("../adapters/bootstrapLocator.cjs"),c=require("./cli/matrixOptions.cjs"),l=require("./cli/options.cjs");require("../adapters/config/harnessState.cjs");const u=require("../adapters/piExtensionDispatcher.cjs"),d=require("../adapters/piExtensionAlias.cjs"),f=require("../adapters/piSettings.cjs"),p=require("../services/config/projectTrust.cjs"),m=require("../adapters/harnessContext.cjs"),h=require("../adapters/layerPackageInstaller.cjs"),g=require("../adapters/projectPiSettings.cjs"),_=require("../adapters/syncedRuntimeBuilder.cjs"),v=require("../adapters/syncDrift.cjs"),y=require("../adapters/apiRoutesSync.cjs"),b=require("../adapters/webBundleSync.cjs"),x=require("./syncPresenter.cjs");let S=require("node:path");S=e.__toESM(S,1);let C=require("node:crypto");C=e.__toESM(C,1);let w=require("node:fs");w=e.__toESM(w,1);let T=require("node:os");T=e.__toESM(T,1);let E=require("@agimon-ai/doompi-config/domains"),D=require("@agimon-ai/doompi-config/majorModes"),O=require("node:module"),k=require("node:child_process"),A=require("@agimon-ai/doompi-ui/theme"),j=require("@agimon-ai/doompi-config/harnessStore");const M=`--check`,N=`--force`,P=S.default.join(`tools`,`harness`,`emit-hooks.mjs`),F=`(none)`,I=`sync`,L=[`DOOMPI_`],R=[`CLAUDE_PROJECT_DIR`,`CODEX_REPO_ROOT`,`ORIGINAL_REPO_PATH`,`MCP_UI_VIEWER`],z=new Set([`DOOMPI_CHILD_EXTENSIONS`,`DOOMPI_COMPOSED`,`DOOMPI_MUTE`,`DOOMPI_TEMP_DIR`,j.HARNESS_STATE_POINTER,`PI_SUBAGENT_PI_BINARY`]);function B(e){let t={};for(let[n,r]of Object.entries(e))r===void 0||z.has(n)||(R.includes(n)||L.some(e=>n.startsWith(e)))&&(t[n]=r);return t}function V(e,t){let{selection:n}=p.loadDoomConfig(e);return n?{...t,...n.majorMode&&!t.DOOMPI_MAJOR_MODE?{[c.DOOMPI_MAJOR_MODE_ENV]:n.majorMode}:{},...n.profile&&!t.DOOMPI_PROFILE?{[c.DOOMPI_PROFILE_ENV]:n.profile}:{},...n.domains&&t.DOOMPI_DOMAINS===void 0?{[c.DOOMPI_DOMAINS_ENV]:n.domains.join(`,`)}:{}}:t}function H(e){return{majorMode:e.majorMode,domains:e.domains,profile:e.profile,preset:e.preset}}function U(e,t,n=T.default.homedir()){let r=(0,D.loadMajorModesConfig)(e,n),i=a.createLayerResolvers(e);return a.resolveExtensionComposition({agents:t.agents,autoStop:!1,mute:!1,preset:t.preset,personaEntry:i.packageEntry(a.PERSONA_ENTRY),majorMode:t.majorMode,layers:(0,D.filterHookDisabledLayers)(r,(0,D.resolveLayers)(r,t.majorMode),t.hooks),majorModesConfig:r,resolvers:i}).fingerprint}function W(e){let t=[],n=S.default.join(f.piThemeDirectory(e),`${A.DEFAULT_THEME_NAME}.json`),r=f.readPiSettings(e),i=f.mergePiSettings(r,e,{themePath:n,themeName:A.DEFAULT_THEME_NAME});f.serializePiSettings(i)!==f.serializePiSettings(r)&&t.push(`Pi user settings are out of date; run doompi init`),d.piExtensionAliasIsCurrent(e)||t.push(`Pi user dispatcher is out of date; run doompi init`);let a=`${JSON.stringify(A.DEFAULT_THEME,null,2)}\n`;return(!w.default.existsSync(n)||w.default.readFileSync(n,`utf8`)!==a)&&t.push(`Pi user theme is out of date; run doompi init`),t}function G(e,t,n,r=process.env,i=`persisted`,c){if(!n)return[`no sync state: run doompi sync`];let l=[];o.syncStateRootMatches(e,n.root)||l.push(`sync state belongs to a different repository`);let u=n.selection;(u.majorMode!==t.majorMode||u.profile!==t.profile||u.preset!==t.preset||u.domains.join(`,`)!==t.domains.join(`,`))&&l.push(`selection changed since the last sync`),o.computeInputsHash(e,u,r.HOME??T.default.homedir())!==n.inputsHash&&l.push(`.doom configuration changed`),JSON.stringify(o.recordResolvedEntries((0,D.loadMajorModesConfig)(e,r.HOME??T.default.homedir()),a.createLayerResolvers(e)))!==JSON.stringify(n.resolved)&&l.push(`resolved extension paths changed`),c&&n.compositionFingerprint!==c&&l.push(`extension composition changed`);try{s.readBootstrapStatus(e,void 0,r.HOME??T.default.homedir()).fresh||l.push(`precompiled runtime is missing or stale`)}catch{l.push(`precompiled runtime is missing or stale`)}if(i===`persisted`){let t=f.piAgentDirectory(r),i=S.default.join(f.piThemeDirectory(t),`${A.DEFAULT_THEME_NAME}.json`);l.push(...W(t)),g.projectRegistersDoom(e)&&l.push(g.DUPLICATE_REGISTRATION_DRIFT),(n.baseline.themePath!==i||n.baseline.themeName!==A.DEFAULT_THEME_NAME)&&l.push(`synced theme location is out of date`)}return l}function K(e,t){let n=S.default.join(e,P);if(!w.default.existsSync(n))return;let r=(0,k.spawnSync)(process.execPath,[n,`--write`],{cwd:e,encoding:`utf8`});if(r.status===0){t.write(`hooks: regenerated for Claude Code and Codex
|
|
2
|
+
`);return}t.write(`hooks: emit-hooks failed (${r.stderr?.trim()||`exit ${String(r.status)}`})\n`)}function q(e,t=`pi`){let{selection:n}=e;return[`mode: ${n.majorMode}`,`domains: ${n.domains.join(`, `)||F}`,`profile: ${n.profile??F}`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,`mcp: ${e.mcpServers.join(`, `)||F}`,`state: ${e.statePath}`,...e.settingsPath?[`settings: ${e.settingsPath}`]:[],...e.projectSettingsPath?[`project: removed duplicate registration from ${e.projectSettingsPath}`]:[],``,`Run ${t} from the repository root to use it.`,``].join(`
|
|
3
|
+
`)}function J(e){try{return S.default.dirname((0,O.createRequire)(S.default.join(e,`package.json`)).resolve(`${n.DOOM_PACKAGE_NAME}/package.json`))}catch{return}}function Y(e){let t=w.default.realpathSync(J(e)??d.doomPiPackageRoot()),n=S.default.join(t,`package.json`),r=JSON.parse(w.default.readFileSync(n,`utf8`)),i=r.version,a=r.pi?.extensions,o=Array.isArray(a)?a.find(e=>typeof e==`string`):void 0;if(typeof i!=`string`||typeof o!=`string`)throw Error(`Installed DoomPi package at ${t} has no versioned Pi extension entry`);return{root:t,version:i,manifestPath:n,entry:w.default.realpathSync(S.default.resolve(t,o))}}function X(e,t,n){let r;try{r=w.default.readdirSync(e,{withFileTypes:!0})}catch(e){n(`could not list generations to prune: ${Z(e)}`);return}let i=r.filter(e=>e.isDirectory()&&e.name!==t).map(e=>e.name).sort(),a=i.slice(0,Math.max(0,i.length-1));for(let t of a)try{w.default.rmSync(S.default.join(e,t),{recursive:!0,force:!0})}catch(e){n(`could not remove superseded generation ${t}: ${Z(e)}`)}a.length>0&&n(`pruned ${String(a.length)} superseded generation(s)`)}function Z(e){return e instanceof Error?e.message:String(e)}var Q=class{name=`sync`;settingsMode;homeDirectory;lockHeld;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.homeDirectory=e.homeDirectory,this.lockHeld=e.lockHeld??!1}matches(e){return e[0]===this.name}async execute(e,n=process.env,i=process.cwd(),s=process.stdout){let c=e.includes(M),p=e.includes(N),m=e.slice(1).filter(e=>e!==M&&e!==N),g=this.homeDirectory??n.HOME??T.default.homedir(),_=n.DOOMPI_ROOT,y=_?S.default.resolve(_):t.resolveDoomConfigurationRoot(i,g),b=(0,D.loadMajorModesConfig)(y,g).defaultMajorMode,C=(0,E.loadDomains)(y,g).defaultDomains,w=l.parseHarnessArgs(m,V(y,n),i,b,C),O=H(w.options),k=f.piAgentDirectory(n,g);if(this.settingsMode===`persisted`&&!c){if(u.piExtensionDispatcherIsUpgradeable(k)){let e=u.piExtensionDispatcherVersion(k);d.writePiExtensionAlias(k),s.write(`repair: upgraded Pi user dispatcher from protocol ${String(e)} to 2\n`)}let e=W(k);if(e.length>0)throw Error(`DoomPi Pi integration is not ready:\n${e.map(e=>` ${e}`).join(`
|
|
4
|
+
`)}`)}if(c){let e=(0,D.loadMajorModesConfig)(y,g),t=h.missingLayerPackageSpecifiers(e,Object.keys(e.layers),a.createLayerResolvers(y));if(t.length>0)return s.write(`doompi sync is out of date:\n${t.map(e=>` configured package is not installed: ${e}`).join(`
|
|
5
|
+
`)}\n`),1;let r;try{r=o.readLocatedSyncState(y,g)}catch(e){let t=e instanceof Error?e.message:String(e);return s.write(`doompi sync is out of date:\n ${t}\n`),1}let i=U(y,w.options,g),c=G(y,O,r?.state,n,this.settingsMode,i);return c.length===0?(s.write(`doompi sync is up to date
|
|
5
6
|
`),0):(s.write(`doompi sync is out of date:\n${c.map(e=>` ${e}`).join(`
|
|
6
|
-
`)}\n`),1)}if(!
|
|
7
|
-
`),0;let
|
|
7
|
+
`)}\n`),1)}if(!p&&v.readSyncDrift({repoRoot:y,homeDirectory:g}).fresh)return s.write(`doompi sync is already up to date
|
|
8
|
+
`),0;let A=new x.SyncProgress(s),j=this.lockHeld?void 0:await r.acquireSyncLocationLock(r.resolveSyncLocation(y,g)),P;try{P=await this.stage(y,w.options,n,g,A)}finally{await j?.()}return K(y,s),s.write(q(P,this.settingsMode===`embedded`?`dpi`:`pi`)),0}async stage(e,t,n,s,c){let l=r.resolveSyncLocation(e,s),u=`${Date.now().toString(36)}-${C.default.randomUUID()}`,d=r.syncGenerationDirectory(l,u);await w.default.promises.mkdir(l.generationsDirectory,{recursive:!0,mode:448}),await w.default.promises.mkdir(d,{mode:448});try{let e=c.start(I,`resolving the matrix and staging resources`),r=await m.buildHarnessContext({...t,repoRoot:l.root,homeDirectory:s,cwd:l.root,resourceDirectory:d});await h.ensureLayerPackages({repoRoot:l.root,config:r.majorModesConfig,layers:Object.keys(r.majorModesConfig.layers),environment:n}),e(`${String(r.resources.skillCount)} skills, ${String(r.resources.agentCount)} agents`);let p=H(t),v=a.createLayerResolvers(l.root),x=o.recordResolvedEntries(r.majorModesConfig,v),C=U(l.root,t,s),w=f.piAgentDirectory(n,s),T=S.default.join(f.piThemeDirectory(w),`${A.DEFAULT_THEME_NAME}.json`),E=this.settingsMode===`persisted`?T:r.defaultThemePath,D={version:13,root:l.root,identity:l.identity,inputsHash:o.computeInputsHash(l.root,p,s),webSourcesHash:o.computeWebSourcesHash(x),compositionFingerprint:C,selection:p,env:B(r.environment),fileState:{profileEnvironment:(0,j.loadHarnessState)(r.environment).state.profileEnvironment,pluginHooks:r.resources.pluginHooks,mcpProjection:r.resources.mcpProjection},resolved:x,baseline:{mcpConfigPath:r.resources.mcpConfigPath,personaFile:r.environment.DOOMPI_PERSONA_FILE,themePath:E,themeName:A.DEFAULT_THEME_NAME}},O=c.start(`runtime`,`precompiling the mode bundles`),k=await _.buildSyncedRuntime(l.root,n,s,{state:D,directory:d});O(`${String(Object.keys(k.bundles).length)} mode bundles`);let M=await o.writeSyncState(l.root,k.state,s,S.default.join(d,`state.json`)),N=c.start(`web`,`bundling the web cockpit plugins`),P=await b.syncWebBundle({repoRoot:l.root,resolvedEntries:k.state.resolved,environment:n,outputDirectory:S.default.join(d,`web-bundle`),onNotice:e=>c.line(`web`,e)});if(P.status===`failed`)throw Error(`Cockpit bundle failed: ${P.reason}`);N(P.status===`bundled`?`cockpit bundled with plugins: ${P.pluginIds.join(`, `)}`:P.reason);let F=c.start(`api`,`generating the package API routes`),L=y.syncApiRoutes({resolvedEntries:k.state.resolved,outputDirectory:S.default.join(d,`api`),onNotice:e=>c.line(`api`,e)});F(`routes written to ${L.directory}`),i.publishSyncRegistration(l.root,{version:1,root:l.root,identity:l.identity,generation:u,generationRoot:d,statePath:M,stateSha256:i.syncStateSha256(M),webDirectory:P.status===`bundled`?P.assetsDir:null,apiDirectory:L.directory,package:Y(l.root)},s),X(l.generationsDirectory,u,e=>c.line(I,e));let R=this.settingsMode===`persisted`?g.writeProjectPiSettings(l.root):void 0;return{statePath:M,...R?{projectSettingsPath:R}:{},selection:p,mcpServers:k.state.baseline.mcpConfigPath?o.readMcpServerNames(k.state.baseline.mcpConfigPath):[],skillCount:r.resources.skillCount,agentCount:r.resources.agentCount}}catch(e){throw await w.default.promises.rm(d,{recursive:!0,force:!0}),e}}};exports.SyncCommand=Q,exports.collectDrift=G,exports.formatSyncResult=q,exports.recordedEnvironment=B,exports.selectionCompositionFingerprint=U,exports.selectionEnvironment=V,exports.toSelection=H;
|
|
8
9
|
//# sourceMappingURL=syncCommand.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncCommand.cjs","names":["path","HARNESS_STATE_POINTER","loadDoomConfig","DOOMPI_MAJOR_MODE_ENV","DOOMPI_PROFILE_ENV","DOOMPI_DOMAINS_ENV","os","loadMajorModesConfig","createLayerResolvers","resolveExtensionComposition","PERSONA_ENTRY","filterHookDisabledLayers","resolveLayers","syncStateRootMatches","computeInputsHash","recordResolvedEntries","readBootstrapStatus","piAgentDirectory","piThemeDirectory","DEFAULT_THEME_NAME","readPiSettings","mergePiSettings","serializePiSettings","projectRegistersDoom","DUPLICATE_REGISTRATION_DRIFT","piExtensionAliasIsCurrent","DEFAULT_THEME","fs","spawnSync","createRequire","DOOM_PACKAGE_NAME","doomPiPackageRoot","resolveDoomConfigurationRoot","loadDomains","parseHarnessArgs","missingLayerPackageSpecifiers","readLocatedSyncState","readSyncDrift","SyncProgress","acquireSyncLocationLock","resolveSyncLocation","crypto","syncGenerationDirectory","buildHarnessContext","ensureLayerPackages","computeWebSourcesHash","loadHarnessState","buildSyncedRuntime","writeSyncState","syncWebBundle","syncApiRoutes","syncStateSha256","writeProjectPiSettings","readMcpServerNames"],"sources":["../../../src/commands/syncCommand.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { filterHookDisabledLayers, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages, missingLayerPackageSpecifiers } from '../adapters/layerPackageInstaller.ts';\nimport { readBootstrapStatus } from '../adapters/bootstrapLocator.ts';\nimport { DOOM_PACKAGE_NAME } from '../adapters/doomPackage.ts';\nimport { doomPiPackageRoot, piExtensionAliasIsCurrent } from '../adapters/piExtensionAlias.ts';\nimport {\n mergePiSettings,\n piAgentDirectory,\n piThemeDirectory,\n readPiSettings,\n serializePiSettings,\n} from '../adapters/piSettings.ts';\nimport {\n DUPLICATE_REGISTRATION_DRIFT,\n projectRegistersDoom,\n writeProjectPiSettings,\n} from '../adapters/projectPiSettings.ts';\nimport { buildSyncedRuntime } from '../adapters/syncedRuntimeBuilder.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation, syncGenerationDirectory } from '../adapters/syncLocation.ts';\nimport {\n publishSyncRegistration,\n SYNC_REGISTRATION_VERSION,\n syncStateSha256,\n type SyncPackageRegistration,\n} from '../adapters/syncRegistration.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { syncApiRoutes } from '../adapters/apiRoutesSync.ts';\nimport { syncWebBundle } from '../adapters/webBundleSync.ts';\nimport {\n computeInputsHash,\n computeWebSourcesHash,\n readLocatedSyncState,\n readMcpServerNames,\n recordResolvedEntries,\n SYNC_STATE_VERSION,\n type SyncSelection,\n type SyncState,\n syncStateRootMatches,\n writeSyncState,\n} from '../adapters/syncState.ts';\nimport { HARNESS_STATE_POINTER, loadHarnessState } from '../adapters/config/harnessState';\nimport { loadDomains } from '@agimon-ai/doompi-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DEFAULT_THEME, DEFAULT_THEME_NAME } from '@agimon-ai/doompi-ui/theme';\nimport { loadDoomConfig } from '../services/config/projectTrust';\nimport { createLayerResolvers, PERSONA_ENTRY, resolveExtensionComposition } from '../services/extensionAssembler.ts';\nimport type { HarnessOptions } from '../types/interfaces/harness';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport { DOOMPI_DOMAINS_ENV, DOOMPI_MAJOR_MODE_ENV, DOOMPI_PROFILE_ENV } from './cli/matrixOptions.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\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 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;\n/** Published generations kept behind the current one, so a running hub mid-read survives a prune. */\nconst RETAINED_GENERATIONS = 1;\nconst SYNC_LABEL = 'sync';\nconst RUNTIME_LABEL = 'runtime';\nconst WEB_LABEL = 'web';\nconst API_LABEL = 'api';\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 * 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(repoRoot: string, environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const { selection } = loadDoomConfig(repoRoot);\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/** 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 (!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 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 (projectRegistersDoom(repoRoot)) drift.push(DUPLICATE_REGISTRATION_DRIFT);\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 if (state.baseline.themePath !== themePath || state.baseline.themeName !== DEFAULT_THEME_NAME) {\n drift.push('synced theme location is out of date');\n }\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 package a repository pins for itself, if it pins one.\n *\n * Extensions are version-coupled to the harness that loads them, so the\n * registration must name the copy the repository resolves rather than whichever\n * copy happened to run sync. A globally installed DoomPi syncing a repository\n * that pins its own would otherwise record itself, and the dispatcher would\n * then load the wrong harness for every session in that repository.\n */\nfunction repositoryPackageRoot(repoRoot: string): string | undefined {\n try {\n return path.dirname(\n createRequire(path.join(repoRoot, 'package.json')).resolve(`${DOOM_PACKAGE_NAME}/package.json`),\n );\n } catch {\n // Not pinned here, which is normal; the executing package stands in.\n return undefined;\n }\n}\n\nfunction packageRegistrationFor(repoRoot: string): SyncPackageRegistration {\n const root = fs.realpathSync(repositoryPackageRoot(repoRoot) ?? doomPiPackageRoot());\n const manifestPath = path.join(root, 'package.json');\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {\n version?: unknown;\n pi?: { extensions?: unknown };\n };\n const version = manifest.version;\n const extensions = manifest.pi?.extensions;\n const extension = Array.isArray(extensions) ? extensions.find((value) => typeof value === 'string') : undefined;\n if (typeof version !== 'string' || typeof extension !== 'string') {\n throw new Error(`Installed DoomPi package at ${root} has no versioned Pi extension entry`);\n }\n return {\n root,\n version,\n manifestPath,\n entry: fs.realpathSync(path.resolve(root, extension)),\n };\n}\n\n/**\n * Removes generations the published one replaced.\n *\n * Each generation holds a full cockpit bundle and runtime, so keeping every one\n * ever built grows without bound. One superseded generation is retained because\n * a hub that resolved its assets a moment ago may still be reading them; older\n * ones have no reader left. Ordered by directory name, whose leading timestamp\n * makes publication order recoverable without reading each state file.\n */\nfunction pruneSupersededGenerations(\n generationsDirectory: string,\n published: string,\n onNotice: (message: string) => void,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(generationsDirectory, { withFileTypes: true });\n } catch (error) {\n // Nothing to prune is indistinguishable from an unreadable directory here,\n // and neither is worth failing a sync that already published.\n onNotice(`could not list generations to prune: ${describeError(error)}`);\n return;\n }\n const superseded = entries\n .filter((entry) => entry.isDirectory() && entry.name !== published)\n .map((entry) => entry.name)\n .sort();\n const removable = superseded.slice(0, Math.max(0, superseded.length - RETAINED_GENERATIONS));\n for (const name of removable) {\n try {\n fs.rmSync(path.join(generationsDirectory, name), { recursive: true, force: true });\n } catch (error) {\n // A generation still held open elsewhere stays; the next sync retries it.\n onNotice(`could not remove superseded generation ${name}: ${describeError(error)}`);\n }\n }\n if (removable.length > 0) onNotice(`pruned ${String(removable.length)} superseded generation(s)`);\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Resolves the matrix, stages it into home-scoped worktree storage, and publishes one generation. */\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 const check = args.includes(CHECK_OPTION);\n const force = args.includes(FORCE_OPTION);\n const rest = args.slice(1).filter((argument) => argument !== CHECK_OPTION && argument !== FORCE_OPTION);\n const homeDirectory = this.homeDirectory ?? environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const defaultMajorMode = loadMajorModesConfig(repoRoot, homeDirectory).defaultMajorMode;\n const defaultDomains = loadDomains(repoRoot, homeDirectory).defaultDomains;\n const parsed = parseHarnessArgs(\n rest,\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n defaultMajorMode,\n defaultDomains,\n );\n const selection = toSelection(parsed.options);\n const agentDirectory = piAgentDirectory(environment, homeDirectory);\n if (this.settingsMode === 'persisted' && !check) {\n const themePath = path.join(piThemeDirectory(agentDirectory), `${DEFAULT_THEME_NAME}.json`);\n const settings = readPiSettings(agentDirectory);\n const expectedSettings = mergePiSettings(settings, agentDirectory, {\n themePath,\n themeName: DEFAULT_THEME_NAME,\n });\n const expectedTheme = `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`;\n const ready =\n piExtensionAliasIsCurrent(agentDirectory) &&\n serializePiSettings(expectedSettings) === serializePiSettings(settings) &&\n fs.existsSync(themePath) &&\n fs.readFileSync(themePath, 'utf8') === expectedTheme;\n if (!ready) {\n throw new Error('DoomPi Pi integration is not initialized. Run doompi init before doompi sync.');\n }\n }\n if (check) {\n const majorModesConfig = loadMajorModesConfig(repoRoot, homeDirectory);\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 environment,\n this.settingsMode,\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 if (!force && readSyncDrift({ repoRoot, homeDirectory }).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 = this.lockHeld\n ? undefined\n : await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n let result: SyncResult;\n try {\n result = await this.stage(repoRoot, parsed.options, environment, homeDirectory, progress);\n } finally {\n await releaseLock?.();\n }\n emitFrontendHooks(repoRoot, output);\n output.write(formatSyncResult(result, this.settingsMode === 'embedded' ? 'dpi' : 'pi'));\n return 0;\n }\n\n private async stage(\n repoRoot: string,\n options: Omit<HarnessOptions, 'repoRoot'>,\n environment: NodeJS.ProcessEnv,\n homeDirectory: string,\n progress: SyncProgress,\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 = this.settingsMode === '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 const precompiled = progress.start(RUNTIME_LABEL, 'precompiling the mode bundles');\n const synced = await buildSyncedRuntime(location.root, environment, homeDirectory, { state, directory });\n precompiled(`${String(Object.keys(synced.bundles).length)} mode bundles`);\n const statePath = await writeSyncState(\n location.root,\n synced.state,\n homeDirectory,\n path.join(directory, 'state.json'),\n );\n\n const webProgress = progress.start(WEB_LABEL, 'bundling the web cockpit plugins');\n const web = await syncWebBundle({\n repoRoot: location.root,\n resolvedEntries: synced.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\n const apiProgress = progress.start(API_LABEL, 'generating the package API routes');\n const api = syncApiRoutes({\n resolvedEntries: synced.state.resolved,\n outputDirectory: path.join(directory, 'api'),\n onNotice: (message) => progress.line(API_LABEL, message),\n });\n apiProgress(`routes written to ${api.directory}`);\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: api.directory,\n package: packageRegistrationFor(location.root),\n },\n homeDirectory,\n );\n pruneSupersededGenerations(location.generationsDirectory, generation, (message) =>\n progress.line(SYNC_LABEL, message),\n );\n const projectSettingsPath = this.settingsMode === 'persisted' ? writeProjectPiSettings(location.root) : undefined;\n\n return {\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 } catch (error) {\n await fs.promises.rm(directory, { recursive: true, force: true });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"syncCommand.cjs","names":["path","HARNESS_STATE_POINTER","loadDoomConfig","DOOMPI_MAJOR_MODE_ENV","DOOMPI_PROFILE_ENV","DOOMPI_DOMAINS_ENV","os","loadMajorModesConfig","createLayerResolvers","resolveExtensionComposition","PERSONA_ENTRY","filterHookDisabledLayers","resolveLayers","piThemeDirectory","DEFAULT_THEME_NAME","readPiSettings","mergePiSettings","serializePiSettings","piExtensionAliasIsCurrent","DEFAULT_THEME","fs","syncStateRootMatches","computeInputsHash","recordResolvedEntries","readBootstrapStatus","piAgentDirectory","projectRegistersDoom","DUPLICATE_REGISTRATION_DRIFT","spawnSync","createRequire","DOOM_PACKAGE_NAME","doomPiPackageRoot","resolveDoomConfigurationRoot","loadDomains","parseHarnessArgs","piExtensionDispatcherIsUpgradeable","piExtensionDispatcherVersion","missingLayerPackageSpecifiers","readLocatedSyncState","readSyncDrift","SyncProgress","acquireSyncLocationLock","resolveSyncLocation","crypto","syncGenerationDirectory","buildHarnessContext","ensureLayerPackages","computeWebSourcesHash","loadHarnessState","buildSyncedRuntime","writeSyncState","syncWebBundle","syncApiRoutes","syncStateSha256","writeProjectPiSettings","readMcpServerNames"],"sources":["../../../src/commands/syncCommand.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { filterHookDisabledLayers, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages, missingLayerPackageSpecifiers } from '../adapters/layerPackageInstaller.ts';\nimport { readBootstrapStatus } from '../adapters/bootstrapLocator.ts';\nimport { DOOM_PACKAGE_NAME } from '../adapters/doomPackage.ts';\nimport { doomPiPackageRoot, piExtensionAliasIsCurrent, writePiExtensionAlias } from '../adapters/piExtensionAlias.ts';\nimport {\n PI_DISPATCHER_VERSION,\n piExtensionDispatcherIsUpgradeable,\n piExtensionDispatcherVersion,\n} from '../adapters/piExtensionDispatcher.ts';\nimport {\n mergePiSettings,\n piAgentDirectory,\n piThemeDirectory,\n readPiSettings,\n serializePiSettings,\n} from '../adapters/piSettings.ts';\nimport {\n DUPLICATE_REGISTRATION_DRIFT,\n projectRegistersDoom,\n writeProjectPiSettings,\n} from '../adapters/projectPiSettings.ts';\nimport { buildSyncedRuntime } from '../adapters/syncedRuntimeBuilder.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation, syncGenerationDirectory } from '../adapters/syncLocation.ts';\nimport {\n publishSyncRegistration,\n SYNC_REGISTRATION_VERSION,\n syncStateSha256,\n type SyncPackageRegistration,\n} from '../adapters/syncRegistration.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { syncApiRoutes } from '../adapters/apiRoutesSync.ts';\nimport { syncWebBundle } from '../adapters/webBundleSync.ts';\nimport {\n computeInputsHash,\n computeWebSourcesHash,\n readLocatedSyncState,\n readMcpServerNames,\n recordResolvedEntries,\n SYNC_STATE_VERSION,\n type SyncSelection,\n type SyncState,\n syncStateRootMatches,\n writeSyncState,\n} from '../adapters/syncState.ts';\nimport { HARNESS_STATE_POINTER, loadHarnessState } from '../adapters/config/harnessState';\nimport { loadDomains } from '@agimon-ai/doompi-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DEFAULT_THEME, DEFAULT_THEME_NAME } from '@agimon-ai/doompi-ui/theme';\nimport { loadDoomConfig } from '../services/config/projectTrust';\nimport { createLayerResolvers, PERSONA_ENTRY, resolveExtensionComposition } from '../services/extensionAssembler.ts';\nimport type { HarnessOptions } from '../types/interfaces/harness';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport { DOOMPI_DOMAINS_ENV, DOOMPI_MAJOR_MODE_ENV, DOOMPI_PROFILE_ENV } from './cli/matrixOptions.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\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 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;\n/** Published generations kept behind the current one, so a running hub mid-read survives a prune. */\nconst RETAINED_GENERATIONS = 1;\nconst SYNC_LABEL = 'sync';\nconst RUNTIME_LABEL = 'runtime';\nconst WEB_LABEL = 'web';\nconst API_LABEL = 'api';\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 * 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(repoRoot: string, environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const { selection } = loadDoomConfig(repoRoot);\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 (!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 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 package a repository pins for itself, if it pins one.\n *\n * Extensions are version-coupled to the harness that loads them, so the\n * registration must name the copy the repository resolves rather than whichever\n * copy happened to run sync. A globally installed DoomPi syncing a repository\n * that pins its own would otherwise record itself, and the dispatcher would\n * then load the wrong harness for every session in that repository.\n */\nfunction repositoryPackageRoot(repoRoot: string): string | undefined {\n try {\n return path.dirname(\n createRequire(path.join(repoRoot, 'package.json')).resolve(`${DOOM_PACKAGE_NAME}/package.json`),\n );\n } catch {\n // Not pinned here, which is normal; the executing package stands in.\n return undefined;\n }\n}\n\nfunction packageRegistrationFor(repoRoot: string): SyncPackageRegistration {\n const root = fs.realpathSync(repositoryPackageRoot(repoRoot) ?? doomPiPackageRoot());\n const manifestPath = path.join(root, 'package.json');\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {\n version?: unknown;\n pi?: { extensions?: unknown };\n };\n const version = manifest.version;\n const extensions = manifest.pi?.extensions;\n const extension = Array.isArray(extensions) ? extensions.find((value) => typeof value === 'string') : undefined;\n if (typeof version !== 'string' || typeof extension !== 'string') {\n throw new Error(`Installed DoomPi package at ${root} has no versioned Pi extension entry`);\n }\n return {\n root,\n version,\n manifestPath,\n entry: fs.realpathSync(path.resolve(root, extension)),\n };\n}\n\n/**\n * Removes generations the published one replaced.\n *\n * Each generation holds a full cockpit bundle and runtime, so keeping every one\n * ever built grows without bound. One superseded generation is retained because\n * a hub that resolved its assets a moment ago may still be reading them; older\n * ones have no reader left. Ordered by directory name, whose leading timestamp\n * makes publication order recoverable without reading each state file.\n */\nfunction pruneSupersededGenerations(\n generationsDirectory: string,\n published: string,\n onNotice: (message: string) => void,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(generationsDirectory, { withFileTypes: true });\n } catch (error) {\n // Nothing to prune is indistinguishable from an unreadable directory here,\n // and neither is worth failing a sync that already published.\n onNotice(`could not list generations to prune: ${describeError(error)}`);\n return;\n }\n const superseded = entries\n .filter((entry) => entry.isDirectory() && entry.name !== published)\n .map((entry) => entry.name)\n .sort();\n const removable = superseded.slice(0, Math.max(0, superseded.length - RETAINED_GENERATIONS));\n for (const name of removable) {\n try {\n fs.rmSync(path.join(generationsDirectory, name), { recursive: true, force: true });\n } catch (error) {\n // A generation still held open elsewhere stays; the next sync retries it.\n onNotice(`could not remove superseded generation ${name}: ${describeError(error)}`);\n }\n }\n if (removable.length > 0) onNotice(`pruned ${String(removable.length)} superseded generation(s)`);\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Resolves the matrix, stages it into home-scoped worktree storage, and publishes one generation. */\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 const check = args.includes(CHECK_OPTION);\n const force = args.includes(FORCE_OPTION);\n const rest = args.slice(1).filter((argument) => argument !== CHECK_OPTION && argument !== FORCE_OPTION);\n const homeDirectory = this.homeDirectory ?? environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const defaultMajorMode = loadMajorModesConfig(repoRoot, homeDirectory).defaultMajorMode;\n const defaultDomains = loadDomains(repoRoot, homeDirectory).defaultDomains;\n const parsed = parseHarnessArgs(\n rest,\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n defaultMajorMode,\n defaultDomains,\n );\n const selection = toSelection(parsed.options);\n const agentDirectory = piAgentDirectory(environment, homeDirectory);\n if (this.settingsMode === 'persisted' && !check) {\n if (piExtensionDispatcherIsUpgradeable(agentDirectory)) {\n const previousVersion = piExtensionDispatcherVersion(agentDirectory);\n writePiExtensionAlias(agentDirectory);\n output.write(\n `repair: upgraded Pi user dispatcher from protocol ${String(previousVersion)} to ${String(PI_DISPATCHER_VERSION)}\\n`,\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 if (check) {\n const majorModesConfig = loadMajorModesConfig(repoRoot, homeDirectory);\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 environment,\n this.settingsMode,\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 if (!force && readSyncDrift({ repoRoot, homeDirectory }).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 = this.lockHeld\n ? undefined\n : await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n let result: SyncResult;\n try {\n result = await this.stage(repoRoot, parsed.options, environment, homeDirectory, progress);\n } finally {\n await releaseLock?.();\n }\n emitFrontendHooks(repoRoot, output);\n output.write(formatSyncResult(result, this.settingsMode === 'embedded' ? 'dpi' : 'pi'));\n return 0;\n }\n\n private async stage(\n repoRoot: string,\n options: Omit<HarnessOptions, 'repoRoot'>,\n environment: NodeJS.ProcessEnv,\n homeDirectory: string,\n progress: SyncProgress,\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 = this.settingsMode === '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 const precompiled = progress.start(RUNTIME_LABEL, 'precompiling the mode bundles');\n const synced = await buildSyncedRuntime(location.root, environment, homeDirectory, { state, directory });\n precompiled(`${String(Object.keys(synced.bundles).length)} mode bundles`);\n const statePath = await writeSyncState(\n location.root,\n synced.state,\n homeDirectory,\n path.join(directory, 'state.json'),\n );\n\n const webProgress = progress.start(WEB_LABEL, 'bundling the web cockpit plugins');\n const web = await syncWebBundle({\n repoRoot: location.root,\n resolvedEntries: synced.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\n const apiProgress = progress.start(API_LABEL, 'generating the package API routes');\n const api = syncApiRoutes({\n resolvedEntries: synced.state.resolved,\n outputDirectory: path.join(directory, 'api'),\n onNotice: (message) => progress.line(API_LABEL, message),\n });\n apiProgress(`routes written to ${api.directory}`);\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: api.directory,\n package: packageRegistrationFor(location.root),\n },\n homeDirectory,\n );\n pruneSupersededGenerations(location.generationsDirectory, generation, (message) =>\n progress.line(SYNC_LABEL, message),\n );\n const projectSettingsPath = this.settingsMode === 'persisted' ? writeProjectPiSettings(location.root) : undefined;\n\n return {\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 } catch (error) {\n await fs.promises.rm(directory, { recursive: true, force: true });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncCommand.d.cts","names":[],"sources":["../../../src/commands/syncCommand.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"syncCommand.d.cts","names":[],"sources":["../../../src/commands/syncCommand.ts"],"mappings":";;;;KAoHK,aAAa;KAEN;UAEK;EACf,eAAe;;EAEf;;EAEA;;UAGe;EACf;;EAEA;;EAEA;EACA,WAAW;EACX;EACA;EACA;;iBAGc,oBAAoB,aAAa,OAAO,aAAa;;;;;;;;;iBAmBrD,qBAAqB,kBAAkB,aAAa,OAAO,aAAa,OAAO;iBAe/E,YACd,SAAS,KAAK,kEACb;iBASa,gCACd,kBACA,SAAS,KAAK,sEACd;;iBAuCc,aACd,kBACA,WAAW,eACX,OAAO,uBACP,cAAa,OAAO,YACpB,eAAc,kBACd;iBAkEc,iBAAiB,QAAQ,YAAY;;cAyGxC;WACF;mBACQ;mBACA;mBACA;EAEjB,YAAY,UAAS;EAMrB,QAAQ;EAIF,QACJ,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ,aACP;UAgGW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncCommand.d.mts","names":[],"sources":["../../../src/commands/syncCommand.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"syncCommand.d.mts","names":[],"sources":["../../../src/commands/syncCommand.ts"],"mappings":";;;;KAoHK,aAAa;KAEN;UAEK;EACf,eAAe;;EAEf;;EAEA;;UAGe;EACf;;EAEA;;EAEA;EACA,WAAW;EACX;EACA;EACA;;iBAGc,oBAAoB,aAAa,OAAO,aAAa;;;;;;;;;iBAmBrD,qBAAqB,kBAAkB,aAAa,OAAO,aAAa,OAAO;iBAe/E,YACd,SAAS,KAAK,kEACb;iBASa,gCACd,kBACA,SAAS,KAAK,sEACd;;iBAuCc,aACd,kBACA,WAAW,eACX,OAAO,uBACP,cAAa,OAAO,YACpB,eAAc,kBACd;iBAkEc,iBAAiB,QAAQ,YAAY;;cAyGxC;WACF;mBACQ;mBACA;mBACA;EAEjB,YAAY,UAAS;EAMrB,QAAQ;EAIF,QACJ,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ,aACP;UAgGW"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import{resolveDoomConfigurationRoot as e}from"../adapters/repository/repository.mjs";import{DOOM_PACKAGE_NAME as t}from"../adapters/doomPackage.mjs";import{acquireSyncLocationLock as n,resolveSyncLocation as r,syncGenerationDirectory as i}from"../adapters/syncLocation.mjs";import{publishSyncRegistration as a,syncStateSha256 as o}from"../adapters/syncRegistration.mjs";import{PERSONA_ENTRY as s,createLayerResolvers as c,resolveExtensionComposition as l}from"../services/extensionAssembler.mjs";import"../adapters/syncStateContract.mjs";import{computeInputsHash as u,computeWebSourcesHash as d,readLocatedSyncState as f,readMcpServerNames as p,recordResolvedEntries as m,syncStateRootMatches as h,writeSyncState as g}from"../adapters/syncState.mjs";import{readBootstrapStatus as _}from"../adapters/bootstrapLocator.mjs";import{DOOMPI_DOMAINS_ENV as v,DOOMPI_MAJOR_MODE_ENV as y,DOOMPI_PROFILE_ENV as b}from"./cli/matrixOptions.mjs";import{parseHarnessArgs as x}from"./cli/options.mjs";import{HARNESS_STATE_POINTER as S,loadHarnessState as C}from"../adapters/config/harnessState.mjs";import{
|
|
2
|
-
`);return}t.write(`hooks: emit-hooks failed (${r.stderr?.trim()||`exit ${String(r.status)}`})\n`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}
|
|
1
|
+
import{resolveDoomConfigurationRoot as e}from"../adapters/repository/repository.mjs";import{DOOM_PACKAGE_NAME as t}from"../adapters/doomPackage.mjs";import{acquireSyncLocationLock as n,resolveSyncLocation as r,syncGenerationDirectory as i}from"../adapters/syncLocation.mjs";import{publishSyncRegistration as a,syncStateSha256 as o}from"../adapters/syncRegistration.mjs";import{PERSONA_ENTRY as s,createLayerResolvers as c,resolveExtensionComposition as l}from"../services/extensionAssembler.mjs";import"../adapters/syncStateContract.mjs";import{computeInputsHash as u,computeWebSourcesHash as d,readLocatedSyncState as f,readMcpServerNames as p,recordResolvedEntries as m,syncStateRootMatches as h,writeSyncState as g}from"../adapters/syncState.mjs";import{readBootstrapStatus as _}from"../adapters/bootstrapLocator.mjs";import{DOOMPI_DOMAINS_ENV as v,DOOMPI_MAJOR_MODE_ENV as y,DOOMPI_PROFILE_ENV as b}from"./cli/matrixOptions.mjs";import{parseHarnessArgs as x}from"./cli/options.mjs";import{HARNESS_STATE_POINTER as S,loadHarnessState as C}from"../adapters/config/harnessState.mjs";import{piExtensionDispatcherIsUpgradeable as w,piExtensionDispatcherVersion as T}from"../adapters/piExtensionDispatcher.mjs";import{doomPiPackageRoot as E,piExtensionAliasIsCurrent as D,writePiExtensionAlias as O}from"../adapters/piExtensionAlias.mjs";import{mergePiSettings as k,piAgentDirectory as A,piThemeDirectory as j,readPiSettings as M,serializePiSettings as N}from"../adapters/piSettings.mjs";import{loadDoomConfig as P}from"../services/config/projectTrust.mjs";import{buildHarnessContext as ee}from"../adapters/harnessContext.mjs";import{ensureLayerPackages as te,missingLayerPackageSpecifiers as F}from"../adapters/layerPackageInstaller.mjs";import{DUPLICATE_REGISTRATION_DRIFT as ne,projectRegistersDoom as re,writeProjectPiSettings as ie}from"../adapters/projectPiSettings.mjs";import{buildSyncedRuntime as ae}from"../adapters/syncedRuntimeBuilder.mjs";import{readSyncDrift as oe}from"../adapters/syncDrift.mjs";import{syncApiRoutes as se}from"../adapters/apiRoutesSync.mjs";import{syncWebBundle as ce}from"../adapters/webBundleSync.mjs";import{SyncProgress as le}from"./syncPresenter.mjs";import{createRequire as ue}from"node:module";import I from"node:path";import de from"node:crypto";import L from"node:fs";import R from"node:os";import{loadDomains as fe}from"@agimon-ai/doompi-config/domains";import{filterHookDisabledLayers as pe,loadMajorModesConfig as z,resolveLayers as me}from"@agimon-ai/doompi-config/majorModes";import{spawnSync as he}from"node:child_process";import{DEFAULT_THEME as ge,DEFAULT_THEME_NAME as B}from"@agimon-ai/doompi-ui/theme";const V=`--check`,H=`--force`,_e=I.join(`tools`,`harness`,`emit-hooks.mjs`),U=`(none)`,W=`sync`,ve=[`DOOMPI_`],ye=[`CLAUDE_PROJECT_DIR`,`CODEX_REPO_ROOT`,`ORIGINAL_REPO_PATH`,`MCP_UI_VIEWER`],be=new Set([`DOOMPI_CHILD_EXTENSIONS`,`DOOMPI_COMPOSED`,`DOOMPI_MUTE`,`DOOMPI_TEMP_DIR`,S,`PI_SUBAGENT_PI_BINARY`]);function G(e){let t={};for(let[n,r]of Object.entries(e))r===void 0||be.has(n)||(ye.includes(n)||ve.some(e=>n.startsWith(e)))&&(t[n]=r);return t}function K(e,t){let{selection:n}=P(e);return n?{...t,...n.majorMode&&!t.DOOMPI_MAJOR_MODE?{[y]:n.majorMode}:{},...n.profile&&!t.DOOMPI_PROFILE?{[b]:n.profile}:{},...n.domains&&t.DOOMPI_DOMAINS===void 0?{[v]:n.domains.join(`,`)}:{}}:t}function q(e){return{majorMode:e.majorMode,domains:e.domains,profile:e.profile,preset:e.preset}}function J(e,t,n=R.homedir()){let r=z(e,n),i=c(e);return l({agents:t.agents,autoStop:!1,mute:!1,preset:t.preset,personaEntry:i.packageEntry(s),majorMode:t.majorMode,layers:pe(r,me(r,t.majorMode),t.hooks),majorModesConfig:r,resolvers:i}).fingerprint}function Y(e){let t=[],n=I.join(j(e),`${B}.json`),r=M(e),i=k(r,e,{themePath:n,themeName:B});N(i)!==N(r)&&t.push(`Pi user settings are out of date; run doompi init`),D(e)||t.push(`Pi user dispatcher is out of date; run doompi init`);let a=`${JSON.stringify(ge,null,2)}\n`;return(!L.existsSync(n)||L.readFileSync(n,`utf8`)!==a)&&t.push(`Pi user theme is out of date; run doompi init`),t}function X(e,t,n,r=process.env,i=`persisted`,a){if(!n)return[`no sync state: run doompi sync`];let o=[];h(e,n.root)||o.push(`sync state belongs to a different repository`);let s=n.selection;(s.majorMode!==t.majorMode||s.profile!==t.profile||s.preset!==t.preset||s.domains.join(`,`)!==t.domains.join(`,`))&&o.push(`selection changed since the last sync`),u(e,s,r.HOME??R.homedir())!==n.inputsHash&&o.push(`.doom configuration changed`),JSON.stringify(m(z(e,r.HOME??R.homedir()),c(e)))!==JSON.stringify(n.resolved)&&o.push(`resolved extension paths changed`),a&&n.compositionFingerprint!==a&&o.push(`extension composition changed`);try{_(e,void 0,r.HOME??R.homedir()).fresh||o.push(`precompiled runtime is missing or stale`)}catch{o.push(`precompiled runtime is missing or stale`)}if(i===`persisted`){let t=A(r),i=I.join(j(t),`${B}.json`);o.push(...Y(t)),re(e)&&o.push(ne),(n.baseline.themePath!==i||n.baseline.themeName!==B)&&o.push(`synced theme location is out of date`)}return o}function xe(e,t){let n=I.join(e,_e);if(!L.existsSync(n))return;let r=he(process.execPath,[n,`--write`],{cwd:e,encoding:`utf8`});if(r.status===0){t.write(`hooks: regenerated for Claude Code and Codex
|
|
2
|
+
`);return}t.write(`hooks: emit-hooks failed (${r.stderr?.trim()||`exit ${String(r.status)}`})\n`)}function Z(e,t=`pi`){let{selection:n}=e;return[`mode: ${n.majorMode}`,`domains: ${n.domains.join(`, `)||U}`,`profile: ${n.profile??U}`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,`mcp: ${e.mcpServers.join(`, `)||U}`,`state: ${e.statePath}`,...e.settingsPath?[`settings: ${e.settingsPath}`]:[],...e.projectSettingsPath?[`project: removed duplicate registration from ${e.projectSettingsPath}`]:[],``,`Run ${t} from the repository root to use it.`,``].join(`
|
|
3
|
+
`)}function Q(e){try{return I.dirname(ue(I.join(e,`package.json`)).resolve(`${t}/package.json`))}catch{return}}function Se(e){let t=L.realpathSync(Q(e)??E()),n=I.join(t,`package.json`),r=JSON.parse(L.readFileSync(n,`utf8`)),i=r.version,a=r.pi?.extensions,o=Array.isArray(a)?a.find(e=>typeof e==`string`):void 0;if(typeof i!=`string`||typeof o!=`string`)throw Error(`Installed DoomPi package at ${t} has no versioned Pi extension entry`);return{root:t,version:i,manifestPath:n,entry:L.realpathSync(I.resolve(t,o))}}function Ce(e,t,n){let r;try{r=L.readdirSync(e,{withFileTypes:!0})}catch(e){n(`could not list generations to prune: ${$(e)}`);return}let i=r.filter(e=>e.isDirectory()&&e.name!==t).map(e=>e.name).sort(),a=i.slice(0,Math.max(0,i.length-1));for(let t of a)try{L.rmSync(I.join(e,t),{recursive:!0,force:!0})}catch(e){n(`could not remove superseded generation ${t}: ${$(e)}`)}a.length>0&&n(`pruned ${String(a.length)} superseded generation(s)`)}function $(e){return e instanceof Error?e.message:String(e)}var we=class{name=`sync`;settingsMode;homeDirectory;lockHeld;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.homeDirectory=e.homeDirectory,this.lockHeld=e.lockHeld??!1}matches(e){return e[0]===this.name}async execute(t,i=process.env,a=process.cwd(),o=process.stdout){let s=t.includes(V),l=t.includes(H),u=t.slice(1).filter(e=>e!==V&&e!==H),d=this.homeDirectory??i.HOME??R.homedir(),p=i.DOOMPI_ROOT,m=p?I.resolve(p):e(a,d),h=z(m,d).defaultMajorMode,g=fe(m,d).defaultDomains,_=x(u,K(m,i),a,h,g),v=q(_.options),y=A(i,d);if(this.settingsMode===`persisted`&&!s){if(w(y)){let e=T(y);O(y),o.write(`repair: upgraded Pi user dispatcher from protocol ${String(e)} to 2\n`)}let e=Y(y);if(e.length>0)throw Error(`DoomPi Pi integration is not ready:\n${e.map(e=>` ${e}`).join(`
|
|
4
|
+
`)}`)}if(s){let e=z(m,d),t=F(e,Object.keys(e.layers),c(m));if(t.length>0)return o.write(`doompi sync is out of date:\n${t.map(e=>` configured package is not installed: ${e}`).join(`
|
|
5
|
+
`)}\n`),1;let n;try{n=f(m,d)}catch(e){let t=e instanceof Error?e.message:String(e);return o.write(`doompi sync is out of date:\n ${t}\n`),1}let r=J(m,_.options,d),a=X(m,v,n?.state,i,this.settingsMode,r);return a.length===0?(o.write(`doompi sync is up to date
|
|
5
6
|
`),0):(o.write(`doompi sync is out of date:\n${a.map(e=>` ${e}`).join(`
|
|
6
|
-
`)}\n`),1)}if(!l&&
|
|
7
|
-
`),0;let b=new
|
|
7
|
+
`)}\n`),1)}if(!l&&oe({repoRoot:m,homeDirectory:d}).fresh)return o.write(`doompi sync is already up to date
|
|
8
|
+
`),0;let b=new le(o),S=this.lockHeld?void 0:await n(r(m,d)),C;try{C=await this.stage(m,_.options,i,d,b)}finally{await S?.()}return xe(m,o),o.write(Z(C,this.settingsMode===`embedded`?`dpi`:`pi`)),0}async stage(e,t,n,s,l){let f=r(e,s),h=`${Date.now().toString(36)}-${de.randomUUID()}`,_=i(f,h);await L.promises.mkdir(f.generationsDirectory,{recursive:!0,mode:448}),await L.promises.mkdir(_,{mode:448});try{let e=l.start(W,`resolving the matrix and staging resources`),r=await ee({...t,repoRoot:f.root,homeDirectory:s,cwd:f.root,resourceDirectory:_});await te({repoRoot:f.root,config:r.majorModesConfig,layers:Object.keys(r.majorModesConfig.layers),environment:n}),e(`${String(r.resources.skillCount)} skills, ${String(r.resources.agentCount)} agents`);let i=q(t),v=c(f.root),y=m(r.majorModesConfig,v),b=J(f.root,t,s),x=A(n,s),S=I.join(j(x),`${B}.json`),w=this.settingsMode===`persisted`?S:r.defaultThemePath,T={version:13,root:f.root,identity:f.identity,inputsHash:u(f.root,i,s),webSourcesHash:d(y),compositionFingerprint:b,selection:i,env:G(r.environment),fileState:{profileEnvironment:C(r.environment).state.profileEnvironment,pluginHooks:r.resources.pluginHooks,mcpProjection:r.resources.mcpProjection},resolved:y,baseline:{mcpConfigPath:r.resources.mcpConfigPath,personaFile:r.environment.DOOMPI_PERSONA_FILE,themePath:w,themeName:B}},E=l.start(`runtime`,`precompiling the mode bundles`),D=await ae(f.root,n,s,{state:T,directory:_});E(`${String(Object.keys(D.bundles).length)} mode bundles`);let O=await g(f.root,D.state,s,I.join(_,`state.json`)),k=l.start(`web`,`bundling the web cockpit plugins`),M=await ce({repoRoot:f.root,resolvedEntries:D.state.resolved,environment:n,outputDirectory:I.join(_,`web-bundle`),onNotice:e=>l.line(`web`,e)});if(M.status===`failed`)throw Error(`Cockpit bundle failed: ${M.reason}`);k(M.status===`bundled`?`cockpit bundled with plugins: ${M.pluginIds.join(`, `)}`:M.reason);let N=l.start(`api`,`generating the package API routes`),P=se({resolvedEntries:D.state.resolved,outputDirectory:I.join(_,`api`),onNotice:e=>l.line(`api`,e)});N(`routes written to ${P.directory}`),a(f.root,{version:1,root:f.root,identity:f.identity,generation:h,generationRoot:_,statePath:O,stateSha256:o(O),webDirectory:M.status===`bundled`?M.assetsDir:null,apiDirectory:P.directory,package:Se(f.root)},s),Ce(f.generationsDirectory,h,e=>l.line(W,e));let F=this.settingsMode===`persisted`?ie(f.root):void 0;return{statePath:O,...F?{projectSettingsPath:F}:{},selection:i,mcpServers:D.state.baseline.mcpConfigPath?p(D.state.baseline.mcpConfigPath):[],skillCount:r.resources.skillCount,agentCount:r.resources.agentCount}}catch(e){throw await L.promises.rm(_,{recursive:!0,force:!0}),e}}};export{we as SyncCommand,X as collectDrift,Z as formatSyncResult,G as recordedEnvironment,J as selectionCompositionFingerprint,K as selectionEnvironment,q as toSelection};
|
|
8
9
|
//# sourceMappingURL=syncCommand.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncCommand.mjs","names":[],"sources":["../../../src/commands/syncCommand.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { filterHookDisabledLayers, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages, missingLayerPackageSpecifiers } from '../adapters/layerPackageInstaller.ts';\nimport { readBootstrapStatus } from '../adapters/bootstrapLocator.ts';\nimport { DOOM_PACKAGE_NAME } from '../adapters/doomPackage.ts';\nimport { doomPiPackageRoot, piExtensionAliasIsCurrent } from '../adapters/piExtensionAlias.ts';\nimport {\n mergePiSettings,\n piAgentDirectory,\n piThemeDirectory,\n readPiSettings,\n serializePiSettings,\n} from '../adapters/piSettings.ts';\nimport {\n DUPLICATE_REGISTRATION_DRIFT,\n projectRegistersDoom,\n writeProjectPiSettings,\n} from '../adapters/projectPiSettings.ts';\nimport { buildSyncedRuntime } from '../adapters/syncedRuntimeBuilder.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation, syncGenerationDirectory } from '../adapters/syncLocation.ts';\nimport {\n publishSyncRegistration,\n SYNC_REGISTRATION_VERSION,\n syncStateSha256,\n type SyncPackageRegistration,\n} from '../adapters/syncRegistration.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { syncApiRoutes } from '../adapters/apiRoutesSync.ts';\nimport { syncWebBundle } from '../adapters/webBundleSync.ts';\nimport {\n computeInputsHash,\n computeWebSourcesHash,\n readLocatedSyncState,\n readMcpServerNames,\n recordResolvedEntries,\n SYNC_STATE_VERSION,\n type SyncSelection,\n type SyncState,\n syncStateRootMatches,\n writeSyncState,\n} from '../adapters/syncState.ts';\nimport { HARNESS_STATE_POINTER, loadHarnessState } from '../adapters/config/harnessState';\nimport { loadDomains } from '@agimon-ai/doompi-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DEFAULT_THEME, DEFAULT_THEME_NAME } from '@agimon-ai/doompi-ui/theme';\nimport { loadDoomConfig } from '../services/config/projectTrust';\nimport { createLayerResolvers, PERSONA_ENTRY, resolveExtensionComposition } from '../services/extensionAssembler.ts';\nimport type { HarnessOptions } from '../types/interfaces/harness';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport { DOOMPI_DOMAINS_ENV, DOOMPI_MAJOR_MODE_ENV, DOOMPI_PROFILE_ENV } from './cli/matrixOptions.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\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 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;\n/** Published generations kept behind the current one, so a running hub mid-read survives a prune. */\nconst RETAINED_GENERATIONS = 1;\nconst SYNC_LABEL = 'sync';\nconst RUNTIME_LABEL = 'runtime';\nconst WEB_LABEL = 'web';\nconst API_LABEL = 'api';\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 * 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(repoRoot: string, environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const { selection } = loadDoomConfig(repoRoot);\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/** 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 (!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 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 (projectRegistersDoom(repoRoot)) drift.push(DUPLICATE_REGISTRATION_DRIFT);\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 if (state.baseline.themePath !== themePath || state.baseline.themeName !== DEFAULT_THEME_NAME) {\n drift.push('synced theme location is out of date');\n }\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 package a repository pins for itself, if it pins one.\n *\n * Extensions are version-coupled to the harness that loads them, so the\n * registration must name the copy the repository resolves rather than whichever\n * copy happened to run sync. A globally installed DoomPi syncing a repository\n * that pins its own would otherwise record itself, and the dispatcher would\n * then load the wrong harness for every session in that repository.\n */\nfunction repositoryPackageRoot(repoRoot: string): string | undefined {\n try {\n return path.dirname(\n createRequire(path.join(repoRoot, 'package.json')).resolve(`${DOOM_PACKAGE_NAME}/package.json`),\n );\n } catch {\n // Not pinned here, which is normal; the executing package stands in.\n return undefined;\n }\n}\n\nfunction packageRegistrationFor(repoRoot: string): SyncPackageRegistration {\n const root = fs.realpathSync(repositoryPackageRoot(repoRoot) ?? doomPiPackageRoot());\n const manifestPath = path.join(root, 'package.json');\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {\n version?: unknown;\n pi?: { extensions?: unknown };\n };\n const version = manifest.version;\n const extensions = manifest.pi?.extensions;\n const extension = Array.isArray(extensions) ? extensions.find((value) => typeof value === 'string') : undefined;\n if (typeof version !== 'string' || typeof extension !== 'string') {\n throw new Error(`Installed DoomPi package at ${root} has no versioned Pi extension entry`);\n }\n return {\n root,\n version,\n manifestPath,\n entry: fs.realpathSync(path.resolve(root, extension)),\n };\n}\n\n/**\n * Removes generations the published one replaced.\n *\n * Each generation holds a full cockpit bundle and runtime, so keeping every one\n * ever built grows without bound. One superseded generation is retained because\n * a hub that resolved its assets a moment ago may still be reading them; older\n * ones have no reader left. Ordered by directory name, whose leading timestamp\n * makes publication order recoverable without reading each state file.\n */\nfunction pruneSupersededGenerations(\n generationsDirectory: string,\n published: string,\n onNotice: (message: string) => void,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(generationsDirectory, { withFileTypes: true });\n } catch (error) {\n // Nothing to prune is indistinguishable from an unreadable directory here,\n // and neither is worth failing a sync that already published.\n onNotice(`could not list generations to prune: ${describeError(error)}`);\n return;\n }\n const superseded = entries\n .filter((entry) => entry.isDirectory() && entry.name !== published)\n .map((entry) => entry.name)\n .sort();\n const removable = superseded.slice(0, Math.max(0, superseded.length - RETAINED_GENERATIONS));\n for (const name of removable) {\n try {\n fs.rmSync(path.join(generationsDirectory, name), { recursive: true, force: true });\n } catch (error) {\n // A generation still held open elsewhere stays; the next sync retries it.\n onNotice(`could not remove superseded generation ${name}: ${describeError(error)}`);\n }\n }\n if (removable.length > 0) onNotice(`pruned ${String(removable.length)} superseded generation(s)`);\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Resolves the matrix, stages it into home-scoped worktree storage, and publishes one generation. */\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 const check = args.includes(CHECK_OPTION);\n const force = args.includes(FORCE_OPTION);\n const rest = args.slice(1).filter((argument) => argument !== CHECK_OPTION && argument !== FORCE_OPTION);\n const homeDirectory = this.homeDirectory ?? environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const defaultMajorMode = loadMajorModesConfig(repoRoot, homeDirectory).defaultMajorMode;\n const defaultDomains = loadDomains(repoRoot, homeDirectory).defaultDomains;\n const parsed = parseHarnessArgs(\n rest,\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n defaultMajorMode,\n defaultDomains,\n );\n const selection = toSelection(parsed.options);\n const agentDirectory = piAgentDirectory(environment, homeDirectory);\n if (this.settingsMode === 'persisted' && !check) {\n const themePath = path.join(piThemeDirectory(agentDirectory), `${DEFAULT_THEME_NAME}.json`);\n const settings = readPiSettings(agentDirectory);\n const expectedSettings = mergePiSettings(settings, agentDirectory, {\n themePath,\n themeName: DEFAULT_THEME_NAME,\n });\n const expectedTheme = `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`;\n const ready =\n piExtensionAliasIsCurrent(agentDirectory) &&\n serializePiSettings(expectedSettings) === serializePiSettings(settings) &&\n fs.existsSync(themePath) &&\n fs.readFileSync(themePath, 'utf8') === expectedTheme;\n if (!ready) {\n throw new Error('DoomPi Pi integration is not initialized. Run doompi init before doompi sync.');\n }\n }\n if (check) {\n const majorModesConfig = loadMajorModesConfig(repoRoot, homeDirectory);\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 environment,\n this.settingsMode,\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 if (!force && readSyncDrift({ repoRoot, homeDirectory }).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 = this.lockHeld\n ? undefined\n : await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n let result: SyncResult;\n try {\n result = await this.stage(repoRoot, parsed.options, environment, homeDirectory, progress);\n } finally {\n await releaseLock?.();\n }\n emitFrontendHooks(repoRoot, output);\n output.write(formatSyncResult(result, this.settingsMode === 'embedded' ? 'dpi' : 'pi'));\n return 0;\n }\n\n private async stage(\n repoRoot: string,\n options: Omit<HarnessOptions, 'repoRoot'>,\n environment: NodeJS.ProcessEnv,\n homeDirectory: string,\n progress: SyncProgress,\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 = this.settingsMode === '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 const precompiled = progress.start(RUNTIME_LABEL, 'precompiling the mode bundles');\n const synced = await buildSyncedRuntime(location.root, environment, homeDirectory, { state, directory });\n precompiled(`${String(Object.keys(synced.bundles).length)} mode bundles`);\n const statePath = await writeSyncState(\n location.root,\n synced.state,\n homeDirectory,\n path.join(directory, 'state.json'),\n );\n\n const webProgress = progress.start(WEB_LABEL, 'bundling the web cockpit plugins');\n const web = await syncWebBundle({\n repoRoot: location.root,\n resolvedEntries: synced.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\n const apiProgress = progress.start(API_LABEL, 'generating the package API routes');\n const api = syncApiRoutes({\n resolvedEntries: synced.state.resolved,\n outputDirectory: path.join(directory, 'api'),\n onNotice: (message) => progress.line(API_LABEL, message),\n });\n apiProgress(`routes written to ${api.directory}`);\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: api.directory,\n package: packageRegistrationFor(location.root),\n },\n homeDirectory,\n );\n pruneSupersededGenerations(location.generationsDirectory, generation, (message) =>\n progress.line(SYNC_LABEL, message),\n );\n const projectSettingsPath = this.settingsMode === 'persisted' ? writeProjectPiSettings(location.root) : undefined;\n\n return {\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 } catch (error) {\n await fs.promises.rm(directory, { recursive: true, force: true });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"syncCommand.mjs","names":[],"sources":["../../../src/commands/syncCommand.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { filterHookDisabledLayers, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages, missingLayerPackageSpecifiers } from '../adapters/layerPackageInstaller.ts';\nimport { readBootstrapStatus } from '../adapters/bootstrapLocator.ts';\nimport { DOOM_PACKAGE_NAME } from '../adapters/doomPackage.ts';\nimport { doomPiPackageRoot, piExtensionAliasIsCurrent, writePiExtensionAlias } from '../adapters/piExtensionAlias.ts';\nimport {\n PI_DISPATCHER_VERSION,\n piExtensionDispatcherIsUpgradeable,\n piExtensionDispatcherVersion,\n} from '../adapters/piExtensionDispatcher.ts';\nimport {\n mergePiSettings,\n piAgentDirectory,\n piThemeDirectory,\n readPiSettings,\n serializePiSettings,\n} from '../adapters/piSettings.ts';\nimport {\n DUPLICATE_REGISTRATION_DRIFT,\n projectRegistersDoom,\n writeProjectPiSettings,\n} from '../adapters/projectPiSettings.ts';\nimport { buildSyncedRuntime } from '../adapters/syncedRuntimeBuilder.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation, syncGenerationDirectory } from '../adapters/syncLocation.ts';\nimport {\n publishSyncRegistration,\n SYNC_REGISTRATION_VERSION,\n syncStateSha256,\n type SyncPackageRegistration,\n} from '../adapters/syncRegistration.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { syncApiRoutes } from '../adapters/apiRoutesSync.ts';\nimport { syncWebBundle } from '../adapters/webBundleSync.ts';\nimport {\n computeInputsHash,\n computeWebSourcesHash,\n readLocatedSyncState,\n readMcpServerNames,\n recordResolvedEntries,\n SYNC_STATE_VERSION,\n type SyncSelection,\n type SyncState,\n syncStateRootMatches,\n writeSyncState,\n} from '../adapters/syncState.ts';\nimport { HARNESS_STATE_POINTER, loadHarnessState } from '../adapters/config/harnessState';\nimport { loadDomains } from '@agimon-ai/doompi-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DEFAULT_THEME, DEFAULT_THEME_NAME } from '@agimon-ai/doompi-ui/theme';\nimport { loadDoomConfig } from '../services/config/projectTrust';\nimport { createLayerResolvers, PERSONA_ENTRY, resolveExtensionComposition } from '../services/extensionAssembler.ts';\nimport type { HarnessOptions } from '../types/interfaces/harness';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport { DOOMPI_DOMAINS_ENV, DOOMPI_MAJOR_MODE_ENV, DOOMPI_PROFILE_ENV } from './cli/matrixOptions.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\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 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;\n/** Published generations kept behind the current one, so a running hub mid-read survives a prune. */\nconst RETAINED_GENERATIONS = 1;\nconst SYNC_LABEL = 'sync';\nconst RUNTIME_LABEL = 'runtime';\nconst WEB_LABEL = 'web';\nconst API_LABEL = 'api';\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 * 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(repoRoot: string, environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const { selection } = loadDoomConfig(repoRoot);\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 (!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 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 package a repository pins for itself, if it pins one.\n *\n * Extensions are version-coupled to the harness that loads them, so the\n * registration must name the copy the repository resolves rather than whichever\n * copy happened to run sync. A globally installed DoomPi syncing a repository\n * that pins its own would otherwise record itself, and the dispatcher would\n * then load the wrong harness for every session in that repository.\n */\nfunction repositoryPackageRoot(repoRoot: string): string | undefined {\n try {\n return path.dirname(\n createRequire(path.join(repoRoot, 'package.json')).resolve(`${DOOM_PACKAGE_NAME}/package.json`),\n );\n } catch {\n // Not pinned here, which is normal; the executing package stands in.\n return undefined;\n }\n}\n\nfunction packageRegistrationFor(repoRoot: string): SyncPackageRegistration {\n const root = fs.realpathSync(repositoryPackageRoot(repoRoot) ?? doomPiPackageRoot());\n const manifestPath = path.join(root, 'package.json');\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {\n version?: unknown;\n pi?: { extensions?: unknown };\n };\n const version = manifest.version;\n const extensions = manifest.pi?.extensions;\n const extension = Array.isArray(extensions) ? extensions.find((value) => typeof value === 'string') : undefined;\n if (typeof version !== 'string' || typeof extension !== 'string') {\n throw new Error(`Installed DoomPi package at ${root} has no versioned Pi extension entry`);\n }\n return {\n root,\n version,\n manifestPath,\n entry: fs.realpathSync(path.resolve(root, extension)),\n };\n}\n\n/**\n * Removes generations the published one replaced.\n *\n * Each generation holds a full cockpit bundle and runtime, so keeping every one\n * ever built grows without bound. One superseded generation is retained because\n * a hub that resolved its assets a moment ago may still be reading them; older\n * ones have no reader left. Ordered by directory name, whose leading timestamp\n * makes publication order recoverable without reading each state file.\n */\nfunction pruneSupersededGenerations(\n generationsDirectory: string,\n published: string,\n onNotice: (message: string) => void,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(generationsDirectory, { withFileTypes: true });\n } catch (error) {\n // Nothing to prune is indistinguishable from an unreadable directory here,\n // and neither is worth failing a sync that already published.\n onNotice(`could not list generations to prune: ${describeError(error)}`);\n return;\n }\n const superseded = entries\n .filter((entry) => entry.isDirectory() && entry.name !== published)\n .map((entry) => entry.name)\n .sort();\n const removable = superseded.slice(0, Math.max(0, superseded.length - RETAINED_GENERATIONS));\n for (const name of removable) {\n try {\n fs.rmSync(path.join(generationsDirectory, name), { recursive: true, force: true });\n } catch (error) {\n // A generation still held open elsewhere stays; the next sync retries it.\n onNotice(`could not remove superseded generation ${name}: ${describeError(error)}`);\n }\n }\n if (removable.length > 0) onNotice(`pruned ${String(removable.length)} superseded generation(s)`);\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Resolves the matrix, stages it into home-scoped worktree storage, and publishes one generation. */\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 const check = args.includes(CHECK_OPTION);\n const force = args.includes(FORCE_OPTION);\n const rest = args.slice(1).filter((argument) => argument !== CHECK_OPTION && argument !== FORCE_OPTION);\n const homeDirectory = this.homeDirectory ?? environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const defaultMajorMode = loadMajorModesConfig(repoRoot, homeDirectory).defaultMajorMode;\n const defaultDomains = loadDomains(repoRoot, homeDirectory).defaultDomains;\n const parsed = parseHarnessArgs(\n rest,\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n defaultMajorMode,\n defaultDomains,\n );\n const selection = toSelection(parsed.options);\n const agentDirectory = piAgentDirectory(environment, homeDirectory);\n if (this.settingsMode === 'persisted' && !check) {\n if (piExtensionDispatcherIsUpgradeable(agentDirectory)) {\n const previousVersion = piExtensionDispatcherVersion(agentDirectory);\n writePiExtensionAlias(agentDirectory);\n output.write(\n `repair: upgraded Pi user dispatcher from protocol ${String(previousVersion)} to ${String(PI_DISPATCHER_VERSION)}\\n`,\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 if (check) {\n const majorModesConfig = loadMajorModesConfig(repoRoot, homeDirectory);\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 environment,\n this.settingsMode,\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 if (!force && readSyncDrift({ repoRoot, homeDirectory }).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 = this.lockHeld\n ? undefined\n : await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n let result: SyncResult;\n try {\n result = await this.stage(repoRoot, parsed.options, environment, homeDirectory, progress);\n } finally {\n await releaseLock?.();\n }\n emitFrontendHooks(repoRoot, output);\n output.write(formatSyncResult(result, this.settingsMode === 'embedded' ? 'dpi' : 'pi'));\n return 0;\n }\n\n private async stage(\n repoRoot: string,\n options: Omit<HarnessOptions, 'repoRoot'>,\n environment: NodeJS.ProcessEnv,\n homeDirectory: string,\n progress: SyncProgress,\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 = this.settingsMode === '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 const precompiled = progress.start(RUNTIME_LABEL, 'precompiling the mode bundles');\n const synced = await buildSyncedRuntime(location.root, environment, homeDirectory, { state, directory });\n precompiled(`${String(Object.keys(synced.bundles).length)} mode bundles`);\n const statePath = await writeSyncState(\n location.root,\n synced.state,\n homeDirectory,\n path.join(directory, 'state.json'),\n );\n\n const webProgress = progress.start(WEB_LABEL, 'bundling the web cockpit plugins');\n const web = await syncWebBundle({\n repoRoot: location.root,\n resolvedEntries: synced.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\n const apiProgress = progress.start(API_LABEL, 'generating the package API routes');\n const api = syncApiRoutes({\n resolvedEntries: synced.state.resolved,\n outputDirectory: path.join(directory, 'api'),\n onNotice: (message) => progress.line(API_LABEL, message),\n });\n apiProgress(`routes written to ${api.directory}`);\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: api.directory,\n package: packageRegistrationFor(location.root),\n },\n homeDirectory,\n );\n pruneSupersededGenerations(location.generationsDirectory, generation, (message) =>\n progress.line(SYNC_LABEL, message),\n );\n const projectSettingsPath = this.settingsMode === 'persisted' ? writeProjectPiSettings(location.root) : undefined;\n\n return {\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 } catch (error) {\n await fs.promises.rm(directory, { recursive: true, force: true });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../services/modeCatalog.cjs"),t=require("../../services/
|
|
1
|
+
const e=require("../../services/modeCatalog.cjs"),t=require("../../services/contextCatalog.cjs"),n=require("../../services/minorModeProjection.cjs"),r=require("./minorModeCommand.cjs");let i=require("@agimon-ai/doompi-extension-contracts/cordis-host"),a=require("@agimon-ai/doompi-extension-contracts/mode"),o=require("@agimon-ai/doompi-extension-contracts/help"),s=require("@agimon-ai/doompi-extension-contracts/notification"),c=require("@agimon-ai/doompi-extension-contracts/transition");function l(e,t,n,r){let i=(0,s.readDoomNotificationService)(e);if(i){try{Promise.resolve(i.request({body:n,level:r})).catch(()=>void 0)}catch{}return}t.ui.notify(n,r)}function u(e){return e.includes(`voice`)?`voice`:e.includes(`leader`)?`leader`:e.includes(`ui`)?`ui`:`system`}async function d(e){let n={current:void 0};r.registerMinorModeCommand(e,()=>n.current);let a={};e.on(`session_start`,()=>{setTimeout(()=>{n.republish?.(),a.publisher?.publish()},500)}),e.on(`turn_start`,()=>{a.publisher?.publish()});let o=await(0,i.connectDoomCordisHost)(e,`@agimon-ai/doompi/mode-catalog`),s=o.root.plugin(r=>(a.publisher=t.createContextPublisher(e,r),f(r,e,n,()=>void a.publisher?.publish()),()=>{a.publisher?.dispose(),a.publisher=void 0}));try{await s}catch(e){throw await s.dispose(),await o.dispose(),e}let c;e.on(`session_shutdown`,()=>c??=(async()=>{try{await s.dispose()}finally{await o.dispose()}})())}function f(t,r,s,d){t.inject([o.DOOM_HELP_SERVICE],e=>{let t=(0,o.requireDoomHelpService)(e).register({source:`@agimon-ai/doompi`,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-author-extension`,description:`Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.`}]});return()=>t.dispose()}),t.inject([i.DOOM_CORDIS_SESSION_SERVICE,c.DOOM_TRANSITION_SERVICE],t=>{let o=t.get(i.DOOM_CORDIS_SESSION_SERVICE),f=o.context,p=(0,c.requireDoomTransitionCoordinator)(t),m=o.reason===`reload`,h=o.sessionId,g=m?(0,c.consumeMinorModeReloadHandoff)(h):void 0;m||(0,c.discardMinorModeReloadHandoff)(h);let _=f.hasUI&&f.mode===`tui`?`tui`:`headless`,v=e.createMinorModeCatalogHost({sessionKind:_,context:f,restoreSnapshot:g,onRestorationError(e){l(t,f,`Could not restore a minor mode after reload: ${e instanceof Error?e.message:String(e)}`,`warning`)},async routeInvocation(e,t,n){let r,i=await p.execute({sessionId:f.sessionManager.getSessionId(),hostGeneration:p.hostGeneration,operationId:e.operationId,source:u(t),target:{axis:`minor-mode`,action:e,requesterSource:t}},async()=>(r=await n(),`applied`));if(i.outcome!==`applied`||!r)throw Error(`Minor-mode transition was ${i.outcome}: ${i.diagnostics.join(`, `)}`);return r}});t.provide(a.DOOM_MINOR_MODE_CATALOG_SERVICE,v),s.current=v;let y,b,x=()=>{b=void 0;let e=n.projectMinorModes(v.getSnapshot(),_),t=JSON.stringify(e);t!==y&&(y=t,r.appendEntry(a.DOOM_MINOR_MODE_ENTRY_TYPE,e),d())},S=v.subscribe(()=>{b??=setTimeout(x,50)});return s.republish=()=>{y=void 0,x()},()=>{b&&clearTimeout(b),S(),s.republish=void 0,s.current=void 0,v.dispose()}})}exports.default=d,exports.modeCatalogExtension=d;
|
|
2
2
|
//# sourceMappingURL=modeCatalog.cjs.map
|