A module had one channel back to its caller: the int returned from dpm_module_execute, handed through by dpm_execute. Any detail behind that number could only reach a log, so a caller wanting the reason had to read output rather than ask for it. dpm_set_last_error joins the exported API. A module records its reason on the context handed to its entry point, which belongs to the caller, and the caller reads it back with dpm_get_last_error. The two accessors on the context now say what they do to it: dpm_module_path becomes dpm_get_resolved_module_path, naming the value it reports rather than the setting it came from, and dpm_last_error becomes dpm_get_last_error, pairing with the setter. Path normalization moves to sanitizers.cpp, which holds the conversions that put a value written by a person into the single form the library stores it in.
Internal Headers
libdpm-core.so's own headers, used by its sources and never installed.
They declare the types and functions the library's translation units share with each other: the definitions behind the opaque handles <dpm/core.h> exposes, and the helpers those sources call across file boundaries.
Nothing here is part of the public interface. The install rule ships include/dpm/ alone, so a consumer or a module compiles against <dpm/core.h> and never sees this directory.