dpm_module_info_of becomes dpm_get_module_info, joining the other two
readers on the context in stating that a call fetches a value.
Recording an error had two entry points doing the same write: the
exported dpm_set_last_error and an internal dpm_core::set_last_error
taking a std::string. The internal one is gone and the loader calls the
exported function, so a reason reaches the context by one path whether a
module or the library records it.
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.
context.cpp had grown to hold three unrelated concerns: the context
lifecycle, everything about the .conf file format, and everything about
writing a log message.
conf.cpp now owns the format end to end - parsing a file into the store,
reading values back out, and interpreting a configured string as the
boolean or log level a setting holds. logging.cpp owns the write path:
the level filter, the stream choice, and the name a level carries in
output.
context.cpp keeps what a context is: resolving each setting from the
override, the configured value, or the built-in default, and reporting
what it resolved.
dpm_core carries a namespace block saying what it holds and why its
members keep external linkage while staying off the export table. Each
unnamed namespace says its contents are private to that translation
unit, and the one in the info module says why it has to be unnamed
there: a module is built without hidden visibility or a version script,
so a helper with external linkage would reach that module's exports.
The three opaque handles in the public header were undocumented. What
documentation they had came from the struct definitions in
include/internal, which a consumer never sees.
EXTRACT_ANON_NSPACES was off, so the documentation on every file-private
helper was written and discarded. Doxygen also capitalizes the first
letter of a brief, which turned libdpm-core.so into Libdpm-core.so
wherever a brief opened with it; those are reworded.
Bare references to the library are replaced with the artifact name
throughout, including three in the info module's output. The
cli_info_version regex follows.
Namespace and extern "C" bodies are indented a level, so nesting is
visible from the indentation rather than only from the braces. Opening
braces stay on the line that opens the scope, including function
definitions, which previously carried theirs on a line of their own.
The project version moves to 1.0.0, which the library soname, the
reported version, the test expectations, and the generated document
filename all derive from. SOVERSION now matches the major version.
The generated reference is built from the source and its documentation
comments alone. Prose from docs/ was briefly part of the input and is
removed: development notes are written and read on their own, and a
generator that reproduces them adds nothing. The reference opens on a
front page declared in the public header, followed by the module
contract.
One target builds it. Both PDF and HTML are produced by default, the
finished documents land in the build tree under docs/pdf and docs/html,
and the generators work in docs/tmp.
The internal namespace is dpm_core, matching the artifact name as
closely as a C++ identifier permits.
Building the docs target now generates the reference and leaves finished
documents in the build tree's docs directory: pdf/ holds the compiled
PDF, html/ holds the browsable reference when that format is enabled.
Doxygen and LaTeX work under docs/tmp/, which clean removes along with
the rest of the tree.
The reference has a front page and a structure. The markdown documents
in docs/ are part of the input, OVERVIEW.md becomes the landing page,
and the rest follow as chapters ahead of the namespace, class, and file
reference. The module contract, previously a plain comment block
invisible to Doxygen, is a page in its own right.
Struct and enum members throughout the headers carry documentation, on
their own lines above what they describe.
dpm_require no longer takes a minimum version and applies no version
criterion of its own. A handle now means the module is valid, not that
it suits the caller. dpm_module_info_of is added alongside it, reporting
the name, version, description, and minimum-libdpm-core version read at
load, so a consuming module can judge a dependency's version for itself.
The one rule still enforced is the minimum-version handshake, where
libdpm-core is the host and refuses a module that demands a newer library
than the one running.
dpm_module_info_of joins the version script, so the exported surface is
now fourteen symbols under DPM_CORE_1.0.
Separately, the bare word "core" is gone from prose everywhere. It named
both the command-line tool and the library, so every use forced the
reader to guess which. Text now says "the dpm binary" or "libdpm-core".
Identifiers keep their spelling: libdpm-core, core.h, core.conf, the
"core" configuration namespace, dpm_core_version, core_min, DPM_CORE_1.0,
the dpmcore namespace, test_core, core_api.
Three user-visible strings changed with it: the load-refusal message now
reads "requires libdpm-core >= X, running libdpm-core is Y — update
libdpm-core", and the info module's description and help text name the
library. The test asserting on the refusal text was updated to match.
DESIGN.md's terminology line no longer defines "DPM Core" as the CLI,
which was the source of the ambiguity. OVERVIEW.md is restructured around
the three layers a reader meets DPM at — user, developer, filesystem —
so a code-level symbol never appears without saying whose layer it is.
MODULES.md describes the bundled info module as testing and demonstrating
full DPM system functionality rather than as a reference implementation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>