Conform Data Machine to the canonical flat approval envelope#2809
Merged
Conversation
…tage()
Converge Data Machine onto the single canonical approval_required envelope
shape. stage() previously emitted a custom nested payload
({ pending_action: {…}, resolve_with, resolve_params, instruction }); it now
emits the canonical flat envelope via the Agents API pending-action value
object, whose payload carries the full canonical pending-action shape
(action_id, kind, summary, preview, status, expires_at, …) plus the
standardized instruction and grants slots.
All Data Machine behavior is preserved: resolver grants now ride the canonical
grants slot, the durable datamachine_pending_actions table, the
datamachine_pending_action_handlers dispatch, multisite re-entry, and the
generic agents/resolve-pending-action resolution are untouched (the resolver
reads the store, not the envelope). Top-level staged/action_id convenience
fields are unchanged, so internal callers and the frontend diff card keep
working.
Uses WP_Agent_Pending_Action::to_approval_envelope() when present (Agents API
PR for the canonical builder); a transition path builds the identical flat
payload inline for an older vendored Agents API so this stays green until the
dependency bumps.
Updates the approval-envelope smoke to assert the flat shape (and the grants
slot), repoints two sibling smokes that read payload.pending_action to the flat
payload, and adds the transient-fallback guard so the envelope smoke runs in
pure PHP like its siblings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Homeboy Results —
|
The homeboy CI recipe runs changed tests/**/*-smoke.php through the host-smoke backend, which loads a real $wpdb but does not run the plugin's deferred migrations — so the durable datamachine_pending_actions table is absent while PendingActionStore::has_database() still reports true, and the transient fallback never engages. Any smoke that stages a pending action then hits a missing-table DB error. Ensure the durable table exists when a real database is present (mirrors the existing agent-bundle-artifact-store smoke pattern); pure-PHP runs with no real $wpdb keep using the transient fallback. This exercises the real store end-to-end on the host-smoke backend, matching the durable path the WP Codebox PHPUnit backend already covers on main. Applies to the three staging smokes touched by the canonical-envelope change: approval-envelope, memory-bundle-policy, and agent-bundle-upgrade-planner. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The host-smoke backend loads a real WordPress (Playground/PHP WASM) but does not run plugin bootstrap, so these standalone smokes have to wire up what a booted plugin provides. Building on the durable-table fix: - Register the canonical store + resolver adapters in the bundle-upgrade smoke (the memory smoke already did) so agents/resolve-pending-action dispatches instead of returning "no resolver registered". - Stage the bundle-upgrade action as the resolving user so the action's creator matches the resolution scope; otherwise the resolver denies on owner mismatch. - Pass user_id explicitly when staging in the approval-envelope smoke so the recorded creator is deterministic (real WP overrides the stubbed get_current_user_id() with the unauthenticated 0). - Define STDERR in the memory smoke: Playground/PHP WASM does not provide the stream constant, so the assert helper crashed on failure instead of reporting. All three smokes pass standalone (pure PHP) and now exercise the real durable store + resolver on the host-smoke backend. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The host-smoke backend runs as an unauthenticated user, so the pending-action resolver denies on authorization (the pure-PHP stubs simulate an authorized operator with current_user_can => true, which does not apply under real WP). Act as an administrator before staging so the bundle-upgrade and memory resolution smokes share an authorized operator identity for staging and resolution. Guarded behind function_exists so pure-PHP runs are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Converge Data Machine onto the single canonical
approval_requiredenvelope shape so producers emit consistently and consumers read one shape.PendingActionHelper::stage()previously emitted a custom nested payload:It now emits the canonical flat envelope via the Agents API pending-action value object. The payload is the full canonical pending-action shape (
action_id,kind,summary,preview,status,expires_at,apply_input, audit fields, …) plus the standardizedinstructionandgrantsslots.Why
There were two divergent approval-envelope shapes: Agents API's flat
approval_required(from the ability lifecycle bridge) and Data Machine's nested wrapper. Agents API's flat shape is canonical; this PR makes Data Machine conform. As a bonus, the Agents API conversation loop readspayload.action_idfrom the flat shape, so theapproval_requiredruntime event now carries a realaction_idfor Data Machine-staged actions instead ofnull.Behavior preserved
All Data Machine behavior is intact — verified against the code, not assumed:
grantsslot (still also persisted in store metadata).datamachine_pending_actionstable,datamachine_pending_action_handlersdispatch, multisiteblog_idre-entry, and the genericagents/resolve-pending-actionresolution are untouched — the resolver reads the store, never the envelope.staged/action_idconvenience fields are unchanged, so internal callers (content abilities,ToolExecutor, bundle/memory pending actions) and the frontend diff card keep working.PendingActionInspectionAbility::normalize_action_row()already rebuildsresolve_with/resolve_paramsfrom store metadata, so the CLI/frontend inspection rows are unaffected.Blast radius (verified)
No production code anywhere reads the old nested
payload.pending_actionwrapper. Checked Data Machine, frontend-agent-chat (reads the top-levelaction_idand the generic resolve route — handles both shapes),data-machine-events(usesaction_idas a tool input, reads the store), and searchedAutomattic/wpcom(GitHub Enterprise) plus the Extra-Chill org — no nested-shape consumers. Big Sky / Odie and other Agents API consumers read the flat shape and are unaffected.Dependency / sequencing
Depends on the Agents API canonical builder (
WP_Agent_Pending_Action::to_approval_envelope()): Automattic/agents-api#375. Data Machine pinswordpress/agents-api: dev-main.stage()uses the canonical builder when present and otherwise builds the identical flat payload inline, so this PR is green now against the currently-vendored Agents API and adopts the canonical path automatically after #375 lands andcomposer update wordpress/agents-apiruns. The inline path is version-transition only — it emits the same canonical flat shape, not the old nested one.Tests
pending-action-helper-approval-envelope-smoketo assert the flat shape (no nestedpending_action/resolve_with/resolve_params), plus theinstructionandgrantsslots. Verified passing on both the canonical builder path and the inline transition path.memory-bundle-policy,agent-bundle-upgrade-planner) that readpayload.pending_actionto the flat payload.DATAMACHINE_PENDING_ACTION_TRANSIENT_FALLBACKguard to the envelope smoke so it runs in pure PHP like its siblings (it previously relied on an ambient$wpdb).$wpdb) and identical onmain.AI assistance
stage()change, fixing affected test reads, and verifying both dependency paths. Chris reviewed.🤖 Generated with Claude Code