@agimon-ai/po 0.0.0-alpha.2 → 0.0.0-alpha.21

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.
Files changed (255) hide show
  1. package/README.md +14 -11
  2. package/dist/antigravity.mjs +1 -2
  3. package/dist/baseCommand.mjs +1 -2
  4. package/dist/bin/cli.cjs +37 -14
  5. package/dist/bin/cli.cjs.map +1 -1
  6. package/dist/bin/cli.mjs +34 -14
  7. package/dist/bin/cli.mjs.map +1 -1
  8. package/dist/bin/{doomRunner.cjs → poRunner.cjs} +5 -5
  9. package/dist/bin/poRunner.cjs.map +1 -0
  10. package/dist/bin/{doomRunner.d.mts → poRunner.d.mts} +2 -2
  11. package/dist/bin/poRunner.d.mts.map +1 -0
  12. package/dist/bin/{doomRunner.mjs → poRunner.mjs} +5 -5
  13. package/dist/bin/poRunner.mjs.map +1 -0
  14. package/dist/builders/cli/extensionAssembler/index.cjs +14 -12
  15. package/dist/builders/cli/extensionAssembler/index.cjs.map +1 -1
  16. package/dist/builders/cli/extensionAssembler/index.d.mts +2 -1
  17. package/dist/builders/cli/extensionAssembler/index.d.mts.map +1 -1
  18. package/dist/builders/cli/extensionAssembler/index.mjs +14 -12
  19. package/dist/builders/cli/extensionAssembler/index.mjs.map +1 -1
  20. package/dist/catalog/index.json +68 -51
  21. package/dist/cliApp.mjs +1 -2
  22. package/dist/codex.mjs +1 -2
  23. package/dist/compatibilityCommand.mjs +1 -2
  24. package/dist/compatibilityContext.mjs +1 -2
  25. package/dist/compatibilityOptions.mjs +1 -2
  26. package/dist/config.cjs +57 -12
  27. package/dist/config.d.mts +3 -3
  28. package/dist/config.mjs +3 -3
  29. package/dist/doctorCommand.mjs +1 -2
  30. package/dist/emitMcpCommand.mjs +1 -2
  31. package/dist/explainCommand.mjs +1 -2
  32. package/dist/extensions/server.cjs +11 -7
  33. package/dist/extensions/server.cjs.map +1 -1
  34. package/dist/extensions/server.d.mts +2 -2
  35. package/dist/extensions/server.d.mts.map +1 -1
  36. package/dist/extensions/server.mjs +12 -8
  37. package/dist/extensions/server.mjs.map +1 -1
  38. package/dist/harnessContext.mjs +1 -2
  39. package/dist/harnessState.cjs +66 -11
  40. package/dist/harnessState.d.mts +2 -2
  41. package/dist/harnessState.mjs +1 -2
  42. package/dist/index.cjs +60 -15
  43. package/dist/index.d.mts +3 -3
  44. package/dist/index.mjs +3 -3
  45. package/dist/initCommand.mjs +1 -2
  46. package/dist/matrixOptions.mjs +1 -2
  47. package/dist/options.mjs +1 -2
  48. package/dist/process.mjs +1 -2
  49. package/dist/projectTrust.cjs +2 -2
  50. package/dist/projectTrust.d.mts +2 -2
  51. package/dist/projectTrust.mjs +1 -2
  52. package/dist/repository.cjs +1 -1
  53. package/dist/repository.d.mts +2 -2
  54. package/dist/repository.mjs +1 -2
  55. package/dist/router.mjs +1 -2
  56. package/dist/shared.mjs +1 -2
  57. package/dist/src/bin/agentDirectory.cjs +18 -12
  58. package/dist/src/bin/agentDirectory.cjs.map +1 -1
  59. package/dist/src/bin/agentDirectory.mjs +15 -12
  60. package/dist/src/bin/agentDirectory.mjs.map +1 -1
  61. package/dist/src/builders/apiContractExport/index.cjs +6 -6
  62. package/dist/src/builders/apiContractExport/index.cjs.map +1 -1
  63. package/dist/src/builders/apiContractExport/index.mjs +9 -9
  64. package/dist/src/builders/apiContractExport/index.mjs.map +1 -1
  65. package/dist/src/builders/cli/entryResolution.cjs +3 -3
  66. package/dist/src/builders/cli/entryResolution.cjs.map +1 -1
  67. package/dist/src/builders/cli/entryResolution.mjs +3 -3
  68. package/dist/src/builders/cli/entryResolution.mjs.map +1 -1
  69. package/dist/src/builders/cli/harnessContext.cjs +5 -5
  70. package/dist/src/builders/cli/harnessContext.cjs.map +1 -1
  71. package/dist/src/builders/cli/harnessContext.mjs +7 -7
  72. package/dist/src/builders/cli/harnessContext.mjs.map +1 -1
  73. package/dist/src/builders/hooks/index.cjs +1 -1
  74. package/dist/src/builders/hooks/index.cjs.map +1 -1
  75. package/dist/src/builders/hooks/index.mjs +2 -2
  76. package/dist/src/builders/hooks/index.mjs.map +1 -1
  77. package/dist/src/builders/server/backgroundSync.cjs +13 -1
  78. package/dist/src/builders/server/backgroundSync.cjs.map +1 -1
  79. package/dist/src/builders/server/backgroundSync.mjs +13 -1
  80. package/dist/src/builders/server/backgroundSync.mjs.map +1 -1
  81. package/dist/src/builders/server/bundlerService.cjs +151 -0
  82. package/dist/src/builders/server/bundlerService.cjs.map +1 -0
  83. package/dist/src/builders/server/bundlerService.mjs +151 -0
  84. package/dist/src/builders/server/bundlerService.mjs.map +1 -0
  85. package/dist/src/builders/server/computerUseBinding.cjs +2 -2
  86. package/dist/src/builders/server/computerUseBinding.cjs.map +1 -1
  87. package/dist/src/builders/server/computerUseBinding.mjs +3 -3
  88. package/dist/src/builders/server/computerUseBinding.mjs.map +1 -1
  89. package/dist/src/builders/server/defaultWorkspace.cjs +1 -1
  90. package/dist/src/builders/server/defaultWorkspace.cjs.map +1 -1
  91. package/dist/src/builders/server/defaultWorkspace.mjs +2 -2
  92. package/dist/src/builders/server/defaultWorkspace.mjs.map +1 -1
  93. package/dist/src/builders/server/idleRestart.cjs +3 -3
  94. package/dist/src/builders/server/idleRestart.cjs.map +1 -1
  95. package/dist/src/builders/server/idleRestart.mjs +3 -3
  96. package/dist/src/builders/server/idleRestart.mjs.map +1 -1
  97. package/dist/src/builders/server/index.cjs +6 -6
  98. package/dist/src/builders/server/index.cjs.map +1 -1
  99. package/dist/src/builders/server/index.mjs +6 -6
  100. package/dist/src/builders/server/index.mjs.map +1 -1
  101. package/dist/src/builders/server/logSink.cjs +3 -3
  102. package/dist/src/builders/server/logSink.cjs.map +1 -1
  103. package/dist/src/builders/server/logSink.mjs +2 -2
  104. package/dist/src/builders/server/logSink.mjs.map +1 -1
  105. package/dist/src/builders/server/mcpBundle.cjs.map +1 -1
  106. package/dist/src/builders/server/mcpBundle.d.mts +2 -2
  107. package/dist/src/builders/server/mcpBundle.mjs.map +1 -1
  108. package/dist/src/builders/server/packageUrl.cjs +25 -18
  109. package/dist/src/builders/server/packageUrl.cjs.map +1 -1
  110. package/dist/src/builders/server/packageUrl.mjs +25 -18
  111. package/dist/src/builders/server/packageUrl.mjs.map +1 -1
  112. package/dist/src/builders/server/runtime.cjs +157 -168
  113. package/dist/src/builders/server/runtime.cjs.map +1 -1
  114. package/dist/src/builders/server/runtime.mjs +161 -171
  115. package/dist/src/builders/server/runtime.mjs.map +1 -1
  116. package/dist/src/builders/server/selectionStatus.cjs +3 -3
  117. package/dist/src/builders/server/selectionStatus.cjs.map +1 -1
  118. package/dist/src/builders/server/selectionStatus.mjs +3 -3
  119. package/dist/src/builders/server/selectionStatus.mjs.map +1 -1
  120. package/dist/src/builders/server/sessionArguments.cjs.map +1 -1
  121. package/dist/src/builders/server/sessionArguments.mjs.map +1 -1
  122. package/dist/src/builders/server/watcherService.cjs +65 -0
  123. package/dist/src/builders/server/watcherService.cjs.map +1 -0
  124. package/dist/src/builders/server/watcherService.mjs +61 -0
  125. package/dist/src/builders/server/watcherService.mjs.map +1 -0
  126. package/dist/src/builders/server/webTemplateDecision.cjs +1 -1
  127. package/dist/src/builders/server/webTemplateDecision.cjs.map +1 -1
  128. package/dist/src/builders/server/webTemplateDecision.mjs +2 -2
  129. package/dist/src/builders/server/webTemplateDecision.mjs.map +1 -1
  130. package/dist/src/builders/web/bundle.cjs.map +1 -1
  131. package/dist/src/builders/web/bundle.d.mts +4 -3
  132. package/dist/src/builders/web/bundle.mjs.map +1 -1
  133. package/dist/src/builders/web/bundleAssetPolicy.d.mts +1 -0
  134. package/dist/src/builders/web/index.cjs +1 -1
  135. package/dist/src/builders/web/index.cjs.map +1 -1
  136. package/dist/src/builders/web/index.d.mts +1 -0
  137. package/dist/src/builders/web/index.mjs +1 -1
  138. package/dist/src/builders/web/index.mjs.map +1 -1
  139. package/dist/src/builders/web/webPluginGenerate.cjs +4 -15
  140. package/dist/src/builders/web/webPluginGenerate.cjs.map +1 -1
  141. package/dist/src/builders/web/webPluginGenerate.d.mts +5 -9
  142. package/dist/src/builders/web/webPluginGenerate.d.mts.map +1 -1
  143. package/dist/src/builders/web/webPluginGenerate.mjs +4 -15
  144. package/dist/src/builders/web/webPluginGenerate.mjs.map +1 -1
  145. package/dist/src/builders/web/webPluginVite.d.mts +1 -0
  146. package/dist/src/cli/cliApp.cjs +1 -1
  147. package/dist/src/cli/cliApp.cjs.map +1 -1
  148. package/dist/src/cli/cliApp.mjs +1 -1
  149. package/dist/src/cli/cliApp.mjs.map +1 -1
  150. package/dist/src/cli/commands/compat/index.cjs +1 -1
  151. package/dist/src/cli/commands/compat/index.cjs.map +1 -1
  152. package/dist/src/cli/commands/compat/index.mjs +1 -1
  153. package/dist/src/cli/commands/compat/index.mjs.map +1 -1
  154. package/dist/src/cli/commands/doctor/index.cjs +2 -2
  155. package/dist/src/cli/commands/doctor/index.cjs.map +1 -1
  156. package/dist/src/cli/commands/doctor/index.d.mts +1 -0
  157. package/dist/src/cli/commands/doctor/index.d.mts.map +1 -1
  158. package/dist/src/cli/commands/doctor/index.mjs +4 -4
  159. package/dist/src/cli/commands/doctor/index.mjs.map +1 -1
  160. package/dist/src/cli/commands/explain/index.cjs +3 -1
  161. package/dist/src/cli/commands/explain/index.cjs.map +1 -1
  162. package/dist/src/cli/commands/explain/index.d.mts.map +1 -1
  163. package/dist/src/cli/commands/explain/index.mjs +4 -2
  164. package/dist/src/cli/commands/explain/index.mjs.map +1 -1
  165. package/dist/src/cli/commands/init/index.cjs +2 -2
  166. package/dist/src/cli/commands/init/index.cjs.map +1 -1
  167. package/dist/src/cli/commands/init/index.mjs +3 -3
  168. package/dist/src/cli/commands/init/index.mjs.map +1 -1
  169. package/dist/src/cli/commands/init/presenter.cjs +1 -1
  170. package/dist/src/cli/commands/init/presenter.cjs.map +1 -1
  171. package/dist/src/cli/commands/init/presenter.mjs +2 -2
  172. package/dist/src/cli/commands/init/presenter.mjs.map +1 -1
  173. package/dist/src/cli/commands/sync/index.cjs +4 -4
  174. package/dist/src/cli/commands/sync/index.cjs.map +1 -1
  175. package/dist/src/cli/commands/sync/index.d.mts +1 -0
  176. package/dist/src/cli/commands/sync/index.mjs +7 -7
  177. package/dist/src/cli/commands/sync/index.mjs.map +1 -1
  178. package/dist/src/cli/commands/sync/presenter.cjs +1 -1
  179. package/dist/src/cli/commands/sync/presenter.cjs.map +1 -1
  180. package/dist/src/cli/commands/sync/presenter.d.mts +1 -1
  181. package/dist/src/cli/commands/sync/presenter.mjs +1 -1
  182. package/dist/src/cli/commands/sync/presenter.mjs.map +1 -1
  183. package/dist/src/cli/commands/web/index.cjs +2 -1
  184. package/dist/src/cli/commands/web/index.cjs.map +1 -1
  185. package/dist/src/cli/commands/web/index.mjs +2 -1
  186. package/dist/src/cli/commands/web/index.mjs.map +1 -1
  187. package/dist/src/cli/harnessOptions.cjs +1 -1
  188. package/dist/src/cli/harnessOptions.cjs.map +1 -1
  189. package/dist/src/cli/harnessOptions.mjs +2 -2
  190. package/dist/src/cli/harnessOptions.mjs.map +1 -1
  191. package/dist/src/cli/help.cjs +2 -0
  192. package/dist/src/cli/help.cjs.map +1 -1
  193. package/dist/src/cli/help.mjs +2 -0
  194. package/dist/src/cli/help.mjs.map +1 -1
  195. package/dist/src/cli/matrixOptions.cjs +1 -1
  196. package/dist/src/cli/matrixOptions.cjs.map +1 -1
  197. package/dist/src/cli/matrixOptions.d.mts +1 -1
  198. package/dist/src/cli/matrixOptions.mjs +1 -1
  199. package/dist/src/cli/matrixOptions.mjs.map +1 -1
  200. package/dist/src/cli/server/run.cjs +1 -1
  201. package/dist/src/cli/server/run.cjs.map +1 -1
  202. package/dist/src/cli/server/run.mjs +2 -2
  203. package/dist/src/cli/server/run.mjs.map +1 -1
  204. package/dist/src/composition/harnessState/index.cjs +66 -11
  205. package/dist/src/composition/harnessState/index.cjs.map +1 -1
  206. package/dist/src/composition/harnessState/index.d.mts +3 -3
  207. package/dist/src/composition/harnessState/index.mjs +2 -2
  208. package/dist/src/composition/harnessState/index.mjs.map +1 -1
  209. package/dist/src/composition/layerPackageInstaller/index.cjs +5 -4
  210. package/dist/src/composition/layerPackageInstaller/index.cjs.map +1 -1
  211. package/dist/src/composition/layerPackageInstaller/index.mjs +6 -5
  212. package/dist/src/composition/layerPackageInstaller/index.mjs.map +1 -1
  213. package/dist/src/composition/poHomeMigration/index.cjs +1 -1
  214. package/dist/src/composition/poHomeMigration/index.cjs.map +1 -1
  215. package/dist/src/composition/poHomeMigration/index.mjs +1 -1
  216. package/dist/src/composition/poHomeMigration/index.mjs.map +1 -1
  217. package/dist/src/composition/projectTrust/index.cjs +6 -6
  218. package/dist/src/composition/projectTrust/index.cjs.map +1 -1
  219. package/dist/src/composition/projectTrust/index.d.mts +7 -7
  220. package/dist/src/composition/projectTrust/index.d.mts.map +1 -1
  221. package/dist/src/composition/projectTrust/index.mjs +6 -6
  222. package/dist/src/composition/projectTrust/index.mjs.map +1 -1
  223. package/dist/src/composition/repository/index.cjs +8 -8
  224. package/dist/src/composition/repository/index.cjs.map +1 -1
  225. package/dist/src/composition/repository/index.d.mts +5 -5
  226. package/dist/src/composition/repository/index.d.mts.map +1 -1
  227. package/dist/src/composition/repository/index.mjs +10 -10
  228. package/dist/src/composition/repository/index.mjs.map +1 -1
  229. package/dist/src/composition/syncService/index.cjs +29 -9
  230. package/dist/src/composition/syncService/index.cjs.map +1 -1
  231. package/dist/src/composition/syncService/index.d.mts.map +1 -1
  232. package/dist/src/composition/syncService/index.mjs +31 -11
  233. package/dist/src/composition/syncService/index.mjs.map +1 -1
  234. package/dist/src/composition/syncService/localBuilds.cjs +7 -2
  235. package/dist/src/composition/syncService/localBuilds.cjs.map +1 -1
  236. package/dist/src/composition/syncService/localBuilds.mjs +7 -2
  237. package/dist/src/composition/syncService/localBuilds.mjs.map +1 -1
  238. package/dist/src/extensions/setupDiagnostics.cjs +3 -3
  239. package/dist/src/extensions/setupDiagnostics.cjs.map +1 -1
  240. package/dist/src/extensions/setupDiagnostics.mjs +3 -3
  241. package/dist/src/extensions/setupDiagnostics.mjs.map +1 -1
  242. package/dist/utils.mjs +1 -2
  243. package/docs/server/api-export.md +3 -3
  244. package/docs/server/api.md +23 -22
  245. package/docs/server/getting-started.md +7 -7
  246. package/docs/server/index.md +4 -4
  247. package/docs/server/ipc.md +7 -11
  248. package/docs/server/lifecycle.md +17 -17
  249. package/docs/server/security.md +8 -8
  250. package/package.json +42 -45
  251. package/src/prompts/po-author-extension/SKILL.md +1 -1
  252. package/src/prompts/po-author-extension/references/extension-contract.md +4 -4
  253. package/dist/bin/doomRunner.cjs.map +0 -1
  254. package/dist/bin/doomRunner.d.mts.map +0 -1
  255. package/dist/bin/doomRunner.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cliApp.cjs","names":["parseHarnessArgs","HARNESS_VERSION"],"sources":["../../../src/cli/cliApp.ts"],"sourcesContent":["import type { HarnessTelemetry } from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport type { HarnessOptions } from '../composition/types/harness';\nimport type { BaseCommand } from './commands/baseCommand';\nimport { HARNESS_VERSION, printHelp } from './help';\nimport { parseHarnessArgs } from './options';\n\nconst NO_HARNESS_COMMAND = 'No harness command selected: pass --explain or --emit-mcp, or run po to start po-web.';\n\n/**\n * Main CLI Application\n *\n * Owns command registration and dispatch. Preparation is shared: the context\n * is built once and handed to whichever command claims the run.\n */\nasync function selectHarnessCommand(\n options: HarnessOptions,\n): Promise<\n (context: import('../builders/cli/harnessContext').HarnessContext, telemetry: HarnessTelemetry) => Promise<number>\n> {\n if (options.emitMcp) return (await import('./commands/emit-mcp')).runEmitMcp;\n if (options.explain) return (await import('./commands/explain')).runExplain;\n throw new Error(NO_HARNESS_COMMAND);\n}\nasync function selectLegacyCommand(options: HarnessOptions): Promise<BaseCommand> {\n if (options.emitMcp) {\n const { EmitMcpCommand } = await import('./commands/emit-mcp');\n return new EmitMcpCommand();\n }\n if (options.explain) {\n const { ExplainCommand } = await import('./commands/explain');\n return new ExplainCommand();\n }\n throw new Error(NO_HARNESS_COMMAND);\n}\n/**\n * The terminal app reads only what sync prepared. Packages the selected layers name that do not\n * resolve yet start a detached background sync from the repository, which registers it as a\n * workspace so sync covers its packages, and they arrive on the next launch.\n */\nexport async function requestUnsyncedPackages(\n repoRoot: string,\n context: Pick<\n import('../builders/cli/harnessContext').HarnessContext,\n 'majorModesConfig' | 'selectedLayers' | 'environment'\n >,\n): Promise<void> {\n const [{ missingLayerPackageSpecifiers }, { createLayerResolvers }, { createBackgroundSync }] = await Promise.all([\n import('../composition/layerPackageInstaller'),\n import('../builders/cli/extensionAssembler'),\n import('../builders/server/backgroundSync'),\n ]);\n const missing = missingLayerPackageSpecifiers(\n context.majorModesConfig,\n context.selectedLayers,\n createLayerResolvers(repoRoot, context.environment),\n );\n if (missing.length === 0) return;\n const notice = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n };\n const started = createBackgroundSync({\n environment: context.environment,\n onNotice: notice,\n detached: true,\n repoRoot,\n }).request('the terminal app found unsynced packages');\n notice(\n started\n ? `Po is syncing ${missing.join(', ')} in the background; they arrive on the next launch.`\n : `${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} not synced; run po sync to prepare them.`,\n );\n}\n/** Only the diagnostic commands consume a harness context; bare `po` runs po-web. */\nfunction wantsHarnessCommand(options: Pick<HarnessOptions, 'emitMcp' | 'explain'>): boolean {\n return Boolean(options.emitMcp) || options.explain;\n}\nfunction createCliApplication(initialTelemetry?: HarnessTelemetry) {\n let telemetry = initialTelemetry;\n let ownsTelemetry = false;\n async function getTelemetry(): Promise<HarnessTelemetry> {\n if (telemetry) return telemetry;\n const { createHarnessTelemetry } = await import('@agimon-ai/po-core/runtimeLogSinkTelemetry');\n // Telemetry's transport graph costs roughly one launcher budget slice by\n // itself. Startup callbacks and lifecycle events buffer until shutdown, so\n // transport initialization cannot compete with the Pi child for input.\n telemetry = createHarnessTelemetry({ deferSpans: true });\n ownsTelemetry = true;\n return telemetry;\n }\n\n async function runHarness(options: HarnessOptions): Promise<number> {\n const telemetry = await getTelemetry();\n const [{ buildHarnessContext }, { HARNESS_EVENT }] = await Promise.all([\n import('../builders/cli/harnessContext'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return telemetry.runInSpan(\n 'doom_pi.run',\n {\n 'harness.major_mode': options.majorMode,\n 'harness.domain_count': options.domains.length,\n 'harness.agents': options.agents,\n 'harness.mcp': options.mcp,\n 'harness.hooks': options.hooks,\n ...(options.profile ? { 'harness.profile': options.profile } : {}),\n ...(options.preset ? { 'harness.preset': options.preset } : {}),\n },\n async () => {\n const context = await buildHarnessContext(options, telemetry);\n try {\n await requestUnsyncedPackages(options.repoRoot, context);\n const command = await selectHarnessCommand(context.options);\n // Selection uses the same resolved options used to build the context.\n return await command(context, telemetry);\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.cliFailed, error);\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n }\n\n async function run(args: string[]): Promise<number> {\n if (args[0] === 'init') {\n const { runInit } = await import('./commands/init');\n return runInit(args);\n }\n if (args[0] === 'sync') {\n const { runSync } = await import('./commands/sync/workflow');\n return runSync(args);\n }\n if (args[0] === 'api-export') {\n const { runApiExport } = await import('./commands/api-export');\n return runApiExport(args);\n }\n if (args[0] === 'doctor') {\n const { runDoctor } = await import('./commands/doctor');\n return runDoctor(args);\n }\n if (args[0] === 'compat') {\n const [{ runCompatibility }, telemetry] = await Promise.all([import('./commands/compat'), getTelemetry()]);\n return runCompatibility(args, undefined, undefined, telemetry);\n }\n\n // The first pass resolves --cwd without touching repository configuration,\n // which keeps help and version available even when modes.yaml is malformed.\n const initial = parseHarnessArgs(args);\n if (initial.help) {\n printHelp();\n return 0;\n }\n if (initial.version) {\n process.stdout.write(`${HARNESS_VERSION}\\n`);\n return 0;\n }\n // Bare `po` serves the web console. po-web owns its own arguments, so they\n // pass through untouched and never reach repository configuration here.\n if (!wantsHarnessCommand(initial.options)) {\n const { runPoWeb } = await import('./commands/web');\n return runPoWeb(args);\n }\n const telemetry = await getTelemetry();\n const [{ resolveHarnessOptions }, { toFailureReporter }] = await Promise.all([\n import('./harnessOptions'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return runHarness(resolveHarnessOptions({ args, report: toFailureReporter(telemetry) }));\n }\n\n async function shutdown(): Promise<void> {\n if (ownsTelemetry) await telemetry?.shutdown();\n }\n return { run, runHarness, shutdown };\n}\n/** Public compatibility API; execution is implemented by the application functions. */\nexport class CliApp {\n private readonly app: ReturnType<typeof createCliApplication>;\n constructor(telemetry?: HarnessTelemetry) {\n this.app = createCliApplication(telemetry);\n }\n selectCommand(options: HarnessOptions): Promise<BaseCommand> {\n return selectLegacyCommand(options);\n }\n runHarness(options: HarnessOptions): Promise<number> {\n return this.app.runHarness(options);\n }\n run(args: string[]): Promise<number> {\n return this.app.run(args);\n }\n shutdown(): Promise<void> {\n return this.app.shutdown();\n }\n}\n\n/**\n * Convenience wrapper kept so the binary and tests need no CliApp knowledge.\n *\n * Telemetry is shut down here rather than inside runHarness, because this is\n * the only scope that owns the process: flushing earlier would drop the records\n * a later command still emits.\n */\nexport async function runCli(args: string[]): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.run(args);\n } finally {\n await app.shutdown();\n }\n}\n\n/** Runs an already-resolved option set, skipping argument parsing. */\nexport async function runHarness(options: HarnessOptions): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.runHarness(options);\n } finally {\n await app.shutdown();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cliApp.cjs","names":["parseHarnessArgs","HARNESS_VERSION"],"sources":["../../../src/cli/cliApp.ts"],"sourcesContent":["import type { HarnessTelemetry } from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport type { HarnessOptions } from '../composition/types/harness';\nimport type { BaseCommand } from './commands/baseCommand';\nimport { HARNESS_VERSION, printHelp } from './help';\nimport { parseHarnessArgs } from './options';\n\nconst NO_HARNESS_COMMAND = 'No harness command selected: pass --explain or --emit-mcp, or run po to start po-web.';\n\n/**\n * Main CLI Application\n *\n * Owns command registration and dispatch. Preparation is shared: the context\n * is built once and handed to whichever command claims the run.\n */\nasync function selectHarnessCommand(\n options: HarnessOptions,\n): Promise<\n (context: import('../builders/cli/harnessContext').HarnessContext, telemetry: HarnessTelemetry) => Promise<number>\n> {\n if (options.emitMcp) return (await import('./commands/emit-mcp')).runEmitMcp;\n if (options.explain) return (await import('./commands/explain')).runExplain;\n throw new Error(NO_HARNESS_COMMAND);\n}\nasync function selectLegacyCommand(options: HarnessOptions): Promise<BaseCommand> {\n if (options.emitMcp) {\n const { EmitMcpCommand } = await import('./commands/emit-mcp');\n return new EmitMcpCommand();\n }\n if (options.explain) {\n const { ExplainCommand } = await import('./commands/explain');\n return new ExplainCommand();\n }\n throw new Error(NO_HARNESS_COMMAND);\n}\n/**\n * The terminal app reads only what sync prepared. Packages the selected layers name that do not\n * resolve yet start a detached background sync from the repository, which registers it as a\n * workspace so sync covers its packages, and they arrive on the next launch.\n */\nexport async function requestUnsyncedPackages(\n repoRoot: string,\n context: Pick<\n import('../builders/cli/harnessContext').HarnessContext,\n 'majorModesConfig' | 'selectedLayers' | 'environment'\n >,\n): Promise<void> {\n const [{ missingLayerPackageSpecifiers }, { createLayerResolvers }, { createBackgroundSync }] = await Promise.all([\n import('../composition/layerPackageInstaller'),\n import('../builders/cli/extensionAssembler'),\n import('../builders/server/backgroundSync'),\n ]);\n const missing = missingLayerPackageSpecifiers(\n context.majorModesConfig,\n context.selectedLayers,\n createLayerResolvers(repoRoot, context.environment),\n );\n if (missing.length === 0) return;\n const notice = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n };\n const started = createBackgroundSync({\n environment: context.environment,\n onNotice: notice,\n detached: true,\n repoRoot,\n }).request('the terminal app found unsynced packages');\n notice(\n started\n ? `Po is syncing ${missing.join(', ')} in the background; they arrive on the next launch.`\n : `${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} not synced; run po sync to prepare them.`,\n );\n}\n/** Only the diagnostic commands consume a harness context; bare `po` runs po-web. */\nfunction wantsHarnessCommand(options: Pick<HarnessOptions, 'emitMcp' | 'explain'>): boolean {\n return Boolean(options.emitMcp) || options.explain;\n}\nfunction createCliApplication(initialTelemetry?: HarnessTelemetry) {\n let telemetry = initialTelemetry;\n let ownsTelemetry = false;\n async function getTelemetry(): Promise<HarnessTelemetry> {\n if (telemetry) return telemetry;\n const { createHarnessTelemetry } = await import('@agimon-ai/po-core/runtimeLogSinkTelemetry');\n // Telemetry's transport graph costs roughly one launcher budget slice by\n // itself. Startup callbacks and lifecycle events buffer until shutdown, so\n // transport initialization cannot compete with the Pi child for input.\n telemetry = createHarnessTelemetry({ deferSpans: true });\n ownsTelemetry = true;\n return telemetry;\n }\n\n async function runHarness(options: HarnessOptions): Promise<number> {\n const telemetry = await getTelemetry();\n const [{ buildHarnessContext }, { HARNESS_EVENT }] = await Promise.all([\n import('../builders/cli/harnessContext'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return telemetry.runInSpan(\n 'po_pi.run',\n {\n 'harness.major_mode': options.majorMode,\n 'harness.domain_count': options.domains.length,\n 'harness.agents': options.agents,\n 'harness.mcp': options.mcp,\n 'harness.hooks': options.hooks,\n ...(options.profile ? { 'harness.profile': options.profile } : {}),\n ...(options.preset ? { 'harness.preset': options.preset } : {}),\n },\n async () => {\n const context = await buildHarnessContext(options, telemetry);\n try {\n await requestUnsyncedPackages(options.repoRoot, context);\n const command = await selectHarnessCommand(context.options);\n // Selection uses the same resolved options used to build the context.\n return await command(context, telemetry);\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.cliFailed, error);\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n }\n\n async function run(args: string[]): Promise<number> {\n if (args[0] === 'init') {\n const { runInit } = await import('./commands/init');\n return runInit(args);\n }\n if (args[0] === 'sync') {\n const { runSync } = await import('./commands/sync/workflow');\n return runSync(args);\n }\n if (args[0] === 'api-export') {\n const { runApiExport } = await import('./commands/api-export');\n return runApiExport(args);\n }\n if (args[0] === 'doctor') {\n const { runDoctor } = await import('./commands/doctor');\n return runDoctor(args);\n }\n if (args[0] === 'compat') {\n const [{ runCompatibility }, telemetry] = await Promise.all([import('./commands/compat'), getTelemetry()]);\n return runCompatibility(args, undefined, undefined, telemetry);\n }\n\n // The first pass resolves --cwd without touching repository configuration,\n // which keeps help and version available even when modes.yaml is malformed.\n const initial = parseHarnessArgs(args);\n if (initial.help) {\n printHelp();\n return 0;\n }\n if (initial.version) {\n process.stdout.write(`${HARNESS_VERSION}\\n`);\n return 0;\n }\n // Bare `po` serves the web console. po-web owns its own arguments, so they\n // pass through untouched and never reach repository configuration here.\n if (!wantsHarnessCommand(initial.options)) {\n const { runPoWeb } = await import('./commands/web');\n return runPoWeb(args);\n }\n const telemetry = await getTelemetry();\n const [{ resolveHarnessOptions }, { toFailureReporter }] = await Promise.all([\n import('./harnessOptions'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return runHarness(resolveHarnessOptions({ args, report: toFailureReporter(telemetry) }));\n }\n\n async function shutdown(): Promise<void> {\n if (ownsTelemetry) await telemetry?.shutdown();\n }\n return { run, runHarness, shutdown };\n}\n/** Public compatibility API; execution is implemented by the application functions. */\nexport class CliApp {\n private readonly app: ReturnType<typeof createCliApplication>;\n constructor(telemetry?: HarnessTelemetry) {\n this.app = createCliApplication(telemetry);\n }\n selectCommand(options: HarnessOptions): Promise<BaseCommand> {\n return selectLegacyCommand(options);\n }\n runHarness(options: HarnessOptions): Promise<number> {\n return this.app.runHarness(options);\n }\n run(args: string[]): Promise<number> {\n return this.app.run(args);\n }\n shutdown(): Promise<void> {\n return this.app.shutdown();\n }\n}\n\n/**\n * Convenience wrapper kept so the binary and tests need no CliApp knowledge.\n *\n * Telemetry is shut down here rather than inside runHarness, because this is\n * the only scope that owns the process: flushing earlier would drop the records\n * a later command still emits.\n */\nexport async function runCli(args: string[]): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.run(args);\n } finally {\n await app.shutdown();\n }\n}\n\n/** Runs an already-resolved option set, skipping argument parsing. */\nexport async function runHarness(options: HarnessOptions): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.runHarness(options);\n } finally {\n await app.shutdown();\n }\n}\n"],"mappings":"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"}
@@ -64,7 +64,7 @@ function createCliApplication(initialTelemetry) {
64
64
  async function runHarness(options) {
65
65
  const telemetry = await getTelemetry();
66
66
  const [{ buildHarnessContext }, { HARNESS_EVENT }] = await Promise.all([import("../builders/cli/harnessContext.mjs"), import("@agimon-ai/po-core/runtimeLogSinkTelemetry")]);
67
- return telemetry.runInSpan("doom_pi.run", {
67
+ return telemetry.runInSpan("po_pi.run", {
68
68
  "harness.major_mode": options.majorMode,
69
69
  "harness.domain_count": options.domains.length,
70
70
  "harness.agents": options.agents,
@@ -1 +1 @@
1
- {"version":3,"file":"cliApp.mjs","names":[],"sources":["../../../src/cli/cliApp.ts"],"sourcesContent":["import type { HarnessTelemetry } from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport type { HarnessOptions } from '../composition/types/harness';\nimport type { BaseCommand } from './commands/baseCommand';\nimport { HARNESS_VERSION, printHelp } from './help';\nimport { parseHarnessArgs } from './options';\n\nconst NO_HARNESS_COMMAND = 'No harness command selected: pass --explain or --emit-mcp, or run po to start po-web.';\n\n/**\n * Main CLI Application\n *\n * Owns command registration and dispatch. Preparation is shared: the context\n * is built once and handed to whichever command claims the run.\n */\nasync function selectHarnessCommand(\n options: HarnessOptions,\n): Promise<\n (context: import('../builders/cli/harnessContext').HarnessContext, telemetry: HarnessTelemetry) => Promise<number>\n> {\n if (options.emitMcp) return (await import('./commands/emit-mcp')).runEmitMcp;\n if (options.explain) return (await import('./commands/explain')).runExplain;\n throw new Error(NO_HARNESS_COMMAND);\n}\nasync function selectLegacyCommand(options: HarnessOptions): Promise<BaseCommand> {\n if (options.emitMcp) {\n const { EmitMcpCommand } = await import('./commands/emit-mcp');\n return new EmitMcpCommand();\n }\n if (options.explain) {\n const { ExplainCommand } = await import('./commands/explain');\n return new ExplainCommand();\n }\n throw new Error(NO_HARNESS_COMMAND);\n}\n/**\n * The terminal app reads only what sync prepared. Packages the selected layers name that do not\n * resolve yet start a detached background sync from the repository, which registers it as a\n * workspace so sync covers its packages, and they arrive on the next launch.\n */\nexport async function requestUnsyncedPackages(\n repoRoot: string,\n context: Pick<\n import('../builders/cli/harnessContext').HarnessContext,\n 'majorModesConfig' | 'selectedLayers' | 'environment'\n >,\n): Promise<void> {\n const [{ missingLayerPackageSpecifiers }, { createLayerResolvers }, { createBackgroundSync }] = await Promise.all([\n import('../composition/layerPackageInstaller'),\n import('../builders/cli/extensionAssembler'),\n import('../builders/server/backgroundSync'),\n ]);\n const missing = missingLayerPackageSpecifiers(\n context.majorModesConfig,\n context.selectedLayers,\n createLayerResolvers(repoRoot, context.environment),\n );\n if (missing.length === 0) return;\n const notice = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n };\n const started = createBackgroundSync({\n environment: context.environment,\n onNotice: notice,\n detached: true,\n repoRoot,\n }).request('the terminal app found unsynced packages');\n notice(\n started\n ? `Po is syncing ${missing.join(', ')} in the background; they arrive on the next launch.`\n : `${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} not synced; run po sync to prepare them.`,\n );\n}\n/** Only the diagnostic commands consume a harness context; bare `po` runs po-web. */\nfunction wantsHarnessCommand(options: Pick<HarnessOptions, 'emitMcp' | 'explain'>): boolean {\n return Boolean(options.emitMcp) || options.explain;\n}\nfunction createCliApplication(initialTelemetry?: HarnessTelemetry) {\n let telemetry = initialTelemetry;\n let ownsTelemetry = false;\n async function getTelemetry(): Promise<HarnessTelemetry> {\n if (telemetry) return telemetry;\n const { createHarnessTelemetry } = await import('@agimon-ai/po-core/runtimeLogSinkTelemetry');\n // Telemetry's transport graph costs roughly one launcher budget slice by\n // itself. Startup callbacks and lifecycle events buffer until shutdown, so\n // transport initialization cannot compete with the Pi child for input.\n telemetry = createHarnessTelemetry({ deferSpans: true });\n ownsTelemetry = true;\n return telemetry;\n }\n\n async function runHarness(options: HarnessOptions): Promise<number> {\n const telemetry = await getTelemetry();\n const [{ buildHarnessContext }, { HARNESS_EVENT }] = await Promise.all([\n import('../builders/cli/harnessContext'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return telemetry.runInSpan(\n 'doom_pi.run',\n {\n 'harness.major_mode': options.majorMode,\n 'harness.domain_count': options.domains.length,\n 'harness.agents': options.agents,\n 'harness.mcp': options.mcp,\n 'harness.hooks': options.hooks,\n ...(options.profile ? { 'harness.profile': options.profile } : {}),\n ...(options.preset ? { 'harness.preset': options.preset } : {}),\n },\n async () => {\n const context = await buildHarnessContext(options, telemetry);\n try {\n await requestUnsyncedPackages(options.repoRoot, context);\n const command = await selectHarnessCommand(context.options);\n // Selection uses the same resolved options used to build the context.\n return await command(context, telemetry);\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.cliFailed, error);\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n }\n\n async function run(args: string[]): Promise<number> {\n if (args[0] === 'init') {\n const { runInit } = await import('./commands/init');\n return runInit(args);\n }\n if (args[0] === 'sync') {\n const { runSync } = await import('./commands/sync/workflow');\n return runSync(args);\n }\n if (args[0] === 'api-export') {\n const { runApiExport } = await import('./commands/api-export');\n return runApiExport(args);\n }\n if (args[0] === 'doctor') {\n const { runDoctor } = await import('./commands/doctor');\n return runDoctor(args);\n }\n if (args[0] === 'compat') {\n const [{ runCompatibility }, telemetry] = await Promise.all([import('./commands/compat'), getTelemetry()]);\n return runCompatibility(args, undefined, undefined, telemetry);\n }\n\n // The first pass resolves --cwd without touching repository configuration,\n // which keeps help and version available even when modes.yaml is malformed.\n const initial = parseHarnessArgs(args);\n if (initial.help) {\n printHelp();\n return 0;\n }\n if (initial.version) {\n process.stdout.write(`${HARNESS_VERSION}\\n`);\n return 0;\n }\n // Bare `po` serves the web console. po-web owns its own arguments, so they\n // pass through untouched and never reach repository configuration here.\n if (!wantsHarnessCommand(initial.options)) {\n const { runPoWeb } = await import('./commands/web');\n return runPoWeb(args);\n }\n const telemetry = await getTelemetry();\n const [{ resolveHarnessOptions }, { toFailureReporter }] = await Promise.all([\n import('./harnessOptions'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return runHarness(resolveHarnessOptions({ args, report: toFailureReporter(telemetry) }));\n }\n\n async function shutdown(): Promise<void> {\n if (ownsTelemetry) await telemetry?.shutdown();\n }\n return { run, runHarness, shutdown };\n}\n/** Public compatibility API; execution is implemented by the application functions. */\nexport class CliApp {\n private readonly app: ReturnType<typeof createCliApplication>;\n constructor(telemetry?: HarnessTelemetry) {\n this.app = createCliApplication(telemetry);\n }\n selectCommand(options: HarnessOptions): Promise<BaseCommand> {\n return selectLegacyCommand(options);\n }\n runHarness(options: HarnessOptions): Promise<number> {\n return this.app.runHarness(options);\n }\n run(args: string[]): Promise<number> {\n return this.app.run(args);\n }\n shutdown(): Promise<void> {\n return this.app.shutdown();\n }\n}\n\n/**\n * Convenience wrapper kept so the binary and tests need no CliApp knowledge.\n *\n * Telemetry is shut down here rather than inside runHarness, because this is\n * the only scope that owns the process: flushing earlier would drop the records\n * a later command still emits.\n */\nexport async function runCli(args: string[]): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.run(args);\n } finally {\n await app.shutdown();\n }\n}\n\n/** Runs an already-resolved option set, skipping argument parsing. */\nexport async function runHarness(options: HarnessOptions): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.runHarness(options);\n } finally {\n await app.shutdown();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cliApp.mjs","names":[],"sources":["../../../src/cli/cliApp.ts"],"sourcesContent":["import type { HarnessTelemetry } from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport type { HarnessOptions } from '../composition/types/harness';\nimport type { BaseCommand } from './commands/baseCommand';\nimport { HARNESS_VERSION, printHelp } from './help';\nimport { parseHarnessArgs } from './options';\n\nconst NO_HARNESS_COMMAND = 'No harness command selected: pass --explain or --emit-mcp, or run po to start po-web.';\n\n/**\n * Main CLI Application\n *\n * Owns command registration and dispatch. Preparation is shared: the context\n * is built once and handed to whichever command claims the run.\n */\nasync function selectHarnessCommand(\n options: HarnessOptions,\n): Promise<\n (context: import('../builders/cli/harnessContext').HarnessContext, telemetry: HarnessTelemetry) => Promise<number>\n> {\n if (options.emitMcp) return (await import('./commands/emit-mcp')).runEmitMcp;\n if (options.explain) return (await import('./commands/explain')).runExplain;\n throw new Error(NO_HARNESS_COMMAND);\n}\nasync function selectLegacyCommand(options: HarnessOptions): Promise<BaseCommand> {\n if (options.emitMcp) {\n const { EmitMcpCommand } = await import('./commands/emit-mcp');\n return new EmitMcpCommand();\n }\n if (options.explain) {\n const { ExplainCommand } = await import('./commands/explain');\n return new ExplainCommand();\n }\n throw new Error(NO_HARNESS_COMMAND);\n}\n/**\n * The terminal app reads only what sync prepared. Packages the selected layers name that do not\n * resolve yet start a detached background sync from the repository, which registers it as a\n * workspace so sync covers its packages, and they arrive on the next launch.\n */\nexport async function requestUnsyncedPackages(\n repoRoot: string,\n context: Pick<\n import('../builders/cli/harnessContext').HarnessContext,\n 'majorModesConfig' | 'selectedLayers' | 'environment'\n >,\n): Promise<void> {\n const [{ missingLayerPackageSpecifiers }, { createLayerResolvers }, { createBackgroundSync }] = await Promise.all([\n import('../composition/layerPackageInstaller'),\n import('../builders/cli/extensionAssembler'),\n import('../builders/server/backgroundSync'),\n ]);\n const missing = missingLayerPackageSpecifiers(\n context.majorModesConfig,\n context.selectedLayers,\n createLayerResolvers(repoRoot, context.environment),\n );\n if (missing.length === 0) return;\n const notice = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n };\n const started = createBackgroundSync({\n environment: context.environment,\n onNotice: notice,\n detached: true,\n repoRoot,\n }).request('the terminal app found unsynced packages');\n notice(\n started\n ? `Po is syncing ${missing.join(', ')} in the background; they arrive on the next launch.`\n : `${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} not synced; run po sync to prepare them.`,\n );\n}\n/** Only the diagnostic commands consume a harness context; bare `po` runs po-web. */\nfunction wantsHarnessCommand(options: Pick<HarnessOptions, 'emitMcp' | 'explain'>): boolean {\n return Boolean(options.emitMcp) || options.explain;\n}\nfunction createCliApplication(initialTelemetry?: HarnessTelemetry) {\n let telemetry = initialTelemetry;\n let ownsTelemetry = false;\n async function getTelemetry(): Promise<HarnessTelemetry> {\n if (telemetry) return telemetry;\n const { createHarnessTelemetry } = await import('@agimon-ai/po-core/runtimeLogSinkTelemetry');\n // Telemetry's transport graph costs roughly one launcher budget slice by\n // itself. Startup callbacks and lifecycle events buffer until shutdown, so\n // transport initialization cannot compete with the Pi child for input.\n telemetry = createHarnessTelemetry({ deferSpans: true });\n ownsTelemetry = true;\n return telemetry;\n }\n\n async function runHarness(options: HarnessOptions): Promise<number> {\n const telemetry = await getTelemetry();\n const [{ buildHarnessContext }, { HARNESS_EVENT }] = await Promise.all([\n import('../builders/cli/harnessContext'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return telemetry.runInSpan(\n 'po_pi.run',\n {\n 'harness.major_mode': options.majorMode,\n 'harness.domain_count': options.domains.length,\n 'harness.agents': options.agents,\n 'harness.mcp': options.mcp,\n 'harness.hooks': options.hooks,\n ...(options.profile ? { 'harness.profile': options.profile } : {}),\n ...(options.preset ? { 'harness.preset': options.preset } : {}),\n },\n async () => {\n const context = await buildHarnessContext(options, telemetry);\n try {\n await requestUnsyncedPackages(options.repoRoot, context);\n const command = await selectHarnessCommand(context.options);\n // Selection uses the same resolved options used to build the context.\n return await command(context, telemetry);\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.cliFailed, error);\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n }\n\n async function run(args: string[]): Promise<number> {\n if (args[0] === 'init') {\n const { runInit } = await import('./commands/init');\n return runInit(args);\n }\n if (args[0] === 'sync') {\n const { runSync } = await import('./commands/sync/workflow');\n return runSync(args);\n }\n if (args[0] === 'api-export') {\n const { runApiExport } = await import('./commands/api-export');\n return runApiExport(args);\n }\n if (args[0] === 'doctor') {\n const { runDoctor } = await import('./commands/doctor');\n return runDoctor(args);\n }\n if (args[0] === 'compat') {\n const [{ runCompatibility }, telemetry] = await Promise.all([import('./commands/compat'), getTelemetry()]);\n return runCompatibility(args, undefined, undefined, telemetry);\n }\n\n // The first pass resolves --cwd without touching repository configuration,\n // which keeps help and version available even when modes.yaml is malformed.\n const initial = parseHarnessArgs(args);\n if (initial.help) {\n printHelp();\n return 0;\n }\n if (initial.version) {\n process.stdout.write(`${HARNESS_VERSION}\\n`);\n return 0;\n }\n // Bare `po` serves the web console. po-web owns its own arguments, so they\n // pass through untouched and never reach repository configuration here.\n if (!wantsHarnessCommand(initial.options)) {\n const { runPoWeb } = await import('./commands/web');\n return runPoWeb(args);\n }\n const telemetry = await getTelemetry();\n const [{ resolveHarnessOptions }, { toFailureReporter }] = await Promise.all([\n import('./harnessOptions'),\n import('@agimon-ai/po-core/runtimeLogSinkTelemetry'),\n ]);\n return runHarness(resolveHarnessOptions({ args, report: toFailureReporter(telemetry) }));\n }\n\n async function shutdown(): Promise<void> {\n if (ownsTelemetry) await telemetry?.shutdown();\n }\n return { run, runHarness, shutdown };\n}\n/** Public compatibility API; execution is implemented by the application functions. */\nexport class CliApp {\n private readonly app: ReturnType<typeof createCliApplication>;\n constructor(telemetry?: HarnessTelemetry) {\n this.app = createCliApplication(telemetry);\n }\n selectCommand(options: HarnessOptions): Promise<BaseCommand> {\n return selectLegacyCommand(options);\n }\n runHarness(options: HarnessOptions): Promise<number> {\n return this.app.runHarness(options);\n }\n run(args: string[]): Promise<number> {\n return this.app.run(args);\n }\n shutdown(): Promise<void> {\n return this.app.shutdown();\n }\n}\n\n/**\n * Convenience wrapper kept so the binary and tests need no CliApp knowledge.\n *\n * Telemetry is shut down here rather than inside runHarness, because this is\n * the only scope that owns the process: flushing earlier would drop the records\n * a later command still emits.\n */\nexport async function runCli(args: string[]): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.run(args);\n } finally {\n await app.shutdown();\n }\n}\n\n/** Runs an already-resolved option set, skipping argument parsing. */\nexport async function runHarness(options: HarnessOptions): Promise<number> {\n const app = createCliApplication();\n try {\n return await app.runHarness(options);\n } finally {\n await app.shutdown();\n }\n}\n"],"mappings":"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"}
@@ -24,7 +24,7 @@ async function runCompatibility(args, environment = process.env, currentDirector
24
24
  const repoRoot = inheritedRoot ? node_path.default.resolve(inheritedRoot) : require_index.findRepositoryRoot(currentDirectory);
25
25
  const parsed = require_options.parseCompatibilityArgs(args.slice(2), environment, currentDirectory, (0, _agimon_ai_po_config_majorModes.loadMajorModesConfig)(repoRoot).defaultMajorMode, (0, _agimon_ai_po_config_domains.loadDomains)(repoRoot).defaultDomains);
26
26
  const startedAt = Date.now();
27
- return telemetry.runInSpan("doom_pi.compatibility", {
27
+ return telemetry.runInSpan("po_pi.compatibility", {
28
28
  "harness.provider": provider,
29
29
  "harness.mode": "compatibility"
30
30
  }, async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["createHarnessTelemetry","isCompatibilityProvider","wantsHelp","compatHelp","parseCompatibilityProvider","path","findRepositoryRoot","parseCompatibilityArgs","loadMajorModesConfig","loadDomains","buildCompatibilityContext","launchCompatibility","HARNESS_EVENT"],"sources":["../../../../../src/cli/commands/compat/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport {\n createHarnessTelemetry,\n HARNESS_EVENT,\n type HarnessTelemetry,\n} from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport { findRepositoryRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { buildCompatibilityContext } from './context';\nimport { compatHelp } from './help';\nimport { isCompatibilityProvider, parseCompatibilityArgs, parseCompatibilityProvider } from './options';\nimport { launchCompatibility } from './providers';\n\nconst COMPAT_COMMAND = 'compat';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\n\n/** Launches a non-Pi frontend with the po matrix resolved for that run. */\nexport async function runCompatibility(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): Promise<number> {\n // Only when no provider was named. Once one is, every remaining argument\n // belongs to that frontend, so `compat claude --help` is Claude's help.\n if (!isCompatibilityProvider(args[1]) && wantsHelp(args.slice(1))) {\n process.stdout.write(compatHelp());\n return 0;\n }\n const provider = parseCompatibilityProvider(args[1]);\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseCompatibilityArgs(\n args.slice(2),\n environment,\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const startedAt = Date.now();\n\n // Compatibility launches shell out to a third-party CLI and to state-sync\n // scripts, so most of what can go wrong here is invisible to Pi entirely.\n return telemetry.runInSpan(\n 'doom_pi.compatibility',\n { 'harness.provider': provider, 'harness.mode': 'compatibility' },\n async () => {\n const context = await buildCompatibilityContext({ repoRoot, provider, ...parsed.options });\n try {\n const exitCode = await launchCompatibility(context);\n void telemetry.recordEvent(HARNESS_EVENT.launchCompleted, {\n 'harness.provider': provider,\n 'harness.exit_code': exitCode,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n return exitCode;\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.compatibilityLaunchFailed, error, {\n 'harness.provider': provider,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class CompatibilityCommand {\n readonly name = COMPAT_COMMAND;\n private readonly telemetry: HarnessTelemetry;\n\n // Not a constructor parameter property: the launcher scripts run this file\n // straight from source under Node's strip-only TypeScript mode, which\n // rejects them.\n constructor(telemetry: HarnessTelemetry = createHarnessTelemetry()) {\n this.telemetry = telemetry;\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 ): Promise<number> {\n return runCompatibility(args, environment, currentDirectory, this.telemetry);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;;AAGzB,eAAsB,iBACpB,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,aAAA,GAA8BA,2CAAAA,uBAAAA,CAAuB,GACpC;CAGjB,IAAI,CAACC,gBAAAA,wBAAwB,KAAK,EAAE,KAAKC,eAAAA,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EACjE,QAAQ,OAAO,MAAMC,aAAAA,WAAW,CAAC;EACjC,OAAO;CACT;CACA,MAAM,WAAWC,gBAAAA,2BAA2B,KAAK,EAAE;CACnD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBAAgBC,UAAAA,QAAK,QAAQ,aAAa,IAAIC,cAAAA,mBAAmB,gBAAgB;CAClG,MAAM,SAASC,gBAAAA,uBACb,KAAK,MAAM,CAAC,GACZ,aACA,mBAAA,GACAC,gCAAAA,qBAAAA,CAAqB,QAAQ,CAAC,CAAC,mBAAA,GAC/BC,6BAAAA,YAAAA,CAAY,QAAQ,CAAC,CAAC,cACxB;CACA,MAAM,YAAY,KAAK,IAAI;CAI3B,OAAO,UAAU,UACf,yBACA;EAAE,oBAAoB;EAAU,gBAAgB;CAAgB,GAChE,YAAY;EACV,MAAM,UAAU,MAAMC,gBAAAA,0BAA0B;GAAE;GAAU;GAAU,GAAG,OAAO;EAAQ,CAAC;EACzF,IAAI;GACF,MAAM,WAAW,MAAMC,gBAAAA,oBAAoB,OAAO;GAClD,UAAe,YAAYC,2CAAAA,cAAc,iBAAiB;IACxD,oBAAoB;IACpB,qBAAqB;IACrB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,OAAO;EACT,SAAS,OAAO;GACd,MAAM,UAAU,YAAYA,2CAAAA,cAAc,2BAA2B,OAAO;IAC1E,oBAAoB;IACpB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,MAAM;EACR,UAAU;GACR,MAAM,QAAQ,QAAQ;EACxB;CACF,CACF;AACF;;AAGA,IAAa,uBAAb,MAAkC;CAChC,OAAgB;CAChB;CAKA,YAAY,aAAA,GAA8BZ,2CAAAA,uBAAAA,CAAuB,GAAG;EAClE,KAAK,YAAY;CACnB;CAEA,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GACd;EACjB,OAAO,iBAAiB,MAAM,aAAa,kBAAkB,KAAK,SAAS;CAC7E;AACF"}
1
+ {"version":3,"file":"index.cjs","names":["createHarnessTelemetry","isCompatibilityProvider","wantsHelp","compatHelp","parseCompatibilityProvider","path","findRepositoryRoot","parseCompatibilityArgs","loadMajorModesConfig","loadDomains","buildCompatibilityContext","launchCompatibility","HARNESS_EVENT"],"sources":["../../../../../src/cli/commands/compat/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport {\n createHarnessTelemetry,\n HARNESS_EVENT,\n type HarnessTelemetry,\n} from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport { findRepositoryRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { buildCompatibilityContext } from './context';\nimport { compatHelp } from './help';\nimport { isCompatibilityProvider, parseCompatibilityArgs, parseCompatibilityProvider } from './options';\nimport { launchCompatibility } from './providers';\n\nconst COMPAT_COMMAND = 'compat';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\n\n/** Launches a non-Pi frontend with the po matrix resolved for that run. */\nexport async function runCompatibility(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): Promise<number> {\n // Only when no provider was named. Once one is, every remaining argument\n // belongs to that frontend, so `compat claude --help` is Claude's help.\n if (!isCompatibilityProvider(args[1]) && wantsHelp(args.slice(1))) {\n process.stdout.write(compatHelp());\n return 0;\n }\n const provider = parseCompatibilityProvider(args[1]);\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseCompatibilityArgs(\n args.slice(2),\n environment,\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const startedAt = Date.now();\n\n // Compatibility launches shell out to a third-party CLI and to state-sync\n // scripts, so most of what can go wrong here is invisible to Pi entirely.\n return telemetry.runInSpan(\n 'po_pi.compatibility',\n { 'harness.provider': provider, 'harness.mode': 'compatibility' },\n async () => {\n const context = await buildCompatibilityContext({ repoRoot, provider, ...parsed.options });\n try {\n const exitCode = await launchCompatibility(context);\n void telemetry.recordEvent(HARNESS_EVENT.launchCompleted, {\n 'harness.provider': provider,\n 'harness.exit_code': exitCode,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n return exitCode;\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.compatibilityLaunchFailed, error, {\n 'harness.provider': provider,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class CompatibilityCommand {\n readonly name = COMPAT_COMMAND;\n private readonly telemetry: HarnessTelemetry;\n\n // Not a constructor parameter property: the launcher scripts run this file\n // straight from source under Node's strip-only TypeScript mode, which\n // rejects them.\n constructor(telemetry: HarnessTelemetry = createHarnessTelemetry()) {\n this.telemetry = telemetry;\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 ): Promise<number> {\n return runCompatibility(args, environment, currentDirectory, this.telemetry);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;;AAGzB,eAAsB,iBACpB,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,aAAA,GAA8BA,2CAAAA,uBAAAA,CAAuB,GACpC;CAGjB,IAAI,CAACC,gBAAAA,wBAAwB,KAAK,EAAE,KAAKC,eAAAA,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EACjE,QAAQ,OAAO,MAAMC,aAAAA,WAAW,CAAC;EACjC,OAAO;CACT;CACA,MAAM,WAAWC,gBAAAA,2BAA2B,KAAK,EAAE;CACnD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBAAgBC,UAAAA,QAAK,QAAQ,aAAa,IAAIC,cAAAA,mBAAmB,gBAAgB;CAClG,MAAM,SAASC,gBAAAA,uBACb,KAAK,MAAM,CAAC,GACZ,aACA,mBAAA,GACAC,gCAAAA,qBAAAA,CAAqB,QAAQ,CAAC,CAAC,mBAAA,GAC/BC,6BAAAA,YAAAA,CAAY,QAAQ,CAAC,CAAC,cACxB;CACA,MAAM,YAAY,KAAK,IAAI;CAI3B,OAAO,UAAU,UACf,uBACA;EAAE,oBAAoB;EAAU,gBAAgB;CAAgB,GAChE,YAAY;EACV,MAAM,UAAU,MAAMC,gBAAAA,0BAA0B;GAAE;GAAU;GAAU,GAAG,OAAO;EAAQ,CAAC;EACzF,IAAI;GACF,MAAM,WAAW,MAAMC,gBAAAA,oBAAoB,OAAO;GAClD,UAAe,YAAYC,2CAAAA,cAAc,iBAAiB;IACxD,oBAAoB;IACpB,qBAAqB;IACrB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,OAAO;EACT,SAAS,OAAO;GACd,MAAM,UAAU,YAAYA,2CAAAA,cAAc,2BAA2B,OAAO;IAC1E,oBAAoB;IACpB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,MAAM;EACR,UAAU;GACR,MAAM,QAAQ,QAAQ;EACxB;CACF,CACF;AACF;;AAGA,IAAa,uBAAb,MAAkC;CAChC,OAAgB;CAChB;CAKA,YAAY,aAAA,GAA8BZ,2CAAAA,uBAAAA,CAAuB,GAAG;EAClE,KAAK,YAAY;CACnB;CAEA,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GACd;EACjB,OAAO,iBAAiB,MAAM,aAAa,kBAAkB,KAAK,SAAS;CAC7E;AACF"}
@@ -22,7 +22,7 @@ async function runCompatibility(args, environment = process.env, currentDirector
22
22
  const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);
23
23
  const parsed = parseCompatibilityArgs(args.slice(2), environment, currentDirectory, loadMajorModesConfig(repoRoot).defaultMajorMode, loadDomains(repoRoot).defaultDomains);
24
24
  const startedAt = Date.now();
25
- return telemetry.runInSpan("doom_pi.compatibility", {
25
+ return telemetry.runInSpan("po_pi.compatibility", {
26
26
  "harness.provider": provider,
27
27
  "harness.mode": "compatibility"
28
28
  }, async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/compat/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport {\n createHarnessTelemetry,\n HARNESS_EVENT,\n type HarnessTelemetry,\n} from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport { findRepositoryRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { buildCompatibilityContext } from './context';\nimport { compatHelp } from './help';\nimport { isCompatibilityProvider, parseCompatibilityArgs, parseCompatibilityProvider } from './options';\nimport { launchCompatibility } from './providers';\n\nconst COMPAT_COMMAND = 'compat';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\n\n/** Launches a non-Pi frontend with the po matrix resolved for that run. */\nexport async function runCompatibility(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): Promise<number> {\n // Only when no provider was named. Once one is, every remaining argument\n // belongs to that frontend, so `compat claude --help` is Claude's help.\n if (!isCompatibilityProvider(args[1]) && wantsHelp(args.slice(1))) {\n process.stdout.write(compatHelp());\n return 0;\n }\n const provider = parseCompatibilityProvider(args[1]);\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseCompatibilityArgs(\n args.slice(2),\n environment,\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const startedAt = Date.now();\n\n // Compatibility launches shell out to a third-party CLI and to state-sync\n // scripts, so most of what can go wrong here is invisible to Pi entirely.\n return telemetry.runInSpan(\n 'doom_pi.compatibility',\n { 'harness.provider': provider, 'harness.mode': 'compatibility' },\n async () => {\n const context = await buildCompatibilityContext({ repoRoot, provider, ...parsed.options });\n try {\n const exitCode = await launchCompatibility(context);\n void telemetry.recordEvent(HARNESS_EVENT.launchCompleted, {\n 'harness.provider': provider,\n 'harness.exit_code': exitCode,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n return exitCode;\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.compatibilityLaunchFailed, error, {\n 'harness.provider': provider,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class CompatibilityCommand {\n readonly name = COMPAT_COMMAND;\n private readonly telemetry: HarnessTelemetry;\n\n // Not a constructor parameter property: the launcher scripts run this file\n // straight from source under Node's strip-only TypeScript mode, which\n // rejects them.\n constructor(telemetry: HarnessTelemetry = createHarnessTelemetry()) {\n this.telemetry = telemetry;\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 ): Promise<number> {\n return runCompatibility(args, environment, currentDirectory, this.telemetry);\n }\n}\n"],"mappings":";;;;;;;;;;;AAiBA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;;AAGzB,eAAsB,iBACpB,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,YAA8B,uBAAuB,GACpC;CAGjB,IAAI,CAAC,wBAAwB,KAAK,EAAE,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EACjE,QAAQ,OAAO,MAAM,WAAW,CAAC;EACjC,OAAO;CACT;CACA,MAAM,WAAW,2BAA2B,KAAK,EAAE;CACnD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBAAgB,KAAK,QAAQ,aAAa,IAAI,mBAAmB,gBAAgB;CAClG,MAAM,SAAS,uBACb,KAAK,MAAM,CAAC,GACZ,aACA,kBACA,qBAAqB,QAAQ,CAAC,CAAC,kBAC/B,YAAY,QAAQ,CAAC,CAAC,cACxB;CACA,MAAM,YAAY,KAAK,IAAI;CAI3B,OAAO,UAAU,UACf,yBACA;EAAE,oBAAoB;EAAU,gBAAgB;CAAgB,GAChE,YAAY;EACV,MAAM,UAAU,MAAM,0BAA0B;GAAE;GAAU;GAAU,GAAG,OAAO;EAAQ,CAAC;EACzF,IAAI;GACF,MAAM,WAAW,MAAM,oBAAoB,OAAO;GAClD,UAAe,YAAY,cAAc,iBAAiB;IACxD,oBAAoB;IACpB,qBAAqB;IACrB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,OAAO;EACT,SAAS,OAAO;GACd,MAAM,UAAU,YAAY,cAAc,2BAA2B,OAAO;IAC1E,oBAAoB;IACpB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,MAAM;EACR,UAAU;GACR,MAAM,QAAQ,QAAQ;EACxB;CACF,CACF;AACF;;AAGA,IAAa,uBAAb,MAAkC;CAChC,OAAgB;CAChB;CAKA,YAAY,YAA8B,uBAAuB,GAAG;EAClE,KAAK,YAAY;CACnB;CAEA,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GACd;EACjB,OAAO,iBAAiB,MAAM,aAAa,kBAAkB,KAAK,SAAS;CAC7E;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/compat/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport {\n createHarnessTelemetry,\n HARNESS_EVENT,\n type HarnessTelemetry,\n} from '@agimon-ai/po-core/runtimeLogSinkTelemetry';\n\nimport { findRepositoryRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { buildCompatibilityContext } from './context';\nimport { compatHelp } from './help';\nimport { isCompatibilityProvider, parseCompatibilityArgs, parseCompatibilityProvider } from './options';\nimport { launchCompatibility } from './providers';\n\nconst COMPAT_COMMAND = 'compat';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\n\n/** Launches a non-Pi frontend with the po matrix resolved for that run. */\nexport async function runCompatibility(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): Promise<number> {\n // Only when no provider was named. Once one is, every remaining argument\n // belongs to that frontend, so `compat claude --help` is Claude's help.\n if (!isCompatibilityProvider(args[1]) && wantsHelp(args.slice(1))) {\n process.stdout.write(compatHelp());\n return 0;\n }\n const provider = parseCompatibilityProvider(args[1]);\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseCompatibilityArgs(\n args.slice(2),\n environment,\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const startedAt = Date.now();\n\n // Compatibility launches shell out to a third-party CLI and to state-sync\n // scripts, so most of what can go wrong here is invisible to Pi entirely.\n return telemetry.runInSpan(\n 'po_pi.compatibility',\n { 'harness.provider': provider, 'harness.mode': 'compatibility' },\n async () => {\n const context = await buildCompatibilityContext({ repoRoot, provider, ...parsed.options });\n try {\n const exitCode = await launchCompatibility(context);\n void telemetry.recordEvent(HARNESS_EVENT.launchCompleted, {\n 'harness.provider': provider,\n 'harness.exit_code': exitCode,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n return exitCode;\n } catch (error) {\n await telemetry.recordError(HARNESS_EVENT.compatibilityLaunchFailed, error, {\n 'harness.provider': provider,\n 'harness.duration_ms': Date.now() - startedAt,\n });\n throw error;\n } finally {\n await context.cleanup();\n }\n },\n );\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class CompatibilityCommand {\n readonly name = COMPAT_COMMAND;\n private readonly telemetry: HarnessTelemetry;\n\n // Not a constructor parameter property: the launcher scripts run this file\n // straight from source under Node's strip-only TypeScript mode, which\n // rejects them.\n constructor(telemetry: HarnessTelemetry = createHarnessTelemetry()) {\n this.telemetry = telemetry;\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 ): Promise<number> {\n return runCompatibility(args, environment, currentDirectory, this.telemetry);\n }\n}\n"],"mappings":";;;;;;;;;;;AAiBA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;;AAGzB,eAAsB,iBACpB,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,YAA8B,uBAAuB,GACpC;CAGjB,IAAI,CAAC,wBAAwB,KAAK,EAAE,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EACjE,QAAQ,OAAO,MAAM,WAAW,CAAC;EACjC,OAAO;CACT;CACA,MAAM,WAAW,2BAA2B,KAAK,EAAE;CACnD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBAAgB,KAAK,QAAQ,aAAa,IAAI,mBAAmB,gBAAgB;CAClG,MAAM,SAAS,uBACb,KAAK,MAAM,CAAC,GACZ,aACA,kBACA,qBAAqB,QAAQ,CAAC,CAAC,kBAC/B,YAAY,QAAQ,CAAC,CAAC,cACxB;CACA,MAAM,YAAY,KAAK,IAAI;CAI3B,OAAO,UAAU,UACf,uBACA;EAAE,oBAAoB;EAAU,gBAAgB;CAAgB,GAChE,YAAY;EACV,MAAM,UAAU,MAAM,0BAA0B;GAAE;GAAU;GAAU,GAAG,OAAO;EAAQ,CAAC;EACzF,IAAI;GACF,MAAM,WAAW,MAAM,oBAAoB,OAAO;GAClD,UAAe,YAAY,cAAc,iBAAiB;IACxD,oBAAoB;IACpB,qBAAqB;IACrB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,OAAO;EACT,SAAS,OAAO;GACd,MAAM,UAAU,YAAY,cAAc,2BAA2B,OAAO;IAC1E,oBAAoB;IACpB,uBAAuB,KAAK,IAAI,IAAI;GACtC,CAAC;GACD,MAAM;EACR,UAAU;GACR,MAAM,QAAQ,QAAQ;EACxB;CACF,CACF;AACF;;AAGA,IAAa,uBAAb,MAAkC;CAChC,OAAgB;CAChB;CAKA,YAAY,YAA8B,uBAAuB,GAAG;EAClE,KAAK,YAAY;CACnB;CAEA,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GACd;EACjB,OAAO,iBAAiB,MAAM,aAAa,kBAAkB,KAAK,SAAS;CAC7E;AACF"}
@@ -57,11 +57,11 @@ function runDoctor(args, environment = process.env, currentDirectory = process.c
57
57
  function collectDoctorReport(environment, currentDirectory) {
58
58
  const homeDirectory = environment.HOME ?? node_os.default.homedir();
59
59
  const inheritedRoot = environment[HARNESS_ROOT_ENV];
60
- const repoRoot = inheritedRoot ? node_path.default.resolve(inheritedRoot) : require_index.resolveDoomConfigurationRoot(currentDirectory, homeDirectory);
60
+ const repoRoot = inheritedRoot ? node_path.default.resolve(inheritedRoot) : require_index.resolvePoConfigurationRoot(currentDirectory, homeDirectory);
61
61
  const sections = [
62
62
  {
63
63
  label: "config.yaml",
64
- problems: check(() => (0, _agimon_ai_po_config_config.loadDoomConfig)(repoRoot, homeDirectory))
64
+ problems: check(() => (0, _agimon_ai_po_config_config.loadPoConfig)(repoRoot, homeDirectory))
65
65
  },
66
66
  {
67
67
  label: "modes.yaml",
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["wantsHelp","doctorHelp","os","path","resolveDoomConfigurationRoot","loadDoomConfig","loadMajorModesConfig","loadDomains","loadProfiles","syncReadiness"],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { loadDoomConfig } from '@agimon-ai/po-config/config';\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport { loadProfiles } from '@agimon-ai/po-config/profiles';\n\nimport { resolveDoomConfigurationRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { syncReadiness } from '../sync';\nimport { doctorHelp } from './help';\n\nconst DOCTOR_COMMAND = 'doctor';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\nconst LABEL_WIDTH = 14;\n\nexport interface DoctorOutput {\n write(chunk: string): void;\n}\n\n/** One checked area and what it found. Empty problems means the section passed. */\ninterface Section {\n label: string;\n problems: string[];\n}\n\nfunction formatSection(section: Section): string {\n const label = section.label.padEnd(LABEL_WIDTH);\n if (section.problems.length === 0) return `${label}ok\\n`;\n return `${label}${section.problems.length === 1 ? 'FAILED' : `${String(section.problems.length)} problem(s)`}\\n${section.problems\n .map((problem) => ` ${problem}\\n`)\n .join('')}`;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Runs one check, turning the throw a strict parser uses into a reported problem. */\nfunction check(run: () => void): string[] {\n try {\n run();\n return [];\n } catch (error) {\n return [messageOf(error)];\n }\n}\n\n/**\n * Reports what is wrong with a Po installation without changing anything.\n *\n * The strict counterpart to `po sync`, which tolerates unknown config keys\n * so a build cannot break over one. Everything `sync --check` reports is\n * reported here too, so this is the one command to run when something is off.\n */\nexport function runDoctor(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n): number {\n if (wantsHelp(args.slice(1))) {\n output.write(doctorHelp());\n return 0;\n }\n const { sections, problems } = collectDoctorReport(environment, currentDirectory);\n for (const section of sections) output.write(formatSection(section));\n if (problems === 0) {\n output.write('\\nno problems found\\n');\n return 0;\n }\n output.write(`\\n${String(problems)} problem(s) found\\n`);\n return 1;\n}\n\n/** The CLI and session diagnostic tool run the same read-only checks. */\nexport function collectDoctorReport(environment: NodeJS.ProcessEnv, currentDirectory: string) {\n const 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 sections: Section[] = [\n { label: 'config.yaml', problems: check(() => loadDoomConfig(repoRoot, homeDirectory)) },\n { label: 'modes.yaml', problems: check(() => loadMajorModesConfig(repoRoot, homeDirectory)) },\n { label: 'domains.yaml', problems: check(() => loadDomains(repoRoot, homeDirectory)) },\n { label: 'profiles.yaml', problems: check(() => loadProfiles(repoRoot, homeDirectory)) },\n ];\n const skipped = sections.some((section) => section.problems.length > 0) ? ['packages', 'web build'] : [];\n if (skipped.length === 0) {\n try {\n const readiness = syncReadiness(repoRoot, homeDirectory, environment);\n sections.push(\n { label: 'packages', problems: readiness.packages },\n { label: 'web build', problems: readiness.web },\n );\n } catch (error) {\n sections.push({ label: 'installation', problems: [messageOf(error)] });\n }\n }\n return {\n repoRoot,\n homeDirectory,\n sections,\n skipped,\n problems: sections.reduce((total, section) => total + section.problems.length, 0),\n };\n}\n/** Compatibility API. Executables call the command function directly. */\nexport class DoctorCommand {\n readonly name = DOCTOR_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n ): number {\n return runDoctor(args, environment, currentDirectory, output);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,cAAc;AAYpB,SAAS,cAAc,SAA0B;CAC/C,MAAM,QAAQ,QAAQ,MAAM,OAAO,WAAW;CAC9C,IAAI,QAAQ,SAAS,WAAW,GAAG,OAAO,GAAG,MAAM;CACnD,OAAO,GAAG,QAAQ,QAAQ,SAAS,WAAW,IAAI,WAAW,GAAG,OAAO,QAAQ,SAAS,MAAM,EAAE,aAAa,IAAI,QAAQ,SACtH,KAAK,YAAY,KAAK,QAAQ,GAAG,CAAC,CAClC,KAAK,EAAE;AACZ;AAEA,SAAS,UAAU,OAAwB;CACzC,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;AAGA,SAAS,MAAM,KAA2B;CACxC,IAAI;EACF,IAAI;EACJ,OAAO,CAAC;CACV,SAAS,OAAO;EACd,OAAO,CAAC,UAAU,KAAK,CAAC;CAC1B;AACF;;;;;;;;AASA,SAAgB,UACd,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;CACR,IAAIA,eAAAA,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EAC5B,OAAO,MAAMC,aAAAA,WAAW,CAAC;EACzB,OAAO;CACT;CACA,MAAM,EAAE,UAAU,aAAa,oBAAoB,aAAa,gBAAgB;CAChF,KAAK,MAAM,WAAW,UAAU,OAAO,MAAM,cAAc,OAAO,CAAC;CACnE,IAAI,aAAa,GAAG;EAClB,OAAO,MAAM,uBAAuB;EACpC,OAAO;CACT;CACA,OAAO,MAAM,KAAK,OAAO,QAAQ,EAAE,oBAAoB;CACvD,OAAO;AACT;;AAGA,SAAgB,oBAAoB,aAAgC,kBAA0B;CAC5F,MAAM,gBAAgB,YAAY,QAAQC,QAAAA,QAAG,QAAQ;CACrD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBACbC,UAAAA,QAAK,QAAQ,aAAa,IAC1BC,cAAAA,6BAA6B,kBAAkB,aAAa;CAChE,MAAM,WAAsB;EAC1B;GAAE,OAAO;GAAe,UAAU,aAAA,GAAYC,4BAAAA,eAAAA,CAAe,UAAU,aAAa,CAAC;EAAE;EACvF;GAAE,OAAO;GAAc,UAAU,aAAA,GAAYC,gCAAAA,qBAAAA,CAAqB,UAAU,aAAa,CAAC;EAAE;EAC5F;GAAE,OAAO;GAAgB,UAAU,aAAA,GAAYC,6BAAAA,YAAAA,CAAY,UAAU,aAAa,CAAC;EAAE;EACrF;GAAE,OAAO;GAAiB,UAAU,aAAA,GAAYC,8BAAAA,aAAAA,CAAa,UAAU,aAAa,CAAC;EAAE;CACzF;CACA,MAAM,UAAU,SAAS,MAAM,YAAY,QAAQ,SAAS,SAAS,CAAC,IAAI,CAAC,YAAY,WAAW,IAAI,CAAC;CACvG,IAAI,QAAQ,WAAW,GACrB,IAAI;EACF,MAAM,YAAYC,gBAAAA,cAAc,UAAU,eAAe,WAAW;EACpE,SAAS,KACP;GAAE,OAAO;GAAY,UAAU,UAAU;EAAS,GAClD;GAAE,OAAO;GAAa,UAAU,UAAU;EAAI,CAChD;CACF,SAAS,OAAO;EACd,SAAS,KAAK;GAAE,OAAO;GAAgB,UAAU,CAAC,UAAU,KAAK,CAAC;EAAE,CAAC;CACvE;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA,UAAU,SAAS,QAAQ,OAAO,YAAY,QAAQ,QAAQ,SAAS,QAAQ,CAAC;CAClF;AACF;;AAEA,IAAa,gBAAb,MAA2B;CACzB,OAAgB;CAEhB,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,QACE,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;EACR,OAAO,UAAU,MAAM,aAAa,kBAAkB,MAAM;CAC9D;AACF"}
1
+ {"version":3,"file":"index.cjs","names":["wantsHelp","doctorHelp","os","path","resolvePoConfigurationRoot","loadPoConfig","loadMajorModesConfig","loadDomains","loadProfiles","syncReadiness"],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { loadPoConfig } from '@agimon-ai/po-config/config';\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport { loadProfiles } from '@agimon-ai/po-config/profiles';\n\nimport { resolvePoConfigurationRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { syncReadiness } from '../sync';\nimport { doctorHelp } from './help';\n\nconst DOCTOR_COMMAND = 'doctor';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\nconst LABEL_WIDTH = 14;\n\nexport interface DoctorOutput {\n write(chunk: string): void;\n}\n\n/** One checked area and what it found. Empty problems means the section passed. */\ninterface Section {\n label: string;\n problems: string[];\n}\n\nfunction formatSection(section: Section): string {\n const label = section.label.padEnd(LABEL_WIDTH);\n if (section.problems.length === 0) return `${label}ok\\n`;\n return `${label}${section.problems.length === 1 ? 'FAILED' : `${String(section.problems.length)} problem(s)`}\\n${section.problems\n .map((problem) => ` ${problem}\\n`)\n .join('')}`;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Runs one check, turning the throw a strict parser uses into a reported problem. */\nfunction check(run: () => void): string[] {\n try {\n run();\n return [];\n } catch (error) {\n return [messageOf(error)];\n }\n}\n\n/**\n * Reports what is wrong with a Po installation without changing anything.\n *\n * The strict counterpart to `po sync`, which tolerates unknown config keys\n * so a build cannot break over one. Everything `sync --check` reports is\n * reported here too, so this is the one command to run when something is off.\n */\nexport function runDoctor(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n): number {\n if (wantsHelp(args.slice(1))) {\n output.write(doctorHelp());\n return 0;\n }\n const { sections, problems } = collectDoctorReport(environment, currentDirectory);\n for (const section of sections) output.write(formatSection(section));\n if (problems === 0) {\n output.write('\\nno problems found\\n');\n return 0;\n }\n output.write(`\\n${String(problems)} problem(s) found\\n`);\n return 1;\n}\n\n/** The CLI and session diagnostic tool run the same read-only checks. */\nexport function collectDoctorReport(environment: NodeJS.ProcessEnv, currentDirectory: string) {\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolvePoConfigurationRoot(currentDirectory, homeDirectory);\n const sections: Section[] = [\n { label: 'config.yaml', problems: check(() => loadPoConfig(repoRoot, homeDirectory)) },\n { label: 'modes.yaml', problems: check(() => loadMajorModesConfig(repoRoot, homeDirectory)) },\n { label: 'domains.yaml', problems: check(() => loadDomains(repoRoot, homeDirectory)) },\n { label: 'profiles.yaml', problems: check(() => loadProfiles(repoRoot, homeDirectory)) },\n ];\n const skipped = sections.some((section) => section.problems.length > 0) ? ['packages', 'web build'] : [];\n if (skipped.length === 0) {\n try {\n const readiness = syncReadiness(repoRoot, homeDirectory, environment);\n sections.push(\n { label: 'packages', problems: readiness.packages },\n { label: 'web build', problems: readiness.web },\n );\n } catch (error) {\n sections.push({ label: 'installation', problems: [messageOf(error)] });\n }\n }\n return {\n repoRoot,\n homeDirectory,\n sections,\n skipped,\n problems: sections.reduce((total, section) => total + section.problems.length, 0),\n };\n}\n/** Compatibility API. Executables call the command function directly. */\nexport class DoctorCommand {\n readonly name = DOCTOR_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n ): number {\n return runDoctor(args, environment, currentDirectory, output);\n }\n}\n"],"mappings":"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"}
@@ -30,4 +30,5 @@ export declare class DoctorCommand {
30
30
  execute(args: string[], environment?: NodeJS.ProcessEnv, currentDirectory?: string, output?: DoctorOutput): number;
31
31
  }
32
32
  //#endregion
33
+ export {};
33
34
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"mappings":";iBAiBiB;EACf,MAAM;;;UAIE;EACR;EACA;;;;;;;;;wBAgCc,UACd,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ;;wBAiBM,oBAAoB,aAAa,OAAO,YAAY;;;;;;;;qBAiCvD;WACF;EAET,QAAQ;EAIR,QACE,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"mappings":";iBAiBiB;EACf,MAAM;;;UAIE;EACR;EACA;;;;;;;;;wBAgCc,UACd,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ;;wBAiBM,oBAAoB,aAAa,OAAO,YAAY;;;YAAZ;;;;;qBAiC3C;WACF;EAET,QAAQ;EAIR,QACE,gBACA,cAAa,OAAO,YACpB,2BACA,SAAQ"}
@@ -1,11 +1,11 @@
1
1
  import { doctorHelp } from "./help.mjs";
2
- import { resolveDoomConfigurationRoot } from "../../../composition/repository/index.mjs";
2
+ import { resolvePoConfigurationRoot } from "../../../composition/repository/index.mjs";
3
3
  import { wantsHelp } from "../../router.mjs";
4
4
  import { syncReadiness } from "../sync/index.mjs";
5
5
  import path from "node:path";
6
6
  import os from "node:os";
7
7
  import { loadDomains } from "@agimon-ai/po-config/domains";
8
- import { loadDoomConfig } from "@agimon-ai/po-config/config";
8
+ import { loadPoConfig } from "@agimon-ai/po-config/config";
9
9
  import { loadMajorModesConfig } from "@agimon-ai/po-config/majorModes";
10
10
  import { loadProfiles } from "@agimon-ai/po-config/profiles";
11
11
  //#region src/cli/commands/doctor/index.ts
@@ -54,11 +54,11 @@ function runDoctor(args, environment = process.env, currentDirectory = process.c
54
54
  function collectDoctorReport(environment, currentDirectory) {
55
55
  const homeDirectory = environment.HOME ?? os.homedir();
56
56
  const inheritedRoot = environment[HARNESS_ROOT_ENV];
57
- const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);
57
+ const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : resolvePoConfigurationRoot(currentDirectory, homeDirectory);
58
58
  const sections = [
59
59
  {
60
60
  label: "config.yaml",
61
- problems: check(() => loadDoomConfig(repoRoot, homeDirectory))
61
+ problems: check(() => loadPoConfig(repoRoot, homeDirectory))
62
62
  },
63
63
  {
64
64
  label: "modes.yaml",
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { loadDoomConfig } from '@agimon-ai/po-config/config';\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport { loadProfiles } from '@agimon-ai/po-config/profiles';\n\nimport { resolveDoomConfigurationRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { syncReadiness } from '../sync';\nimport { doctorHelp } from './help';\n\nconst DOCTOR_COMMAND = 'doctor';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\nconst LABEL_WIDTH = 14;\n\nexport interface DoctorOutput {\n write(chunk: string): void;\n}\n\n/** One checked area and what it found. Empty problems means the section passed. */\ninterface Section {\n label: string;\n problems: string[];\n}\n\nfunction formatSection(section: Section): string {\n const label = section.label.padEnd(LABEL_WIDTH);\n if (section.problems.length === 0) return `${label}ok\\n`;\n return `${label}${section.problems.length === 1 ? 'FAILED' : `${String(section.problems.length)} problem(s)`}\\n${section.problems\n .map((problem) => ` ${problem}\\n`)\n .join('')}`;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Runs one check, turning the throw a strict parser uses into a reported problem. */\nfunction check(run: () => void): string[] {\n try {\n run();\n return [];\n } catch (error) {\n return [messageOf(error)];\n }\n}\n\n/**\n * Reports what is wrong with a Po installation without changing anything.\n *\n * The strict counterpart to `po sync`, which tolerates unknown config keys\n * so a build cannot break over one. Everything `sync --check` reports is\n * reported here too, so this is the one command to run when something is off.\n */\nexport function runDoctor(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n): number {\n if (wantsHelp(args.slice(1))) {\n output.write(doctorHelp());\n return 0;\n }\n const { sections, problems } = collectDoctorReport(environment, currentDirectory);\n for (const section of sections) output.write(formatSection(section));\n if (problems === 0) {\n output.write('\\nno problems found\\n');\n return 0;\n }\n output.write(`\\n${String(problems)} problem(s) found\\n`);\n return 1;\n}\n\n/** The CLI and session diagnostic tool run the same read-only checks. */\nexport function collectDoctorReport(environment: NodeJS.ProcessEnv, currentDirectory: string) {\n const 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 sections: Section[] = [\n { label: 'config.yaml', problems: check(() => loadDoomConfig(repoRoot, homeDirectory)) },\n { label: 'modes.yaml', problems: check(() => loadMajorModesConfig(repoRoot, homeDirectory)) },\n { label: 'domains.yaml', problems: check(() => loadDomains(repoRoot, homeDirectory)) },\n { label: 'profiles.yaml', problems: check(() => loadProfiles(repoRoot, homeDirectory)) },\n ];\n const skipped = sections.some((section) => section.problems.length > 0) ? ['packages', 'web build'] : [];\n if (skipped.length === 0) {\n try {\n const readiness = syncReadiness(repoRoot, homeDirectory, environment);\n sections.push(\n { label: 'packages', problems: readiness.packages },\n { label: 'web build', problems: readiness.web },\n );\n } catch (error) {\n sections.push({ label: 'installation', problems: [messageOf(error)] });\n }\n }\n return {\n repoRoot,\n homeDirectory,\n sections,\n skipped,\n problems: sections.reduce((total, section) => total + section.problems.length, 0),\n };\n}\n/** Compatibility API. Executables call the command function directly. */\nexport class DoctorCommand {\n readonly name = DOCTOR_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n ): number {\n return runDoctor(args, environment, currentDirectory, output);\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,cAAc;AAYpB,SAAS,cAAc,SAA0B;CAC/C,MAAM,QAAQ,QAAQ,MAAM,OAAO,WAAW;CAC9C,IAAI,QAAQ,SAAS,WAAW,GAAG,OAAO,GAAG,MAAM;CACnD,OAAO,GAAG,QAAQ,QAAQ,SAAS,WAAW,IAAI,WAAW,GAAG,OAAO,QAAQ,SAAS,MAAM,EAAE,aAAa,IAAI,QAAQ,SACtH,KAAK,YAAY,KAAK,QAAQ,GAAG,CAAC,CAClC,KAAK,EAAE;AACZ;AAEA,SAAS,UAAU,OAAwB;CACzC,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;AAGA,SAAS,MAAM,KAA2B;CACxC,IAAI;EACF,IAAI;EACJ,OAAO,CAAC;CACV,SAAS,OAAO;EACd,OAAO,CAAC,UAAU,KAAK,CAAC;CAC1B;AACF;;;;;;;;AASA,SAAgB,UACd,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;CACR,IAAI,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EAC5B,OAAO,MAAM,WAAW,CAAC;EACzB,OAAO;CACT;CACA,MAAM,EAAE,UAAU,aAAa,oBAAoB,aAAa,gBAAgB;CAChF,KAAK,MAAM,WAAW,UAAU,OAAO,MAAM,cAAc,OAAO,CAAC;CACnE,IAAI,aAAa,GAAG;EAClB,OAAO,MAAM,uBAAuB;EACpC,OAAO;CACT;CACA,OAAO,MAAM,KAAK,OAAO,QAAQ,EAAE,oBAAoB;CACvD,OAAO;AACT;;AAGA,SAAgB,oBAAoB,aAAgC,kBAA0B;CAC5F,MAAM,gBAAgB,YAAY,QAAQ,GAAG,QAAQ;CACrD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBACb,KAAK,QAAQ,aAAa,IAC1B,6BAA6B,kBAAkB,aAAa;CAChE,MAAM,WAAsB;EAC1B;GAAE,OAAO;GAAe,UAAU,YAAY,eAAe,UAAU,aAAa,CAAC;EAAE;EACvF;GAAE,OAAO;GAAc,UAAU,YAAY,qBAAqB,UAAU,aAAa,CAAC;EAAE;EAC5F;GAAE,OAAO;GAAgB,UAAU,YAAY,YAAY,UAAU,aAAa,CAAC;EAAE;EACrF;GAAE,OAAO;GAAiB,UAAU,YAAY,aAAa,UAAU,aAAa,CAAC;EAAE;CACzF;CACA,MAAM,UAAU,SAAS,MAAM,YAAY,QAAQ,SAAS,SAAS,CAAC,IAAI,CAAC,YAAY,WAAW,IAAI,CAAC;CACvG,IAAI,QAAQ,WAAW,GACrB,IAAI;EACF,MAAM,YAAY,cAAc,UAAU,eAAe,WAAW;EACpE,SAAS,KACP;GAAE,OAAO;GAAY,UAAU,UAAU;EAAS,GAClD;GAAE,OAAO;GAAa,UAAU,UAAU;EAAI,CAChD;CACF,SAAS,OAAO;EACd,SAAS,KAAK;GAAE,OAAO;GAAgB,UAAU,CAAC,UAAU,KAAK,CAAC;EAAE,CAAC;CACvE;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA,UAAU,SAAS,QAAQ,OAAO,YAAY,QAAQ,QAAQ,SAAS,QAAQ,CAAC;CAClF;AACF;;AAEA,IAAa,gBAAb,MAA2B;CACzB,OAAgB;CAEhB,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,QACE,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;EACR,OAAO,UAAU,MAAM,aAAa,kBAAkB,MAAM;CAC9D;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/doctor/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { loadPoConfig } from '@agimon-ai/po-config/config';\nimport { loadDomains } from '@agimon-ai/po-config/domains';\nimport { loadMajorModesConfig } from '@agimon-ai/po-config/majorModes';\nimport { loadProfiles } from '@agimon-ai/po-config/profiles';\n\nimport { resolvePoConfigurationRoot } from '../../../composition/repository';\nimport { wantsHelp } from '../../router';\nimport { syncReadiness } from '../sync';\nimport { doctorHelp } from './help';\n\nconst DOCTOR_COMMAND = 'doctor';\nconst HARNESS_ROOT_ENV = 'PO_ROOT';\nconst LABEL_WIDTH = 14;\n\nexport interface DoctorOutput {\n write(chunk: string): void;\n}\n\n/** One checked area and what it found. Empty problems means the section passed. */\ninterface Section {\n label: string;\n problems: string[];\n}\n\nfunction formatSection(section: Section): string {\n const label = section.label.padEnd(LABEL_WIDTH);\n if (section.problems.length === 0) return `${label}ok\\n`;\n return `${label}${section.problems.length === 1 ? 'FAILED' : `${String(section.problems.length)} problem(s)`}\\n${section.problems\n .map((problem) => ` ${problem}\\n`)\n .join('')}`;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Runs one check, turning the throw a strict parser uses into a reported problem. */\nfunction check(run: () => void): string[] {\n try {\n run();\n return [];\n } catch (error) {\n return [messageOf(error)];\n }\n}\n\n/**\n * Reports what is wrong with a Po installation without changing anything.\n *\n * The strict counterpart to `po sync`, which tolerates unknown config keys\n * so a build cannot break over one. Everything `sync --check` reports is\n * reported here too, so this is the one command to run when something is off.\n */\nexport function runDoctor(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n): number {\n if (wantsHelp(args.slice(1))) {\n output.write(doctorHelp());\n return 0;\n }\n const { sections, problems } = collectDoctorReport(environment, currentDirectory);\n for (const section of sections) output.write(formatSection(section));\n if (problems === 0) {\n output.write('\\nno problems found\\n');\n return 0;\n }\n output.write(`\\n${String(problems)} problem(s) found\\n`);\n return 1;\n}\n\n/** The CLI and session diagnostic tool run the same read-only checks. */\nexport function collectDoctorReport(environment: NodeJS.ProcessEnv, currentDirectory: string) {\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolvePoConfigurationRoot(currentDirectory, homeDirectory);\n const sections: Section[] = [\n { label: 'config.yaml', problems: check(() => loadPoConfig(repoRoot, homeDirectory)) },\n { label: 'modes.yaml', problems: check(() => loadMajorModesConfig(repoRoot, homeDirectory)) },\n { label: 'domains.yaml', problems: check(() => loadDomains(repoRoot, homeDirectory)) },\n { label: 'profiles.yaml', problems: check(() => loadProfiles(repoRoot, homeDirectory)) },\n ];\n const skipped = sections.some((section) => section.problems.length > 0) ? ['packages', 'web build'] : [];\n if (skipped.length === 0) {\n try {\n const readiness = syncReadiness(repoRoot, homeDirectory, environment);\n sections.push(\n { label: 'packages', problems: readiness.packages },\n { label: 'web build', problems: readiness.web },\n );\n } catch (error) {\n sections.push({ label: 'installation', problems: [messageOf(error)] });\n }\n }\n return {\n repoRoot,\n homeDirectory,\n sections,\n skipped,\n problems: sections.reduce((total, section) => total + section.problems.length, 0),\n };\n}\n/** Compatibility API. Executables call the command function directly. */\nexport class DoctorCommand {\n readonly name = DOCTOR_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: DoctorOutput = process.stdout,\n ): number {\n return runDoctor(args, environment, currentDirectory, output);\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,cAAc;AAYpB,SAAS,cAAc,SAA0B;CAC/C,MAAM,QAAQ,QAAQ,MAAM,OAAO,WAAW;CAC9C,IAAI,QAAQ,SAAS,WAAW,GAAG,OAAO,GAAG,MAAM;CACnD,OAAO,GAAG,QAAQ,QAAQ,SAAS,WAAW,IAAI,WAAW,GAAG,OAAO,QAAQ,SAAS,MAAM,EAAE,aAAa,IAAI,QAAQ,SACtH,KAAK,YAAY,KAAK,QAAQ,GAAG,CAAC,CAClC,KAAK,EAAE;AACZ;AAEA,SAAS,UAAU,OAAwB;CACzC,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;AAGA,SAAS,MAAM,KAA2B;CACxC,IAAI;EACF,IAAI;EACJ,OAAO,CAAC;CACV,SAAS,OAAO;EACd,OAAO,CAAC,UAAU,KAAK,CAAC;CAC1B;AACF;;;;;;;;AASA,SAAgB,UACd,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;CACR,IAAI,UAAU,KAAK,MAAM,CAAC,CAAC,GAAG;EAC5B,OAAO,MAAM,WAAW,CAAC;EACzB,OAAO;CACT;CACA,MAAM,EAAE,UAAU,aAAa,oBAAoB,aAAa,gBAAgB;CAChF,KAAK,MAAM,WAAW,UAAU,OAAO,MAAM,cAAc,OAAO,CAAC;CACnE,IAAI,aAAa,GAAG;EAClB,OAAO,MAAM,uBAAuB;EACpC,OAAO;CACT;CACA,OAAO,MAAM,KAAK,OAAO,QAAQ,EAAE,oBAAoB;CACvD,OAAO;AACT;;AAGA,SAAgB,oBAAoB,aAAgC,kBAA0B;CAC5F,MAAM,gBAAgB,YAAY,QAAQ,GAAG,QAAQ;CACrD,MAAM,gBAAgB,YAAY;CAClC,MAAM,WAAW,gBACb,KAAK,QAAQ,aAAa,IAC1B,2BAA2B,kBAAkB,aAAa;CAC9D,MAAM,WAAsB;EAC1B;GAAE,OAAO;GAAe,UAAU,YAAY,aAAa,UAAU,aAAa,CAAC;EAAE;EACrF;GAAE,OAAO;GAAc,UAAU,YAAY,qBAAqB,UAAU,aAAa,CAAC;EAAE;EAC5F;GAAE,OAAO;GAAgB,UAAU,YAAY,YAAY,UAAU,aAAa,CAAC;EAAE;EACrF;GAAE,OAAO;GAAiB,UAAU,YAAY,aAAa,UAAU,aAAa,CAAC;EAAE;CACzF;CACA,MAAM,UAAU,SAAS,MAAM,YAAY,QAAQ,SAAS,SAAS,CAAC,IAAI,CAAC,YAAY,WAAW,IAAI,CAAC;CACvG,IAAI,QAAQ,WAAW,GACrB,IAAI;EACF,MAAM,YAAY,cAAc,UAAU,eAAe,WAAW;EACpE,SAAS,KACP;GAAE,OAAO;GAAY,UAAU,UAAU;EAAS,GAClD;GAAE,OAAO;GAAa,UAAU,UAAU;EAAI,CAChD;CACF,SAAS,OAAO;EACd,SAAS,KAAK;GAAE,OAAO;GAAgB,UAAU,CAAC,UAAU,KAAK,CAAC;EAAE,CAAC;CACvE;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA,UAAU,SAAS,QAAQ,OAAO,YAAY,QAAQ,QAAQ,SAAS,QAAQ,CAAC;CAClF;AACF;;AAEA,IAAa,gBAAb,MAA2B;CACzB,OAAgB;CAEhB,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,QACE,MACA,cAAiC,QAAQ,KACzC,mBAAmB,QAAQ,IAAI,GAC/B,SAAuB,QAAQ,QACvB;EACR,OAAO,UAAU,MAAM,aAAa,kBAAkB,MAAM;CAC9D;AACF"}
@@ -6,6 +6,7 @@ let node_path = require("node:path");
6
6
  node_path = require_runtime.__toESM(node_path, 1);
7
7
  let _agimon_ai_po_config = require("@agimon-ai/po-config");
8
8
  let _agimon_ai_po_core_mcpSchemaCost = require("@agimon-ai/po-core/mcpSchemaCost");
9
+ let _agimon_ai_po_core_nodePlatform = require("@agimon-ai/po-core/nodePlatform");
9
10
  let _agimon_ai_po_skill_catalog = require("@agimon-ai/po-skill/catalog");
10
11
  //#region src/cli/commands/explain/index.ts
11
12
  function readMcpServers(configPath) {
@@ -86,13 +87,14 @@ async function costExplain(context) {
86
87
  try {
87
88
  const [catalog, countTokens] = await Promise.all([(0, _agimon_ai_po_skill_catalog.buildSkillCatalog)({
88
89
  repoRoot: options.repoRoot,
90
+ fs: (0, _agimon_ai_po_core_nodePlatform.createNodePlatform)().env(options.repoRoot),
89
91
  activeSkillDirectories: resources.skillDirectories,
90
92
  extensionSources: []
91
93
  }), (0, _agimon_ai_po_skill_catalog.counter)()]);
92
94
  const persona = context.personaDirectory ? (0, _agimon_ai_po_config.buildPersonaPrompt)(context.personaRoot ?? options.repoRoot, context.personaDirectory) : void 0;
93
95
  const mcp = resources.mcpConfigPath ? await (0, _agimon_ai_po_core_mcpSchemaCost.priceMcpToolSchemas)({
94
96
  configPath: resources.mcpConfigPath,
95
- homeDoomDirectory: (0, _agimon_ai_po_config.globalDoomConfigDirectory)(),
97
+ homePoDirectory: (0, _agimon_ai_po_config.globalPoConfigDirectory)(),
96
98
  cwd: options.repoRoot,
97
99
  environment: context.environment,
98
100
  countTokens
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["fs","path","buildSkillCatalog","counter","buildPersonaPrompt","priceMcpToolSchemas","globalDoomConfigDirectory","BaseCommand"],"sources":["../../../../../src/cli/commands/explain/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { buildPersonaPrompt, globalDoomConfigDirectory } from '@agimon-ai/po-config';\nimport { type McpServerCost, priceMcpToolSchemas } from '@agimon-ai/po-core/mcpSchemaCost';\nimport { buildSkillCatalog, counter } from '@agimon-ai/po-skill/catalog';\n\nimport type { HarnessContext } from '../../../builders/cli/harnessContext';\nimport type { HarnessOptions } from '../../../composition/types/harness';\nimport { BaseCommand } from '../baseCommand';\n\n/**\n * What the selection costs before the first prompt, in tokens.\n *\n * Every figure is an estimate of what the provider will be sent, not a billed\n * total: skills are counted from files on disk and MCP tools from the schemas\n * their servers advertise, both with the same tokenizer.\n */\nexport interface MatrixCost {\n /** The always-on skill block Pi puts in the system prompt. */\n skillPromptTokens: number;\n /** Skill bodies on disk, read only when a skill is invoked. */\n skillBodyTokens: number;\n /** The persona prompt, when a profile selected one. */\n personaTokens: number;\n /** Always-on tool schemas, per configured MCP server. */\n mcpServers: McpServerCost[];\n mcpToolTokens: number;\n}\n\nexport interface MatrixExplanation {\n majorMode: string;\n profile?: string;\n persona?: string;\n domains: string[];\n plugins: string[];\n layers: string[];\n hookGroups: string[];\n hooksEnabled: boolean;\n skillDirectories: string[];\n skillCount: number;\n agentCount: number;\n agentDirectories: string[];\n mcpConfigPath?: string;\n mcpServers: string[];\n mcpProxyUpstreams?: string[];\n mcpFiltered: boolean;\n cost?: MatrixCost;\n}\n\nfunction readMcpServers(configPath: string): Record<string, unknown> {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as { mcpServers?: Record<string, unknown> };\n return config.mcpServers ?? {};\n}\n\n/**\n * Renders the resolved matrix for --explain. Composition spans three config\n * files, so this answers \"why is that loaded\" in one command instead of a\n * manual trace through domains, major modes, and plugin subsets.\n */\nexport function explainMatrix(explanation: MatrixExplanation): string {\n const section = (label: string, values: string[], empty = '(none)'): string =>\n `${label}:\\n${values.length === 0 ? ` ${empty}` : values.map((value) => ` ${value}`).join('\\n')}\\n`;\n\n return [\n `po resolved matrix\\n\\n`,\n `major mode: ${explanation.majorMode}\\n\\n`,\n section('profile', explanation.profile ? [explanation.profile] : [], '(none)'),\n '\\n',\n section('persona', explanation.persona ? [explanation.persona] : [], '(none)'),\n '\\n',\n section('domains (content)', explanation.domains),\n '\\n',\n section('layers (behavior, from the major mode)', explanation.layers, 'core only'),\n '\\n',\n section(\n 'hook groups from layers',\n explanation.hookGroups,\n explanation.hooksEnabled ? '(core groups only)' : '(hooks disabled)',\n ),\n '\\n',\n section(\n 'plugins',\n explanation.plugins.map((directory) => path.basename(directory)),\n ),\n '\\n',\n section(\n 'skill paths',\n explanation.skillDirectories.map((directory) => path.relative(process.cwd(), directory)),\n ),\n '\\n',\n section(\n explanation.mcpFiltered ? 'mcp servers (filtered by domain allowlist)' : 'mcp servers (unfiltered)',\n explanation.mcpServers,\n '(mcp disabled)',\n ),\n '\\n',\n explanation.mcpProxyUpstreams\n ? section('mcp proxy upstreams (filtered)', explanation.mcpProxyUpstreams)\n : 'mcp proxy upstreams:\\n (unfiltered, every upstream in mcp-config.yaml)\\n',\n '\\n',\n `skills: ${explanation.skillCount} (from ${explanation.skillDirectories.length} paths)\\n`,\n `agents: ${explanation.agentCount}\\n`,\n `mcp config: ${explanation.mcpConfigPath ?? '(disabled)'}\\n`,\n explanation.cost ? renderCost(explanation.cost) : '',\n ].join('');\n}\n\nconst TOKEN_COLUMN = 9;\n\nfunction tokenLine(label: string, tokens: number, note = ''): string {\n const row = ` ${label.padEnd(16)}${tokens.toLocaleString('en-US').padStart(TOKEN_COLUMN)}`;\n return `${note ? `${row} ${note}` : row}\\n`;\n}\n\n/**\n * The bill, rendered last so the sections above keep their order.\n *\n * Skill and persona figures are derived from files on disk and MCP figures\n * from a cached handshake, so two runs of the same selection print the same\n * numbers and a reader can reproduce them without trusting this output.\n */\nfunction renderCost(cost: MatrixCost): string {\n const startup = cost.skillPromptTokens + cost.personaTokens + cost.mcpToolTokens;\n const unpriced = cost.mcpServers.filter((server) => server.unavailable);\n return [\n '\\ncontext cost (tokens)\\n',\n tokenLine('skills prompt', cost.skillPromptTokens, 'always on'),\n tokenLine('persona', cost.personaTokens, 'always on'),\n tokenLine('mcp tools', cost.mcpToolTokens, mcpNote(cost.mcpServers)),\n tokenLine('startup total', startup),\n tokenLine('skill bodies', cost.skillBodyTokens, 'read on demand'),\n ...cost.mcpServers.filter((server) => !server.unavailable).map(serverLine),\n unpriced.length > 0\n ? `\\n Not priced: ${unpriced.map((server) => `${server.name} (${server.unavailable})`).join(', ')}\\n`\n : '',\n '\\n Excludes skills contributed by extensions, which register after startup.\\n',\n ].join('');\n}\n\nfunction mcpNote(servers: McpServerCost[]): string {\n const priced = servers.filter((server) => !server.unavailable);\n if (priced.length === 0) return 'always on';\n const tools = priced.reduce((total, server) => total + server.toolCount, 0);\n return `always on, ${tools} tools from ${priced.length} server${priced.length === 1 ? '' : 's'}`;\n}\n\nfunction serverLine(server: McpServerCost): string {\n return tokenLine(` ${server.name}`, server.tokens, server.cached ? 'cached' : 'measured now');\n}\n\n/** Prints the fully resolved matrix instead of launching Pi. */\nasync function costExplain(context: HarnessContext): Promise<MatrixCost | undefined> {\n const { options, resources } = context;\n try {\n const [catalog, countTokens] = await Promise.all([\n buildSkillCatalog({\n repoRoot: options.repoRoot,\n activeSkillDirectories: resources.skillDirectories,\n extensionSources: [],\n }),\n counter(),\n ]);\n const persona = context.personaDirectory\n ? buildPersonaPrompt(context.personaRoot ?? options.repoRoot, context.personaDirectory)\n : undefined;\n const mcp = resources.mcpConfigPath\n ? await priceMcpToolSchemas({\n configPath: resources.mcpConfigPath,\n homeDoomDirectory: globalDoomConfigDirectory(),\n cwd: options.repoRoot,\n environment: context.environment,\n countTokens,\n })\n : { servers: [], totalTokens: 0 };\n return {\n skillPromptTokens: catalog.promptTokens,\n skillBodyTokens: catalog.bodyTokens,\n personaTokens: persona ? countTokens(persona) : 0,\n mcpServers: mcp.servers,\n mcpToolTokens: mcp.totalTokens,\n };\n } catch (error) {\n // Pricing reads the skill files, so an unreadable one must not take the\n // whole explanation down: the resolved matrix is the point, the bill is\n // the extra. Reported rather than swallowed.\n const detail = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[po] ${'explain'}: could not price the selection: ${detail}\\n`);\n return undefined;\n }\n}\n\nexport async function runExplain(context: HarnessContext): Promise<number> {\n const { options, resources, plugins, mcpAllowlist } = context;\n const cost = await costExplain(context);\n\n process.stdout.write(\n explainMatrix({\n cost,\n majorMode: options.majorMode,\n profile: context.profile,\n persona: context.personaDirectory,\n domains: options.domains,\n plugins: plugins.map((entry) => entry.directory),\n layers: context.selectedLayers,\n hookGroups: context.hookGroups,\n hooksEnabled: options.hooks,\n skillDirectories: resources.skillDirectories,\n skillCount: resources.skillCount,\n agentCount: resources.agentCount,\n agentDirectories: resources.agentDirectories,\n mcpConfigPath: resources.mcpConfigPath,\n // Read back from the generated config so this reports what Pi will\n // actually load, not what the allowlist intended.\n mcpServers: resources.mcpConfigPath ? Object.keys(readMcpServers(resources.mcpConfigPath)) : [],\n mcpProxyUpstreams: mcpAllowlist?.proxy,\n mcpFiltered: Boolean(mcpAllowlist),\n }),\n );\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class ExplainCommand extends BaseCommand {\n readonly name = 'explain';\n\n matches(options: HarnessOptions): boolean {\n return options.explain;\n }\n\n async execute(context: HarnessContext): Promise<number> {\n return runExplain(context);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["fs","path","buildSkillCatalog","createNodePlatform","counter","buildPersonaPrompt","priceMcpToolSchemas","globalPoConfigDirectory","BaseCommand"],"sources":["../../../../../src/cli/commands/explain/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { buildPersonaPrompt, globalPoConfigDirectory } from '@agimon-ai/po-config';\nimport { type McpServerCost, priceMcpToolSchemas } from '@agimon-ai/po-core/mcpSchemaCost';\nimport { createNodePlatform } from '@agimon-ai/po-core/nodePlatform';\nimport { buildSkillCatalog, counter } from '@agimon-ai/po-skill/catalog';\n\nimport type { HarnessContext } from '../../../builders/cli/harnessContext';\nimport type { HarnessOptions } from '../../../composition/types/harness';\nimport { BaseCommand } from '../baseCommand';\n\n/**\n * What the selection costs before the first prompt, in tokens.\n *\n * Every figure is an estimate of what the provider will be sent, not a billed\n * total: skills are counted from files on disk and MCP tools from the schemas\n * their servers advertise, both with the same tokenizer.\n */\nexport interface MatrixCost {\n /** The always-on skill block Pi puts in the system prompt. */\n skillPromptTokens: number;\n /** Skill bodies on disk, read only when a skill is invoked. */\n skillBodyTokens: number;\n /** The persona prompt, when a profile selected one. */\n personaTokens: number;\n /** Always-on tool schemas, per configured MCP server. */\n mcpServers: McpServerCost[];\n mcpToolTokens: number;\n}\n\nexport interface MatrixExplanation {\n majorMode: string;\n profile?: string;\n persona?: string;\n domains: string[];\n plugins: string[];\n layers: string[];\n hookGroups: string[];\n hooksEnabled: boolean;\n skillDirectories: string[];\n skillCount: number;\n agentCount: number;\n agentDirectories: string[];\n mcpConfigPath?: string;\n mcpServers: string[];\n mcpProxyUpstreams?: string[];\n mcpFiltered: boolean;\n cost?: MatrixCost;\n}\n\nfunction readMcpServers(configPath: string): Record<string, unknown> {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as { mcpServers?: Record<string, unknown> };\n return config.mcpServers ?? {};\n}\n\n/**\n * Renders the resolved matrix for --explain. Composition spans three config\n * files, so this answers \"why is that loaded\" in one command instead of a\n * manual trace through domains, major modes, and plugin subsets.\n */\nexport function explainMatrix(explanation: MatrixExplanation): string {\n const section = (label: string, values: string[], empty = '(none)'): string =>\n `${label}:\\n${values.length === 0 ? ` ${empty}` : values.map((value) => ` ${value}`).join('\\n')}\\n`;\n\n return [\n `po resolved matrix\\n\\n`,\n `major mode: ${explanation.majorMode}\\n\\n`,\n section('profile', explanation.profile ? [explanation.profile] : [], '(none)'),\n '\\n',\n section('persona', explanation.persona ? [explanation.persona] : [], '(none)'),\n '\\n',\n section('domains (content)', explanation.domains),\n '\\n',\n section('layers (behavior, from the major mode)', explanation.layers, 'core only'),\n '\\n',\n section(\n 'hook groups from layers',\n explanation.hookGroups,\n explanation.hooksEnabled ? '(core groups only)' : '(hooks disabled)',\n ),\n '\\n',\n section(\n 'plugins',\n explanation.plugins.map((directory) => path.basename(directory)),\n ),\n '\\n',\n section(\n 'skill paths',\n explanation.skillDirectories.map((directory) => path.relative(process.cwd(), directory)),\n ),\n '\\n',\n section(\n explanation.mcpFiltered ? 'mcp servers (filtered by domain allowlist)' : 'mcp servers (unfiltered)',\n explanation.mcpServers,\n '(mcp disabled)',\n ),\n '\\n',\n explanation.mcpProxyUpstreams\n ? section('mcp proxy upstreams (filtered)', explanation.mcpProxyUpstreams)\n : 'mcp proxy upstreams:\\n (unfiltered, every upstream in mcp-config.yaml)\\n',\n '\\n',\n `skills: ${explanation.skillCount} (from ${explanation.skillDirectories.length} paths)\\n`,\n `agents: ${explanation.agentCount}\\n`,\n `mcp config: ${explanation.mcpConfigPath ?? '(disabled)'}\\n`,\n explanation.cost ? renderCost(explanation.cost) : '',\n ].join('');\n}\n\nconst TOKEN_COLUMN = 9;\n\nfunction tokenLine(label: string, tokens: number, note = ''): string {\n const row = ` ${label.padEnd(16)}${tokens.toLocaleString('en-US').padStart(TOKEN_COLUMN)}`;\n return `${note ? `${row} ${note}` : row}\\n`;\n}\n\n/**\n * The bill, rendered last so the sections above keep their order.\n *\n * Skill and persona figures are derived from files on disk and MCP figures\n * from a cached handshake, so two runs of the same selection print the same\n * numbers and a reader can reproduce them without trusting this output.\n */\nfunction renderCost(cost: MatrixCost): string {\n const startup = cost.skillPromptTokens + cost.personaTokens + cost.mcpToolTokens;\n const unpriced = cost.mcpServers.filter((server) => server.unavailable);\n return [\n '\\ncontext cost (tokens)\\n',\n tokenLine('skills prompt', cost.skillPromptTokens, 'always on'),\n tokenLine('persona', cost.personaTokens, 'always on'),\n tokenLine('mcp tools', cost.mcpToolTokens, mcpNote(cost.mcpServers)),\n tokenLine('startup total', startup),\n tokenLine('skill bodies', cost.skillBodyTokens, 'read on demand'),\n ...cost.mcpServers.filter((server) => !server.unavailable).map(serverLine),\n unpriced.length > 0\n ? `\\n Not priced: ${unpriced.map((server) => `${server.name} (${server.unavailable})`).join(', ')}\\n`\n : '',\n '\\n Excludes skills contributed by extensions, which register after startup.\\n',\n ].join('');\n}\n\nfunction mcpNote(servers: McpServerCost[]): string {\n const priced = servers.filter((server) => !server.unavailable);\n if (priced.length === 0) return 'always on';\n const tools = priced.reduce((total, server) => total + server.toolCount, 0);\n return `always on, ${tools} tools from ${priced.length} server${priced.length === 1 ? '' : 's'}`;\n}\n\nfunction serverLine(server: McpServerCost): string {\n return tokenLine(` ${server.name}`, server.tokens, server.cached ? 'cached' : 'measured now');\n}\n\n/** Prints the fully resolved matrix instead of launching Pi. */\nasync function costExplain(context: HarnessContext): Promise<MatrixCost | undefined> {\n const { options, resources } = context;\n try {\n const [catalog, countTokens] = await Promise.all([\n buildSkillCatalog({\n repoRoot: options.repoRoot,\n fs: createNodePlatform().env(options.repoRoot),\n activeSkillDirectories: resources.skillDirectories,\n extensionSources: [],\n }),\n counter(),\n ]);\n const persona = context.personaDirectory\n ? buildPersonaPrompt(context.personaRoot ?? options.repoRoot, context.personaDirectory)\n : undefined;\n const mcp = resources.mcpConfigPath\n ? await priceMcpToolSchemas({\n configPath: resources.mcpConfigPath,\n homePoDirectory: globalPoConfigDirectory(),\n cwd: options.repoRoot,\n environment: context.environment,\n countTokens,\n })\n : { servers: [], totalTokens: 0 };\n return {\n skillPromptTokens: catalog.promptTokens,\n skillBodyTokens: catalog.bodyTokens,\n personaTokens: persona ? countTokens(persona) : 0,\n mcpServers: mcp.servers,\n mcpToolTokens: mcp.totalTokens,\n };\n } catch (error) {\n // Pricing reads the skill files, so an unreadable one must not take the\n // whole explanation down: the resolved matrix is the point, the bill is\n // the extra. Reported rather than swallowed.\n const detail = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[po] ${'explain'}: could not price the selection: ${detail}\\n`);\n return undefined;\n }\n}\n\nexport async function runExplain(context: HarnessContext): Promise<number> {\n const { options, resources, plugins, mcpAllowlist } = context;\n const cost = await costExplain(context);\n\n process.stdout.write(\n explainMatrix({\n cost,\n majorMode: options.majorMode,\n profile: context.profile,\n persona: context.personaDirectory,\n domains: options.domains,\n plugins: plugins.map((entry) => entry.directory),\n layers: context.selectedLayers,\n hookGroups: context.hookGroups,\n hooksEnabled: options.hooks,\n skillDirectories: resources.skillDirectories,\n skillCount: resources.skillCount,\n agentCount: resources.agentCount,\n agentDirectories: resources.agentDirectories,\n mcpConfigPath: resources.mcpConfigPath,\n // Read back from the generated config so this reports what Pi will\n // actually load, not what the allowlist intended.\n mcpServers: resources.mcpConfigPath ? Object.keys(readMcpServers(resources.mcpConfigPath)) : [],\n mcpProxyUpstreams: mcpAllowlist?.proxy,\n mcpFiltered: Boolean(mcpAllowlist),\n }),\n );\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class ExplainCommand extends BaseCommand {\n readonly name = 'explain';\n\n matches(options: HarnessOptions): boolean {\n return options.explain;\n }\n\n async execute(context: HarnessContext): Promise<number> {\n return runExplain(context);\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/cli/commands/explain/index.ts"],"mappings":";;;;;;;;;;;;iBAkBiB;;EAEf;;EAEA;;EAEA;;EAEA,YAAY;EACZ;;iBAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO;;;;;;;wBAaO,cAAc,aAAa;wBAoIrB,WAAW,SAAS,iBAAiB;;qBA+B9C,uBAAuB;WACzB;EAET,QAAQ,SAAS;EAIX,QAAQ,SAAS,iBAAiB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/cli/commands/explain/index.ts"],"mappings":";;;;;;;;;;;;iBAmBiB;;EAEf;;EAEA;;EAEA;;EAEA,YAAY;EACZ;;iBAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO;;;;;;;wBAaO,cAAc,aAAa;wBAqIrB,WAAW,SAAS,iBAAiB;;qBA+B9C,uBAAuB;WACzB;EAET,QAAQ,SAAS;EAIX,QAAQ,SAAS,iBAAiB"}
@@ -1,8 +1,9 @@
1
1
  import { BaseCommand } from "../baseCommand.mjs";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import { buildPersonaPrompt, globalDoomConfigDirectory } from "@agimon-ai/po-config";
4
+ import { buildPersonaPrompt, globalPoConfigDirectory } from "@agimon-ai/po-config";
5
5
  import { priceMcpToolSchemas } from "@agimon-ai/po-core/mcpSchemaCost";
6
+ import { createNodePlatform } from "@agimon-ai/po-core/nodePlatform";
6
7
  import { buildSkillCatalog, counter } from "@agimon-ai/po-skill/catalog";
7
8
  //#region src/cli/commands/explain/index.ts
8
9
  function readMcpServers(configPath) {
@@ -83,13 +84,14 @@ async function costExplain(context) {
83
84
  try {
84
85
  const [catalog, countTokens] = await Promise.all([buildSkillCatalog({
85
86
  repoRoot: options.repoRoot,
87
+ fs: createNodePlatform().env(options.repoRoot),
86
88
  activeSkillDirectories: resources.skillDirectories,
87
89
  extensionSources: []
88
90
  }), counter()]);
89
91
  const persona = context.personaDirectory ? buildPersonaPrompt(context.personaRoot ?? options.repoRoot, context.personaDirectory) : void 0;
90
92
  const mcp = resources.mcpConfigPath ? await priceMcpToolSchemas({
91
93
  configPath: resources.mcpConfigPath,
92
- homeDoomDirectory: globalDoomConfigDirectory(),
94
+ homePoDirectory: globalPoConfigDirectory(),
93
95
  cwd: options.repoRoot,
94
96
  environment: context.environment,
95
97
  countTokens
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/explain/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { buildPersonaPrompt, globalDoomConfigDirectory } from '@agimon-ai/po-config';\nimport { type McpServerCost, priceMcpToolSchemas } from '@agimon-ai/po-core/mcpSchemaCost';\nimport { buildSkillCatalog, counter } from '@agimon-ai/po-skill/catalog';\n\nimport type { HarnessContext } from '../../../builders/cli/harnessContext';\nimport type { HarnessOptions } from '../../../composition/types/harness';\nimport { BaseCommand } from '../baseCommand';\n\n/**\n * What the selection costs before the first prompt, in tokens.\n *\n * Every figure is an estimate of what the provider will be sent, not a billed\n * total: skills are counted from files on disk and MCP tools from the schemas\n * their servers advertise, both with the same tokenizer.\n */\nexport interface MatrixCost {\n /** The always-on skill block Pi puts in the system prompt. */\n skillPromptTokens: number;\n /** Skill bodies on disk, read only when a skill is invoked. */\n skillBodyTokens: number;\n /** The persona prompt, when a profile selected one. */\n personaTokens: number;\n /** Always-on tool schemas, per configured MCP server. */\n mcpServers: McpServerCost[];\n mcpToolTokens: number;\n}\n\nexport interface MatrixExplanation {\n majorMode: string;\n profile?: string;\n persona?: string;\n domains: string[];\n plugins: string[];\n layers: string[];\n hookGroups: string[];\n hooksEnabled: boolean;\n skillDirectories: string[];\n skillCount: number;\n agentCount: number;\n agentDirectories: string[];\n mcpConfigPath?: string;\n mcpServers: string[];\n mcpProxyUpstreams?: string[];\n mcpFiltered: boolean;\n cost?: MatrixCost;\n}\n\nfunction readMcpServers(configPath: string): Record<string, unknown> {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as { mcpServers?: Record<string, unknown> };\n return config.mcpServers ?? {};\n}\n\n/**\n * Renders the resolved matrix for --explain. Composition spans three config\n * files, so this answers \"why is that loaded\" in one command instead of a\n * manual trace through domains, major modes, and plugin subsets.\n */\nexport function explainMatrix(explanation: MatrixExplanation): string {\n const section = (label: string, values: string[], empty = '(none)'): string =>\n `${label}:\\n${values.length === 0 ? ` ${empty}` : values.map((value) => ` ${value}`).join('\\n')}\\n`;\n\n return [\n `po resolved matrix\\n\\n`,\n `major mode: ${explanation.majorMode}\\n\\n`,\n section('profile', explanation.profile ? [explanation.profile] : [], '(none)'),\n '\\n',\n section('persona', explanation.persona ? [explanation.persona] : [], '(none)'),\n '\\n',\n section('domains (content)', explanation.domains),\n '\\n',\n section('layers (behavior, from the major mode)', explanation.layers, 'core only'),\n '\\n',\n section(\n 'hook groups from layers',\n explanation.hookGroups,\n explanation.hooksEnabled ? '(core groups only)' : '(hooks disabled)',\n ),\n '\\n',\n section(\n 'plugins',\n explanation.plugins.map((directory) => path.basename(directory)),\n ),\n '\\n',\n section(\n 'skill paths',\n explanation.skillDirectories.map((directory) => path.relative(process.cwd(), directory)),\n ),\n '\\n',\n section(\n explanation.mcpFiltered ? 'mcp servers (filtered by domain allowlist)' : 'mcp servers (unfiltered)',\n explanation.mcpServers,\n '(mcp disabled)',\n ),\n '\\n',\n explanation.mcpProxyUpstreams\n ? section('mcp proxy upstreams (filtered)', explanation.mcpProxyUpstreams)\n : 'mcp proxy upstreams:\\n (unfiltered, every upstream in mcp-config.yaml)\\n',\n '\\n',\n `skills: ${explanation.skillCount} (from ${explanation.skillDirectories.length} paths)\\n`,\n `agents: ${explanation.agentCount}\\n`,\n `mcp config: ${explanation.mcpConfigPath ?? '(disabled)'}\\n`,\n explanation.cost ? renderCost(explanation.cost) : '',\n ].join('');\n}\n\nconst TOKEN_COLUMN = 9;\n\nfunction tokenLine(label: string, tokens: number, note = ''): string {\n const row = ` ${label.padEnd(16)}${tokens.toLocaleString('en-US').padStart(TOKEN_COLUMN)}`;\n return `${note ? `${row} ${note}` : row}\\n`;\n}\n\n/**\n * The bill, rendered last so the sections above keep their order.\n *\n * Skill and persona figures are derived from files on disk and MCP figures\n * from a cached handshake, so two runs of the same selection print the same\n * numbers and a reader can reproduce them without trusting this output.\n */\nfunction renderCost(cost: MatrixCost): string {\n const startup = cost.skillPromptTokens + cost.personaTokens + cost.mcpToolTokens;\n const unpriced = cost.mcpServers.filter((server) => server.unavailable);\n return [\n '\\ncontext cost (tokens)\\n',\n tokenLine('skills prompt', cost.skillPromptTokens, 'always on'),\n tokenLine('persona', cost.personaTokens, 'always on'),\n tokenLine('mcp tools', cost.mcpToolTokens, mcpNote(cost.mcpServers)),\n tokenLine('startup total', startup),\n tokenLine('skill bodies', cost.skillBodyTokens, 'read on demand'),\n ...cost.mcpServers.filter((server) => !server.unavailable).map(serverLine),\n unpriced.length > 0\n ? `\\n Not priced: ${unpriced.map((server) => `${server.name} (${server.unavailable})`).join(', ')}\\n`\n : '',\n '\\n Excludes skills contributed by extensions, which register after startup.\\n',\n ].join('');\n}\n\nfunction mcpNote(servers: McpServerCost[]): string {\n const priced = servers.filter((server) => !server.unavailable);\n if (priced.length === 0) return 'always on';\n const tools = priced.reduce((total, server) => total + server.toolCount, 0);\n return `always on, ${tools} tools from ${priced.length} server${priced.length === 1 ? '' : 's'}`;\n}\n\nfunction serverLine(server: McpServerCost): string {\n return tokenLine(` ${server.name}`, server.tokens, server.cached ? 'cached' : 'measured now');\n}\n\n/** Prints the fully resolved matrix instead of launching Pi. */\nasync function costExplain(context: HarnessContext): Promise<MatrixCost | undefined> {\n const { options, resources } = context;\n try {\n const [catalog, countTokens] = await Promise.all([\n buildSkillCatalog({\n repoRoot: options.repoRoot,\n activeSkillDirectories: resources.skillDirectories,\n extensionSources: [],\n }),\n counter(),\n ]);\n const persona = context.personaDirectory\n ? buildPersonaPrompt(context.personaRoot ?? options.repoRoot, context.personaDirectory)\n : undefined;\n const mcp = resources.mcpConfigPath\n ? await priceMcpToolSchemas({\n configPath: resources.mcpConfigPath,\n homeDoomDirectory: globalDoomConfigDirectory(),\n cwd: options.repoRoot,\n environment: context.environment,\n countTokens,\n })\n : { servers: [], totalTokens: 0 };\n return {\n skillPromptTokens: catalog.promptTokens,\n skillBodyTokens: catalog.bodyTokens,\n personaTokens: persona ? countTokens(persona) : 0,\n mcpServers: mcp.servers,\n mcpToolTokens: mcp.totalTokens,\n };\n } catch (error) {\n // Pricing reads the skill files, so an unreadable one must not take the\n // whole explanation down: the resolved matrix is the point, the bill is\n // the extra. Reported rather than swallowed.\n const detail = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[po] ${'explain'}: could not price the selection: ${detail}\\n`);\n return undefined;\n }\n}\n\nexport async function runExplain(context: HarnessContext): Promise<number> {\n const { options, resources, plugins, mcpAllowlist } = context;\n const cost = await costExplain(context);\n\n process.stdout.write(\n explainMatrix({\n cost,\n majorMode: options.majorMode,\n profile: context.profile,\n persona: context.personaDirectory,\n domains: options.domains,\n plugins: plugins.map((entry) => entry.directory),\n layers: context.selectedLayers,\n hookGroups: context.hookGroups,\n hooksEnabled: options.hooks,\n skillDirectories: resources.skillDirectories,\n skillCount: resources.skillCount,\n agentCount: resources.agentCount,\n agentDirectories: resources.agentDirectories,\n mcpConfigPath: resources.mcpConfigPath,\n // Read back from the generated config so this reports what Pi will\n // actually load, not what the allowlist intended.\n mcpServers: resources.mcpConfigPath ? Object.keys(readMcpServers(resources.mcpConfigPath)) : [],\n mcpProxyUpstreams: mcpAllowlist?.proxy,\n mcpFiltered: Boolean(mcpAllowlist),\n }),\n );\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class ExplainCommand extends BaseCommand {\n readonly name = 'explain';\n\n matches(options: HarnessOptions): boolean {\n return options.explain;\n }\n\n async execute(context: HarnessContext): Promise<number> {\n return runExplain(context);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/cli/commands/explain/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { buildPersonaPrompt, globalPoConfigDirectory } from '@agimon-ai/po-config';\nimport { type McpServerCost, priceMcpToolSchemas } from '@agimon-ai/po-core/mcpSchemaCost';\nimport { createNodePlatform } from '@agimon-ai/po-core/nodePlatform';\nimport { buildSkillCatalog, counter } from '@agimon-ai/po-skill/catalog';\n\nimport type { HarnessContext } from '../../../builders/cli/harnessContext';\nimport type { HarnessOptions } from '../../../composition/types/harness';\nimport { BaseCommand } from '../baseCommand';\n\n/**\n * What the selection costs before the first prompt, in tokens.\n *\n * Every figure is an estimate of what the provider will be sent, not a billed\n * total: skills are counted from files on disk and MCP tools from the schemas\n * their servers advertise, both with the same tokenizer.\n */\nexport interface MatrixCost {\n /** The always-on skill block Pi puts in the system prompt. */\n skillPromptTokens: number;\n /** Skill bodies on disk, read only when a skill is invoked. */\n skillBodyTokens: number;\n /** The persona prompt, when a profile selected one. */\n personaTokens: number;\n /** Always-on tool schemas, per configured MCP server. */\n mcpServers: McpServerCost[];\n mcpToolTokens: number;\n}\n\nexport interface MatrixExplanation {\n majorMode: string;\n profile?: string;\n persona?: string;\n domains: string[];\n plugins: string[];\n layers: string[];\n hookGroups: string[];\n hooksEnabled: boolean;\n skillDirectories: string[];\n skillCount: number;\n agentCount: number;\n agentDirectories: string[];\n mcpConfigPath?: string;\n mcpServers: string[];\n mcpProxyUpstreams?: string[];\n mcpFiltered: boolean;\n cost?: MatrixCost;\n}\n\nfunction readMcpServers(configPath: string): Record<string, unknown> {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as { mcpServers?: Record<string, unknown> };\n return config.mcpServers ?? {};\n}\n\n/**\n * Renders the resolved matrix for --explain. Composition spans three config\n * files, so this answers \"why is that loaded\" in one command instead of a\n * manual trace through domains, major modes, and plugin subsets.\n */\nexport function explainMatrix(explanation: MatrixExplanation): string {\n const section = (label: string, values: string[], empty = '(none)'): string =>\n `${label}:\\n${values.length === 0 ? ` ${empty}` : values.map((value) => ` ${value}`).join('\\n')}\\n`;\n\n return [\n `po resolved matrix\\n\\n`,\n `major mode: ${explanation.majorMode}\\n\\n`,\n section('profile', explanation.profile ? [explanation.profile] : [], '(none)'),\n '\\n',\n section('persona', explanation.persona ? [explanation.persona] : [], '(none)'),\n '\\n',\n section('domains (content)', explanation.domains),\n '\\n',\n section('layers (behavior, from the major mode)', explanation.layers, 'core only'),\n '\\n',\n section(\n 'hook groups from layers',\n explanation.hookGroups,\n explanation.hooksEnabled ? '(core groups only)' : '(hooks disabled)',\n ),\n '\\n',\n section(\n 'plugins',\n explanation.plugins.map((directory) => path.basename(directory)),\n ),\n '\\n',\n section(\n 'skill paths',\n explanation.skillDirectories.map((directory) => path.relative(process.cwd(), directory)),\n ),\n '\\n',\n section(\n explanation.mcpFiltered ? 'mcp servers (filtered by domain allowlist)' : 'mcp servers (unfiltered)',\n explanation.mcpServers,\n '(mcp disabled)',\n ),\n '\\n',\n explanation.mcpProxyUpstreams\n ? section('mcp proxy upstreams (filtered)', explanation.mcpProxyUpstreams)\n : 'mcp proxy upstreams:\\n (unfiltered, every upstream in mcp-config.yaml)\\n',\n '\\n',\n `skills: ${explanation.skillCount} (from ${explanation.skillDirectories.length} paths)\\n`,\n `agents: ${explanation.agentCount}\\n`,\n `mcp config: ${explanation.mcpConfigPath ?? '(disabled)'}\\n`,\n explanation.cost ? renderCost(explanation.cost) : '',\n ].join('');\n}\n\nconst TOKEN_COLUMN = 9;\n\nfunction tokenLine(label: string, tokens: number, note = ''): string {\n const row = ` ${label.padEnd(16)}${tokens.toLocaleString('en-US').padStart(TOKEN_COLUMN)}`;\n return `${note ? `${row} ${note}` : row}\\n`;\n}\n\n/**\n * The bill, rendered last so the sections above keep their order.\n *\n * Skill and persona figures are derived from files on disk and MCP figures\n * from a cached handshake, so two runs of the same selection print the same\n * numbers and a reader can reproduce them without trusting this output.\n */\nfunction renderCost(cost: MatrixCost): string {\n const startup = cost.skillPromptTokens + cost.personaTokens + cost.mcpToolTokens;\n const unpriced = cost.mcpServers.filter((server) => server.unavailable);\n return [\n '\\ncontext cost (tokens)\\n',\n tokenLine('skills prompt', cost.skillPromptTokens, 'always on'),\n tokenLine('persona', cost.personaTokens, 'always on'),\n tokenLine('mcp tools', cost.mcpToolTokens, mcpNote(cost.mcpServers)),\n tokenLine('startup total', startup),\n tokenLine('skill bodies', cost.skillBodyTokens, 'read on demand'),\n ...cost.mcpServers.filter((server) => !server.unavailable).map(serverLine),\n unpriced.length > 0\n ? `\\n Not priced: ${unpriced.map((server) => `${server.name} (${server.unavailable})`).join(', ')}\\n`\n : '',\n '\\n Excludes skills contributed by extensions, which register after startup.\\n',\n ].join('');\n}\n\nfunction mcpNote(servers: McpServerCost[]): string {\n const priced = servers.filter((server) => !server.unavailable);\n if (priced.length === 0) return 'always on';\n const tools = priced.reduce((total, server) => total + server.toolCount, 0);\n return `always on, ${tools} tools from ${priced.length} server${priced.length === 1 ? '' : 's'}`;\n}\n\nfunction serverLine(server: McpServerCost): string {\n return tokenLine(` ${server.name}`, server.tokens, server.cached ? 'cached' : 'measured now');\n}\n\n/** Prints the fully resolved matrix instead of launching Pi. */\nasync function costExplain(context: HarnessContext): Promise<MatrixCost | undefined> {\n const { options, resources } = context;\n try {\n const [catalog, countTokens] = await Promise.all([\n buildSkillCatalog({\n repoRoot: options.repoRoot,\n fs: createNodePlatform().env(options.repoRoot),\n activeSkillDirectories: resources.skillDirectories,\n extensionSources: [],\n }),\n counter(),\n ]);\n const persona = context.personaDirectory\n ? buildPersonaPrompt(context.personaRoot ?? options.repoRoot, context.personaDirectory)\n : undefined;\n const mcp = resources.mcpConfigPath\n ? await priceMcpToolSchemas({\n configPath: resources.mcpConfigPath,\n homePoDirectory: globalPoConfigDirectory(),\n cwd: options.repoRoot,\n environment: context.environment,\n countTokens,\n })\n : { servers: [], totalTokens: 0 };\n return {\n skillPromptTokens: catalog.promptTokens,\n skillBodyTokens: catalog.bodyTokens,\n personaTokens: persona ? countTokens(persona) : 0,\n mcpServers: mcp.servers,\n mcpToolTokens: mcp.totalTokens,\n };\n } catch (error) {\n // Pricing reads the skill files, so an unreadable one must not take the\n // whole explanation down: the resolved matrix is the point, the bill is\n // the extra. Reported rather than swallowed.\n const detail = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[po] ${'explain'}: could not price the selection: ${detail}\\n`);\n return undefined;\n }\n}\n\nexport async function runExplain(context: HarnessContext): Promise<number> {\n const { options, resources, plugins, mcpAllowlist } = context;\n const cost = await costExplain(context);\n\n process.stdout.write(\n explainMatrix({\n cost,\n majorMode: options.majorMode,\n profile: context.profile,\n persona: context.personaDirectory,\n domains: options.domains,\n plugins: plugins.map((entry) => entry.directory),\n layers: context.selectedLayers,\n hookGroups: context.hookGroups,\n hooksEnabled: options.hooks,\n skillDirectories: resources.skillDirectories,\n skillCount: resources.skillCount,\n agentCount: resources.agentCount,\n agentDirectories: resources.agentDirectories,\n mcpConfigPath: resources.mcpConfigPath,\n // Read back from the generated config so this reports what Pi will\n // actually load, not what the allowlist intended.\n mcpServers: resources.mcpConfigPath ? Object.keys(readMcpServers(resources.mcpConfigPath)) : [],\n mcpProxyUpstreams: mcpAllowlist?.proxy,\n mcpFiltered: Boolean(mcpAllowlist),\n }),\n );\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class ExplainCommand extends BaseCommand {\n readonly name = 'explain';\n\n matches(options: HarnessOptions): boolean {\n return options.explain;\n }\n\n async execute(context: HarnessContext): Promise<number> {\n return runExplain(context);\n }\n}\n"],"mappings":"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"}
@@ -27,11 +27,11 @@ async function runInit(args, homeDirectory = node_os.default.homedir(), output =
27
27
  if (unknown !== void 0) throw new Error(`po init does not accept ${unknown}`);
28
28
  const presenter = new require_presenter.InitPresenter(output, environment);
29
29
  presenter.brand();
30
- const configDirectory = (0, _agimon_ai_po_config.globalDoomConfigDirectory)(homeDirectory);
30
+ const configDirectory = (0, _agimon_ai_po_config.globalPoConfigDirectory)(homeDirectory);
31
31
  presenter.stage(1, SETUP_STAGE_COUNT, "WRITE CONFIGURATION", configDirectory);
32
32
  let configResult;
33
33
  try {
34
- configResult = (0, _agimon_ai_po_config.initializeGlobalDoomConfig)(homeDirectory, { force: flags.includes(FORCE_FLAG) });
34
+ configResult = (0, _agimon_ai_po_config.initializeGlobalPoConfig)(homeDirectory, { force: flags.includes(FORCE_FLAG) });
35
35
  presenter.stageReady("Configuration files are ready.");
36
36
  } catch (error) {
37
37
  presenter.stageFailed("Configuration setup failed.", ["Fix the reported path or permissions, then run po init again."]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["os","wantsHelp","initHelp","InitPresenter","globalDoomConfigDirectory","initializeGlobalDoomConfig","path","removePoPiSettings"],"sources":["../../../../../src/cli/commands/init/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { type GlobalDoomInitResult, globalDoomConfigDirectory, initializeGlobalDoomConfig } from '@agimon-ai/po-config';\nimport { removePoPiSettings } from '@agimon-ai/po-core/piSettings';\n\nimport { wantsHelp } from '../../router';\nimport { initHelp } from './help';\nimport { InitPresenter, type InitOutput } from './presenter';\n\nconst INIT_COMMAND = 'init';\nconst FORCE_FLAG = '--force';\nconst SETUP_STAGE_COUNT = 2;\n\nfunction setupFailure(activity: string, target: string, error: unknown): Error {\n const detail = error instanceof Error ? error.message : String(error);\n return new Error(`po init failed while ${activity} at ${target}: ${detail}`, { cause: error });\n}\n\n/** Handles the repository-independent `po init` command. */\nexport async function runInit(\n args: string[],\n homeDirectory = os.homedir(),\n output: InitOutput = process.stdout,\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<number> {\n const flags = args.slice(1);\n const unknown = flags.find((flag) => flag !== FORCE_FLAG);\n if (wantsHelp(args)) {\n process.stdout.write(initHelp());\n return 0;\n }\n if (unknown !== undefined) throw new Error(`po init does not accept ${unknown}`);\n\n const presenter = new InitPresenter(output, environment);\n presenter.brand();\n\n const configDirectory = globalDoomConfigDirectory(homeDirectory);\n presenter.stage(1, SETUP_STAGE_COUNT, 'WRITE CONFIGURATION', configDirectory);\n let configResult: GlobalDoomInitResult;\n try {\n configResult = initializeGlobalDoomConfig(homeDirectory, { force: flags.includes(FORCE_FLAG) });\n presenter.stageReady('Configuration files are ready.');\n } catch (error) {\n presenter.stageFailed('Configuration setup failed.', [\n 'Fix the reported path or permissions, then run po init again.',\n ]);\n throw setupFailure('writing configuration', configDirectory, error);\n }\n\n // Po no longer registers with Pi; init only removes what earlier versions wrote.\n const agentDirectory = path.join(homeDirectory, '.pi', 'agent');\n presenter.stage(2, SETUP_STAGE_COUNT, 'REMOVE PI REGISTRATION', agentDirectory);\n let removed: string[];\n try {\n removed = removePoPiSettings(agentDirectory);\n presenter.stageReady(removed.length > 0 ? 'Removed Po entries from Pi.' : 'No Po entries in Pi.');\n } catch (error) {\n presenter.stageFailed('Pi cleanup failed.', [\n `Your Po configuration remains at ${configResult.directory}.`,\n 'Fix the reported settings or filesystem issue, then run po init again.',\n ]);\n throw setupFailure('removing Po from Pi settings', agentDirectory, error);\n }\n\n presenter.complete(configResult, removed);\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class InitCommand {\n readonly name = INIT_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n homeDirectory = os.homedir(),\n output: InitOutput = process.stdout,\n environment: NodeJS.ProcessEnv = process.env,\n ): Promise<number> {\n return runInit(args, homeDirectory, output, environment);\n }\n}\n"],"mappings":";;;;;;;;;;;AAUA,MAAM,eAAe;AACrB,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAE1B,SAAS,aAAa,UAAkB,QAAgB,OAAuB;CAC7E,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACpE,OAAO,IAAI,MAAM,wBAAwB,SAAS,MAAM,OAAO,IAAI,UAAU,EAAE,OAAO,MAAM,CAAC;AAC/F;;AAGA,eAAsB,QACpB,MACA,gBAAgBA,QAAAA,QAAG,QAAQ,GAC3B,SAAqB,QAAQ,QAC7B,cAAiC,QAAQ,KACxB;CACjB,MAAM,QAAQ,KAAK,MAAM,CAAC;CAC1B,MAAM,UAAU,MAAM,MAAM,SAAS,SAAS,UAAU;CACxD,IAAIC,eAAAA,UAAU,IAAI,GAAG;EACnB,QAAQ,OAAO,MAAMC,aAAAA,SAAS,CAAC;EAC/B,OAAO;CACT;CACA,IAAI,YAAY,KAAA,GAAW,MAAM,IAAI,MAAM,2BAA2B,SAAS;CAE/E,MAAM,YAAY,IAAIC,kBAAAA,cAAc,QAAQ,WAAW;CACvD,UAAU,MAAM;CAEhB,MAAM,mBAAA,GAAkBC,qBAAAA,0BAAAA,CAA0B,aAAa;CAC/D,UAAU,MAAM,GAAG,mBAAmB,uBAAuB,eAAe;CAC5E,IAAI;CACJ,IAAI;EACF,gBAAA,GAAeC,qBAAAA,2BAAAA,CAA2B,eAAe,EAAE,OAAO,MAAM,SAAS,UAAU,EAAE,CAAC;EAC9F,UAAU,WAAW,gCAAgC;CACvD,SAAS,OAAO;EACd,UAAU,YAAY,+BAA+B,CACnD,+DACF,CAAC;EACD,MAAM,aAAa,yBAAyB,iBAAiB,KAAK;CACpE;CAGA,MAAM,iBAAiBC,UAAAA,QAAK,KAAK,eAAe,OAAO,OAAO;CAC9D,UAAU,MAAM,GAAG,mBAAmB,0BAA0B,cAAc;CAC9E,IAAI;CACJ,IAAI;EACF,WAAA,GAAUC,8BAAAA,mBAAAA,CAAmB,cAAc;EAC3C,UAAU,WAAW,QAAQ,SAAS,IAAI,gCAAgC,sBAAsB;CAClG,SAAS,OAAO;EACd,UAAU,YAAY,sBAAsB,CAC1C,oCAAoC,aAAa,UAAU,IAC3D,wEACF,CAAC;EACD,MAAM,aAAa,gCAAgC,gBAAgB,KAAK;CAC1E;CAEA,UAAU,SAAS,cAAc,OAAO;CACxC,OAAO;AACT;;AAGA,IAAa,cAAb,MAAyB;CACvB,OAAgB;CAEhB,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,gBAAgBP,QAAAA,QAAG,QAAQ,GAC3B,SAAqB,QAAQ,QAC7B,cAAiC,QAAQ,KACxB;EACjB,OAAO,QAAQ,MAAM,eAAe,QAAQ,WAAW;CACzD;AACF"}
1
+ {"version":3,"file":"index.cjs","names":["os","wantsHelp","initHelp","InitPresenter","globalPoConfigDirectory","initializeGlobalPoConfig","path","removePoPiSettings"],"sources":["../../../../../src/cli/commands/init/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { type GlobalPoInitResult, globalPoConfigDirectory, initializeGlobalPoConfig } from '@agimon-ai/po-config';\nimport { removePoPiSettings } from '@agimon-ai/po-core/piSettings';\n\nimport { wantsHelp } from '../../router';\nimport { initHelp } from './help';\nimport { InitPresenter, type InitOutput } from './presenter';\n\nconst INIT_COMMAND = 'init';\nconst FORCE_FLAG = '--force';\nconst SETUP_STAGE_COUNT = 2;\n\nfunction setupFailure(activity: string, target: string, error: unknown): Error {\n const detail = error instanceof Error ? error.message : String(error);\n return new Error(`po init failed while ${activity} at ${target}: ${detail}`, { cause: error });\n}\n\n/** Handles the repository-independent `po init` command. */\nexport async function runInit(\n args: string[],\n homeDirectory = os.homedir(),\n output: InitOutput = process.stdout,\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<number> {\n const flags = args.slice(1);\n const unknown = flags.find((flag) => flag !== FORCE_FLAG);\n if (wantsHelp(args)) {\n process.stdout.write(initHelp());\n return 0;\n }\n if (unknown !== undefined) throw new Error(`po init does not accept ${unknown}`);\n\n const presenter = new InitPresenter(output, environment);\n presenter.brand();\n\n const configDirectory = globalPoConfigDirectory(homeDirectory);\n presenter.stage(1, SETUP_STAGE_COUNT, 'WRITE CONFIGURATION', configDirectory);\n let configResult: GlobalPoInitResult;\n try {\n configResult = initializeGlobalPoConfig(homeDirectory, { force: flags.includes(FORCE_FLAG) });\n presenter.stageReady('Configuration files are ready.');\n } catch (error) {\n presenter.stageFailed('Configuration setup failed.', [\n 'Fix the reported path or permissions, then run po init again.',\n ]);\n throw setupFailure('writing configuration', configDirectory, error);\n }\n\n // Po no longer registers with Pi; init only removes what earlier versions wrote.\n const agentDirectory = path.join(homeDirectory, '.pi', 'agent');\n presenter.stage(2, SETUP_STAGE_COUNT, 'REMOVE PI REGISTRATION', agentDirectory);\n let removed: string[];\n try {\n removed = removePoPiSettings(agentDirectory);\n presenter.stageReady(removed.length > 0 ? 'Removed Po entries from Pi.' : 'No Po entries in Pi.');\n } catch (error) {\n presenter.stageFailed('Pi cleanup failed.', [\n `Your Po configuration remains at ${configResult.directory}.`,\n 'Fix the reported settings or filesystem issue, then run po init again.',\n ]);\n throw setupFailure('removing Po from Pi settings', agentDirectory, error);\n }\n\n presenter.complete(configResult, removed);\n return 0;\n}\n\n/** Compatibility API. Executables call the command function directly. */\nexport class InitCommand {\n readonly name = INIT_COMMAND;\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n homeDirectory = os.homedir(),\n output: InitOutput = process.stdout,\n environment: NodeJS.ProcessEnv = process.env,\n ): Promise<number> {\n return runInit(args, homeDirectory, output, environment);\n }\n}\n"],"mappings":";;;;;;;;;;;AAUA,MAAM,eAAe;AACrB,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAE1B,SAAS,aAAa,UAAkB,QAAgB,OAAuB;CAC7E,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACpE,OAAO,IAAI,MAAM,wBAAwB,SAAS,MAAM,OAAO,IAAI,UAAU,EAAE,OAAO,MAAM,CAAC;AAC/F;;AAGA,eAAsB,QACpB,MACA,gBAAgBA,QAAAA,QAAG,QAAQ,GAC3B,SAAqB,QAAQ,QAC7B,cAAiC,QAAQ,KACxB;CACjB,MAAM,QAAQ,KAAK,MAAM,CAAC;CAC1B,MAAM,UAAU,MAAM,MAAM,SAAS,SAAS,UAAU;CACxD,IAAIC,eAAAA,UAAU,IAAI,GAAG;EACnB,QAAQ,OAAO,MAAMC,aAAAA,SAAS,CAAC;EAC/B,OAAO;CACT;CACA,IAAI,YAAY,KAAA,GAAW,MAAM,IAAI,MAAM,2BAA2B,SAAS;CAE/E,MAAM,YAAY,IAAIC,kBAAAA,cAAc,QAAQ,WAAW;CACvD,UAAU,MAAM;CAEhB,MAAM,mBAAA,GAAkBC,qBAAAA,wBAAAA,CAAwB,aAAa;CAC7D,UAAU,MAAM,GAAG,mBAAmB,uBAAuB,eAAe;CAC5E,IAAI;CACJ,IAAI;EACF,gBAAA,GAAeC,qBAAAA,yBAAAA,CAAyB,eAAe,EAAE,OAAO,MAAM,SAAS,UAAU,EAAE,CAAC;EAC5F,UAAU,WAAW,gCAAgC;CACvD,SAAS,OAAO;EACd,UAAU,YAAY,+BAA+B,CACnD,+DACF,CAAC;EACD,MAAM,aAAa,yBAAyB,iBAAiB,KAAK;CACpE;CAGA,MAAM,iBAAiBC,UAAAA,QAAK,KAAK,eAAe,OAAO,OAAO;CAC9D,UAAU,MAAM,GAAG,mBAAmB,0BAA0B,cAAc;CAC9E,IAAI;CACJ,IAAI;EACF,WAAA,GAAUC,8BAAAA,mBAAAA,CAAmB,cAAc;EAC3C,UAAU,WAAW,QAAQ,SAAS,IAAI,gCAAgC,sBAAsB;CAClG,SAAS,OAAO;EACd,UAAU,YAAY,sBAAsB,CAC1C,oCAAoC,aAAa,UAAU,IAC3D,wEACF,CAAC;EACD,MAAM,aAAa,gCAAgC,gBAAgB,KAAK;CAC1E;CAEA,UAAU,SAAS,cAAc,OAAO;CACxC,OAAO;AACT;;AAGA,IAAa,cAAb,MAAyB;CACvB,OAAgB;CAEhB,QAAQ,MAAyB;EAC/B,OAAO,KAAK,OAAO,KAAK;CAC1B;CAEA,MAAM,QACJ,MACA,gBAAgBP,QAAAA,QAAG,QAAQ,GAC3B,SAAqB,QAAQ,QAC7B,cAAiC,QAAQ,KACxB;EACjB,OAAO,QAAQ,MAAM,eAAe,QAAQ,WAAW;CACzD;AACF"}