Skip to content

Commit be109aa

Browse files
authored
Make technical bootstrap execute required workspace writes (#179)
* Make technical bootstrap execute required workspace writes * Correct technical bootstrap package provenance
1 parent 7b67d34 commit be109aa

11 files changed

Lines changed: 56 additions & 18 deletions

.github/workflows/maintain-docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Maintain Docs
22

33
env:
44
# Advance this revision and all package digests together when package bytes change.
5-
DOCS_AGENT_PACKAGE_REVISION: a39d9db230eb9e0b72ed84465f4d61bd8dda1bab
5+
DOCS_AGENT_PACKAGE_REVISION: a51e79ac698610177852170332a1135a9c315951
66
# Advance independently when the post-command completion validator changes.
77
DOCS_AGENT_COMPLETION_CONTRACT_REVISION: b136f9bc84e6f0ad9d5d0d5cdbb3df9c62e382e2
88

@@ -153,7 +153,7 @@ jobs:
153153
technical:bootstrap)
154154
package_path="bundles/technical-docs-agent/native/technical-docs-bootstrap-agent.agent.json"
155155
agent_slug="technical-docs-bootstrap-agent"
156-
package_digest="sha256-bytes-v1:0230e0e3fd8a4f045a545407d3d01c22df537b05f031260e29d6b531285b7839"
156+
package_digest="sha256-bytes-v1:124924f004474d5296294a3f2c99285d0848c46ed622926b1b283ed018b2bcf0"
157157
lane_requires_pr=true
158158
default_prompt="Bootstrap source-grounded developer documentation that helps developers understand, use, and extend the code in the repository."
159159
;;

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ Docs Agent has one canonical architecture: five standalone native Agents API pac
230230
- `bundles/user-docs-agent/native/user-docs-maintenance-agent.agent.json`
231231
- `bundles/skills-agent/native/skills-maintenance-agent.agent.json`
232232

233-
These five `.agent.json` files are the complete executable package surface. Each package is the sole executable instruction authority for its lane. The reusable workflow maps `audience` and `run_kind` to exactly one package and its canonical agent slug; it does not select a separate manifest, flow, pipeline, or memory envelope. Every descriptor uses the package-source revision `a39d9db230eb9e0b72ed84465f4d61bd8dda1bab`, independently of the revision that invokes the reusable workflow, and supplies a byte-level `sha256-bytes-v1` digest.
233+
These five `.agent.json` files are the complete executable package surface. Each package is the sole executable instruction authority for its lane. The reusable workflow maps `audience` and `run_kind` to exactly one package and its canonical agent slug; it does not select a separate manifest, flow, pipeline, or memory envelope. Every descriptor uses the package-source revision `a51e79ac698610177852170332a1135a9c315951`, independently of the revision that invokes the reusable workflow, and supplies a byte-level `sha256-bytes-v1` digest.
234234

235235
Package updates advance the package-source revision and all five declared digests atomically. The immutable-source validator reads each package blob from that Git revision, recomputes its digest and canonical slug, and rejects a descriptor that does not match those historical bytes.
236236

237-
All five packages support direct import through `wp_agent_import_runtime_bundles()` and retain the source-grounded workspace-only editing boundary. They intentionally have no required write-tool gate: deterministic report/diff postconditions reject no-op writes while allowing honest no-change maintenance.
237+
All five packages support direct import through `wp_agent_import_runtime_bundles()` and retain the source-grounded workspace-only editing boundary. Technical bootstrap has an Agents API completion gate that requires a workspace documentation write before it can finish, so a fresh surface cannot complete as prose only. Maintenance and the other no-change-capable lanes intentionally have no required write-tool gate; deterministic report/diff postconditions continue to reject no-op writes while allowing honest no-change maintenance.
238238

239239
### Compatibility Impact
240240

bundles/technical-docs-agent/native/technical-docs-bootstrap-agent.agent.json

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"schema_version": 1,
33
"bundle_slug": "technical-docs-bootstrap-agent",
44
"bundle_version": "0.1.0",
5-
"source_ref": "Automattic/docs-agent@3da1b8076359db9bf9f4ee7dadcc3932c080ed71",
6-
"source_revision": "3da1b8076359db9bf9f4ee7dadcc3932c080ed71",
5+
"source_ref": "Automattic/docs-agent@a51e79ac698610177852170332a1135a9c315951",
6+
"source_revision": "a51e79ac698610177852170332a1135a9c315951",
77
"agent": {
88
"agent_slug": "technical-docs-bootstrap-agent",
99
"agent_name": "Technical Docs Bootstrap Agent",
@@ -30,12 +30,23 @@
3030
"workspace_git_status",
3131
"workspace_git_diff"
3232
],
33-
"tool_call_rules": []
33+
"tool_call_rules": [
34+
{
35+
"id": "require-bootstrap-workspace-write",
36+
"require_tool_use": true,
37+
"min_tool_calls": 1,
38+
"require_one_of": [
39+
"workspace_write",
40+
"workspace_edit",
41+
"workspace_apply_patch"
42+
]
43+
}
44+
]
3445
},
3546
"meta": {
3647
"source_type": "runtime-agent-package",
3748
"source_package": "technical-docs-agent",
38-
"source_version": "3da1b8076359db9bf9f4ee7dadcc3932c080ed71",
49+
"source_version": "a51e79ac698610177852170332a1135a9c315951",
3950
"role": "technical-docs-bootstrap",
4051
"runtime": "agents-api-native-chat",
4152
"default_provider": "openai",

ci/docs-agent-runner-recipe.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"docsAgent": {
66
"externalPackageSource": {
77
"repository": "Automattic/docs-agent",
8-
"revision": "a39d9db230eb9e0b72ed84465f4d61bd8dda1bab",
8+
"revision": "a51e79ac698610177852170332a1135a9c315951",
99
"path": "bundles/technical-docs-agent/native/technical-docs-maintenance-agent.agent.json",
1010
"digest": "sha256-bytes-v1:975c7b0a0a7aff52897c52be5ac903a7fb110ea3c33e16227f8694c74c932519"
1111
},

examples/runner-recipe.example.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"docsAgent": {
66
"externalPackageSource": {
77
"repository": "Automattic/docs-agent",
8-
"revision": "a39d9db230eb9e0b72ed84465f4d61bd8dda1bab",
8+
"revision": "a51e79ac698610177852170332a1135a9c315951",
99
"path": "bundles/technical-docs-agent/native/technical-docs-maintenance-agent.agent.json",
1010
"digest": "sha256-bytes-v1:975c7b0a0a7aff52897c52be5ac903a7fb110ea3c33e16227f8694c74c932519"
1111
},

tests/native-agent-import.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public function get_error_data(): mixed {
3636
$passes = 0;
3737

3838
require_once $agents_api_dir . '/tests/agents-api-smoke-helpers.php';
39+
require_once $agents_api_dir . '/src/Runtime/class-wp-agent-message.php';
40+
require_once $agents_api_dir . '/src/Runtime/class-wp-agent-tool-call-gate.php';
3941
agents_api_smoke_require_module();
4042
do_action( 'init' );
4143

@@ -69,7 +71,21 @@ public function get_error_data(): mixed {
6971
$rules = is_array( $config['tool_call_rules'] ?? null ) ? $config['tool_call_rules'] : array();
7072

7173
agents_api_smoke_assert_equals( true, in_array( 'workspace_write', $config['enabled_tools'] ?? array(), true ), "{$slug} preserves the workspace write tool", $failures, $passes );
72-
agents_api_smoke_assert_equals( array(), $rules, "{$slug} permits clean evidence-backed no-change completion", $failures, $passes );
74+
if ( 'technical-docs-bootstrap-agent' === $slug ) {
75+
$gate = AgentsAPI\AI\WP_Agent_Tool_Call_Gate::from_config( $rules );
76+
agents_api_smoke_assert_equals( true, $gate instanceof AgentsAPI\AI\WP_Agent_Tool_Call_Gate, "{$slug} creates a completion gate for a fresh documentation surface", $failures, $passes );
77+
78+
$fresh_surface = array( AgentsAPI\AI\WP_Agent_Message::text( 'user', 'The workspace has no docs/README.md. Create the caller-required documentation paths.' ) );
79+
$blocked = $gate instanceof AgentsAPI\AI\WP_Agent_Tool_Call_Gate ? $gate->evaluate_completion( $fresh_surface ) : array();
80+
agents_api_smoke_assert_equals( false, $blocked['allowed'] ?? null, "{$slug} blocks prose-only completion on a fresh documentation surface", $failures, $passes );
81+
agents_api_smoke_assert_equals( 'require-bootstrap-workspace-write', $blocked['context']['rule_id'] ?? '', "{$slug} identifies the required bootstrap write gate", $failures, $passes );
82+
83+
$after_write = array_merge( $fresh_surface, array( AgentsAPI\AI\WP_Agent_Message::toolCall( '', 'workspace_write', array( 'path' => 'docs/README.md' ), 1, array( 'tool_call_id' => 'bootstrap-docs-index' ) ) ) );
84+
$allowed = $gate instanceof AgentsAPI\AI\WP_Agent_Tool_Call_Gate ? $gate->evaluate_completion( $after_write ) : array();
85+
agents_api_smoke_assert_equals( true, $allowed['allowed'] ?? null, "{$slug} accepts completion after a required workspace write", $failures, $passes );
86+
} else {
87+
agents_api_smoke_assert_equals( array(), $rules, "{$slug} permits clean evidence-backed no-change completion", $failures, $passes );
88+
}
7389

7490
$chat = AgentsAPI\AI\Channels\WP_Agent_Default_Chat_Handler::execute( array( 'agent' => $slug, 'message' => 'Verify native registration.' ) );
7591
agents_api_smoke_assert_equals( 'agents_chat_provider_required', $chat instanceof WP_Error ? $chat->get_error_code() : '', "{$slug} resolves through the default native chat handler", $failures, $passes );

tests/native-agent.validate-package-spec.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"technical-docs-bootstrap-agent.agent.json": {
1717
"package": "technical-docs-agent",
1818
"agent_slug": "technical-docs-bootstrap-agent",
19-
"source_revision": "3da1b8076359db9bf9f4ee7dadcc3932c080ed71",
19+
"source_revision": "a51e79ac698610177852170332a1135a9c315951",
2020
"required_tools": [
2121
"get_github_file",
2222
"workspace_read",
@@ -26,6 +26,12 @@
2626
"workspace_git_diff"
2727
],
2828
"permitted_workspace_tools": ["workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"],
29+
"required_tool_call_rule": {
30+
"id": "require-bootstrap-workspace-write",
31+
"require_tool_use": true,
32+
"min_tool_calls": 1,
33+
"require_one_of": ["workspace_write", "workspace_edit", "workspace_apply_patch"]
34+
},
2935
"instructions_must_contain": [
3036
"living documentation",
3137
"understand, use, and extend",

tests/reusable-workflow-empty-called-workflow-context.fixture.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"called_workflow_context": {
44
"job_workflow_sha": ""
55
},
6-
"expected_package_revision": "a39d9db230eb9e0b72ed84465f4d61bd8dda1bab"
6+
"expected_package_revision": "a51e79ac698610177852170332a1135a9c315951"
77
}

tests/validate-docs-agent-packages.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
$assert( 'docs-agent/runner-recipe/v1' === ( $recipe['schema'] ?? null ), 'Runner recipe must use the portable Docs Agent runner recipe schema.' );
4646
$expected_package_source = array(
4747
'repository' => 'Automattic/docs-agent',
48-
'revision' => 'a39d9db230eb9e0b72ed84465f4d61bd8dda1bab',
48+
'revision' => 'a51e79ac698610177852170332a1135a9c315951',
4949
'path' => 'bundles/technical-docs-agent/native/technical-docs-maintenance-agent.agent.json',
5050
'digest' => 'sha256-bytes-v1:975c7b0a0a7aff52897c52be5ac903a7fb110ea3c33e16227f8694c74c932519',
5151
);
@@ -217,7 +217,12 @@
217217
);
218218
$assert( ( $native_assertions['permitted_workspace_tools'] ?? array() ) === $workspace_tools, "Native package {$native_file} workspace tools do not match its permitted workspace tool policy." );
219219

220-
$assert( array() === ( $config['tool_call_rules'] ?? null ), "Native package {$native_file} must allow evidence-backed no-change completion without a no-op write." );
220+
$required_tool_call_rule = $native_assertions['required_tool_call_rule'] ?? null;
221+
if ( is_array( $required_tool_call_rule ) ) {
222+
$assert( in_array( $required_tool_call_rule, $config['tool_call_rules'] ?? array(), true ), "Native package {$native_file} must enforce its required tool-call rule." );
223+
} else {
224+
$assert( array() === ( $config['tool_call_rules'] ?? null ), "Native package {$native_file} must allow evidence-backed no-change completion without a no-op write." );
225+
}
221226

222227
// Runner-neutral boundary: no agent-owned publication tools.
223228
foreach ( $native_spec['forbidden_publication_tools'] ?? array() as $forbidden_tool ) {

tests/validate-external-native-package-sources.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
return $contents;
3131
};
3232

33-
$package_revision = 'a39d9db230eb9e0b72ed84465f4d61bd8dda1bab';
33+
$package_revision = 'a51e79ac698610177852170332a1135a9c315951';
3434
$packages = array(
35-
'technical:bootstrap' => array( 'path' => 'bundles/technical-docs-agent/native/technical-docs-bootstrap-agent.agent.json', 'slug' => 'technical-docs-bootstrap-agent', 'digest' => '0230e0e3fd8a4f045a545407d3d01c22df537b05f031260e29d6b531285b7839' ),
35+
'technical:bootstrap' => array( 'path' => 'bundles/technical-docs-agent/native/technical-docs-bootstrap-agent.agent.json', 'slug' => 'technical-docs-bootstrap-agent', 'digest' => '124924f004474d5296294a3f2c99285d0848c46ed622926b1b283ed018b2bcf0' ),
3636
'technical:maintenance' => array( 'path' => 'bundles/technical-docs-agent/native/technical-docs-maintenance-agent.agent.json', 'slug' => 'technical-docs-maintenance-agent', 'digest' => '975c7b0a0a7aff52897c52be5ac903a7fb110ea3c33e16227f8694c74c932519' ),
3737
'user:bootstrap' => array( 'path' => 'bundles/user-docs-agent/native/user-docs-bootstrap-agent.agent.json', 'slug' => 'user-docs-bootstrap-agent', 'digest' => 'a3ada797a125f638364caac43004bbb47fcc8c7bdc89021f25fcfcdc4c2d502f' ),
3838
'user:maintenance' => array( 'path' => 'bundles/user-docs-agent/native/user-docs-maintenance-agent.agent.json', 'slug' => 'user-docs-maintenance-agent', 'digest' => '747de10fdb52d7c1543b404030e0e0a2604b6496e95d50143149f72c975a98fb' ),

0 commit comments

Comments
 (0)