User-defined function on dict not found

I have a dictionary of dictionaries, like this:

type{name: person, args: [arg{name: name}, arg{name:dob}]}

Types and arguments have optional descriptions; if missing, the description is to be sourced from the name. I want to say that with a user-defined function:

D.description() := D.get(description) :- !.
D.description() := D.name.

When I use the function within the module where I defined it as with SomeType.description(), I get:

ERROR: -g main: eval_dict_function/4: Unknown procedure: type:description/2

Reverting to a normal predicate works just fine:

spec_description(Spec, Description) :-
  Description = Spec.get(description), !.
spec_description(Spec, Spec.name).

Perplexingly, the user-defined function works fine when I use it in a different module.

Side question: how come these user-defined functions don’t have to be published in the module header in order to be used in other modules? Are these definitions global?

Side question: what’s the best way to make a user-defined function work only with certain dictionary types? Do I need to put conditions on the dictionary tag name? D.description() := … :- D = type{_}?

Side note: the error message doesn’t have a file and line number like typical error messages do. That makes dictionary error debugging more cumbersome than it needs to be.

The function is looked up in the module with the same name as your tag (which also answers your second side question). See SWI-Prolog -- User defined functions on dicts
I created a module named mydict, and from the user module saw the below.

mydict.pl

:-module(mydict,[]).
D.description() := D.get('description',D.name).

And at the top level.

?- use_module(mydict).
true.

?- Z=mydict{description:'Hello',name:'N/A'},writeln(Z.description()).
Hello
Z = mydict{description:'Hello', name:'N/A'}.

?- module(mydict).
true.

mydict:  ?- Z=mydict{description:'Hello',name:'N/A'},writeln(Z.description()).
Hello
Z = mydict{description:'Hello', name:'N/A'}.

mydict:  ?- Z=mydict{name:'Ian'}.description().
Z = 'Ian'.

I’ve read something in the doc about there being a module for each dictionary. Then do I have to define description() once for type and once for arg, in separate modules?

And can I create the same module in multiple places? It seems so based on your example.

Also, does the very fact of defining a dictionary create a module? How does that interact with modules of the same name elsewhere in the project? Do we have to keep the module names separate across the board?

Your question is a bit ambiguous, but seems to me that modules are involved only when you’re defining your own code for a specialized dictionary.
FWIW, a quick test could use current_module/1:

...
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- setof(M,current_module(M),Ms).
Ms = [ansi_term, base32, link_xpce, pce_swi_hooks, predicate_options, predopts_analysis, prolog, prolog_clause, prolog_debug|...].

?- P=a_point{x:1,y:2}.
P = a_point{x:1, y:2}.

?- setof(M,current_module(M),Ms).
Ms = [ansi_term, base32, link_xpce, pce_swi_hooks, predicate_options, predopts_analysis, prolog, prolog_clause, prolog_debug|...].