@phase1 @domain @repository @tool_registry Feature: Tool Registry Persistence As a system operator managing tools and validations I want the tool registry to reliably persist, retrieve, and filter tools So that the execution layer can discover and invoke tools at runtime Background: Given a clean in-memory database with the tool registry schema And a tool registry repository backed by the database And a validation attachment repository backed by the database # --------------------------------------------------------------------------- # Registering tools # --------------------------------------------------------------------------- @tool_reg_create Scenario: A new builtin tool is registered and retrievable Given a valid tool dict named "core/read-file" with source "builtin" When the tool is registered through the tool registry repository Then the tool registry repository should not raise an error And the persisted tool should have the registry name "core/read-file" @tool_reg_create Scenario: A custom tool with inline code is registered Given a valid tool dict named "local/custom-lint" with source "custom" And the tool dict includes inline code "return {'passed': True}" When the tool is registered through the tool registry repository Then the persisted tool should have the registry name "local/custom-lint" And the persisted tool should have source "custom" @tool_reg_create Scenario: An MCP tool is registered with server fields Given a valid tool dict named "mcp/github-search" with source "mcp" And the tool dict includes mcp_server "github" and mcp_tool_name "search" When the tool is registered through the tool registry repository Then the persisted tool should have the registry name "mcp/github-search" @tool_reg_create Scenario: A validation tool is registered with mode Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" When the tool is registered through the tool registry repository Then the persisted tool should have tool_type "validation" @tool_reg_create Scenario: A tool is registered with resource bindings Given a valid tool dict named "core/git-commit" with source "builtin" And the tool dict includes a resource binding for slot "repo" When the tool is registered through the tool registry repository Then the persisted tool should have 1 resource binding @tool_reg_create @error_handling Scenario: Registering a tool with a duplicate name is rejected Given a valid tool dict named "core/read-file" with source "builtin" And the tool has already been registered once in the tool registry When a second tool with the same registry name "core/read-file" is registered Then a DuplicateToolError should be raised mentioning "core/read-file" # --------------------------------------------------------------------------- # Retrieving tools by name # --------------------------------------------------------------------------- @tool_reg_read Scenario: A tool is retrieved by its namespaced name Given a valid tool dict named "core/write-file" with source "builtin" And the tool has been registered through the tool registry repository When the tool is looked up by registry name "core/write-file" Then the returned tool should have the registry name "core/write-file" @tool_reg_read Scenario: Looking up a non-existent tool name returns nothing When the tool is looked up by registry name "core/does-not-exist" Then no tool should be returned from the registry # --------------------------------------------------------------------------- # Listing tools with filters # --------------------------------------------------------------------------- @tool_reg_list Scenario: All tools are listed without filters Given the following tools have been registered: | name | source | tool_type | | core/read-file | builtin | tool | | core/write-file | builtin | tool | | local/custom-lint | custom | validation | When all tools are listed from the tool registry Then 3 tools should be returned from the registry @tool_reg_list Scenario: Tools are filtered by namespace Given the following tools have been registered: | name | source | tool_type | | core/read-file | builtin | tool | | local/custom-lint | custom | validation | When tools in the "core" namespace are listed from the registry Then 1 tools should be returned from the registry And the returned tool names from the registry should include "core/read-file" @tool_reg_list Scenario: Tools are filtered by tool_type Given the following tools have been registered: | name | source | tool_type | | core/read-file | builtin | tool | | core/schema-check | builtin | validation | When tools of type "validation" are listed from the registry Then 1 tools should be returned from the registry @tool_reg_list Scenario: Tools are filtered by source Given the following tools have been registered: | name | source | tool_type | | core/read-file | builtin | tool | | local/custom-lint | custom | tool | When tools with source "custom" are listed from the registry Then 1 tools should be returned from the registry # --------------------------------------------------------------------------- # Updating tools # --------------------------------------------------------------------------- @tool_reg_update Scenario: A tool description is updated Given a valid tool dict named "core/read-file" with source "builtin" And the tool has been registered through the tool registry repository When the tool description is updated to "Updated description" Then the persisted tool should have description "Updated description" @tool_reg_update Scenario: Tool resource bindings are replaced on update Given a valid tool dict named "core/git-commit" with source "builtin" And the tool dict includes a resource binding for slot "repo" And the tool has been registered through the tool registry repository When the tool is updated with a new resource binding for slot "workspace" Then the persisted tool should have 1 resource binding And the persisted tool binding slot should be "workspace" # --------------------------------------------------------------------------- # Deleting tools # --------------------------------------------------------------------------- @tool_reg_delete Scenario: A tool is removed from the registry Given a valid tool dict named "core/read-file" with source "builtin" And the tool has been registered through the tool registry repository When the tool "core/read-file" is removed from the registry Then the removal should return true from the registry And the tool should no longer exist in the registry @tool_reg_delete Scenario: Removing a non-existent tool returns false When the tool "core/nonexistent" is removed from the registry Then the removal should return false from the registry @tool_reg_delete @error_handling Scenario: Deleting a tool with active attachments is rejected Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And an unscoped validation attachment for "core/schema-check" on resource "res-001" When the tool "core/schema-check" is removed from the registry Then a ToolInUseError should be raised mentioning "core/schema-check" # --------------------------------------------------------------------------- # Validation attachment lifecycle # --------------------------------------------------------------------------- @tool_reg_attach Scenario: A validation is attached to a resource Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository When the validation "core/schema-check" is attached to resource "res-001" Then the attachment should have a valid ULID identifier And the attachment should reference resource "res-001" @tool_reg_attach Scenario: A validation is detached from a resource Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And an unscoped validation attachment for "core/schema-check" on resource "res-001" When the validation attachment is detached by its identifier Then the detachment should return true @tool_reg_attach Scenario: Detaching a non-existent attachment returns false When the validation attachment "01ZZZZZZZZZZZZZZZZZZZZZZZZ" is detached Then the non-existent detachment should return false @tool_reg_attach Scenario: Attachments are listed for a resource Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And an unscoped validation attachment for "core/schema-check" on resource "res-001" When all attachments for resource "res-001" are listed Then 1 attachment should be returned @tool_reg_attach Scenario: Attachments are scoped by project name Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And a project-scoped validation attachment for "core/schema-check" on resource "res-001" in project "my-project" And a project-scoped validation attachment for "core/schema-check" on resource "res-001" in project "other-project" When project-filtered attachments for resource "res-001" in project "my-project" are listed Then 1 attachment should be returned @tool_reg_attach Scenario: Attachments are scoped by plan identifier Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And a plan-scoped validation attachment for "core/schema-check" on resource "res-001" in plan "01PLAN00000000000000000001" When plan-filtered attachments for resource "res-001" with plan "01PLAN00000000000000000001" are listed Then 1 attachment should be returned @tool_reg_attach Scenario: An attachment is retrieved by its identifier Given a valid tool dict named "core/schema-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the tool registry repository And an unscoped validation attachment for "core/schema-check" on resource "res-001" When the attachment is retrieved by its stored identifier Then the retrieved attachment should reference validation "core/schema-check" # --------------------------------------------------------------------------- # Service layer integration # --------------------------------------------------------------------------- @tool_reg_service Scenario: The service registers and retrieves a tool Given a tool registry service backed by the repositories And a valid tool dict named "svc/echo" with source "builtin" When the tool is registered through the service And the tool is retrieved from the service by name "svc/echo" Then the service-returned tool should have the registry name "svc/echo" @tool_reg_service Scenario: The service attaches and detaches a validation Given a tool registry service backed by the repositories And a valid tool dict named "svc/val-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the service When the service attaches validation "svc/val-check" to resource "svc-res-001" And the service detaches the validation attachment Then the service detachment should return true @tool_reg_service Scenario: The service lists validations for a resource Given a tool registry service backed by the repositories And a valid tool dict named "svc/val-check" with source "builtin" And the tool dict has tool_type "validation" and mode "required" And the tool has been registered through the service And the service has attached validation "svc/val-check" to resource "svc-res-002" When the service lists validations for resource "svc-res-002" Then the service should return 1 validation attachment