{"id":1309,"date":"2026-02-15T20:14:30","date_gmt":"2026-02-15T20:14:30","guid":{"rendered":"https:\/\/docs.ai.drawconclusions.org\/?page_id=1309"},"modified":"2026-02-24T12:45:55","modified_gmt":"2026-02-24T12:45:55","slug":"devdocs-wordpress-publishing-pipeline","status":"publish","type":"page","link":"https:\/\/docs.ai.drawconclusions.org\/?page_id=1309","title":{"rendered":"DevDocs -> WordPress Publishing Pipeline (Hash Artifacts)"},"content":{"rendered":"<p>This page describes the current intended pipeline for publishing DevDocs pages into WordPress.<\/p>\n<h2>Goals<\/h2>\n<ul>\n<li>Author pages directly in <code>.\/docs\/devdocs\/<\/code> (source of truth).<\/li>\n<li>Detect changes cheaply and deterministically.<\/li>\n<li>Ensure WordPress ends up exactly matching the DevDocs set (add\/update\/delete) with minimal work.<\/li>\n<\/ul>\n<h2>Key Concepts<\/h2>\n<ul>\n<li>Stable page identity: every DevDocs page must contain a stable identifier (<code>DEVELOPERDOCS_ID<\/code>). This identifier is the primary key for reconciliation in WordPress.<\/li>\n<li>Hash artifacts: hashes are used to detect changes, not to define identity.<\/li>\n<li>One artifact per page: the build produces one generated artifact file per page, named by its hash, plus an index\/manifest.<\/li>\n<\/ul>\n<h2>Page Header Contract<\/h2>\n<ul>\n<li><code>DEVELOPERDOCS_ID: dd_id_&lt;10 lowercase alphanumeric&gt;<\/code><\/li>\n<li>Mandatory for every DevDocs page.<\/li>\n<li>Auto-generated on first page creation, then stable forever.<\/li>\n<li>The alphanumeric string is always lowercase.<\/li>\n<li><code>PARENT_DEVELOPERDOCS_ID: dd_id_&lt;10 lowercase alphanumeric&gt;<\/code><\/li>\n<li>Optional.<\/li>\n<li>If present, it references the parent page by its <code>DEVELOPERDOCS_ID<\/code>.<\/li>\n<li>Default is empty: the line is missing entirely.<\/li>\n<li><code>sorting_priority: &lt;integer&gt;<\/code><\/li>\n<li>Optional. Default is <code>0<\/code> (line missing).<\/li>\n<li>Used to order siblings in the left sidebar: higher values appear higher.<\/li>\n<li>If priorities are equal, order is alphabetical ascending by title.<\/li>\n<li>Implementation detail: the WordPress <code>menu_order<\/code> field is set to <code>-sorting_priority<\/code>.<\/li>\n<\/ul>\n<h2>Pipeline<\/h2>\n<p>1. Authoring (local)<\/p>\n<ul>\n<li>Developers edit Markdown pages in <code>.\/docs\/devdocs\/*.md<\/code>.<\/li>\n<li>Each page contains all page information needed for publishing (at minimum: stable id, title, body; and any ordering\/parent data the build requires).<\/li>\n<\/ul>\n<p>2. Build artifacts (local or server)<\/p>\n<ul>\n<li>A Python build script reads <code>.\/docs\/devdocs\/*.md<\/code>.<\/li>\n<li>For each page it:<\/li>\n<li>Parses the stable id from the source file.<\/li>\n<li>Derives the WordPress-relevant metadata (title, slug, parent id, menu order, etc.).<\/li>\n<li>Converts Markdown to the HTML payload to be stored in WordPress.<\/li>\n<li>Computes a content hash (and optionally a metadata hash).<\/li>\n<li>Writes one generated artifact file per page, named by the hash.<\/li>\n<li>The script also writes a single index file (manifest) that lists the complete expected set of pages.<\/li>\n<\/ul>\n<p>3. Sync to server<\/p>\n<ul>\n<li>The build outputs are placed under <code>\/var\/www\/devdocs\/<\/code> (including the manifest and per-page hash artifacts).<\/li>\n<li>The project sync pushes these files to the server.<\/li>\n<\/ul>\n<p>4. WordPress ingestion (plugin)<\/p>\n<ul>\n<li>A WordPress plugin is triggered to ingest DevDocs from <code>\/var\/www\/devdocs\/<\/code>.<\/li>\n<li>The plugin:<\/li>\n<li>Loads the manifest as the source of truth for which pages must exist.<\/li>\n<li>Permanently deletes WordPress pages whose stable id is no longer present in the manifest.<\/li>\n<li>Creates pages whose stable id is present in the manifest but missing in WordPress.<\/li>\n<li>Updates pages whose stable id exists but whose stored hash differs from the manifest\/artifact hash.<\/li>\n<li>Skips pages whose stable id exists and whose hash matches.<\/li>\n<\/ul>\n<h2>Deletion And Safety<\/h2>\n<ul>\n<li>Deletions are determined by stable id absence in the manifest, not by hash filenames.<\/li>\n<li>Hash filenames must never be treated as identity, because any edit would otherwise appear as delete+create.<\/li>\n<\/ul>\n<p class=\"developerdocs-id-search\" aria-hidden=\"true\">DeveloperDoc ID: dd_id_h9qvuokrif<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This page describes the current intended pipeline for publishing DevDocs pages into WordPress. Goals Author pages directly in .\/docs\/devdocs\/ (source of truth). Detect changes cheaply and deterministically. Ensure WordPress ends up exactly matching the DevDocs set (add\/update\/delete) with minimal work. Key Concepts Stable page identity: every DevDocs page must contain a stable identifier (DEVELOPERDOCS_ID). This [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1357,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"doc_category":[],"doc_layer":[26],"class_list":["post-1309","page","type-page","status-publish","hentry","layer-dd_id_d920cc6a97"],"_links":{"self":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1309"}],"version-history":[{"count":5,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1309\/revisions"}],"predecessor-version":[{"id":3826,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1309\/revisions\/3826"}],"up":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1357"}],"wp:attachment":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1309"}],"wp:term":[{"taxonomy":"doc_category","embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_category&post=1309"},{"taxonomy":"doc_layer","embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_layer&post=1309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}