diff --git a/docs/agent-skill-sharing-implementation-checklist.md b/docs/agent-skill-sharing-implementation-checklist.md index fc7095519cc..9b5ad78f8ba 100644 --- a/docs/agent-skill-sharing-implementation-checklist.md +++ b/docs/agent-skill-sharing-implementation-checklist.md @@ -1314,7 +1314,9 @@ platform gates below. junction coverage remains open. - [ ] Test concurrent desktop, headless runtime, CLI, SSH, and recovery attempts. The shared transaction core now serializes two simultaneous installs into one installed and - one unchanged result, one receipt, and no staging residue; cross-entry-point contention + one unchanged result, one receipt, and no staging residue. The host request service also + serializes simultaneous download-grant and trusted-local ingress requests with the same + guarantees; contention across separate desktop, headless, CLI, SSH, and recovery processes remains open. - [ ] Test permission and read-only failures, disk exhaustion, cancellation, process termination, and host disconnect. Simulated `EACCES` and `ENOSPC` preservation plus lost-response retry are diff --git a/src/main/skills/skill-install-request-service.test.ts b/src/main/skills/skill-install-request-service.test.ts index 1645d54c806..1f08fdcc1e1 100644 --- a/src/main/skills/skill-install-request-service.test.ts +++ b/src/main/skills/skill-install-request-service.test.ts @@ -81,6 +81,31 @@ describe('executeSkillInstallRequest', () => { ).toContain('# Request') }) + it('serializes download and trusted-local requests through one destination transaction', async () => { + const { root, request, dependencies, archive } = await fixture() + const [downloaded, local] = await Promise.all([ + executeSkillInstallRequest(request, dependencies), + executeSkillInstallRequest( + { + ...request, + operationId: 'operation_2', + ingress: { kind: 'local-file', path: archive.archivePath } + }, + { ...dependencies, allowTrustedLocalFile: true } + ) + ]) + + expect([downloaded.status, local.status].sort()).toEqual(['installed', 'unchanged']) + expect( + await readdir(join(dependencies.stateDirectory, 'skill-installs', 'receipts')) + ).toHaveLength(1) + expect( + (await readdir(join(root, 'home', '.agents', 'skills'))).filter((name) => + name.includes('.orca-') + ) + ).toEqual([]) + }) + it('rejects local paths at the remote request boundary', async () => { const { request, dependencies, archive } = await fixture() await expect(