I thought you’d never ask. =) This is something I thought a lot about when designing the Dialog standard library.
A major insight was that most players will examine a lot, but won’t search or look inside objects unless they’re explicitly told to look closer. Some players will do it unprompted. Therefore, while story authors can be expected to provide custom examine-text for every object, there is little incentive to modify the default responses to Search and Look In. They can be bland and procedurally generated—except in very special story-specific cases that are clearly signposted.
Now, the role of a standard library is to provide reasonable defaults that story authors can override and reshape to fit a particular situation. I very much agree with @tayruh that the desired behaviour of these commands is context dependent. So the following is intended to function as a sensible baseline, but above all to be malleable.
Look In and friends
In Dialog, objects can be located in, on, under, or behind other objects. Consequently, there are four distinct player commands to LOOK IN/ON/UNDER/BEHIND something. By default, these commands result in a list of objects with the specified relation to the parent object, e.g. LOOK ON FRIDGE might yield “On the fridge is a postcard and a todo list”, with no mention of the food inside the fridge.
Dialog treats Search as a separate action from Look In and friends. The default implementation of search will report any child objects, regardless of preposition. Furthermore, it will report them in roughly the same style as “look preposition”. So for SEARCH FRIDGE, you’d get “On the fridge …” and “In the fridge …” as separate sentences in the same response. If the fridge is closed and opaque, the objects inside the fridge are not reported. If all child objects have the same relation, e.g. “on”, then the default output of SEARCH is indistinguishable from the default output of LOOK ON.
So in practice, in many cases, SEARCH will behave as if it were a synonym of LOOK IN or LOOK ON. Players can surely be expected to make that assumption. Unfortunately, this puts an extra burden on the story writer—one that I think is unavoidable unless we restrict objects to be either containers or supporters, but not both. The burden is that whenever the author overrides the default behaviour of one of these actions, they probably have to override the other as well.
Of course, parser game authors are already used to working hard to cover every possible way of expressing the same intent. Every time they override “show x to y”, they have to think about overriding “give x to y”, and maybe “tell y about x”. But still, being forced to override two rules instead of one is clearly a downside to my approach.
Examine, descriptions, and appearances
Every object has a description, which is shown in response to EXAMINE (for which LOOK AT is a synonym). The story author can easily, on a case-by-case basis, insert code for listing child objects as part of the description. Thus, for instance:
It's a large sturdy oak table.
(list objects #on #table)
> X TABLE
It’s a large sturdy oak table. On the table is a bowl of fruit.
Objects may also call attention to themselves with an appearance. For instance: “A service robot whirrs around on the floor, humming to itself.” This gets appended to the description of the parent object, usually a room. But the same mechanism can be used for child objects, like so:
White and tall.
(appearance #todo #on #fridge)
A todo-list is stuck to the fridge with a magnet.
Then, if you X FRIDGE, you get:
This happens because the default implementation of Examine invokes both the description of the object itself, and the appearance of each of its children. As always, the story author can override the default implementation, generally and/or in specific cases. Thus, when we explicitly list child objects as part of an object description, it’s prudent to turn off their appearances (in case they have any) to prevent them from being mentioned twice:
It's a large sturdy oak table.
(list of objects #on #table)
~(appearance $ #on #table)
I don’t know… maybe that this is complex? It certainly depends on context. Dialog offers many different ways of overriding the default behaviour, in order to meet the particular demands of each story. But the baseline behaviour must be sensible, since some players will expect these commands to provide reasonable responses, while a good proportion of players don’t even know that they exist.