Skip to content

Address review feedback for state attribute feature#1098

Closed
xbrianh wants to merge 3 commits into
mainfrom
issue-1090-state-attribute-review
Closed

Address review feedback for state attribute feature#1098
xbrianh wants to merge 3 commits into
mainfrom
issue-1090-state-attribute-review

Conversation

@xbrianh
Copy link
Copy Markdown
Owner

@xbrianh xbrianh commented Jun 3, 2026

Summary

Address review feedback on the state attribute feature:

  • Extract duplicate cwd computation to _resolve_cwd() helper method
  • Ensure self.state is set during stage execution via closure wrapper
  • Initialize self.state after build_state() is called in the executor

Test coverage

Added comprehensive tests for the state attribute initialization and access patterns.

Closes #1090

xbrianh and others added 2 commits June 3, 2026 13:39
- Add state attribute to Gremlin class initialized in __init__ to None
- Populate gremlin.state in initialize_with_runtime via build_state()
- Update _collect_stages() to set gremlin.state before each stage.run() call via make_runner closure
- Add comprehensive tests for gremlin.state attribute accessibility

Stages can now access current state via self.gremlin.state in addition to the state parameter.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Extract duplicate cwd computation to _resolve_cwd() helper
- Remove dead gremlin_ref alias; use self directly in closure
- Remove redundant _set_gremlin_recursive() call in test

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Owner Author

@xbrianh xbrianh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One correctness bug: the new build_state call in initialize_with_runtime sits outside the try/except that guards worktree cleanup, so a failure there leaks the worktree. Everything else looks clean — the default-arg capture in _set_state_and_run is the right pattern, _resolve_cwd is a nice extraction, and the tests cover the key scenarios.

Comment thread gremlins/executor/gremlin.py Outdated
raise

cwd = self._resolve_cwd()
self.state = build_state(
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This build_state call is outside the try/except block that cleans up worktree_created on failure (the handler ends at line 532). If build_state raises, the worktree is leaked.

Move these lines inside the try block:

        try:
            ...
            # existing registry setup
            ...
            cwd = self._resolve_cwd()
            self.state = build_state(...)
        except Exception:
            if worktree_created:
                _git_mod.remove_worktree(self.project_root, worktree_created)
            raise

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Moved the build_state() call inside the try block to ensure worktree cleanup on error.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refines the in-progress “Gremlin carries a .state attribute” feature (Issue #1090) by reducing duplicated cwd logic and ensuring Gremlin.state is available both after initialization and during stage execution.

Changes:

  • Extracts repeated cwd selection logic into Gremlin._resolve_cwd().
  • Initializes Gremlin.state in initialize_with_runtime() via build_state(...).
  • Wraps top-level stage runners so Gremlin.state is set immediately before stage.run(...) executes, and adds unit tests covering initialization/access patterns.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
gremlins/executor/gremlin.py Adds/initializes Gremlin.state, factors out cwd computation, and wraps top-level runners to set self.state during execution.
tests/test_gremlin_state.py Adds tests asserting Gremlin.state is populated after initialization and visible during a stage run.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 102 to 105
class Gremlin:
registry: ArtifactRegistry
state: State | None

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added state: Any to GremlinProtocol to enable type checking for stage code using self.gremlin.state.

Comment on lines +308 to +317
base_runner = stage_state.make_runner(e, scope=stages)

async def _set_state_and_run(
runner: Callable[[], Awaitable[Any]] = base_runner,
state: State = stage_state,
) -> Any:
self.state = state
return await runner()

built.append((e.name, _set_state_and_run))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Wrapped nested stage runners in sequence, loop, and parallel stages to set child.gremlin.state before execution. This ensures nested stages have access to their correct child state.

- Move build_state() call inside try/except to prevent worktree leak on error
- Add state attribute to GremlinProtocol for type checking
- Wrap nested stage runners to set child.gremlin.state during execution

Fixes the issue where nested stages in sequence, loop, and parallel groups
did not have their gremlin.state updated to the appropriate child state.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@xbrianh xbrianh closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 1 (#1075): Expand Gremlin to carry .state slot + convenience delegates

2 participants