diff --git a/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.i18n.yaml b/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.i18n.yaml index d495efc1bc..38fbdd5b28 100644 --- a/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md -2026-09-04-plugin-manager-over-the-profile-runtime.md: 4fcf693beb74949b3813fe24c6255ec3d9f5ac36 -2026-09-04-plugin-manager-over-the-profile-runtime.zh.md: b396aa9bb23b66d60119eb2868539bec5b97ad13 +2026-09-04-plugin-manager-over-the-profile-runtime.md: af44e57a6b1be94cd0df24c3dfeede50a1c8285d +2026-09-04-plugin-manager-over-the-profile-runtime.zh.md: 5754187f79e167fe9f4a54dbccc8c6dc782edff2 diff --git a/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md b/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md index 4fcf693beb..af44e57a6b 100644 --- a/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md +++ b/.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md @@ -14,7 +14,7 @@ Installing a plugin was a terminal-only act: `dsh plugin --profile web add config.installLogTailBytes && tail.length > 1) { tailBytes -= Buffer.byteLength(tail.shift() as string) } - this.options.installLog({ jobId, argv, spec, stream, text }) + this.options.installLog({ jobId, argv, cwd: profileDir, spec, stream, text }) } // Windows resolves pnpm through its .cmd shim, which spawn() refuses // without a shell since the CVE-2024-27980 hardening. The parent @@ -287,10 +287,10 @@ export class PluginInstaller { ).catch((error: unknown) => { const message = messageOf(error) record('stderr', `${message}\n`) - this.options.installLog({ jobId, argv, spec, stream: 'stderr', text: '', exitCode: null }) + this.options.installLog({ jobId, argv, cwd: profileDir, spec, stream: 'stderr', text: '', exitCode: null }) throw new PluginOperationError('plugins/install-failed', `${NAME}: ${message}`, { spec, exitCode: null, log: tail.join('') }, { cause: error }) }) - this.options.installLog({ jobId, argv, spec, stream: 'stdout', text: '', exitCode }) + this.options.installLog({ jobId, argv, cwd: profileDir, spec, stream: 'stdout', text: '', exitCode }) if (exitCode !== 0) { throw new PluginOperationError( 'plugins/install-failed', diff --git a/packages/boot/plugin-manager/src/types.ts b/packages/boot/plugin-manager/src/types.ts index a9521892f5..de0288a27e 100644 --- a/packages/boot/plugin-manager/src/types.ts +++ b/packages/boot/plugin-manager/src/types.ts @@ -190,6 +190,8 @@ export interface PluginInstallLogChunk { readonly jobId: string /** The command line the run executes: pnpm's command name, then its arguments. */ readonly argv: readonly string[] + /** The directory the run executes in: the profile directory. */ + readonly cwd: string /** The package spec the run installs or removes. */ readonly spec: string readonly stream: 'stdout' | 'stderr' diff --git a/packages/boot/plugin-manager/tests/plugin-manager.spec.ts b/packages/boot/plugin-manager/tests/plugin-manager.spec.ts index 867bc29019..6d9a451e46 100644 --- a/packages/boot/plugin-manager/tests/plugin-manager.spec.ts +++ b/packages/boot/plugin-manager/tests/plugin-manager.spec.ts @@ -599,9 +599,9 @@ describe('PluginManager', () => { // The fake pnpm records the spec itself as the dependency name, which // resolves to nothing: a plain dependency whose probe cannot run. expect(result).toEqual({ installed: ['github:acme/ext-new'], removed: [], enabled: [], installedOnly: [], plain: ['github:acme/ext-new'], jobId: expect.any(String) as string }) - expect(log.map(chunk => [chunk.argv, chunk.stream, chunk.text, chunk.exitCode])).toEqual([ - [['pnpm', 'add', 'github:acme/ext-new'], 'stdout', '+ github:acme/ext-new 1.0.0\n', undefined], - [['pnpm', 'add', 'github:acme/ext-new'], 'stdout', '', 0], + expect(log.map(chunk => [chunk.argv, chunk.cwd, chunk.stream, chunk.text, chunk.exitCode])).toEqual([ + [['pnpm', 'add', 'github:acme/ext-new'], staged.profileDir, 'stdout', '+ github:acme/ext-new 1.0.0\n', undefined], + [['pnpm', 'add', 'github:acme/ext-new'], staged.profileDir, 'stdout', '', 0], ]) expect(changes).toEqual([{ reason: 'install' }]) }) diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index 6d0a9f4f9c..3fa5b5ffb1 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -4805,7 +4805,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'PluginInstallLogChunk', - declaration: 'export interface PluginInstallLogChunk {\n readonly jobId: string;\n readonly spec: string;\n readonly stream: \'stdout\' | \'stderr\';\n readonly text: string;\n readonly exitCode?: number | null;\n}', + declaration: 'export interface PluginInstallLogChunk {\n readonly jobId: string;\n readonly argv: readonly string[];\n readonly cwd: string;\n readonly spec: string;\n readonly stream: \'stdout\' | \'stderr\';\n readonly text: string;\n readonly exitCode?: number | null;\n}', }, { name: 'PluginInstallRejection',