Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/docs-agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
audience: technical
run_kind: maintenance
base_ref: main
docs_branch: docs-agent/agents-api-docs-upkeep
docs_branch: docs-agent/agents-api-docs-upkeep-v2
writable_paths: README.md,docs/**
source_delta: |
[
Expand All @@ -36,7 +36,7 @@ jobs:
"src/Workflows/class-wp-agent-workflow-run-awaiter.php",
"tests/workflow-run-awaiter-smoke.php"
],
"requires_documentation_change": true
"requires_documentation_change": false
}
]
verification_commands: |
Expand Down
27 changes: 27 additions & 0 deletions docs/channels-workflows-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,33 @@ Consumers extend the runner through the constructor or the `wp_agent_workflow_st

Recorder behavior is conservative: `start()` runs before input validation, per-step `update()` calls follow state changes, and recorder-start failure returns a failed run result without executing steps.

### Awaiting suspended workflow runs

`WP_Agent_Workflow_Run_Awaiter` is the storage-neutral foreground await service for persisted workflow runs. Call `await( string $run_id, WP_Agent_Workflow_Run_Recorder $recorder, array $options = array() )` from a foreground/orchestrator context such as a CLI command, `wp-cron.php` request, or explicit status poll. The recorder is always caller-owned: Agents API does not resolve an ambient workflow recorder and the awaiter does not implement storage. Pass the same recorder implementation that owns the run so the awaiter and drained branch actions can re-read live state.

The await contract is:

- If `find( $run_id )` returns `null` before or after a drain, the call returns `WP_Error` with code `agents_workflow_run_not_found` and does not fabricate a response.
- If the current run is not `suspended`, no Action Scheduler work is claimed. The response still includes a zero-work `drain` shape with `stop_reason: terminal_status`, the current status in `terminal_state`, normalized hooks/group, and the scoped-drain availability flag.
- If the run is `suspended`, the awaiter delegates to `WP_Agent_Workflow_Scoped_Drain::drain_suspended_run()`. That helper drains only the configured hook + group scope until the run leaves `suspended`, the scope empties, a safety budget stops the loop, Action Scheduler is unavailable, or a re-entrant/claimed-action guard refuses the drain.
- After draining, the awaiter reloads the run from the caller recorder and returns the latest persisted status.

The await response uses schema `agents-api/workflow-run-await/v1` and includes:

| Field | Contract |
| --- | --- |
| `schema` | Versioned await response schema. |
| `run_id` | The persisted run id from the reloaded result. |
| `status` | Latest workflow-run status. |
| `terminal` | `true` only for `succeeded`, `failed`, `skipped`, or `cancelled`. |
| `reconnectable` | `false` for terminal runs; `true` for any nonterminal response, including a budget-exhausted or drain-refused suspended run. |
| `result` | Canonical `agents-api/run-result/v1` run-result envelope when `terminal` is true; `null` while nonterminal. Failed terminal results preserve the canonical error payload. |
| `drain` | Scoped-drain stats: `batches`, `actions_processed`, `completions`, `failures`, `remaining_pending`, `total_pending`, `warnings`, `stop_reason`, `terminal_state`, comma-separated `hooks`, `group`, and `available`. |

Supported await/drain options are forwarded to the scoped drain after validation: `hooks` (string list), `group`, `batch_size`, `limit`, `time_limit_ms`, `time_limit`, `stop_before_timeout_ms`, `stop_before_timeout`, and `execution_context`. Omitted or empty hooks fall back to the Action Scheduler branch executor's branch and resume hooks; an omitted group falls back to the workflow Action Scheduler group. Budget stop reasons such as `limit`, `time_limit`, `timeout_margin`, `memory_limit`, `no_progress`, `as_unavailable`, `refused_reentrant`, and `refused_in_claimed_action` are reported in `drain.stop_reason` rather than converted into errors, so callers can return a reconnectable polling response.

Do not call the drain from inside one of the scoped branch or resume actions. `WP_Agent_Workflow_Scoped_Drain` checks the live action stack and a process-level guard and refuses those contexts to avoid self-deadlocking a worker that is holding an Action Scheduler claim while trying to claim sibling actions.

## Workflow abilities and permissions

`src/Workflows/register-agents-workflow-abilities.php` registers three abilities:
Expand Down
6 changes: 3 additions & 3 deletions docs/docs-agent-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ The workflow contract is intentionally narrow:
- `audience: technical`
- `run_kind: maintenance`
- `base_ref: main`
- `docs_branch: docs-agent/agents-api-docs-upkeep`
- `docs_branch: docs-agent/agents-api-docs-upkeep-v2`
- `writable_paths: README.md,docs/**`
- `source_delta`: the known documentation drift introduced by Agents API PR #422, bounded to the workflow run awaiter implementation and smoke test
- `source_delta`: the satisfied documentation record for Agents API PR #422, bounded to the workflow run awaiter implementation and smoke test
- `verification_commands`: `composer install --no-interaction --prefer-dist --no-progress`, `composer test`, then `php tests/no-product-imports-smoke.php`
- `drift_checks`: `git diff --check`

Expand Down Expand Up @@ -50,7 +50,7 @@ Docs Agent then calls WP Codebox's reusable workflow:
Automattic/wp-codebox/.github/workflows/run-agent-task.yml@a6fe2d208e990a8d04104aa74aacbb8d1539fbc1
```

The contract test verifies that this WP Codebox producer exposes the `wp-codebox/reusable-workflow-interface/v1` schema and preserves the release, external-package, runtime-source, target repository, writable path, verification, drift-check, publication, access-repository, and allowed-repository chain. The completion contract requires one evidence-backed report item for the `workflow-run-awaiter` source delta and rejects a no-change disposition until that known drift is documented. WP Codebox returns the reviewer-safe result projection and stages the validated completion report as a declared command artifact.
The contract test verifies that this WP Codebox producer exposes the `wp-codebox/reusable-workflow-interface/v1` schema and preserves the release, external-package, runtime-source, target repository, writable path, verification, drift-check, publication, access-repository, and allowed-repository chain. The host generates the completion report from the bounded `workflow-run-awaiter` source record, Git diff, and writable scope; because that source is now documented, a clean workspace is a valid no-change outcome. WP Codebox returns the reviewer-safe result projection and stages the generated completion report as a declared command artifact.

## Secrets And Publication Credentials

Expand Down
4 changes: 2 additions & 2 deletions tests/docs-agent-native-workflow-contract.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ function agents_api_docs_agent_contract_match( string $content, string $pattern,
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*audience:\s*technical\s*$~m', 'Consumer audience must be technical.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*run_kind:\s*maintenance\s*$~m', 'Consumer run kind must be maintenance.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*base_ref:\s*main\s*$~m', 'Consumer target base must be main.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*docs_branch:\s*docs-agent/agents-api-docs-upkeep\s*$~m', 'Consumer publication branch must be stable and exact.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*docs_branch:\s*docs-agent/agents-api-docs-upkeep-v2\s*$~m', 'Consumer publication branch must be stable and exact.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*writable_paths:\s*README\.md,docs/\*\*\s*$~m', 'Consumer writable paths must be README.md,docs/**.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~"id":\s*"workflow-run-awaiter".*?"https://github\.com/Automattic/agents-api/pull/422".*?"src/Workflows/class-wp-agent-workflow-run-awaiter\.php".*?"tests/workflow-run-awaiter-smoke\.php".*?"requires_documentation_change":\s*true~s', 'Consumer must declare the bounded workflow awaiter documentation drift.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~"id":\s*"workflow-run-awaiter".*?"https://github\.com/Automattic/agents-api/pull/422".*?"src/Workflows/class-wp-agent-workflow-run-awaiter\.php".*?"tests/workflow-run-awaiter-smoke\.php".*?"requires_documentation_change":\s*false~s', 'Consumer must retain the bounded, satisfied workflow awaiter source record.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~"composer install --no-interaction --prefer-dist --no-progress"\s*,\s*"composer test"\s*,\s*"php tests/no-product-imports-smoke\.php"~s', 'Consumer verification commands must hydrate dependencies before the test chain.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~"git diff --check"~', 'Consumer drift check must run git diff --check.', $failures );
agents_api_docs_agent_contract_match( $consumer_workflow, '~^\s*OPENAI_API_KEY:\s*\$\{\{ secrets\.OPENAI_API_KEY \}\}\s*$~m', 'Consumer must forward OPENAI_API_KEY.', $failures );
Expand Down