JOURNAL

AI Publishing in WordPress: Drafts, Review Receipts and Approval Boundaries

A tested NanoClaw publishing workflow with draft-first writing, content fingerprints, CMS permissions and explicit review limitations.

Implemented helper flow: a changed draft needs a fresh receipt. The review flag is an operator assertion.

Read with AI

Choose content to copy and paste into your AI assistant. Nothing is sent automatically. CMS content is converted to Markdown; original Markdown is used when available.

An AI publishing workflow needs a saved draft, an explicit review step, and a way to detect changes after review. In the NanoClaw-to-WordPress integration for this portfolio, a dedicated writer creates drafts and a content fingerprint protects the reviewed version. The result is a useful human-in-the-loop workflow, with an important boundary: a review receipt identifies content; it does not independently prove that a human approved publication.

The product problem: make the proposed action reviewable

“Publish this article” is too broad when the article, diagrams, metadata, and destination are still changing. A reviewer needs a concrete result: the draft, its editor and preview links, and the exact version that will be sent to WordPress.

The integration therefore defaults to draft. Existing Astro writing jobs retain their established destination and only request a WordPress draft mirror after the original workflow succeeds. A WordPress mirror is not automatically published merely because the Astro task was allowed to publish elsewhere. This separation matters when testing a parallel site and when a publishing credential fails independently of the writing task.

The workflow described here was exercised through the helpers inside the actual NanoClaw agent container. It was not an end-to-end autonomous language-model publishing run, and no outbound test message was sent.

Separate CMS authority from review policy

The writer is a dedicated WordPress author, with the additional ability to manage article tags. It can manage its own articles and media but cannot administer the site or edit imported administrator-owned articles. A live attempt to edit an imported article returned HTTP 403.

WordPress capabilities provide the CMS boundary. They do not understand this project’s review policy. The author account retains publication authority, so a direct API request could bypass the helper’s review step. WordPress roles and capabilities describe the underlying permission model.

Authentication uses a dedicated application password through the existing credential gateway. The helper does not read a token from an article file or prompt. Application passwords allow integration-specific credentials without sharing the user’s main login password; they still act with that user’s capabilities. WordPress application passwords

Create a receipt for the actual draft

The helper saves an article with its title, locale, excerpt, native block HTML, tags, and optional featured image. It refuses an existing locale slug, including an existing private article. It also checks the saved slug so that a collision cannot silently become an unintended “-2” copy.

The receipt contains the post ID, editor and preview URLs, and a fingerprint derived from the stored content. The fingerprint covers title, body, excerpt, slug, locale, featured media, tags, SEO title, and SEO description. Publication status is checked separately.

The editor and preview serve different purposes. The editor checks blocks and metadata. The preview checks reading order, code, diagram labels, mobile width, and the destination of links. The receipt is useful only after these checks have happened.

Implemented helper flow: a changed draft needs a fresh receipt. The review flag is an operator assertion.
Implemented helper flow: a changed draft needs a fresh receipt. The review flag is an operator assertion.

Make edits invalidate the previous review

A draft can change after the first preview. The writer may fix a sentence, replace a diagram, or adjust the SEO description. A publication command that still relies on the first receipt would be approving an earlier version.

The helper reads the current WordPress article before publication and compares its fingerprint with the receipt. When they differ, publication fails and a fresh review is required. The review command also runs the editorial checklist: locale, summary, body headings, image descriptions, and link formats. It returns the links for inspection; it does not claim that every external destination has been verified automatically.

The following commands illustrate the workflow. The post ID is an example, and the final command is used only after publication has been explicitly authorized:

node /app/skills/wordpress-post/scripts/wordpress.mjs draft post.json
node /app/skills/wordpress-post/scripts/wordpress.mjs review 123 post.json.receipt.json
node /app/skills/wordpress-post/scripts/wordpress.mjs publish post.json.receipt.json --reviewed

A --reviewed flag is an operator assertion. It is not a human identity signature. That distinction should stay visible in both the implementation and the case study.

Test rejection paths, not only successful publication

The live helper checks covered draft creation, duplicate-slug refusal, reviewed publication, and cleanup. An edited draft was rejected with its stale receipt and could be published only after issuing a fresh review receipt. Changing SEO metadata also invalidated the old receipt. The private-slug collision check refused the second article, and the imported-article edit remained forbidden.

Diagram rendering and PNG upload were exercised in the same agent environment. Temporary articles and uploads used for verification were removed. These checks establish specific behavior; they are not a claim that the whole agent system is safe under every prompt or every concurrent edit.

Useful acceptance tests for a similar workflow include a wrong destination, a wrong locale, a missing image description, a replaced featured image, and an author trying to mutate somebody else’s content. Test the controls at the CMS boundary as well as in the helper.

Where stronger approval would need a different design

The current fingerprint comparison and publication are separate API calls. An edit between those calls is still a possible race. The workflow also lacks a server-side approval record bound to a named reviewer, an expiry time, and an atomic content-version check.

For a higher-risk publishing service, I would remove publication capability from the writing identity and use a separate promotion service. That service would validate a reviewer-authenticated approval for a specific content version and record the result atomically. This is a proposed extension, not a feature already implemented in this portfolio.

Retries also need clear behavior. After an uncertain network result, inspect the stored post before creating another copy or repeating a side effect. Keep the draft and its receipt available when authentication fails; a failed connection should not turn into an instruction to weaken the review rule.

What I would measure after adoption

The next product questions are how often drafts need correction, whether stale-version refusals catch useful mistakes, how long review takes, and whether people inspect diagrams and links before publishing. None of those usage outcomes has been measured here yet.

The technical outcome is narrower and defensible: the WordPress writing path is reviewable, its normal helper rejects changed content, and the CMS limits which articles its identity can edit. For a broader testing approach, see evals for agentic systems. For running the underlying site, start with the homelab guide.

Discussion

Comments are reviewed before publication. Your email is kept private.

Add a comment

Name and email are required. Do not include confidential information.

Privacy & data

Loading anti-spam verification…

← Back to allĐọc tiếng Việt