diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 4c5a1b1..11c735b 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -14,7 +14,7 @@ The reusable workflow declares the expected typed review artifacts for Docs Agen The target repository grants `contents: write`, `pull-requests: write`, and `issues: write`. Docs Agent forwards the caller-scoped `${{ github.token }}` to WP Codebox for same-repository publication, so consumers do not configure `ACCESS_TOKEN`. `OPENAI_API_KEY` is an optional workflow secret and is required only for a live OpenAI run; skipped and dry-run calls do not require it. `EXTERNAL_PACKAGE_SOURCE_POLICY` remains a separate required v1 JSON secret. Migrate its value to the exact one-line JSON in the root README: it authorizes the selected Docs Agent package, the pinned Agents API component, the pinned PHP AI Client overlay, and the checksum-pinned OpenAI provider artifact. Both secrets are forwarded to WP Codebox without serialization into the task descriptor. -Docs Agent consumes the released [WP Codebox v0.12.17](https://github.com/Automattic/wp-codebox/releases/tag/v0.12.17) workflow and passes the matching `wp_codebox_release_ref: v0.12.17` input. WP Codebox validates that the paired tags match, resolves the release tag, verifies its package version, materializes the declared native runtime closure, and executes the selected imported package identity. It creates a secret-filtered external seed snapshot and passes it through canonical `task_input.workspaces` for the sandbox-local copy-on-write workspace. Canonical changed-files and patch references become actionable host-workspace changes; WP Codebox applies the bounded patch, runs validation and verification, then publishes approved host changes. Provider artifacts retain only canonical runtime-source and seed provenance: uploads contain allowlisted review artifacts, controlled workflow envelopes, and provenance metadata, never prepared source bytes or temporary snapshot paths. v0.12.17 independently uploads one compact reviewer transcript from a normalized canonical `codebox-transcript` ref. Its `wp-codebox/reviewer-agent-transcript/v1` projection records verified source and projection digests while preserving bounded review evidence. It omits raw stdout, source trees, secrets, setup stacks, package payloads, unknown fields, and private paths. Before persisting workflow results or artifact uploads, WP Codebox sanitizes private runtime paths from nested values, object keys, diagnostics, and command arguments. Lifecycle and downstream failures retain normalized runtime evidence in their normalized failed result, even when artifact preparation cannot complete. Diagnostic messages that name runtime classes remain reviewable; PHP-shaped runtime source remains blocked even under a reviewer-safe extension. See [WP Codebox #1767](https://github.com/Automattic/wp-codebox/issues/1767), [WP Codebox #1786](https://github.com/Automattic/wp-codebox/issues/1786), [WP Codebox #1788](https://github.com/Automattic/wp-codebox/issues/1788), [WP Codebox #1790](https://github.com/Automattic/wp-codebox/pull/1790), and [WP Codebox #1791](https://github.com/Automattic/wp-codebox/issues/1791). Regression references: [canonical transcript run `29344070545`](https://github.com/Automattic/wp-codebox/actions/runs/29344070545), [workspace handoff run `29324157852`](https://github.com/Automattic/build-with-wordpress/actions/runs/29324157852), and [snapshot topology run `29324563665`](https://github.com/Automattic/build-with-wordpress/actions/runs/29324563665). +Docs Agent consumes the released [WP Codebox v0.12.18](https://github.com/Automattic/wp-codebox/releases/tag/v0.12.18) workflow and passes the matching `wp_codebox_release_ref: v0.12.18` input. WP Codebox validates that the paired tags match, resolves the release tag, verifies its package version, materializes the declared native runtime closure, and executes the selected imported package identity. It creates a secret-filtered external seed snapshot and passes it through canonical `task_input.workspaces` for the sandbox-local copy-on-write workspace. Canonical changed-files and patch references become actionable host-workspace changes; WP Codebox applies the bounded patch, runs validation and verification, then publishes approved host changes. Provider artifacts retain only canonical runtime-source and seed provenance: uploads contain allowlisted review artifacts, controlled workflow envelopes, and provenance metadata, never prepared source bytes or temporary snapshot paths. v0.12.18 captures a pre-sanitization reviewer-evidence descriptor from exactly one trusted canonical `codebox-transcript`, persisting its artifact-relative path, schema, source digest, and size before runtime-result cleanup can rewrite paths. The uploader consumes only that descriptor and revalidates artifact-root containment, file type, schema, digest, and size before emitting the compact reviewer transcript as a `wp-codebox/reviewer-agent-transcript/v1` projection. The projection records verified source and projection digests while preserving bounded review evidence. It omits raw stdout, source trees, secrets, setup stacks, package payloads, unknown fields, and private paths. Before persisting workflow results or artifact uploads, WP Codebox sanitizes private runtime paths from nested values, object keys, diagnostics, and command arguments while preserving the stable relative reviewer-evidence descriptor. Lifecycle and downstream failures retain normalized runtime evidence in their normalized failed result, even when artifact preparation cannot complete. Diagnostic messages that name runtime classes remain reviewable; PHP-shaped runtime source remains blocked even under a reviewer-safe extension. See [WP Codebox #1767](https://github.com/Automattic/wp-codebox/issues/1767), [WP Codebox #1786](https://github.com/Automattic/wp-codebox/issues/1786), [WP Codebox #1788](https://github.com/Automattic/wp-codebox/issues/1788), [WP Codebox #1790](https://github.com/Automattic/wp-codebox/pull/1790), [WP Codebox #1791](https://github.com/Automattic/wp-codebox/issues/1791), and [WP Codebox #1795](https://github.com/Automattic/wp-codebox/issues/1795). Regression reference: [hosted canonical reviewer-evidence run `29350690551`](https://github.com/Automattic/build-with-wordpress/actions/runs/29350690551). ## Docs Agent Runner Recipe diff --git a/.github/workflows/maintain-docs.yml b/.github/workflows/maintain-docs.yml index 0b9e981..933b8fe 100644 --- a/.github/workflows/maintain-docs.yml +++ b/.github/workflows/maintain-docs.yml @@ -249,9 +249,9 @@ jobs: contents: write pull-requests: write issues: write - uses: Automattic/wp-codebox/.github/workflows/run-agent-task.yml@v0.12.17 + uses: Automattic/wp-codebox/.github/workflows/run-agent-task.yml@v0.12.18 with: - wp_codebox_release_ref: v0.12.17 + wp_codebox_release_ref: v0.12.18 external_package_source: ${{ needs.prepare.outputs.external_package_source }} runtime_sources: ${{ needs.prepare.outputs.runtime_sources }} workload_id: docs-agent-${{ inputs.audience }}-${{ inputs.run_kind }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index a919234..6e0ba53 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v4 with: repository: Automattic/wp-codebox - ref: v0.12.17 + ref: v0.12.18 path: .wp-codebox - name: Validate Docs Agent env: diff --git a/README.md b/README.md index 401fbd1..8ea3ff6 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Docs Agent declares the review artifacts it expects the runner to materialize as `maintain-docs.yml` writes `expected_artifacts` and `artifact_declarations` into a portable Docs Agent recipe and exposes the same declaration objects as `declared_artifacts_json`. -WP Codebox v0.12.17 separately uploads one compact reviewer transcript from the normalized canonical `codebox-transcript` reference. The `wp-codebox/reviewer-agent-transcript/v1` projection preserves bounded command, status, diagnostic, and workspace-tool evidence with verified source and projection digests. It excludes raw stdout, payloads, source trees, secrets, setup stacks, package data, and private paths. +WP Codebox v0.12.18 separately uploads one compact reviewer transcript through a pre-sanitization canonical reviewer-evidence descriptor. It resolves exactly one trusted `codebox-transcript` under the artifact root and records its artifact-relative path, schema, verified source digest, and size before runtime-result sanitization. The uploader revalidates that descriptor before producing the `wp-codebox/reviewer-agent-transcript/v1` projection, which preserves bounded command, status, diagnostic, and workspace-tool evidence with verified source and projection digests. It excludes raw stdout, payloads, source trees, secrets, setup stacks, package data, and private paths. Docs Agent owns native package selection, lane, artifact, prompt, and workspace mapping. Execution, credentials, AI provider selection, sandboxing, and publication are runner-owned concerns outside this repository. diff --git a/tests/validate-docs-agent-packages.php b/tests/validate-docs-agent-packages.php index 5988b48..85e673e 100644 --- a/tests/validate-docs-agent-packages.php +++ b/tests/validate-docs-agent-packages.php @@ -91,11 +91,11 @@ $transitional_homeboy_extensions_workflow = 'uses: Extra-Chill/homeboy-extensions/.github/workflows/runtime-agent-full-run.yml@main'; $forbidden_docs_agent_codebox_workflow = 'uses: Automattic/wp-codebox/.github/workflows/docs-agent-runner.yml@main'; -$generic_codebox_agent_task_workflow = 'uses: Automattic/wp-codebox/.github/workflows/run-agent-task.yml@v0.12.17'; +$generic_codebox_agent_task_workflow = 'uses: Automattic/wp-codebox/.github/workflows/run-agent-task.yml@v0.12.18'; $assert( ! str_contains( $maintain_docs_workflow, $transitional_homeboy_extensions_workflow ), 'maintain-docs.yml must not call Homeboy Extensions directly.' ); $assert( ! str_contains( $maintain_docs_workflow, $forbidden_docs_agent_codebox_workflow ), 'maintain-docs.yml must not call a Codebox-owned Docs Agent wrapper.' ); $assert( str_contains( $maintain_docs_workflow, $generic_codebox_agent_task_workflow ), 'maintain-docs.yml must call the generic Codebox agent-task workflow.' ); -$assert( str_contains( $maintain_docs_workflow, 'wp_codebox_release_ref: v0.12.17' ), 'maintain-docs.yml must pass the matching WP Codebox release tag.' ); +$assert( str_contains( $maintain_docs_workflow, 'wp_codebox_release_ref: v0.12.18' ), 'maintain-docs.yml must pass the matching WP Codebox release tag.' ); $workflow_blocked_runtime_fragments = array_values( array_diff( $blocked_runtime_fragments, array( 'wp-codebox', 'Automattic/wp-codebox', 'OPENAI_API_KEY' ) ) ); $workflow_internal_fragments = array_merge( $workflow_blocked_runtime_fragments, array( 'homeboy_extensions_ref:', 'runtime_ref:', 'runtime_ref }}', 'runtime_provider:', 'runtime_provider }}', 'runtime_profile:', 'runtime_profile }}', 'runtime_profiles:', 'runtime_profiles }}', 'runtime_execution:', 'runtime_execution }}', 'runtime_config:', 'runtime_config }}', 'component_contracts:', 'component_contracts }}', 'ability_requirements:', 'ability_requirements }}', 'runtime_components:', 'runtime_components }}', 'runtime_mounts:', 'runtime_mounts }}', 'required_abilities:', 'required_abilities }}', 'extra_wp_config_defines:' ) ); @@ -132,7 +132,7 @@ foreach ( array( 'Docs Agent Runner Recipe', 'portable recipe', 'Docs Agent owns the native package' ) as $migration_note_text ) { $assert( str_contains( $workflow_readme, $migration_note_text ), "Workflow README missing agent runtime note: {$migration_note_text}" ); } -$assert( str_contains( $workflow_readme, 'v0.12.17' ), 'Workflow README must record the WP Codebox release tag.' ); +$assert( str_contains( $workflow_readme, 'v0.12.18' ), 'Workflow README must record the WP Codebox release tag.' ); $assert( str_contains( $workflow_readme, 'Diagnostic messages that name runtime classes remain reviewable' ), 'Workflow README must document diagnostic-versus-source detection.' ); $assert( str_contains( $workflow_readme, 'allowlisted review artifacts' ), 'Workflow README must document the WP Codebox upload allowlist.' ); $assert( str_contains( $workflow_readme, 'normalized failed result' ), 'Workflow README must document normalized WP Codebox failures.' ); @@ -142,6 +142,7 @@ $assert( str_contains( $workflow_readme, 'WP Codebox materializes and lowers them under its generic runtime contract' ), 'Workflow README must document the generic producer lowering boundary.' ); $assert( str_contains( $workflow_readme, 'compact reviewer transcript' ), 'Workflow README must document the compact reviewer transcript upload.' ); $assert( str_contains( $workflow_readme, 'private paths' ), 'Workflow README must document the reviewer transcript privacy boundary.' ); +$assert( str_contains( $workflow_readme, 'pre-sanitization reviewer-evidence descriptor' ), 'Workflow README must document the pre-sanitization reviewer-evidence descriptor.' ); $public_docs = strtolower( (string) file_get_contents( $root . '/README.md' ) . "\n" . (string) file_get_contents( $root . '/.github/workflows/README.md' ) ); foreach ( array( 'hidden internals', 'implementation details', 'compatibility plumbing', 'consumers should not know', 'should not know', 'implementation internals', 'implementation evidence internal', 'plumbing to consumer workflows' ) as $old_boundary_phrase ) { diff --git a/tests/validate-wp-codebox-run-agent-task-contract.php b/tests/validate-wp-codebox-run-agent-task-contract.php index 0e83be8..876d506 100644 --- a/tests/validate-wp-codebox-run-agent-task-contract.php +++ b/tests/validate-wp-codebox-run-agent-task-contract.php @@ -76,6 +76,7 @@ $assert( true === ( $release['failure_evidence_preserved'] ?? null ), 'WP Codebox release fixture must preserve normalized runtime evidence on failures.' ); $assert( true === ( $release['canonical_compact_reviewer_transcript_upload'] ?? null ), 'WP Codebox release fixture must upload the canonical compact reviewer transcript.' ); $assert( true === ( $release['canonical_transcript_privacy_boundary'] ?? null ), 'WP Codebox release fixture must preserve the canonical transcript privacy boundary.' ); +$assert( true === ( $release['pre_sanitization_canonical_reviewer_evidence_descriptor'] ?? null ), 'WP Codebox release fixture must preserve the pre-sanitization canonical reviewer-evidence descriptor.' ); $native_result_path = $release['native_result_path'] ?? null; $workflow_result_path = $release['workflow_result_path'] ?? null; $assert( '.codebox/native-agent-task-result.json' === $native_result_path, 'WP Codebox release fixture must declare the controlled native result path.' ); @@ -257,7 +258,11 @@ $assert( str_contains( $producer_execute, 'runtime_result: redact(runtimeRecord)' ) && str_contains( $producer_execute, '...(downstreamFailure ? { failure:' ), 'WP Codebox must retain normalized runtime evidence when downstream execution fails.' ); $assert( str_contains( $producer_upload, 'function runtimeProvenance(request)' ) && str_contains( $producer_upload, 'runtime-provenance.json' ), 'WP Codebox uploads must retain runtime provenance without prepared source content.' ); $assert( str_contains( $producer_upload, 'function compactNativeInput(text)' ) && str_contains( $producer_upload, 'Temporary runner workspace seed paths must never be persisted in artifact uploads.' ), 'WP Codebox uploads must preserve seed provenance without exposing secret-filtered snapshot paths.' ); -$assert( str_contains( $producer_upload, 'async function canonicalTranscript(result)' ) && str_contains( $producer_upload, 'Canonical transcript requires exactly one trusted codebox-transcript path.' ), 'WP Codebox must derive reviewer evidence from exactly one normalized canonical transcript ref.' ); +$assert( str_contains( $producer_execute, 'async function canonicalReviewerTranscript(nativeRuntimeResult, artifactsPath)' ) && str_contains( $producer_execute, 'Canonical transcript requires exactly one distinct existing file.' ), 'WP Codebox must canonicalize reviewer evidence from one trusted transcript before sanitization.' ); +$assert( str_contains( $producer_execute, 'reviewerEvidence = await canonicalReviewerTranscript(nativeRuntimeResult, artifactsPath)' ) && str_contains( $producer_execute, 'let runtimeResult = sanitizeRuntimeSourceValue(nativeRuntimeResult, privateRuntimeSourceRootForSanitization)' ), 'WP Codebox must capture reviewer evidence before runtime-result sanitization.' ); +$assert( str_contains( $producer_execute, '...(reviewerEvidence ? { reviewer_evidence: reviewerEvidence } : {})' ), 'WP Codebox must persist the canonical reviewer-evidence descriptor in workflow results.' ); +$assert( str_contains( $producer_upload, 'const descriptor = record(record(result).reviewer_evidence).transcript' ) && str_contains( $producer_upload, 'Reviewer evidence transcript descriptor is malformed.' ), 'WP Codebox uploads must consume only the persisted reviewer-evidence descriptor.' ); +$assert( str_contains( $producer_upload, 'Canonical transcript digest does not match its reviewer evidence descriptor.' ) && str_contains( $producer_upload, 'Canonical transcript size does not match its reviewer evidence descriptor.' ), 'WP Codebox uploads must revalidate canonical reviewer-evidence digest and size.' ); $assert( str_contains( $producer_upload, 'schema: "wp-codebox/reviewer-agent-transcript/v1"' ) && str_contains( $producer_upload, '".codebox", "agent-task-artifacts", "transcript.json"' ), 'WP Codebox must upload the compact reviewer transcript at its controlled path.' ); $assert( str_contains( $producer_upload, 'source_sha256: actualDigest, projection_sha256: projectionDigest' ) && str_contains( $producer_upload, 'canonical_transcripts: [transcript]' ), 'WP Codebox must retain verified canonical transcript provenance.' ); $assert( str_contains( $producer_upload, 'omitted_payloads' ) && str_contains( $producer_upload, '[host-path]' ) && str_contains( $producer_upload, '[redacted-source-content]' ), 'WP Codebox reviewer transcripts must omit payloads and redact private paths or source content.' ); @@ -269,7 +274,7 @@ $assert( in_array( '.codebox/agent-task-request.json', $producer_upload_regression['observed']['uploaded'] ?? array(), true ), 'WP Codebox upload regression fixture must retain the controlled request upload.' ); $assert( ! array_intersect( array( 'MODEL_PROVIDER_SECRET_1', 'MODEL_PROVIDER_SECRET_2', 'MODEL_PROVIDER_SECRET_3', 'MODEL_PROVIDER_SECRET_4', 'MODEL_PROVIDER_SECRET_5' ), array_keys( $caller_secrets ) ), 'Docs Agent must forward only the OPENAI_API_KEY provider secret name.' ); -$assert( str_contains( $workflow, 'output_projections="$(jq -cn --arg path \'metadata.runner_workspace_publication.url\' --argjson required "$success_requires_pr" \'{docs_agent_publication:{path:$path,required:$required}}\')"' ), 'Docs Agent must define the v0.12.17 publication projection descriptor.' ); +$assert( str_contains( $workflow, 'output_projections="$(jq -cn --arg path \'metadata.runner_workspace_publication.url\' --argjson required "$success_requires_pr" \'{docs_agent_publication:{path:$path,required:$required}}\')"' ), 'Docs Agent must define the v0.12.18 publication projection descriptor.' ); $docs_projections = array( 'docs_agent_publication' => array( 'path' => 'metadata.runner_workspace_publication.url', @@ -279,7 +284,7 @@ $publication_descriptor = $docs_projections['docs_agent_publication'] ?? null; $assert( is_array( $publication_descriptor ), 'Docs Agent must define the docs_agent_publication projection descriptor.' ); $publication_path = $publication_descriptor['path'] ?? null; -$assert( 'metadata.runner_workspace_publication.url' === $publication_path, 'Docs Agent publication projection must use the v0.12.17 runner workspace publication URL path.' ); +$assert( 'metadata.runner_workspace_publication.url' === $publication_path, 'Docs Agent publication projection must use the v0.12.18 runner workspace publication URL path.' ); $producer_request_fixture = $read_json( rtrim( $wp_codebox_dir, '/' ) . '/contracts/agent-task-workflow-request.fixture.json' ); $producer_projection_paths = array_values( $producer_request_fixture['outputs']['projections'] ?? array() ); diff --git a/tests/wp-codebox-release.fixture.json b/tests/wp-codebox-release.fixture.json index 5402684..b5b6fc5 100644 --- a/tests/wp-codebox-release.fixture.json +++ b/tests/wp-codebox-release.fixture.json @@ -1,7 +1,7 @@ { - "tag": "v0.12.17", - "package_version": "0.12.17", - "run": "29344070545", + "tag": "v0.12.18", + "package_version": "0.12.18", + "run": "29350690551", "diagnostic_regression_run": "29307978522", "upload_regression_run": "29306539573", "successful_noop_optional_artifacts": true, @@ -23,6 +23,7 @@ "failure_evidence_preserved": true, "canonical_compact_reviewer_transcript_upload": true, "canonical_transcript_privacy_boundary": true, + "pre_sanitization_canonical_reviewer_evidence_descriptor": true, "native_result_path": ".codebox/native-agent-task-result.json", "workflow_result_path": ".codebox/agent-task-workflow-result.json" }