fix(resources): remove unsupported executable resource type #3248

Merged
HAL9000 merged 2 commits from fix/remove-executable-resource-type into master 2026-05-30 20:11:57 +00:00
10 changed files with 53 additions and 134 deletions
+1
View File
@@ -6,6 +6,7 @@ Changed `wf10_batch.robot` to be less likely to create files, and
`plan_generation_graph.robot` to give more test answers.
## [Unreleased]
- **fix(resources): remove unsupported executable resource type and fix resource list columns** (#3077 / PR #3248): Removed `executable` from `LSP_RESOURCE_TYPES` and `BUILTIN_TYPE_NAMES` (the specification defines no such built-in type). Updated `agents resource list` CLI table columns from `[ID, Name, Type, Status, Kind, Location, Description]` to the spec-required `[Name, ID, Type, Phys/Virt, Children, Projects]`. Deleted orphaned `examples/resource-types/executable.yaml`. Lifecycle state for container resources is now displayed as a note below the resource table.
- **fix(cli): add Read-Only and Writes columns to tool list output** (#1476): Rewrote
`list_tools()` in `src/cleveragents/cli/commands/tool.py` to render exactly the 5
spec-required columns (Name, Type, Source, Read-Only, Writes), removed the legacy
+1
View File
@@ -55,3 +55,4 @@ Below are some of the specific details of various contributions.
dropped. Includes Behave BDD and Robot Framework regression tests.
* HAL 9000 has contributed the config-actor combined-format support fix (PR #11232 / issue #11189): added ``_detect_nested_config_actor()``, ``_flatten_config_actor()``, and handling in ``ActorConfiguration.from_blob()`` to transparently flatten the nested ``config.actor`` block from both compact-string and nested-dict forms so v3 detection, schema validation, and canonicalisation see flat data — eliminating the ``"provider is required"`` crash.
* HAL 9000 has contributed the actor compiler `actor_ref` field fix (issue #1429): corrected `_map_node()` and `compile_actor()` in `src/cleveragents/actor/compiler.py` to read `actor_ref` from the top-level `NodeDefinition.actor_ref` field instead of `node.config.get("actor_ref")`, resolving silent failures on all SUBGRAPH nodes where `subgraph_refs` was always empty and `NodeConfig.subgraph` was always `None`.
* HAL 9000 has contributed the removal of the unsupported executable resource type (PR #3248 / issue #3077): removed `executable` from `LSP_RESOURCE_TYPES` and `BUILTIN_TYPE_NAMES`, updated `agents resource list` CLI table columns to the spec-required `[Name, ID, Type, Phys/Virt, Children, Projects]`, deleted orphaned `examples/resource-types/executable.yaml`, and updated related BDD test coverage.
-29
View File
@@ -1,29 +0,0 @@
# Spec reference: docs/adr/ADR-039-container-resource-types.md lines 207-226
schema_version: "1.0"
name: executable
description: "System executable (language runtime, compiler, LSP server binary). Discovered from container or host PATH."
resource_kind: physical
sandbox_strategy: none
user_addable: true
built_in: true
cli_args:
- name: path
type: string
required: true
description: Absolute path to the executable
- name: version
type: string
required: false
description: Executable version if detectable
parent_types: ["container-exec-env", "fs-directory"]
child_types: []
handler: "cleveragents.resource.handlers.executable:ExecutableHandler"
auto_discovery:
trigger_types: ["container-exec-env", "fs-directory"]
scan_paths: []
lazy: true
capabilities:
read: true
write: false
sandbox: false
checkpoint: false
+8
View File
@@ -102,6 +102,14 @@ Feature: Resource CLI commands
When I run resource list with format "json"
Then the resource output should be valid JSON
Scenario: List resources shows spec-required columns
Given built-in types are bootstrapped
And I run resource add "git-checkout" "local/col-test" with path "/tmp/ctest"
When I run resource list
Then the resource output should contain "Phys/Virt"
And the resource output should contain "Children"
And the resource output should contain "Projects"
# ---- Resource Show ----
Scenario: Show a resource by name
@@ -7,10 +7,12 @@ Feature: agents resource list shows devcontainer lifecycle state column
Given a fresh in-memory resource registry
And built-in types are bootstrapped
Scenario: resource list shows "Status" column header
Scenario: resource list shows spec-required column headers
Given a devcontainer-instance resource is registered
When I run resource list with all flag
Then the resource output should contain "Status"
Then the resource output should contain "Phys/Virt"
And the resource output should contain "Children"
And the resource output should contain "Projects"
Scenario: resource list shows "detected (not built)" for a new devcontainer-instance
Given a devcontainer-instance resource is registered
@@ -68,8 +70,7 @@ Feature: agents resource list shows devcontainer lifecycle state column
Scenario: resource list shows lifecycle state for container-instance resources
Given a container-instance resource is registered
When I run resource list with all flag
Then the resource output should contain "Status"
And the resource output should contain "detected (not built)"
Then the resource output should contain "detected (not built)"
Scenario: resource list succeeds gracefully when lifecycle tracker raises an error
Given a devcontainer-instance resource is registered
+1 -23
View File
@@ -16,18 +16,12 @@ Feature: LSP Resource Types
Examples:
| type_name |
| executable |
| lsp-server |
| lsp-workspace |
| lsp-document |
# ── User-addable flags ────────────────────────────────────────
Scenario: executable is user-addable for lsp_rt
Given the built-in executable YAML file for lsp_rt
When I load the YAML via schema for lsp_rt
Then the lsp_rt schema user_addable should be true
Scenario: lsp-server is user-addable for lsp_rt
Given the built-in lsp-server YAML file for lsp_rt
When I load the YAML via schema for lsp_rt
@@ -51,12 +45,6 @@ Feature: LSP Resource Types
Then the lsp_rt capability read should be true
And the lsp_rt capability write should be true
Scenario: executable has read-only capabilities for lsp_rt
Given the built-in executable YAML file for lsp_rt
When I load the YAML via schema for lsp_rt
Then the lsp_rt capability read should be true
And the lsp_rt capability write should be false
# ── Parent/child hierarchy ────────────────────────────────────
Scenario: lsp-server has lsp-workspace as child type for lsp_rt
@@ -81,12 +69,6 @@ Feature: LSP Resource Types
# ── Auto-discovery ────────────────────────────────────────────
Scenario: executable has auto-discovery from container-exec-env for lsp_rt
Given the built-in executable YAML file for lsp_rt
When I load the YAML via schema for lsp_rt
Then the lsp_rt auto_discovery should be present
And the lsp_rt auto_discovery trigger_types should contain "container-exec-env"
Scenario: lsp-workspace has auto-discovery from lsp-server for lsp_rt
Given the built-in lsp-workspace YAML file for lsp_rt
When I load the YAML via schema for lsp_rt
@@ -97,8 +79,7 @@ Feature: LSP Resource Types
Scenario: BUILTIN_NAMES includes all LSP types for lsp_rt
Given the ResourceTypeSpec BUILTIN_NAMES set for lsp_rt
Then BUILTIN_NAMES should contain "executable" for lsp_rt
And BUILTIN_NAMES should contain "lsp-server" for lsp_rt
Then BUILTIN_NAMES should contain "lsp-server" for lsp_rt
And BUILTIN_NAMES should contain "lsp-workspace" for lsp_rt
And BUILTIN_NAMES should contain "lsp-document" for lsp_rt
@@ -106,9 +87,6 @@ Feature: LSP Resource Types
Scenario: LSP types survive DB roundtrip after bootstrap for lsp_rt
Given a lsp_rt fresh in-memory resource registry with bootstrap
When I query the lsp_rt registry for type "executable"
Then the lsp_rt db type "executable" should exist
And the lsp_rt db type "executable" should have kind "physical"
When I query the lsp_rt registry for type "lsp-server"
Then the lsp_rt db type "lsp-server" should exist
When I query the lsp_rt registry for type "lsp-workspace"
+18 -19
View File
@@ -15,26 +15,30 @@ def _import_lsp_types() -> None:
LSP_RESOURCE_TYPES,
)
assert len(LSP_RESOURCE_TYPES) == 4, f"Expected 4, got {len(LSP_RESOURCE_TYPES)}"
assert len(LSP_RESOURCE_TYPES) == 3, f"Expected 3, got {len(LSP_RESOURCE_TYPES)}"
names = [t["name"] for t in LSP_RESOURCE_TYPES]
for expected in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
for expected in ("lsp-server", "lsp-workspace", "lsp-document"):
assert expected in names, f"{expected} not in LSP_RESOURCE_TYPES: {names}"
print("import-lsp-types-ok")
def _check_builtin_names() -> None:
"""Verify all 4 LSP types are in BUILTIN_NAMES."""
"""Verify all 3 LSP types are in BUILTIN_NAMES."""
from cleveragents.domain.models.core.resource_type import ResourceTypeSpec
for name in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
for name in ("lsp-server", "lsp-workspace", "lsp-document"):
assert name in ResourceTypeSpec.BUILTIN_NAMES, f"{name} not in BUILTIN_NAMES"
assert "executable" not in ResourceTypeSpec.BUILTIN_NAMES, (
"executable should not be in BUILTIN_NAMES (not a spec-defined type)"
)
print("check-builtin-names-ok")
def _db_roundtrip() -> None:
"""Bootstrap in-memory DB and verify all 4 LSP types are retrievable."""
"""Bootstrap in-memory DB and verify all 3 LSP types are retrievable."""
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
@@ -48,7 +52,7 @@ def _db_roundtrip() -> None:
factory = sessionmaker(bind=engine, expire_on_commit=False)
svc = ResourceRegistryService(session_factory=factory)
for name in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
for name in ("lsp-server", "lsp-workspace", "lsp-document"):
spec = svc.show_type(name)
assert spec is not None, f"{name} not found after bootstrap"
assert str(spec.resource_kind) == "physical", (
@@ -85,32 +89,27 @@ def _check_hierarchy() -> None:
assert "lsp-workspace" in types["lsp-document"]["parent_types"], (
"lsp-document missing lsp-workspace parent"
)
# executable has no children
assert types["executable"]["child_types"] == [], (
"executable should have no children"
)
print("check-hierarchy-ok")
def _check_auto_discovery() -> None:
"""Verify executable has auto_discovery with trigger_types."""
"""Verify lsp-workspace has auto_discovery with trigger_types."""
from cleveragents.application.services._resource_registry_lsp import (
LSP_RESOURCE_TYPES,
)
types = {t["name"]: t for t in LSP_RESOURCE_TYPES}
types = {t["name"] for t in LSP_RESOURCE_TYPES}
# executable has auto_discovery
ad = types["executable"].get("auto_discovery")
assert ad is not None, "executable missing auto_discovery"
assert "container-exec-env" in ad.get("trigger_types", []), (
"executable missing container-exec-env trigger"
# executable should not be present
assert "executable" not in types, (
"executable should not be in LSP_RESOURCE_TYPES (not a spec-defined type)"
)
assert ad.get("lazy") is True, "executable auto_discovery should be lazy"
lsp_types = {t["name"]: t for t in LSP_RESOURCE_TYPES}
# lsp-workspace has auto_discovery from lsp-server
ad_ws = types["lsp-workspace"].get("auto_discovery")
ad_ws = lsp_types["lsp-workspace"].get("auto_discovery")
assert ad_ws is not None, "lsp-workspace missing auto_discovery"
assert "lsp-server" in ad_ws.get("trigger_types", []), (
"lsp-workspace missing lsp-server trigger"
@@ -1,15 +1,14 @@
"""LSP resource type definitions for the Resource Registry.
Contains the built-in LSP-related type entries (``executable``,
``lsp-server``, ``lsp-workspace``, ``lsp-document``) that are appended
to ``BUILTIN_TYPES`` in ``_resource_registry_data``.
Contains the built-in LSP-related type entries (``lsp-server``,
``lsp-workspace``, ``lsp-document``) that are appended to
``BUILTIN_TYPES`` in ``_resource_registry_data``.
These types bridge the resource system with the LSP runtime, allowing
actors to discover available language tooling and the LSP system to know
which resources it operates on.
Spec reference: docs/adr/ADR-039-container-resource-types.md (executable),
docs/adr/ADR-040-lsp-resource-types.md (lsp-server,
Spec reference: docs/adr/ADR-040-lsp-resource-types.md (lsp-server,
lsp-workspace, lsp-document)
.. note::
@@ -28,52 +27,11 @@ __all__ = ["LSP_RESOURCE_TYPES"]
# === LSP Resource Types (#832) ===
#
# These types model language tooling infrastructure in the resource DAG.
# - executable: system binary / interpreter / LSP server binary
# - lsp-server: a configured or running LSP server instance
# - lsp-workspace: workspace root tracked by an LSP server
# - lsp-document: text document tracked by an LSP server
LSP_RESOURCE_TYPES: list[dict[str, Any]] = [
# ── executable ───────────────────────────────────────────────
{
"name": "executable",
"description": (
"System executable (language runtime, compiler, LSP server "
"binary). Discovered from container or host PATH."
),
"resource_kind": "physical",
"sandbox_strategy": "none",
"user_addable": True,
"built_in": True,
"cli_args": [
{
"name": "path",
"type": "string",
"required": True,
"description": "Absolute path to the executable",
},
{
"name": "version",
"type": "string",
"required": False,
"description": "Executable version if detectable",
},
],
"parent_types": ["container-exec-env", "fs-directory"],
"child_types": [],
"handler": "cleveragents.resource.handlers.executable:ExecutableHandler",
"auto_discovery": {
"trigger_types": ["container-exec-env", "fs-directory"],
"scan_paths": [],
"lazy": True,
},
"capabilities": {
"read": True,
"write": False,
"sandbox": False,
"checkpoint": False,
},
},
# ── lsp-server ───────────────────────────────────────────────
{
"name": "lsp-server",
+15 -12
View File
@@ -860,37 +860,40 @@ def resource_list(
return
table = Table(title=f"Resources ({len(resources)} total)")
table.add_column("ID", style="dim")
table.add_column("Name", style="cyan")
table.add_column("ID", style="dim")
table.add_column("Type", style="blue")
table.add_column("Status", style="yellow")
table.add_column("Kind", style="magenta")
table.add_column("Location", style="dim")
table.add_column("Description", style="dim")
table.add_column("Phys/Virt", style="magenta")
table.add_column("Children", justify="right")
table.add_column("Projects", justify="right")
detected_devcontainers: list[Any] = []
lifecycle_states: list[tuple[Any, str]] = []
for res in resources:
desc = res.description or ""
if len(desc) > 40:
desc = desc[:37] + "..."
res_id = res.resource_id
if len(res_id) > 12:
res_id = res_id[:12] + "..."
lifecycle_state = _get_lifecycle_state_str(res)
if lifecycle_state == "detected (not built)":
detected_devcontainers.append(res)
if lifecycle_state:
lifecycle_states.append((res, lifecycle_state))
table.add_row(
res_id,
res.name or "(unnamed)",
res_id,
res.resource_type_name,
lifecycle_state or "",
str(res.classification),
res.location or "",
desc,
str(len(res.children)),
str(len(res.linked_projects)),
)
console.print(table)
for res, state in lifecycle_states:
style = "yellow" if state in ("detected (not built)", "failed") else "blue"
label = res.name or res.resource_id
console.print(f"[{style}] {label}: {state}[/{style}]")
for res in detected_devcontainers:
location = res.location or "(unknown path)"
devcontainer_json = f"{location}/.devcontainer/devcontainer.json"
@@ -125,7 +125,6 @@ BUILTIN_TYPE_NAMES: frozenset[str] = frozenset(
"submodule",
"symlink",
# LSP resource types (#832)
"executable",
"lsp-server",
"lsp-workspace",
"lsp-document",