diff --git a/CHANGELOG.md b/CHANGELOG.md index dca5c2ea6..5901227b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1264eaf25..1e635e434 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -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. diff --git a/examples/resource-types/executable.yaml b/examples/resource-types/executable.yaml deleted file mode 100644 index fae10cde5..000000000 --- a/examples/resource-types/executable.yaml +++ /dev/null @@ -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 diff --git a/features/resource_cli.feature b/features/resource_cli.feature index e1033fafa..ed2da316e 100644 --- a/features/resource_cli.feature +++ b/features/resource_cli.feature @@ -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 diff --git a/features/resource_list_lifecycle_state.feature b/features/resource_list_lifecycle_state.feature index 0c411b472..9eded453d 100644 --- a/features/resource_list_lifecycle_state.feature +++ b/features/resource_list_lifecycle_state.feature @@ -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 diff --git a/features/resource_type_lsp.feature b/features/resource_type_lsp.feature index ad09affd6..616a25cf9 100644 --- a/features/resource_type_lsp.feature +++ b/features/resource_type_lsp.feature @@ -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" diff --git a/robot/helper_resource_type_lsp.py b/robot/helper_resource_type_lsp.py index 004179b3e..c7090c786 100644 --- a/robot/helper_resource_type_lsp.py +++ b/robot/helper_resource_type_lsp.py @@ -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" diff --git a/src/cleveragents/application/services/_resource_registry_lsp.py b/src/cleveragents/application/services/_resource_registry_lsp.py index 3f6b594f6..bbaf2032d 100644 --- a/src/cleveragents/application/services/_resource_registry_lsp.py +++ b/src/cleveragents/application/services/_resource_registry_lsp.py @@ -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", diff --git a/src/cleveragents/cli/commands/resource.py b/src/cleveragents/cli/commands/resource.py index 1dc7457ef..6e04b110d 100644 --- a/src/cleveragents/cli/commands/resource.py +++ b/src/cleveragents/cli/commands/resource.py @@ -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" diff --git a/src/cleveragents/domain/models/core/_resource_type_validation.py b/src/cleveragents/domain/models/core/_resource_type_validation.py index f9bae83b5..d6b9dfd8d 100644 --- a/src/cleveragents/domain/models/core/_resource_type_validation.py +++ b/src/cleveragents/domain/models/core/_resource_type_validation.py @@ -125,7 +125,6 @@ BUILTIN_TYPE_NAMES: frozenset[str] = frozenset( "submodule", "symlink", # LSP resource types (#832) - "executable", "lsp-server", "lsp-workspace", "lsp-document",