UAT: find_nearest_devcontainer() traverses UPWARD through parent_map but spec requires DOWNWARD traversal through children of linked resources #2904

Open
opened 2026-04-05 02:46:30 +00:00 by freemo · 2 comments
Owner

Metadata

  • Branch: fix/execution-env-resolver-downward-traversal
  • Commit Message: fix(execution-environment-resolver): traverse children map downward to find nearest devcontainer

Summary

ExecutionEnvironmentResolver.find_nearest_devcontainer() in src/cleveragents/application/services/execution_environment_resolver.py traverses upward through parent_map (ancestors) when looking for a devcontainer, but the specification requires traversing downward through children of linked resources.

Expected Behavior (from spec)

The spec's routing algorithm (§Execution Environment Routing) states:

for resource in project.linked_resources (ordered by DAG depth, shallowest first):
    devcontainer = find_child_of_type(resource, "devcontainer-instance")
    if devcontainer:
        if devcontainer.state == "detected":
            build_and_start(devcontainer)   # lazy activation
        return devcontainer

The devcontainer is a child (or descendant) of a resource linked to the project. The search should walk downward through the resource DAG from each linked resource.

Actual Behavior

The find_nearest_devcontainer() method performs BFS from resource_id through parent_map:

def find_nearest_devcontainer(
    self,
    resource_id: str,
    linked_resource_types: dict[str, str],
    parent_map: dict[str, list[str]],
) -> str | None:
    visited: set[str] = set()
    queue: deque[str] = deque([resource_id])

    while queue:
        current = queue.popleft()
        if current in visited:
            continue
        visited.add(current)

        rtype = linked_resource_types.get(current, "")
        if rtype == _DEVCONTAINER_TYPE and current != resource_id:
            return current

        for parent_id in parent_map.get(current, []):  # ← walks UPWARD
            if parent_id not in visited:
                queue.append(parent_id)

    return None

parent_map maps resource_id → list[parent_ids]. The BFS walks upward through ancestors, looking for a devcontainer that is an ancestor of the current resource. This is the opposite of what the spec requires.

Code Location

  • File: src/cleveragents/application/services/execution_environment_resolver.py
  • Method: find_nearest_devcontainer() (lines ~200-230)
  • Called from: resolve_with_dag()

Steps to Reproduce

  1. Add a git-checkout resource with a .devcontainer/devcontainer.json file
  2. Link the resource to a project
  3. The auto-discovered devcontainer-instance child resource should be selected as the execution environment at Level 3 of the precedence chain
  4. Instead, no devcontainer is found and the resolver falls through to Level 4/5/6

Fix Direction

The method should walk downward through children (using a children_map: dict[str, list[str]] instead of parent_map), or alternatively, the caller should pass the set of linked resource IDs and the method should check if any of them have a devcontainer-instance child.

Subtasks

  • Audit find_nearest_devcontainer() signature and all call sites in resolve_with_dag() to understand what maps are available
  • Replace parent_map parameter with children_map: dict[str, list[str]] (mapping resource → list of child resource IDs)
  • Rewrite BFS to walk downward through children_map from each linked resource
  • Update resolve_with_dag() (and any other callers) to pass children_map instead of parent_map
  • Tests (Behave): Add/update scenarios covering downward traversal — devcontainer as child of git-checkout, devcontainer as grandchild, no devcontainer in subtree
  • Tests (Behave): Add regression scenario confirming upward traversal no longer occurs
  • Tests (Robot): Add integration test verifying Level 3 precedence selects a child devcontainer correctly
  • Run nox -e typecheck — confirm no Pyright errors
  • Run nox -e unit_tests — all Behave scenarios pass
  • Run nox -e coverage_report — coverage remains =97%
  • Run nox (all default sessions) — no failures

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/execution-env-resolver-downward-traversal` - **Commit Message**: `fix(execution-environment-resolver): traverse children map downward to find nearest devcontainer` ## Summary `ExecutionEnvironmentResolver.find_nearest_devcontainer()` in `src/cleveragents/application/services/execution_environment_resolver.py` traverses **upward** through `parent_map` (ancestors) when looking for a devcontainer, but the specification requires traversing **downward** through children of linked resources. ## Expected Behavior (from spec) The spec's routing algorithm (§Execution Environment Routing) states: ``` for resource in project.linked_resources (ordered by DAG depth, shallowest first): devcontainer = find_child_of_type(resource, "devcontainer-instance") if devcontainer: if devcontainer.state == "detected": build_and_start(devcontainer) # lazy activation return devcontainer ``` The devcontainer is a **child (or descendant)** of a resource linked to the project. The search should walk **downward** through the resource DAG from each linked resource. ## Actual Behavior The `find_nearest_devcontainer()` method performs BFS from `resource_id` through `parent_map`: ```python def find_nearest_devcontainer( self, resource_id: str, linked_resource_types: dict[str, str], parent_map: dict[str, list[str]], ) -> str | None: visited: set[str] = set() queue: deque[str] = deque([resource_id]) while queue: current = queue.popleft() if current in visited: continue visited.add(current) rtype = linked_resource_types.get(current, "") if rtype == _DEVCONTAINER_TYPE and current != resource_id: return current for parent_id in parent_map.get(current, []): # ← walks UPWARD if parent_id not in visited: queue.append(parent_id) return None ``` `parent_map` maps `resource_id → list[parent_ids]`. The BFS walks **upward** through ancestors, looking for a devcontainer that is an **ancestor** of the current resource. This is the opposite of what the spec requires. ## Code Location - **File**: `src/cleveragents/application/services/execution_environment_resolver.py` - **Method**: `find_nearest_devcontainer()` (lines ~200-230) - **Called from**: `resolve_with_dag()` ## Steps to Reproduce 1. Add a `git-checkout` resource with a `.devcontainer/devcontainer.json` file 2. Link the resource to a project 3. The auto-discovered `devcontainer-instance` child resource should be selected as the execution environment at Level 3 of the precedence chain 4. Instead, no devcontainer is found and the resolver falls through to Level 4/5/6 ## Fix Direction The method should walk **downward** through children (using a `children_map: dict[str, list[str]]` instead of `parent_map`), or alternatively, the caller should pass the set of linked resource IDs and the method should check if any of them have a `devcontainer-instance` child. ## Subtasks - [ ] Audit `find_nearest_devcontainer()` signature and all call sites in `resolve_with_dag()` to understand what maps are available - [ ] Replace `parent_map` parameter with `children_map: dict[str, list[str]]` (mapping resource → list of child resource IDs) - [ ] Rewrite BFS to walk **downward** through `children_map` from each linked resource - [ ] Update `resolve_with_dag()` (and any other callers) to pass `children_map` instead of `parent_map` - [ ] Tests (Behave): Add/update scenarios covering downward traversal — devcontainer as child of `git-checkout`, devcontainer as grandchild, no devcontainer in subtree - [ ] Tests (Behave): Add regression scenario confirming upward traversal no longer occurs - [ ] Tests (Robot): Add integration test verifying Level 3 precedence selects a child devcontainer correctly - [ ] Run `nox -e typecheck` — confirm no Pyright errors - [ ] Run `nox -e unit_tests` — all Behave scenarios pass - [ ] Run `nox -e coverage_report` — coverage remains =97% - [ ] Run `nox` (all default sessions) — no failures --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.6.0 milestone 2026-04-05 02:46:34 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High (confirmed)
  • MoSCoW: Should Have — traversal direction wrong per spec

Valid UAT finding verified during batch triage.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High (confirmed) - **MoSCoW**: Should Have — traversal direction wrong per spec Valid UAT finding verified during batch triage. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Author
Owner

Transition request: State/Verified -> State/In Progress for issue #2904.

Preconditions checked:

  • Current state label is State/Verified. No Paused state detected.
  • Blocked label is not present, so no blocker to resolve.

Action plan:

  • Remove old State/* label (State/Verified).
  • Add new State/In Progress label.

Note: The Forgejo API in this environment does not expose direct label manipulation endpoints. I am documenting the intended label transition in this comment. Please apply the label changes in the repository as appropriate.

Current labels before change: State/Verified, Priority/High, MoSCoW/Should have, Type/Bug

Expected labels after change: State/In Progress, Priority/High, MoSCoW/Should have, Type/Bug


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-state-updater

Transition request: State/Verified -> State/In Progress for issue #2904. Preconditions checked: - Current state label is State/Verified. No Paused state detected. - Blocked label is not present, so no blocker to resolve. Action plan: - Remove old State/* label (State/Verified). - Add new State/In Progress label. Note: The Forgejo API in this environment does not expose direct label manipulation endpoints. I am documenting the intended label transition in this comment. Please apply the label changes in the repository as appropriate. Current labels before change: State/Verified, Priority/High, MoSCoW/Should have, Type/Bug Expected labels after change: State/In Progress, Priority/High, MoSCoW/Should have, Type/Bug --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-state-updater
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
Reference
cleveragents/cleveragents-core#2904
No description provided.