From 0d6ee3530596cf726735b13f61fa8030a4e1b7b4 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Tue, 14 Jul 2026 08:10:13 -0400 Subject: [PATCH] Remove legacy Data Machine Docs Agent bundles --- .github/workflows/README.md | 6 +- .github/workflows/tests.yml | 6 +- .github/workflows/validate.yml | 2 +- README.md | 14 +- .../flows/skills-maintenance-flow.json | 23 -- bundles/skills-agent/manifest.json | 42 ---- bundles/skills-agent/memory/agent/MEMORY.md | 40 ---- bundles/skills-agent/memory/agent/SOUL.md | 7 - .../pipelines/skills-pipeline.json | 17 -- .../flows/technical-docs-bootstrap-flow.json | 32 --- .../technical-docs-maintenance-flow.json | 23 -- bundles/technical-docs-agent/manifest.json | 43 ---- .../memory/agent/MEMORY.md | 53 ----- .../technical-docs-agent/memory/agent/SOUL.md | 7 - .../pipelines/technical-docs-pipeline.json | 17 -- .../flows/user-docs-bootstrap-flow.json | 32 --- .../flows/user-docs-maintenance-flow.json | 23 -- bundles/user-docs-agent/manifest.json | 43 ---- .../user-docs-agent/memory/agent/MEMORY.md | 47 ---- bundles/user-docs-agent/memory/agent/SOUL.md | 7 - .../pipelines/user-docs-pipeline.json | 17 -- tests/docs-agent.validate-bundle-spec.json | 122 ---------- ...> native-agent.validate-package-spec.json} | 12 +- tests/skills-agent.validate-bundle-spec.json | 31 --- ...nical-docs-agent.validate-bundle-spec.json | 45 ---- .../user-docs-agent.validate-bundle-spec.json | 48 ---- ...e.php => validate-docs-agent-packages.php} | 218 +++++------------- 27 files changed, 85 insertions(+), 892 deletions(-) delete mode 100644 bundles/skills-agent/flows/skills-maintenance-flow.json delete mode 100644 bundles/skills-agent/manifest.json delete mode 100644 bundles/skills-agent/memory/agent/MEMORY.md delete mode 100644 bundles/skills-agent/memory/agent/SOUL.md delete mode 100644 bundles/skills-agent/pipelines/skills-pipeline.json delete mode 100644 bundles/technical-docs-agent/flows/technical-docs-bootstrap-flow.json delete mode 100644 bundles/technical-docs-agent/flows/technical-docs-maintenance-flow.json delete mode 100644 bundles/technical-docs-agent/manifest.json delete mode 100644 bundles/technical-docs-agent/memory/agent/MEMORY.md delete mode 100644 bundles/technical-docs-agent/memory/agent/SOUL.md delete mode 100644 bundles/technical-docs-agent/pipelines/technical-docs-pipeline.json delete mode 100644 bundles/user-docs-agent/flows/user-docs-bootstrap-flow.json delete mode 100644 bundles/user-docs-agent/flows/user-docs-maintenance-flow.json delete mode 100644 bundles/user-docs-agent/manifest.json delete mode 100644 bundles/user-docs-agent/memory/agent/MEMORY.md delete mode 100644 bundles/user-docs-agent/memory/agent/SOUL.md delete mode 100644 bundles/user-docs-agent/pipelines/user-docs-pipeline.json delete mode 100644 tests/docs-agent.validate-bundle-spec.json rename tests/{native-agent.validate-bundle-spec.json => native-agent.validate-package-spec.json} (96%) delete mode 100644 tests/skills-agent.validate-bundle-spec.json delete mode 100644 tests/technical-docs-agent.validate-bundle-spec.json delete mode 100644 tests/user-docs-agent.validate-bundle-spec.json rename tests/{validate-docs-agent-bundle.php => validate-docs-agent-packages.php} (58%) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 61cad08..b6fa99a 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,6 +4,8 @@ The consumer workflow supports separate lanes for technical docs, user docs, and live skills maintenance. Use `audience: skills` with skills/package writable paths instead of broad docs paths. +The canonical execution architecture consists of exactly five native Agents API packages: technical bootstrap, technical maintenance, user bootstrap, user maintenance, and skills maintenance. Each `.agent.json` package is the sole executable instruction authority for its lane; `maintain-docs.yml` selects one immutable package without a separate manifest, flow, pipeline, or memory envelope. + Schedule skills upkeep separately from docs upkeep. The skills lane should use a dedicated branch such as `docs-agent/skills-upkeep`, skill/package writable paths, verification commands, and drift checks through the portable recipe. When validation setup, verification commands, or drift checks are needed, pass them through the reusable workflow inputs above. `validation_dependencies` is an optional caller-owned command that runs before verification during a live execution. The reusable workflow includes those executable inputs in the portable recipe and keeps the target repository as the writable Docs Agent workspace. @@ -22,4 +24,6 @@ The recipe boundary covers standalone native package selection, complete native Native package selection is expressed through recipe `docsAgent.externalPackageSource`. Workspace boundaries are expressed through recipe `runner` fields so agents remain workspace editors while caller-owned execution handles sandboxing and publication handoff. -Run `php tests/validate-docs-agent-bundle.php` after workflow changes so workflow routing and runner config stay aligned. +Direct consumers of the removed legacy manifests, flows, pipelines, or memory envelopes must migrate to the corresponding native `.agent.json` package. Existing `maintain-docs.yml` consumers already select native packages and are unaffected. + +Run `php tests/validate-docs-agent-packages.php` after workflow changes so package structure, workflow routing, and runner config stay aligned. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 960679e..cd02599 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ permissions: jobs: test: - name: Validate bundles and native imports + name: Validate native packages and imports runs-on: ubuntu-24.04 steps: - name: Check out Docs Agent @@ -29,9 +29,9 @@ jobs: token: ${{ github.token }} persist-credentials: false - - name: Run structural, link, and native importer tests + - name: Run package, link, and native importer tests run: | - php tests/validate-docs-agent-bundle.php + php tests/validate-docs-agent-packages.php php tests/validate-external-native-package-sources.php php tests/repair-docs-links-smoke.php AGENTS_API_DIR="$GITHUB_WORKSPACE/agents-api" php tests/native-agent-import.php diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 9cab132..4b99314 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -23,7 +23,7 @@ jobs: env: WP_CODEBOX_DIR: ${{ github.workspace }}/.wp-codebox run: | - php tests/validate-docs-agent-bundle.php + php tests/validate-docs-agent-packages.php php tests/validate-external-native-package-sources.php php tests/validate-wp-codebox-run-agent-task-contract.php php tests/repair-docs-links-smoke.php diff --git a/README.md b/README.md index 6ddec3e..8c97b3a 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Run skills upkeep as its own scheduled lane with `verification_commands`, `drift ## Native Packages -Docs Agent ships standalone native Agents API packages selected by the reusable workflow: +Docs Agent has one canonical architecture: five standalone native Agents API packages selected by the reusable workflow: - `bundles/technical-docs-agent/native/technical-docs-bootstrap-agent.agent.json` - `bundles/technical-docs-agent/native/technical-docs-maintenance-agent.agent.json` @@ -188,11 +188,15 @@ Docs Agent ships standalone native Agents API packages selected by the reusable - `bundles/user-docs-agent/native/user-docs-maintenance-agent.agent.json` - `bundles/skills-agent/native/skills-maintenance-agent.agent.json` -The reusable workflow maps `audience` and `run_kind` to exactly one package and its canonical agent slug. Every descriptor uses the package-source revision `7b2df969c34de112ec7ad13189ba94226a7f76f3`, independently of the revision that invokes the reusable workflow, and supplies a byte-level `sha256-bytes-v1` digest. +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 `7b2df969c34de112ec7ad13189ba94226a7f76f3`, independently of the revision that invokes the reusable workflow, and supplies a byte-level `sha256-bytes-v1` digest. 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. -Each lane also ships native Agents API runtime packages for direct import through `wp_agent_import_runtime_bundles()`: technical docs bootstrap and maintenance, user docs bootstrap and maintenance, and skills maintenance. These packages retain the same source-grounded workspace-only editing boundary and required workspace-write gate as their corresponding bundle lanes. +All five packages support direct import through `wp_agent_import_runtime_bundles()` and retain the source-grounded workspace-only editing boundary and required workspace-write gate. + +### Compatibility Impact + +Direct consumers of the removed legacy `manifest.json`, `flows/`, `pipelines/`, or memory envelopes must migrate to the corresponding native `.agent.json` package listed above. Consumers of `maintain-docs.yml` already use these native packages and require no workflow migration. ## Workflow Operation @@ -215,7 +219,7 @@ For skills PRs, also confirm the live instructions match current upstream tool b ## Validation ```bash -php tests/validate-docs-agent-bundle.php +php tests/validate-docs-agent-packages.php php tests/validate-external-native-package-sources.php php tests/repair-docs-links-smoke.php WP_CODEBOX_DIR=/path/to/wp-codebox php tests/validate-wp-codebox-run-agent-task-contract.php @@ -231,4 +235,4 @@ AGENTS_API_DIR=/path/to/agents-api php tests/native-agent-import.php It imports every native package through `wp_agent_import_runtime_bundles()`, verifies registration and preserved write-gate defaults, and invokes the default native chat handler far enough to resolve each registered agent. It intentionally fails when `AGENTS_API_DIR` is unavailable rather than treating an unexecuted importer as a passing test. It does not execute a model turn because the packages intentionally leave provider/model selection to the caller. -The `Docs Agent Tests` GitHub Actions workflow runs on pull requests and pushes. It fetches Docs Agent history so it can run the immutable native package source validator, then runs the structural bundle validator, docs-link repair smoke test, and native importer integration test against `Automattic/agents-api` at `fbd5641d412af76a1b8288426a577e750838b4be`, the merged commit from [Agents API #425](https://github.com/Automattic/agents-api/pull/425). +The `Docs Agent Tests` GitHub Actions workflow runs on pull requests and pushes. It fetches Docs Agent history so it can run the immutable native package source validator, then runs the structural package validator, docs-link repair smoke test, and native importer integration test against `Automattic/agents-api` at `fbd5641d412af76a1b8288426a577e750838b4be`, the merged commit from [Agents API #425](https://github.com/Automattic/agents-api/pull/425). diff --git a/bundles/skills-agent/flows/skills-maintenance-flow.json b/bundles/skills-agent/flows/skills-maintenance-flow.json deleted file mode 100644 index 5c45554..0000000 --- a/bundles/skills-agent/flows/skills-maintenance-flow.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "max_items": [], - "name": "Skills Maintenance", - "pipeline_slug": "skills-pipeline", - "schedule": "manual", - "schema_version": 1, - "slug": "skills-maintenance-flow", - "steps": [ - { - "enabled_tools": ["list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file", "workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"], - "handler_configs": {}, - "prompt_queue": [ - { - "added_at": "2026-05-10T00:00:00Z", - "prompt": "Maintenance pass for live agent skill instructions and generated packaged skill outputs. Review skills/**, plugins/**/skills/**, relevant build scripts, generated package outputs, package manifests, recent issues, recent pull requests, and available read-only context repository aliases for skill drift, prompt quality problems, stale upstream tool guidance, routing mistakes, writable-path policy gaps, verification gaps, and generated-output drift. This is a skills maintenance lane, not a technical docs maintenance lane: technical docs document skills, while this lane maintains the live skill instructions and generated copies themselves. Prefer focused updates that preserve prompt quality, task routing, tool-use policy, workspace safety, and reviewable behavior changes. For repositories with packaged skills, keep changes inside the consumer-declared writable paths, and update generated config or packaging files only when build scripts intentionally update them. Use context repository aliases as read-only source evidence when supplied; do not describe or depend on checkout mechanics. Run consumer-required verification such as build commands, repository checks, and generated-output drift checks when requested. When a workspace is provided, inspect and edit skills through workspace tools, then run workspace_git_status and workspace_git_diff before finishing. Use no_changes when existing live skills are accurate, generated outputs are aligned, verification expectations are already satisfied, and no focused skill behavior update is needed." - } - ], - "queue_mode": "static", - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/skills-agent/manifest.json b/bundles/skills-agent/manifest.json deleted file mode 100644 index e40f0e1..0000000 --- a/bundles/skills-agent/manifest.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "schema_version": 1, - "bundle_slug": "skills-agent", - "bundle_version": "0.1.0", - "source_ref": "Automattic/docs-agent@v0.1.0", - "source_revision": "edd29f580cc8c83f99e9f72b70973651ef6da905", - "exported_at": "2026-05-10T00:00:00Z", - "exported_by": "Franklin", - "agent": { - "slug": "skills-agent", - "label": "Skills Agent", - "description": "Reusable maintenance agent for live agent skill instructions and packaged skill outputs.", - "agent_config": { - "max_turns": 12, - "daily_memory": { - "enabled": false, - "recent_days": 0 - } - } - }, - "run_artifacts": { - "completion_assertions": { - "egress": ["pr-body"] - }, - "transcript_summary": { - "egress": ["artifact"] - } - }, - "included": { - "memory": ["MEMORY.md", "SOUL.md"], - "pipelines": ["skills-pipeline"], - "flows": [ - "skills-maintenance-flow" - ], - "prompts": [], - "rubrics": [], - "tool_policies": [], - "auth_refs": [], - "seed_queues": [], - "handler_auth": "refs" - } -} diff --git a/bundles/skills-agent/memory/agent/MEMORY.md b/bundles/skills-agent/memory/agent/MEMORY.md deleted file mode 100644 index 9a79db0..0000000 --- a/bundles/skills-agent/memory/agent/MEMORY.md +++ /dev/null @@ -1,40 +0,0 @@ -# Skills Agent Memory - -## Operating Model - -- Reusable bundle source: `Automattic/docs-agent`. -- Bundle path: `bundles/skills-agent`. -- Agent slug: `skills-agent`. -- The primitive is maintenance of live agent skill instructions and intentionally generated packaged copies. -- Consumer repositories provide target repo, event context, writable path scope, and credentials through their chosen runner. -- Skill updates must stay inside the runner-enforced writable path scope. -- No-op success is valid when live skills and generated package outputs are already aligned. -- One focused pull request is the review boundary when changes are needed. -- Maintenance flows keep skill instructions accurate as upstream tools, workflows, and package outputs change. - -## Skills Maintenance Rubric - -Good skills maintenance keeps executable agent instructions accurate, bounded, and reviewable. Before returning no-op success, audit whether the live skill files clearly cover: - -- Current upstream tool, build, package, and verification contracts used by the skills. -- Prompt quality, task routing, tool-use policy, workspace safety, writable-path constraints, and review expectations. -- Build and verification commands that prove skill packaging and generated outputs are aligned. -- Generated packaged copies and plugin skill outputs that build scripts intentionally maintain. -- Focused behavior changes that reviewers can evaluate without broad documentation rewrites. - -The technical docs lane may explain how skills work. This skills lane maintains the live skill instruction files themselves. - -## Supported Workflows - -- `skills-maintenance-flow`: ongoing live skill instruction and packaged-output maintenance. - -## Default Writable Scope - -Consumers should usually allow skills paths such as: - -- `skills/**` -- `plugins/**/skills/**` -- `plugins/**/README.md` when generated packaging docs must stay aligned -- generated MCP or plugin configuration files only when repository build scripts intentionally update them - -For repository-specific skills upkeep, use a canonical branch for the skills lane and verify with the consumer-declared build commands, repository checks, and generated-output drift checks. diff --git a/bundles/skills-agent/memory/agent/SOUL.md b/bundles/skills-agent/memory/agent/SOUL.md deleted file mode 100644 index 07af46c..0000000 --- a/bundles/skills-agent/memory/agent/SOUL.md +++ /dev/null @@ -1,7 +0,0 @@ -# Skills Agent Soul - -I am Skills Agent, a focused maintenance agent for live agent skill instructions and their packaged outputs. - -I maintain executable skill behavior from source evidence, current upstream tool contracts, build scripts, generated package outputs, and existing skill instructions. - -My best output is either a clean no-change result or one reviewable skills pull request. I optimize for accurate prompt behavior, tool routing, writable-path safety, packaging consistency, and focused review of behavior changes. diff --git a/bundles/skills-agent/pipelines/skills-pipeline.json b/bundles/skills-agent/pipelines/skills-pipeline.json deleted file mode 100644 index a6f5bcb..0000000 --- a/bundles/skills-agent/pipelines/skills-pipeline.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "Skills Maintenance", - "schema_version": 1, - "slug": "skills-pipeline", - "steps": [ - { - "step_config": { - "execution_order": 0, - "label": "Maintain live agent skill instructions and packaged outputs", - "step_type": "ai", - "system_prompt": "Maintain live agent skill instructions and intentionally generated packaged skill outputs in the target repository. The goal is a coherent living documentation surface for executable agent behavior: accurate prompts, routing rules, tool-use policy, writable-path guidance, build expectations, verification expectations, and review boundaries as upstream tool contracts change. Ground every skill change in source evidence, existing skill files, build scripts, generated outputs, tests, current upstream tool behavior, issues, pull requests, or available read-only context repository aliases. Treat skills as runtime behavior rather than prose-only documentation. The technical docs lane documents skills; this skills lane maintains the live skill instructions and generated packaged copies themselves. Preserve prompt quality and focused task routing, avoid broad docs rewrites, and treat each skill edit as a behavior change requiring focused review. Use context repository aliases as source evidence when supplied, while keeping the target workspace as the only writable boundary. Use no_changes when live skills and generated outputs are already aligned. When changes are needed, use the provided workspace for file edits, run repository verification expected by the consumer prompt such as build commands, repository checks, and generated-output drift checks, inspect the diff, and stop with the workspace changes in place." - }, - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/technical-docs-agent/flows/technical-docs-bootstrap-flow.json b/bundles/technical-docs-agent/flows/technical-docs-bootstrap-flow.json deleted file mode 100644 index da3b83e..0000000 --- a/bundles/technical-docs-agent/flows/technical-docs-bootstrap-flow.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "max_items": [], - "name": "Technical Documentation Bootstrap", - "pipeline_slug": "technical-docs-pipeline", - "schedule": "manual", - "schema_version": 1, - "slug": "technical-docs-bootstrap-flow", - "steps": [ - { - "enabled_tools": ["list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file", "workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"], - "tool_runtime_rules": [ - { - "id": "bootstrap-write-after-discovery", - "after_tool": "workspace_show", - "limited_tools": ["workspace_ls", "workspace_read", "workspace_grep", "list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file"], - "max_calls": 12, - "then_require_one_of": ["workspace_write", "workspace_edit", "workspace_apply_patch"] - } - ], - "handler_configs": {}, - "prompt_queue": [ - { - "added_at": "2026-05-10T00:00:00Z", - "prompt": "Bootstrap the repository's technical, developer-facing living documentation from source code. Treat this as a one-shot first-run documentation generation pass for developers who need to understand, use, and extend the code in this repository. Study README.md, docs/**, source directories, generated outputs, tests, examples, issues, and pull requests. Use open and recently closed issues and pull requests as source evidence for current architecture, accepted decisions, recently shipped behavior, rejected approaches, and known documentation gaps. Begin by building a source inventory of the repository-native product names, packages, modules, public helpers, interfaces/classes, hooks, filters, abilities, wire contracts, generated-output contracts, tests, storage boundaries, lifecycle paths, auth/permission behavior, failure modes, operational workflows, contributor-facing design principles, and the existing documentation information architecture. Use that inventory to create the complete initial documentation system needed for a new developer to understand the repository architecture, generated artifacts, build and verification flow, and supported integration contracts. Preserve or improve the repository's existing docs taxonomy, index convention, and topic grouping. Build the written documentation surface as repository documentation: README.md for entry points, docs/README.md for the technical docs index, focused docs/** topic pages for architecture/reference/workflows, and plugin README.md pages for plugin-specific developer contracts that need local coverage. Document generated agent-facing or tool-facing artifacts through docs/** reference pages and plugin README.md files that explain generator inputs, output layout, build pipeline, verification contract, and maintenance workflow. Organize the output into a concise docs index plus separate digestible topic pages whose hierarchy mirrors the repository architecture and logical module boundaries. Use clear titles, bounded scope, parent/child relationships, and useful cross-links so readers can move from architecture overview to focused implementation details without reading a monolithic page. Include reference-level details for public surfaces: names, purposes, core fields or method responsibilities, representative payloads or examples for common integration paths, generated-output responsibilities, and the tests or source areas that prove each behavior. Write topic pages first, then write or update the index last so navigation reflects written files. Make the index describe the completed written documentation system and link to pages that exist in the repository. Reconcile the written docs against the source inventory before finishing so the index and topic pages accurately reflect the inspected source. When the caller provides a bootstrap contract, satisfy its required paths, required glob counts, entry point links, and phrase checks as positive completion criteria for the completed documentation system. Use the provided workspace for all repository file changes. After writing docs, run workspace_git_status and workspace_git_diff before finishing. Record no_changes when the repository already has a navigable, source-grounded technical documentation surface that satisfies the complete bootstrap scope and any caller-declared bootstrap contract." - } - ], - "queue_mode": "static", - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/technical-docs-agent/flows/technical-docs-maintenance-flow.json b/bundles/technical-docs-agent/flows/technical-docs-maintenance-flow.json deleted file mode 100644 index 5c367a2..0000000 --- a/bundles/technical-docs-agent/flows/technical-docs-maintenance-flow.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "max_items": [], - "name": "Technical Documentation Maintenance", - "pipeline_slug": "technical-docs-pipeline", - "schedule": "manual", - "schema_version": 1, - "slug": "technical-docs-maintenance-flow", - "steps": [ - { - "enabled_tools": ["list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file", "workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"], - "handler_configs": {}, - "prompt_queue": [ - { - "added_at": "2026-05-10T00:00:00Z", - "prompt": "Maintenance pass for technical, developer-facing living documentation that helps developers understand, use, and extend the code in the repository. Review the repository source code, generated outputs, tests, existing docs, open and recently closed issues, and open and recently closed pull requests as source evidence for documentation drift, newly shipped behavior, changed public surfaces, changed generated-output contracts, and stale developer guidance. When source behavior changed, update the existing documentation pages that describe that behavior and add focused sections for new features, commands, APIs, extension points, workflows, compatibility boundaries, or operational requirements. When documentation changed without corresponding source behavior changes, verify that the written docs remain accurate, navigable, and aligned with source evidence, then record no_changes when they are already aligned. When a workspace is provided, inspect and edit documentation through workspace tools, then run workspace_git_status and workspace_git_diff before finishing. Preserve or improve the repository's existing docs taxonomy, index convention, and topic grouping. For source-code GitHub repositories, README.md and docs/ are the default technical documentation surfaces. Consumer prompts may declare a different audience namespace. Keep repository documentation organized as README.md entry points, docs/README.md indexes, focused docs/** topic pages, and plugin README.md pages for plugin-specific developer contracts that need local coverage. Prefer focused updates that keep existing docs aligned with current code behavior across repository-native product names, public APIs, generated-output contracts, internal processes, module connections, extension points, lifecycle, data contracts, auth/permissions, errors and failure modes, examples, operational workflows, compatibility boundaries, and software philosophy. For repositories that package agent-facing or tool-facing outputs, keep docs/** reference pages and plugin README.md files current about the generator inputs, output layout, build pipeline, verification contract, and maintenance workflow. Use no_changes when existing docs are accurate for the changed or inspected source areas and the docs are easy to navigate." - } - ], - "queue_mode": "static", - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/technical-docs-agent/manifest.json b/bundles/technical-docs-agent/manifest.json deleted file mode 100644 index ae284af..0000000 --- a/bundles/technical-docs-agent/manifest.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "bundle_slug": "technical-docs-agent", - "bundle_version": "0.1.0", - "source_ref": "Automattic/docs-agent@v0.1.0", - "source_revision": "4689706678a582c180686b43fb2beabbf7ee3059", - "exported_at": "2026-05-10T00:00:00Z", - "exported_by": "Franklin", - "agent": { - "slug": "technical-docs-agent", - "label": "Technical Docs Agent", - "description": "Reusable developer and operator documentation agent for GitHub repositories.", - "agent_config": { - "max_turns": 12, - "daily_memory": { - "enabled": false, - "recent_days": 0 - } - } - }, - "run_artifacts": { - "completion_assertions": { - "egress": ["pr-body"] - }, - "transcript_summary": { - "egress": ["artifact"] - } - }, - "included": { - "memory": ["MEMORY.md", "SOUL.md"], - "pipelines": ["technical-docs-pipeline"], - "flows": [ - "technical-docs-bootstrap-flow", - "technical-docs-maintenance-flow" - ], - "prompts": [], - "rubrics": [], - "tool_policies": [], - "auth_refs": [], - "seed_queues": [], - "handler_auth": "refs" - } -} diff --git a/bundles/technical-docs-agent/memory/agent/MEMORY.md b/bundles/technical-docs-agent/memory/agent/MEMORY.md deleted file mode 100644 index 072e9f4..0000000 --- a/bundles/technical-docs-agent/memory/agent/MEMORY.md +++ /dev/null @@ -1,53 +0,0 @@ -# Technical Docs Agent Memory - -## Operating Model - -- Reusable bundle source: `Automattic/docs-agent`. -- Bundle path: `bundles/technical-docs-agent`. -- Agent slug: `technical-docs-agent`. -- The primitive is source-code-derived technical documentation generation. -- Consumer repositories provide target repo, event context, writable path scope, and credentials through their chosen runner. -- Documentation updates must stay inside the runner-enforced writable path scope. -- No-op success is valid when technical docs are already aligned. -- One focused pull request is the review boundary when changes are needed. -- Bootstrap flows build the broad initial technical documentation surface; maintenance flows keep that surface accurate over time. - -## Technical Documentation Rubric - -Good technical documentation should make it easy for developers to understand, use, and extend the code in the repository. Before returning no-op success, audit whether existing docs clearly cover: - -- Public APIs, exported interfaces, commands, abilities, hooks, filters, events, and configuration. -- Internal processes, lifecycle, scheduling, queues, workflows, state transitions, and failure handling. -- Architecture boundaries, module relationships, data flow, and how the important pieces connect. -- Data contracts, value objects, storage, persistence, auth, permissions, and compatibility boundaries. -- Build, test, release, local development, and operational workflows. -- Practical examples for common integration, contribution, and extension paths. -- Software philosophy, ownership boundaries, constraints, and design principles that guide contributors. - -Prefer one clean, navigable documentation surface with useful cross-links over scattered fragments. `no_changes` means the docs are accurate, sufficiently broad, and easy to use across the rubric, not merely that some README exists. - -Use repository-native product names and source-grounded terminology. A technical docs run should explain generated outputs as part of the repository's architecture, build, verification, and maintenance contract. - -For repositories that package agent-facing or tool-facing outputs, document the generator inputs, output layout, generated artifact responsibilities, build pipeline, verification contract, and contributor workflow as repository documentation. - -## Supported Workflows - -- `technical-docs-bootstrap-flow`: first-run developer-facing documentation from source code. -- `technical-docs-maintenance-flow`: ongoing developer-facing documentation maintenance from source code. - -## Default Writable Scope - -Consumers should usually allow technical docs paths such as: - -- `README.md` -- `docs/**` -- `plugins/**/README.md` when plugin-specific developer contracts need local coverage - -Consumers may narrow or expand this list explicitly. - -## Documentation Structure Policy - -- Always inventory the repository's existing documentation information architecture before writing files. -- Preserve or improve the existing docs taxonomy, index convention, and topic grouping. -- Prefer a `docs/README.md` or existing docs index that links focused topic pages by architecture, API, runtime, operations, and integration areas when the repo has no stronger convention. -- Treat README.md, docs indexes, docs topic pages, and plugin README.md files as the written technical documentation surface. diff --git a/bundles/technical-docs-agent/memory/agent/SOUL.md b/bundles/technical-docs-agent/memory/agent/SOUL.md deleted file mode 100644 index e3f5d98..0000000 --- a/bundles/technical-docs-agent/memory/agent/SOUL.md +++ /dev/null @@ -1,7 +0,0 @@ -# Technical Docs Agent Soul - -I am Technical Docs Agent, a focused documentation agent for developers, site owners, operators, contributors, and integrators. - -I generate and maintain developer-facing living documentation from source code, tests, configuration, examples, issues, pull requests, and existing docs. - -My best output is either a clean no-change result or one reviewable technical documentation pull request. I optimize for accurate architecture, APIs, extension points, operational workflows, and contribution guidance. diff --git a/bundles/technical-docs-agent/pipelines/technical-docs-pipeline.json b/bundles/technical-docs-agent/pipelines/technical-docs-pipeline.json deleted file mode 100644 index 6143540..0000000 --- a/bundles/technical-docs-agent/pipelines/technical-docs-pipeline.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "Technical Documentation", - "schema_version": 1, - "slug": "technical-docs-pipeline", - "steps": [ - { - "step_config": { - "execution_order": 0, - "label": "Generate or maintain developer-facing documentation from source code", - "step_type": "ai", - "system_prompt": "Generate or maintain technical, developer-facing documentation from the target repository source code. The goal is a coherent living documentation surface that makes it easy for developers, site owners, operators, contributors, and integrators to work on, use, and extend the codebase as the code changes. Ground every claim in source code, tests, examples, existing docs, issues, or pull requests. Cover public APIs and exported interfaces; extension points, hooks, filters, abilities, events, commands, and configuration; internal processes, lifecycle, scheduling, queues, workflows, and state transitions; architecture boundaries and how modules connect; data contracts, value objects, storage, persistence, auth, permissions, and error/failure behavior; build, test, release, compatibility, and operational workflows; examples for common integration and extension paths; and the software philosophy, ownership boundaries, constraints, and design principles that should guide contributors. Start by inventorying the existing documentation information architecture. Preserve or improve the repository's current docs taxonomy, index conventions, and topic grouping. Write clean, navigable, practical documentation with clear sectioning and cross-links. Prefer improving the repo's existing documentation structure over creating scattered new pages. The selected flow defines whether this run is a first-run bootstrap pass or an ongoing maintenance pass. When the selected flow includes a caller-declared bootstrap contract, treat its required paths, required glob counts, entry point links, and phrase checks as positive completion criteria for the documentation surface. Use no_changes when the selected flow's completion criteria are satisfied by existing docs. When changes are needed, use the provided workspace for file edits and inspect the diff before finishing." - }, - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/user-docs-agent/flows/user-docs-bootstrap-flow.json b/bundles/user-docs-agent/flows/user-docs-bootstrap-flow.json deleted file mode 100644 index c33ee2d..0000000 --- a/bundles/user-docs-agent/flows/user-docs-bootstrap-flow.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "max_items": [], - "name": "User Documentation Bootstrap", - "pipeline_slug": "user-docs-pipeline", - "schedule": "manual", - "schema_version": 1, - "slug": "user-docs-bootstrap-flow", - "steps": [ - { - "enabled_tools": ["list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file", "workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"], - "tool_runtime_rules": [ - { - "id": "bootstrap-write-after-discovery", - "after_tool": "workspace_show", - "limited_tools": ["workspace_ls", "workspace_read", "workspace_grep", "list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file"], - "max_calls": 12, - "then_require_one_of": ["workspace_write", "workspace_edit", "workspace_apply_patch"] - } - ], - "handler_configs": {}, - "prompt_queue": [ - { - "added_at": "2026-05-10T00:00:00Z", - "prompt": "Bootstrap the repository's non-technical product documentation for frontend users. Treat this as a one-shot first-run user documentation generation pass. Study README overview language, existing user docs, UI strings and visible labels, product assets, support-style issues, release notes, and pull requests that describe user-visible behavior. Begin by building a private inventory of product features, user journeys, onboarding paths, settings users see, permissions or requirements users encounter, common tasks, expected outcomes, compatibility boundaries, troubleshooting paths, FAQ-worthy behaviors, and the existing user documentation information architecture. Use that inventory to create the complete initial documentation system that helps a new user understand the product and complete common tasks confidently. For source-code GitHub repositories where docs/ is already the technical documentation surface, place user docs in their own namespace such as docs/user/. Use docs/ as the primary user documentation surface for repositories that are explicitly user-docs-only or when the consumer prompt provides that product-docs path. Organize the output into a concise user docs index plus separate digestible task/topic pages whose hierarchy mirrors the product's user-facing architecture, feature areas, and natural task flows. Use clear titles, bounded scope, parent/child relationships, and useful cross-links so readers can move from overview to focused instructions without reading a monolithic page. Include practical product details: prerequisites as users experience them, setup steps through the product surface, expected outcomes, permission requirements, troubleshooting cues, and behavior notes. Write topic pages first, then write or update the user docs index last so navigation reflects written files. Make the index describe the completed written documentation system and link to pages that exist in the repository. Write every linked documentation page before finishing. When the caller provides a bootstrap contract, satisfy its required paths, required glob counts, entry point links, and phrase checks as positive completion criteria for the completed documentation system. Use the provided workspace for all repository file changes. After writing docs, run workspace_git_status and workspace_git_diff before finishing. Reconcile the written docs against the private product inventory before finishing so the index and topic pages accurately reflect the inspected product evidence. Record no_changes when the repository already has a navigable, product-grounded user documentation surface that satisfies the complete bootstrap scope and any caller-declared bootstrap contract." - } - ], - "queue_mode": "static", - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/user-docs-agent/flows/user-docs-maintenance-flow.json b/bundles/user-docs-agent/flows/user-docs-maintenance-flow.json deleted file mode 100644 index 29d7979..0000000 --- a/bundles/user-docs-agent/flows/user-docs-maintenance-flow.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "max_items": [], - "name": "User Documentation Maintenance", - "pipeline_slug": "user-docs-pipeline", - "schedule": "manual", - "schema_version": 1, - "slug": "user-docs-maintenance-flow", - "steps": [ - { - "enabled_tools": ["list_github_issues", "get_github_issue", "list_github_pulls", "get_github_pull", "get_github_pull_files", "get_github_pull_review_context", "github_pr_documentation_impact", "list_github_tree", "get_github_file", "workspace_show", "workspace_ls", "workspace_read", "workspace_grep", "workspace_write", "workspace_edit", "workspace_apply_patch", "workspace_git_status", "workspace_git_diff"], - "handler_configs": {}, - "prompt_queue": [ - { - "added_at": "2026-05-10T00:00:00Z", - "prompt": "Maintenance pass for non-technical product documentation. Review existing user docs, README overview language, UI strings and visible labels, product assets, support-style issues, release notes, and recent pull requests for user documentation gaps, drift, fragmentation, unclear guidance, and information architecture problems. When a workspace is provided, inspect and edit documentation through workspace tools, then run workspace_git_status and workspace_git_diff before finishing. For source-code GitHub repositories where docs/ is already the technical documentation surface, keep user docs in their own namespace such as docs/user/. Use docs/ as the primary user documentation surface only when the repository is explicitly user-docs-only or the consumer prompt provides that product-docs path. Prefer focused updates that keep existing user docs aligned with current product behavior: what users can do, getting started, product-surface setup, common tasks, visible settings, permissions, compatibility, expected outcomes, and troubleshooting. Use no_changes when existing user docs are accurate, sufficiently broad for the changed or inspected areas, and easy to navigate." - } - ], - "queue_mode": "static", - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/bundles/user-docs-agent/manifest.json b/bundles/user-docs-agent/manifest.json deleted file mode 100644 index 40c041f..0000000 --- a/bundles/user-docs-agent/manifest.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "bundle_slug": "user-docs-agent", - "bundle_version": "0.1.0", - "source_ref": "Automattic/docs-agent@v0.1.0", - "source_revision": "4689706678a582c180686b43fb2beabbf7ee3059", - "exported_at": "2026-05-10T00:00:00Z", - "exported_by": "Franklin", - "agent": { - "slug": "user-docs-agent", - "label": "User Docs Agent", - "description": "Reusable non-technical product documentation agent for frontend users.", - "agent_config": { - "max_turns": 12, - "daily_memory": { - "enabled": false, - "recent_days": 0 - } - } - }, - "run_artifacts": { - "completion_assertions": { - "egress": ["pr-body"] - }, - "transcript_summary": { - "egress": ["artifact"] - } - }, - "included": { - "memory": ["MEMORY.md", "SOUL.md"], - "pipelines": ["user-docs-pipeline"], - "flows": [ - "user-docs-bootstrap-flow", - "user-docs-maintenance-flow" - ], - "prompts": [], - "rubrics": [], - "tool_policies": [], - "auth_refs": [], - "seed_queues": [], - "handler_auth": "refs" - } -} diff --git a/bundles/user-docs-agent/memory/agent/MEMORY.md b/bundles/user-docs-agent/memory/agent/MEMORY.md deleted file mode 100644 index bfa8090..0000000 --- a/bundles/user-docs-agent/memory/agent/MEMORY.md +++ /dev/null @@ -1,47 +0,0 @@ -# User Docs Agent Memory - -## Operating Model - -- Reusable bundle source: `Automattic/docs-agent`. -- Bundle path: `bundles/user-docs-agent`. -- Agent slug: `user-docs-agent`. -- The primitive is non-technical product documentation for frontend users. -- Consumer repositories provide target repo, event context, writable path scope, and credentials through their chosen runner. -- Documentation updates must stay inside the runner-enforced writable path scope. -- No-op success is valid when user docs are already aligned. -- One focused pull request is the review boundary when changes are needed. -- Bootstrap flows build the broad initial user documentation surface; maintenance flows keep that surface accurate over time. - -## User Documentation Rubric - -Good user documentation should make it easy for non-technical product users to understand what the product does and complete work without understanding the implementation. Before returning no-op success, audit whether existing docs clearly cover: - -- Product purpose, core concepts, and expected outcomes. -- First-run setup and onboarding as experienced through the product surface. -- Common tasks and workflows in plain language. -- Settings, permissions, and requirements as users encounter them. -- Compatibility boundaries and feature availability in user-facing terms. -- Troubleshooting cues, recovery steps, and FAQ-worthy behavior. -- Navigation that moves from overview to task pages without one giant page. - -Write for frontend users. Use product names, feature names, visible labels, task steps, and outcomes. Use source evidence to make published product documentation accurate without exposing code-level mechanics. - -## Supported Workflows - -- `user-docs-bootstrap-flow`: first-run non-technical product documentation. -- `user-docs-maintenance-flow`: ongoing non-technical product documentation maintenance. - -## Default Writable Scope - -Consumers should usually give this agent a separate user-docs namespace such as: - -- `docs/user/**` - -Consumers may choose a different product-docs path explicitly, but the path should not share a flat index with technical docs. - -## Documentation Structure Policy - -- Keep user docs in their own namespace, such as `docs/user/`, with their own index. -- Organize pages by product task and user journey. -- Write plain-language pages focused on product concepts, visible labels, tasks, and outcomes. -- Use focused topic pages with cross-links instead of a monolithic guide. diff --git a/bundles/user-docs-agent/memory/agent/SOUL.md b/bundles/user-docs-agent/memory/agent/SOUL.md deleted file mode 100644 index bbddc00..0000000 --- a/bundles/user-docs-agent/memory/agent/SOUL.md +++ /dev/null @@ -1,7 +0,0 @@ -# User Docs Agent Soul - -I am User Docs Agent, a focused product documentation agent for non-technical frontend users. - -I generate and maintain plain-language documentation that helps people understand the product, get started, complete common tasks, recognize expected outcomes, and solve common problems. - -My best output is either a clean no-change result or one reviewable user documentation pull request. I write like a product support specialist, not a developer advocate. diff --git a/bundles/user-docs-agent/pipelines/user-docs-pipeline.json b/bundles/user-docs-agent/pipelines/user-docs-pipeline.json deleted file mode 100644 index 8dc30de..0000000 --- a/bundles/user-docs-agent/pipelines/user-docs-pipeline.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "User Documentation", - "schema_version": 1, - "slug": "user-docs-pipeline", - "steps": [ - { - "step_config": { - "execution_order": 0, - "label": "Generate or maintain non-technical product documentation", - "step_type": "ai", - "system_prompt": "Generate or maintain non-technical product documentation for frontend users of the target software. The goal is a coherent living documentation surface that helps users understand what the product does, get started, complete common tasks, recognize expected outcomes, and troubleshoot common problems. Use product-facing evidence: existing user docs, README overview language, UI strings and visible labels, screenshots or product assets when available, support-style issues, release notes, and pull requests that describe user-visible behavior. Write published pages in plain language for non-technical readers using product concepts, visible labels, task steps, expected outcomes, and troubleshooting cues. Start by inventorying the existing user documentation information architecture. For source-code GitHub repositories where docs/ is already the technical documentation surface, keep user docs in their own namespace such as docs/user/. Use docs/ as the primary user documentation surface only when the repository is explicitly user-docs-only or the consumer prompt provides that product-docs path. Create or update a user-docs index inside the selected namespace. The selected flow defines whether this run is a first-run bootstrap pass or an ongoing maintenance pass. When the selected flow includes a caller-declared bootstrap contract, treat its required paths, required glob counts, entry point links, and phrase checks as positive completion criteria for the documentation surface. Use no_changes when the selected flow's completion criteria are satisfied by existing user docs. When changes are needed, use the provided workspace for file edits and inspect the diff before finishing." - }, - "step_position": 0, - "step_type": "ai" - } - ] -} diff --git a/tests/docs-agent.validate-bundle-spec.json b/tests/docs-agent.validate-bundle-spec.json deleted file mode 100644 index 0a8536b..0000000 --- a/tests/docs-agent.validate-bundle-spec.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "bundles": { - "technical-docs-agent": { - "bundle_dir": "../bundles/technical-docs-agent", - "bundle_slug": "technical-docs-agent", - "agent_slug": "technical-docs-agent", - "expected_pipelines": ["technical-docs-pipeline"], - "expected_flows": [ - "technical-docs-bootstrap-flow", - "technical-docs-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"] - }, - "user-docs-agent": { - "bundle_dir": "../bundles/user-docs-agent", - "bundle_slug": "user-docs-agent", - "agent_slug": "user-docs-agent", - "expected_pipelines": ["user-docs-pipeline"], - "expected_flows": [ - "user-docs-bootstrap-flow", - "user-docs-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"] - }, - "skills-agent": { - "bundle_dir": "../bundles/skills-agent", - "bundle_slug": "skills-agent", - "agent_slug": "skills-agent", - "expected_pipelines": ["skills-pipeline"], - "expected_flows": [ - "skills-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"] - } - }, - "flow_assertions": { - "technical-docs-bootstrap-flow": { - "pipeline_slug": "technical-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_write", - "workspace_git_status", - "workspace_git_diff" - ] - }, - "technical-docs-maintenance-flow": { - "pipeline_slug": "technical-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["documentation drift", "newly shipped behavior", "changed public surfaces", "changed generated-output contracts", "documentation changed without corresponding source behavior changes", "README.md and docs/ are the default technical documentation surfaces", "plugin README.md pages"] - }, - "user-docs-bootstrap-flow": { - "pipeline_slug": "user-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_write", - "workspace_git_status", - "workspace_git_diff" - ], - "prompt_must_contain": ["one-shot first-run user documentation generation pass", "complete initial documentation system", "source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only", "bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"], - "prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - }, - "user-docs-maintenance-flow": { - "pipeline_slug": "user-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only"], - "prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - }, - "skills-maintenance-flow": { - "pipeline_slug": "skills-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["skills maintenance lane", "technical docs document skills", "read-only context repository aliases", "consumer-declared writable paths", "build commands", "repository checks", "generated-output drift checks"] - } - }, - "pipeline_assertions": { - "technical-docs-pipeline": { - "system_prompt_must_contain": "source code", - "system_prompt_must_contain_all": ["caller-declared bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"] - }, - "user-docs-pipeline": { - "system_prompt_must_contain": "frontend users", - "system_prompt_must_contain_all": ["source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only", "caller-declared bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"], - "system_prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - }, - "skills-pipeline": { - "system_prompt_must_contain": "live agent skill instructions", - "system_prompt_must_contain_all": ["runtime behavior", "technical docs lane documents skills", "read-only context repository aliases", "target workspace as the only writable boundary", "build commands", "repository checks", "generated-output drift checks"] - } - }, - "example_runner_config": "../examples/runner-recipe.example.json", - "example_assertions": { - "schema": "docs-agent/runner-recipe/v1", - "targetRepository": "OWNER/REPO" - } -} diff --git a/tests/native-agent.validate-bundle-spec.json b/tests/native-agent.validate-package-spec.json similarity index 96% rename from tests/native-agent.validate-bundle-spec.json rename to tests/native-agent.validate-package-spec.json index 442d23d..13a031a 100644 --- a/tests/native-agent.validate-bundle-spec.json +++ b/tests/native-agent.validate-package-spec.json @@ -1,5 +1,5 @@ { - "native_bundle_dirs": { + "native_package_dirs": { "technical-docs-agent": "../bundles/technical-docs-agent/native", "user-docs-agent": "../bundles/user-docs-agent/native", "skills-agent": "../bundles/skills-agent/native" @@ -25,7 +25,7 @@ ], "agents": { "technical-docs-bootstrap-agent.agent.json": { - "bundle": "technical-docs-agent", + "package": "technical-docs-agent", "agent_slug": "technical-docs-bootstrap-agent", "source_revision": "3da1b8076359db9bf9f4ee7dadcc3932c080ed71", "required_tools": [ @@ -55,7 +55,7 @@ ] }, "technical-docs-maintenance-agent.agent.json": { - "bundle": "technical-docs-agent", + "package": "technical-docs-agent", "agent_slug": "technical-docs-maintenance-agent", "source_revision": "3da1b8076359db9bf9f4ee7dadcc3932c080ed71", "required_tools": [ @@ -80,7 +80,7 @@ ] }, "user-docs-bootstrap-agent.agent.json": { - "bundle": "user-docs-agent", + "package": "user-docs-agent", "agent_slug": "user-docs-bootstrap-agent", "source_revision": "02e01e6d72ee158e45413185c32fcf30a5a04724", "required_tools": ["get_github_file", "workspace_read", "workspace_grep", "workspace_write", "workspace_git_status", "workspace_git_diff"], @@ -89,7 +89,7 @@ "instructions_must_contain": ["non-technical product documentation", "frontend users", "one-shot first-run user documentation generation pass", "product-facing evidence", "complete initial documentation system", "docs/user/", "consumer-declared writable paths", "required documentation write", "workspace_git_status", "workspace_git_diff"] }, "user-docs-maintenance-agent.agent.json": { - "bundle": "user-docs-agent", + "package": "user-docs-agent", "agent_slug": "user-docs-maintenance-agent", "source_revision": "02e01e6d72ee158e45413185c32fcf30a5a04724", "required_tools": ["get_github_file", "workspace_read", "workspace_grep", "workspace_edit", "workspace_git_status", "workspace_git_diff"], @@ -98,7 +98,7 @@ "instructions_must_contain": ["non-technical product documentation", "maintenance pass", "product-facing evidence", "docs/user/", "consumer-declared writable paths", "no_changes", "required documentation write", "workspace_git_status", "workspace_git_diff"] }, "skills-maintenance-agent.agent.json": { - "bundle": "skills-agent", + "package": "skills-agent", "agent_slug": "skills-maintenance-agent", "source_revision": "02e01e6d72ee158e45413185c32fcf30a5a04724", "required_tools": ["get_github_file", "workspace_read", "workspace_grep", "workspace_edit", "workspace_git_status", "workspace_git_diff"], diff --git a/tests/skills-agent.validate-bundle-spec.json b/tests/skills-agent.validate-bundle-spec.json deleted file mode 100644 index bd70e34..0000000 --- a/tests/skills-agent.validate-bundle-spec.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "bundle_dir": "../bundles/skills-agent", - "bundle_slug": "skills-agent", - "agent_slug": "skills-agent", - "expected_pipelines": ["skills-pipeline"], - "expected_flows": [ - "skills-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"], - "flow_assertions": { - "skills-maintenance-flow": { - "pipeline_slug": "skills-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["skills maintenance lane", "technical docs document skills", "read-only context repository aliases", "consumer-declared writable paths", "build commands", "repository checks", "generated-output drift checks"] - } - }, - "pipeline_assertions": { - "skills-pipeline": { - "system_prompt_must_contain": "live agent skill instructions", - "system_prompt_must_contain_all": ["runtime behavior", "technical docs lane documents skills", "read-only context repository aliases", "target workspace as the only writable PR boundary", "build commands", "repository checks", "generated-output drift checks"] - } - } -} diff --git a/tests/technical-docs-agent.validate-bundle-spec.json b/tests/technical-docs-agent.validate-bundle-spec.json deleted file mode 100644 index 9f73327..0000000 --- a/tests/technical-docs-agent.validate-bundle-spec.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "bundle_dir": "../bundles/technical-docs-agent", - "bundle_slug": "technical-docs-agent", - "agent_slug": "technical-docs-agent", - "expected_pipelines": ["technical-docs-pipeline"], - "expected_flows": [ - "technical-docs-bootstrap-flow", - "technical-docs-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"], - "flow_assertions": { - "technical-docs-bootstrap-flow": { - "pipeline_slug": "technical-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_write", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["understand, use, and extend the code in this repository", "one-shot first-run documentation generation pass", "complete initial documentation system", "open and recently closed issues and pull requests", "accepted decisions", "recently shipped behavior", "repository-native product names", "generated-output contracts", "README.md for entry points", "docs/README.md for the technical docs index", "plugin README.md pages", "generator inputs", "output layout", "verification contract", "bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"] - }, - "technical-docs-maintenance-flow": { - "pipeline_slug": "technical-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["understand, use, and extend the code in the repository", "open and recently closed issues", "open and recently closed pull requests", "source evidence", "documentation drift", "newly shipped behavior", "changed public surfaces", "changed generated-output contracts", "documentation changed without corresponding source behavior changes", "README.md and docs/ are the default technical documentation surfaces", "plugin README.md pages", "repository-native product names", "generated-output contracts", "generator inputs", "output layout", "verification contract"] - } - }, - "pipeline_assertions": { - "technical-docs-pipeline": { - "system_prompt_must_contain": "source code", - "system_prompt_must_contain_all": ["caller-declared bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"] - } - } -} diff --git a/tests/user-docs-agent.validate-bundle-spec.json b/tests/user-docs-agent.validate-bundle-spec.json deleted file mode 100644 index 031e197..0000000 --- a/tests/user-docs-agent.validate-bundle-spec.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "bundle_dir": "../bundles/user-docs-agent", - "bundle_slug": "user-docs-agent", - "agent_slug": "user-docs-agent", - "expected_pipelines": ["user-docs-pipeline"], - "expected_flows": [ - "user-docs-bootstrap-flow", - "user-docs-maintenance-flow" - ], - "memory_files": ["SOUL.md", "MEMORY.md"], - "flow_assertions": { - "user-docs-bootstrap-flow": { - "pipeline_slug": "user-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_write", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["one-shot first-run user documentation generation pass", "complete initial documentation system", "source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only", "bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"], - "prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - }, - "user-docs-maintenance-flow": { - "pipeline_slug": "user-docs-pipeline", - "ai_step_required_tools": [ - "get_github_file", - "workspace_read", - "workspace_grep", - "workspace_edit", - "workspace_git_status", - "workspace_git_diff" - ], - "completion_assertions_empty": true, - "prompt_must_contain": ["source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only"], - "prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - } - }, - "pipeline_assertions": { - "user-docs-pipeline": { - "system_prompt_must_contain": "frontend users", - "system_prompt_must_contain_all": ["source-code GitHub repositories", "docs/ is already the technical documentation surface", "docs/user/", "explicitly user-docs-only", "caller-declared bootstrap contract", "required paths", "required glob counts", "entry point links", "positive completion criteria"], - "system_prompt_forbidden": ["source code", "commands", "configuration examples", "CLI", "code snippets"] - } - } -} diff --git a/tests/validate-docs-agent-bundle.php b/tests/validate-docs-agent-packages.php similarity index 58% rename from tests/validate-docs-agent-bundle.php rename to tests/validate-docs-agent-packages.php index da4c5a9..6647980 100644 --- a/tests/validate-docs-agent-bundle.php +++ b/tests/validate-docs-agent-packages.php @@ -1,8 +1,8 @@ 'docs-agent/workspace-publication/v1', ); -$spec = $read_json( $root . '/tests/docs-agent.validate-bundle-spec.json' ); - -foreach ( $spec['bundles'] ?? array() as $bundle_name => $bundle_spec ) { - $bundle_dir = realpath( $root . '/tests/' . ( $bundle_spec['bundle_dir'] ?? '' ) ); - $assert( is_string( $bundle_dir ) && is_dir( $bundle_dir ), "Spec bundle_dir must point to an existing directory for {$bundle_name}." ); - - $manifest = $read_json( $bundle_dir . '/manifest.json' ); - $assert( ( $bundle_spec['bundle_slug'] ?? '' ) === ( $manifest['bundle_slug'] ?? '' ), "Manifest bundle_slug mismatch for {$bundle_name}." ); - $assert( ( $bundle_spec['agent_slug'] ?? '' ) === ( $manifest['agent']['slug'] ?? '' ), "Manifest agent slug mismatch for {$bundle_name}." ); - $assert( preg_match( '/^Automattic\/docs-agent@v\d+\.\d+\.\d+$/', (string) ( $manifest['source_ref'] ?? '' ) ) === 1, "Manifest source_ref must point at a Docs Agent release tag for {$bundle_name}." ); - $assert( preg_match( '/^[0-9a-f]{40}$/', (string) ( $manifest['source_revision'] ?? '' ) ) === 1, "Manifest source_revision must be a 40-character commit SHA for {$bundle_name}." ); - $assert( ! str_contains( strtolower( (string) ( $manifest['source_revision'] ?? '' ) ), 'initial-' ), "Manifest source_revision must not use placeholder provenance for {$bundle_name}." ); - - foreach ( $bundle_spec['memory_files'] ?? array() as $memory_file ) { - $assert( is_file( $bundle_dir . '/memory/agent/' . $memory_file ), "Missing {$bundle_name} memory file: {$memory_file}" ); - } - - foreach ( $bundle_spec['expected_pipelines'] ?? array() as $pipeline_slug ) { - $assert( in_array( $pipeline_slug, $manifest['included']['pipelines'] ?? array(), true ), "Manifest {$bundle_name} must include pipeline {$pipeline_slug}." ); - $pipeline = $read_json( $bundle_dir . '/pipelines/' . $pipeline_slug . '.json' ); - $pipeline_spec = $spec['pipeline_assertions'][ $pipeline_slug ] ?? array(); - $assert( $pipeline_slug === ( $pipeline['slug'] ?? '' ), "Pipeline slug mismatch for {$pipeline_slug}." ); - - $system_prompt = (string) ( $pipeline['steps'][0]['step_config']['system_prompt'] ?? '' ); - if ( isset( $pipeline_spec['system_prompt_must_contain'] ) ) { - $assert( str_contains( $system_prompt, (string) $pipeline_spec['system_prompt_must_contain'] ), "Pipeline {$pipeline_slug} system prompt missing required text." ); - } - foreach ( $pipeline_spec['system_prompt_must_contain_all'] ?? array() as $required ) { - $assert( str_contains( $system_prompt, (string) $required ), "Pipeline {$pipeline_slug} system prompt missing required text: {$required}" ); - } - foreach ( $pipeline_spec['system_prompt_forbidden'] ?? array() as $forbidden ) { - $assert( ! str_contains( $system_prompt, (string) $forbidden ), "Pipeline {$pipeline_slug} system prompt must not contain: {$forbidden}" ); - } - if ( str_contains( $pipeline_slug, 'docs-' ) || str_contains( $pipeline_slug, 'skills-' ) ) { - foreach ( array( 'runner', 'workspace_git_add', 'workspace_git_commit', 'workspace_git_push', 'create_github_pull_request', 'commit, push', 'open one reviewable pull request' ) as $forbidden_prompt_text ) { - $assert( ! str_contains( $system_prompt, $forbidden_prompt_text ), "Pipeline {$pipeline_slug} system prompt must not reference agent-owned publication: {$forbidden_prompt_text}" ); - } - $assert( str_contains( $system_prompt, 'provided workspace' ) || str_contains( $system_prompt, 'selected flow' ), "Pipeline {$pipeline_slug} must keep agent instructions scoped to workspace editing." ); - } - $assert( str_contains( strtolower( $system_prompt ), 'living documentation' ), "Pipeline {$pipeline_slug} must describe living documentation." ); - } - - foreach ( $bundle_spec['expected_flows'] ?? array() as $flow_slug ) { - $assert( in_array( $flow_slug, $manifest['included']['flows'] ?? array(), true ), "Manifest {$bundle_name} must include flow {$flow_slug}." ); - $flow = $read_json( $bundle_dir . '/flows/' . $flow_slug . '.json' ); - $flow_spec = $spec['flow_assertions'][ $flow_slug ] ?? array(); - $assert( $flow_slug === ( $flow['slug'] ?? '' ), "Flow slug mismatch for {$flow_slug}." ); - $assert( ( $flow_spec['pipeline_slug'] ?? '' ) === ( $flow['pipeline_slug'] ?? '' ), "Flow {$flow_slug} pipeline slug mismatch." ); - - $step = $flow['steps'][0] ?? array(); - $tools = $step['enabled_tools'] ?? array(); - foreach ( $flow_spec['ai_step_required_tools'] ?? array() as $required_tool ) { - $assert( in_array( $required_tool, $tools, true ), "Flow {$flow_slug} missing required tool: {$required_tool}" ); - } - - if ( ! empty( $flow_spec['completion_assertions_empty'] ) ) { - $assert( empty( $step['completion_assertions'] ?? array() ), "Flow {$flow_slug} must allow no-op success without required PR tools." ); - } - - $flow_prompt = strtolower( (string) ( $step['prompt_queue'][0]['prompt'] ?? '' ) ); - foreach ( $flow_spec['prompt_forbidden'] ?? array() as $forbidden ) { - $assert( ! str_contains( $flow_prompt, strtolower( (string) $forbidden ) ), "Flow {$flow_slug} prompt must not contain: {$forbidden}" ); - } - foreach ( $flow_spec['prompt_must_contain'] ?? array() as $required ) { - $assert( str_contains( $flow_prompt, strtolower( (string) $required ) ), "Flow {$flow_slug} prompt missing required text: {$required}" ); - } - if ( str_contains( $flow_slug, 'bootstrap' ) ) { - $completion_assertions = $step['completion_assertions'] ?? array(); - $assert( empty( $completion_assertions['required_tool_names'] ?? array() ), "Bootstrap flow {$flow_slug} must not require publication tools." ); - $assert( str_contains( $flow_prompt, 'provided workspace' ), "Bootstrap flow {$flow_slug} must direct agents to use the provided workspace." ); - foreach ( array( 'workspace_git_add', 'workspace_git_commit', 'workspace_git_push', 'create_github_pull_request', 'comment_github_pull_request' ) as $forbidden_tool ) { - $assert( ! in_array( $forbidden_tool, $tools, true ), "Bootstrap flow {$flow_slug} must not enable {$forbidden_tool}." ); - } - foreach ( array( 'workspace_git_add', 'workspace_git_commit', 'workspace_git_push', 'create_github_pull_request' ) as $forbidden_prompt_text ) { - $assert( ! str_contains( $flow_prompt, $forbidden_prompt_text ), "Bootstrap flow {$flow_slug} prompt must not reference {$forbidden_prompt_text}." ); - } - $assert( ! str_contains( $flow_prompt, 'create_or_update_github_file' ), "Bootstrap flow {$flow_slug} must not reference direct GitHub file writes." ); - foreach ( array( 'future coverage', 'deferred', 'saved for later', 'backlog' ) as $backlog_phrase ) { - $assert( ! str_contains( $flow_prompt, $backlog_phrase ), "Bootstrap flow {$flow_slug} must avoid backlog language: {$backlog_phrase}" ); - } - - $required_phrases = array( 'complete initial documentation system', 'documentation information architecture', 'separate', 'digestible', 'hierarchy mirrors', 'parent/child relationships', 'cross-links', 'completed written documentation system', 'write topic pages first', 'index last', 'link to pages that exist in the repository', 'bootstrap contract', 'required paths', 'required glob counts', 'entry point links', 'positive completion criteria' ); - $required_phrases = array_merge( $required_phrases, str_starts_with( $flow_slug, 'technical-' ) ? array( 'source inventory', 'preserve or improve', 'reference-level details', 'representative payloads or examples', 'reconcile the written docs against the source inventory' ) : array( 'private inventory', 'frontend users', 'user docs index', 'docs/user/', 'practical product details', 'reconcile the written docs against the private product inventory' ) ); - foreach ( $required_phrases as $phrase ) { - $assert( str_contains( $flow_prompt, strtolower( $phrase ) ), "Bootstrap flow {$flow_slug} missing phrase: {$phrase}" ); - } - } - if ( str_contains( $flow_slug, 'maintenance' ) ) { - foreach ( array( 'maintenance pass', 'focused updates', 'no_changes' ) as $phrase ) { - $assert( str_contains( $flow_prompt, $phrase ), "Maintenance flow {$flow_slug} missing phrase: {$phrase}" ); - } - } - if ( str_contains( $flow_slug, 'docs-' ) || str_contains( $flow_slug, 'skills-' ) ) { - foreach ( array( 'workspace_git_add', 'workspace_git_commit', 'workspace_git_push', 'create_github_pull_request', 'comment_github_pull_request' ) as $forbidden_tool ) { - $assert( ! in_array( $forbidden_tool, $tools, true ), "Workspace-editing flow {$flow_slug} must not enable {$forbidden_tool}." ); - } - foreach ( array( 'runner', 'workspace_git_add', 'workspace_git_commit', 'workspace_git_push', 'create_github_pull_request', 'commit, push', 'publish the pull request', 'open one' ) as $forbidden_prompt_text ) { - $assert( ! str_contains( $flow_prompt, $forbidden_prompt_text ), "Workspace-editing flow {$flow_slug} prompt must not reference {$forbidden_prompt_text}." ); - } - $assert( str_contains( $flow_prompt, 'workspace_git_status' ) && str_contains( $flow_prompt, 'workspace_git_diff' ), "Workspace-editing flow {$flow_slug} must end by inspecting status and diff." ); - } - } -} - -$example_path = $root . '/tests/' . ( $spec['example_runner_config'] ?? '' ); +$example_path = $root . '/examples/runner-recipe.example.json'; $example = $read_json( $example_path ); $recipe = $read_json( $root . '/ci/docs-agent-runner-recipe.json' ); -foreach ( $spec['example_assertions'] ?? array() as $key => $expected ) { - $assert( $expected === ( $example[ $key ] ?? null ), "Example config {$key} mismatch." ); -} - $assert( 'docs-agent/runner-recipe/v1' === ( $example['schema'] ?? null ), 'Example config must use the portable Docs Agent runner recipe schema.' ); +$assert( 'OWNER/REPO' === ( $example['targetRepository'] ?? null ), 'Example config must use the portable target repository placeholder.' ); $assert( 'docs-agent/runner-recipe/v1' === ( $recipe['schema'] ?? null ), 'Runner recipe must use the portable Docs Agent runner recipe schema.' ); $expected_package_source = array( 'repository' => 'Automattic/docs-agent', @@ -248,12 +141,7 @@ $assert( str_contains( $workflow_readme, 'Docs Agent declares the runtime sources' ), 'Workflow README must document Docs Agent ownership of the runtime closure.' ); $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.' ); -$public_docs = strtolower( - (string) file_get_contents( $root . '/README.md' ) . "\n" . - (string) file_get_contents( $root . '/.github/workflows/README.md' ) . "\n" . - (string) file_get_contents( $root . '/bundles/user-docs-agent/memory/agent/MEMORY.md' ) . "\n" . - (string) file_get_contents( $root . '/bundles/user-docs-agent/pipelines/user-docs-pipeline.json' ) -); +$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 ) { $assert( ! str_contains( $public_docs, $old_boundary_phrase ), "Public Docs Agent docs must use product-level API wording instead of: {$old_boundary_phrase}" ); } @@ -292,54 +180,70 @@ } /* - * Native agents-api agent bundle validation. + * Native Agents API package validation. * - * The native bundles are flat agent specs that import through the agents-api + * The native packages are flat agent specs that import through the Agents API * runtime bundle importer (`wp_agent_import_runtime_bundles`), which requires - * `agent.{agent_slug, agent_name, agent_config, meta}`. They carry no Data - * Machine pipeline/flow envelope and must preserve the same runner-neutral - * editing boundary as the reusable Data Machine bundle: workspace edits only, - * no agent-owned git/PR publication. + * `agent.{agent_slug, agent_name, agent_config, meta}`. Each package is the sole + * instruction authority for its lane and preserves a workspace-only editing + * boundary with no agent-owned git/PR publication. */ -$native_spec = $read_json( $root . '/tests/native-agent.validate-bundle-spec.json' ); +$native_spec = $read_json( $root . '/tests/native-agent.validate-package-spec.json' ); $native_dirs = array(); -foreach ( $native_spec['native_bundle_dirs'] ?? array() as $bundle_name => $native_bundle_dir ) { - $native_dir = realpath( $root . '/tests/' . $native_bundle_dir ); - $assert( is_string( $native_dir ) && is_dir( $native_dir ), "Native bundle dir must point to an existing directory for {$bundle_name}." ); - $native_dirs[ $bundle_name ] = $native_dir; +foreach ( $native_spec['native_package_dirs'] ?? array() as $package_name => $native_package_dir ) { + $native_dir = realpath( $root . '/tests/' . $native_package_dir ); + $assert( is_string( $native_dir ) && is_dir( $native_dir ), "Native package dir must point to an existing directory for {$package_name}." ); + $native_dirs[ $package_name ] = $native_dir; +} + +$expected_native_paths = array(); +foreach ( $native_spec['agents'] ?? array() as $native_file => $native_assertions ) { + $expected_native_paths[] = $native_dirs[ $native_assertions['package'] ] . '/' . $native_file; +} +sort( $expected_native_paths ); +$actual_native_paths = glob( $root . '/bundles/*/native/*.agent.json' ) ?: array(); +sort( $actual_native_paths ); +$assert( $expected_native_paths === $actual_native_paths, 'Docs Agent must expose exactly the five declared native packages.' ); + +foreach ( array_keys( $native_dirs ) as $package_name ) { + $package_dir = $root . '/bundles/' . $package_name; + $assert( ! is_file( $package_dir . '/manifest.json' ), "{$package_name} must not expose a legacy manifest." ); + foreach ( array( 'flows/*.json', 'pipelines/*.json', 'memory/agent/*' ) as $legacy_glob ) { + $assert( array() === ( glob( $package_dir . '/' . $legacy_glob ) ?: array() ), "{$package_name} must not expose legacy {$legacy_glob} descriptors." ); + } } foreach ( $native_spec['agents'] ?? array() as $native_file => $native_assertions ) { - $native_bundle_name = $native_assertions['bundle'] ?? ''; - $native_dir = $native_dirs[ $native_bundle_name ] ?? null; - $assert( is_string( $native_dir ), "Native bundle {$native_file} must name an existing native bundle directory." ); + $native_package_name = $native_assertions['package'] ?? ''; + $native_dir = $native_dirs[ $native_package_name ] ?? null; + $assert( is_string( $native_dir ), "Native package {$native_file} must name an existing native package directory." ); $native_path = $native_dir . '/' . $native_file; - $assert( is_file( $native_path ), "Missing native agent bundle file: {$native_file}" ); + $assert( is_file( $native_path ), "Missing native agent package file: {$native_file}" ); - $native_text = (string) file_get_contents( $native_path ); - $native_bundle = $read_json( $native_path ); + $native_text = (string) file_get_contents( $native_path ); + $native_package = $read_json( $native_path ); - $agent = $native_bundle['agent'] ?? array(); - $assert( is_array( $agent ), "Native bundle {$native_file} must declare an agent object." ); + $agent = $native_package['agent'] ?? array(); + $assert( is_array( $agent ), "Native package {$native_file} must declare an agent object." ); $source_revision = (string) ( $native_assertions['source_revision'] ?? '' ); - $assert( '' !== $source_revision, "Native bundle {$native_file} must declare its immutable source revision in the test spec." ); - $assert( "Automattic/docs-agent@{$source_revision}" === ( $native_bundle['source_ref'] ?? '' ), "Native bundle {$native_file} source_ref must resolve to the commit that contains this package." ); - $assert( $source_revision === ( $native_bundle['source_revision'] ?? '' ), "Native bundle {$native_file} source_revision must identify the commit that contains this package." ); - $assert( $source_revision === ( $agent['meta']['source_version'] ?? '' ), "Native bundle {$native_file} imported source_version must identify the package commit." ); + $assert( '' !== $source_revision, "Native package {$native_file} must declare its immutable source revision in the test spec." ); + $assert( "Automattic/docs-agent@{$source_revision}" === ( $native_package['source_ref'] ?? '' ), "Native package {$native_file} source_ref must resolve to the commit that contains this package." ); + $assert( $source_revision === ( $native_package['source_revision'] ?? '' ), "Native package {$native_file} source_revision must identify the commit that contains this package." ); + $assert( $source_revision === ( $agent['meta']['source_version'] ?? '' ), "Native package {$native_file} imported source_version must identify the package commit." ); // agents-api importer required shape. - $assert( ( $native_assertions['agent_slug'] ?? '' ) === ( $agent['agent_slug'] ?? '' ), "Native bundle {$native_file} agent_slug mismatch." ); - $assert( is_string( $agent['agent_name'] ?? null ) && '' !== trim( (string) $agent['agent_name'] ), "Native bundle {$native_file} must declare a non-empty agent_name." ); - $assert( is_array( $agent['agent_config'] ?? null ), "Native bundle {$native_file} must declare an agent_config object." ); - $assert( is_array( $agent['meta'] ?? null ), "Native bundle {$native_file} must declare a meta object." ); + $assert( ( $native_assertions['agent_slug'] ?? '' ) === ( $agent['agent_slug'] ?? '' ), "Native package {$native_file} agent_slug mismatch." ); + $assert( is_string( $agent['agent_name'] ?? null ) && '' !== trim( (string) $agent['agent_name'] ), "Native package {$native_file} must declare a non-empty agent_name." ); + $assert( is_array( $agent['agent_config'] ?? null ), "Native package {$native_file} must declare an agent_config object." ); + $assert( is_array( $agent['meta'] ?? null ), "Native package {$native_file} must declare a meta object." ); $config = $agent['agent_config']; - $assert( is_string( $config['instructions'] ?? null ) && '' !== trim( (string) $config['instructions'] ), "Native bundle {$native_file} agent_config.instructions must be a non-empty string." ); + $assert( is_string( $config['instructions'] ?? null ) && '' !== trim( (string) $config['instructions'] ), "Native package {$native_file} agent_config.instructions must be a non-empty string." ); $tools = $config['enabled_tools'] ?? array(); - $assert( is_array( $tools ) && array() !== $tools, "Native bundle {$native_file} agent_config.enabled_tools must be a non-empty list." ); + $assert( is_array( $tools ) && array() !== $tools, "Native package {$native_file} agent_config.enabled_tools must be a non-empty list." ); foreach ( $native_assertions['required_tools'] ?? array() as $required_tool ) { - $assert( in_array( $required_tool, $tools, true ), "Native bundle {$native_file} missing required tool: {$required_tool}" ); + $assert( in_array( $required_tool, $tools, true ), "Native package {$native_file} missing required tool: {$required_tool}" ); } $workspace_tools = array_values( @@ -348,7 +252,7 @@ static fn( $tool ): bool => is_string( $tool ) && str_starts_with( $tool, 'workspace_' ) ) ); - $assert( ( $native_assertions['permitted_workspace_tools'] ?? array() ) === $workspace_tools, "Native bundle {$native_file} workspace tools do not match its permitted workspace tool policy." ); + $assert( ( $native_assertions['permitted_workspace_tools'] ?? array() ) === $workspace_tools, "Native package {$native_file} workspace tools do not match its permitted workspace tool policy." ); $write_gate_id = $native_assertions['required_write_gate'] ?? ''; $write_gates = array_filter( @@ -356,25 +260,25 @@ static fn( $rule ): bool => is_array( $rule ) && $write_gate_id === ( $rule['id'] ?? '' ) ); $write_gate = reset( $write_gates ); - $assert( is_array( $write_gate ), "Native bundle {$native_file} must declare its required write gate." ); - $assert( true === ( $write_gate['require_tool_use'] ?? false ), "Native bundle {$native_file} write gate must require tool use." ); - $assert( 1 === ( $write_gate['min_tool_calls'] ?? 0 ), "Native bundle {$native_file} write gate must require at least one write." ); - $assert( array( 'workspace_write', 'workspace_edit', 'workspace_apply_patch' ) === ( $write_gate['require_one_of'] ?? array() ), "Native bundle {$native_file} write gate must require an allowed workspace write tool." ); + $assert( is_array( $write_gate ), "Native package {$native_file} must declare its required write gate." ); + $assert( true === ( $write_gate['require_tool_use'] ?? false ), "Native package {$native_file} write gate must require tool use." ); + $assert( 1 === ( $write_gate['min_tool_calls'] ?? 0 ), "Native package {$native_file} write gate must require at least one write." ); + $assert( array( 'workspace_write', 'workspace_edit', 'workspace_apply_patch' ) === ( $write_gate['require_one_of'] ?? array() ), "Native package {$native_file} write gate must require an allowed workspace write tool." ); // Runner-neutral boundary: no agent-owned publication tools. foreach ( $native_spec['forbidden_publication_tools'] ?? array() as $forbidden_tool ) { - $assert( ! in_array( $forbidden_tool, $tools, true ), "Native bundle {$native_file} must not enable publication tool: {$forbidden_tool}" ); + $assert( ! in_array( $forbidden_tool, $tools, true ), "Native package {$native_file} must not enable publication tool: {$forbidden_tool}" ); } - // No Data Machine coupling in the native bundle text. + // Native package documents must not carry legacy execution-envelope keys. foreach ( $native_spec['forbidden_dm_fragments'] ?? array() as $dm_fragment ) { - $assert( ! str_contains( $native_text, $dm_fragment ), "Native bundle {$native_file} must not contain Data Machine fragment: {$dm_fragment}" ); + $assert( ! str_contains( $native_text, $dm_fragment ), "Native package {$native_file} must not contain Data Machine fragment: {$dm_fragment}" ); } $instructions = strtolower( (string) $config['instructions'] ); foreach ( $native_assertions['instructions_must_contain'] ?? array() as $required_phrase ) { - $assert( str_contains( $instructions, strtolower( (string) $required_phrase ) ), "Native bundle {$native_file} instructions missing required text: {$required_phrase}" ); + $assert( str_contains( $instructions, strtolower( (string) $required_phrase ) ), "Native package {$native_file} instructions missing required text: {$required_phrase}" ); } } -fwrite( STDOUT, "Docs Agent bundle validation passed.\n" ); +fwrite( STDOUT, "Docs Agent native package validation passed.\n" );