diff --git a/features/agent_evolution_pool_supervisor_metadata.feature b/features/agent_evolution_pool_supervisor_metadata.feature deleted file mode 100644 index 012e3fa33..000000000 --- a/features/agent_evolution_pool_supervisor_metadata.feature +++ /dev/null @@ -1,63 +0,0 @@ -Feature: Agent Evolution Pool Supervisor - Type Label and Milestone Assignment - - As an agent evolution supervisor - I want to automatically assign Type/Automation label and milestone to improvement PRs - So that all improvement PRs have required metadata and don't get blocked by compliance issues - - Background: - Given the agent-evolution-pool-supervisor is configured - And the repository has the Type/Automation label with ID 1397 - And the repository has an open milestone "v3.2.0" with ID 42 - - Scenario: Supervisor looks up Type/Automation label ID before creating PR - Given the supervisor is about to create an improvement PR - When the supervisor looks up the Type/Automation label - Then the label ID 1397 is found - And the label name is "Type/Automation" - - Scenario: Supervisor looks up earliest open milestone before creating PR - Given the supervisor is about to create an improvement PR - And the repository has multiple open milestones - When the supervisor looks up the earliest open milestone - Then the earliest milestone "v3.2.0" with ID 42 is found - And the milestone is in open state - - Scenario: Supervisor passes label and milestone to worker - Given the supervisor has identified an improvement proposal - And the Type/Automation label ID is 1397 - And the earliest open milestone ID is 42 - When the supervisor dispatches a worker to create the PR - Then the worker receives the label ID 1397 in the prompt - And the worker receives the milestone ID 42 in the prompt - - Scenario: Worker creates PR with Type/Automation label and milestone - Given a worker is creating an improvement PR - And the worker has label ID 1397 for Type/Automation - And the worker has milestone ID 42 for v3.2.0 - When the worker creates the PR using pr-creator - Then the PR is created with Type/Automation label - And the PR is assigned to milestone v3.2.0 - - Scenario: Supervisor handles missing Type/Automation label gracefully - Given the supervisor is about to create an improvement PR - And the Type/Automation label does not exist in the repository - When the supervisor looks up the Type/Automation label - Then the label lookup returns no result - And the supervisor logs a warning about missing label - And the supervisor continues without assigning a label - - Scenario: Supervisor handles no open milestones gracefully - Given the supervisor is about to create an improvement PR - And there are no open milestones in the repository - When the supervisor looks up the earliest open milestone - Then the milestone lookup returns no result - And the supervisor logs a warning about missing milestones - And the supervisor continues without assigning a milestone - - Scenario: Agent definition documents label and milestone lookup steps - Given the agent-evolution-pool-supervisor.md file exists - When I read the agent definition - Then the definition includes a section for label lookup - And the definition includes a section for milestone lookup - And the definition explains how to pass these to the worker - And the definition includes error handling for missing label or milestone diff --git a/features/pr_compliance_pool_supervisor.feature b/features/pr_compliance_pool_supervisor.feature deleted file mode 100644 index 114c262d6..000000000 --- a/features/pr_compliance_pool_supervisor.feature +++ /dev/null @@ -1,58 +0,0 @@ -@mock_only -Feature: PR Compliance Checklist in Implementation Pool Supervisor - - As a pool supervisor - I want to pass a mandatory PR compliance checklist to every worker prompt - So that implementation workers complete all required items before creating a PR and avoid systemic merge blockers - - Background: - Given the implementation-pool-supervisor.md agent definition exists - - Scenario: Pool supervisor worker prompt includes the PR compliance checklist - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes the PR compliance checklist section - And Pool: the checklist is marked as MANDATORY - - Scenario: Checklist item 1 — CHANGELOG.md update required - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a CHANGELOG.md checklist item - And Pool: the item instructs workers to add an entry under the Unreleased section - - Scenario: Checklist item 2 — CONTRIBUTORS.md update required - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a CONTRIBUTORS.md checklist item - And Pool: the item instructs workers to add or update their contribution entry - - Scenario: Checklist item 3 — commit footer required - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a commit footer checklist item - And Pool: the item specifies the ISSUES CLOSED footer format - - Scenario: Checklist item 4 — CI must pass before PR creation - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a CI passes checklist item - And Pool: the item instructs workers to verify all quality gates are green - - Scenario: Checklist item 5 — BDD/Behave tests required - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a BDD tests checklist item - And Pool: the item instructs workers to add or update Behave feature files - - Scenario: Checklist item 6 — Epic reference required in PR description - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes an Epic reference checklist item - And Pool: the item instructs workers to reference the parent Epic issue number - - Scenario: Checklist item 7 — Labels must be applied - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a labels checklist item - And Pool: the item instructs workers to apply labels via forgejo-label-manager - - Scenario: Checklist item 8 — Milestone must be assigned - When I read the pool supervisor agent definition - Then Pool: worker prompt body includes a milestone checklist item - And Pool: the item instructs workers to assign the earliest open milestone - - Scenario: All 8 checklist items are present in the worker prompt - When I read the pool supervisor agent definition - Then Pool: worker prompt body contains all 8 mandatory checklist items diff --git a/features/steps/agent_evolution_pool_supervisor_metadata_steps.py b/features/steps/agent_evolution_pool_supervisor_metadata_steps.py deleted file mode 100644 index 25776b099..000000000 --- a/features/steps/agent_evolution_pool_supervisor_metadata_steps.py +++ /dev/null @@ -1,382 +0,0 @@ -"""Step definitions for agent evolution pool supervisor metadata assignment.""" - -from pathlib import Path -from typing import Any - -from behave import given, then, when - - -@given("the agent-evolution-pool-supervisor is configured") -def step_supervisor_configured(context: Any) -> None: - """Initialize the supervisor context.""" - context.supervisor_config = { - "repo_owner": "cleveragents", - "repo_name": "cleveragents-core", - "forgejo_url": "https://git.cleverthis.com", - } - context.labels = {} - context.milestones = {} - - -@given("the repository has the Type/Automation label with ID {label_id:d}") -def step_repo_has_type_automation_label(context: Any, label_id: int) -> None: - """Set up the Type/Automation label in the repository.""" - context.labels["Type/Automation"] = label_id - - -@given( - 'the repository has an open milestone "{milestone_name}" with ID {milestone_id:d}' -) -def step_repo_has_open_milestone( - context: Any, milestone_name: str, milestone_id: int -) -> None: - """Set up an open milestone in the repository.""" - context.milestones[milestone_name] = { - "id": milestone_id, - "state": "open", - "name": milestone_name, - } - - -@given("the supervisor is about to create an improvement PR") -def step_supervisor_about_to_create_pr(context: Any) -> None: - """Set up the context for PR creation.""" - context.pr_creation_context = { - "proposal_issue": 7888, - "branch": "improve/agent-evolution-pool-supervisor-metadata", - "title": "Proposal: improve agent-evolution-pool-supervisor — add Type label " - "and milestone assignment to improvement PRs", - } - - -@when("the supervisor looks up the Type/Automation label") -def step_supervisor_looks_up_label(context: Any) -> None: - """Simulate looking up the Type/Automation label.""" - label_name = "Type/Automation" - if label_name in context.labels: - context.found_label = { - "name": label_name, - "id": context.labels[label_name], - } - else: - context.found_label = None - - -@then("the label ID {label_id:d} is found") -def step_label_id_found(context: Any, label_id: int) -> None: - """Verify the label ID was found.""" - assert context.found_label is not None, "Label should be found" - assert context.found_label["id"] == label_id, ( - f"Expected label ID {label_id}, got {context.found_label['id']}" - ) - - -@then('the label name is "{label_name}"') -def step_label_name_is(context: Any, label_name: str) -> None: - """Verify the label name.""" - assert context.found_label is not None, "Label should be found" - assert context.found_label["name"] == label_name, ( - f"Expected label name {label_name}, got {context.found_label['name']}" - ) - - -@given("the repository has multiple open milestones") -def step_repo_has_multiple_milestones(context: Any) -> None: - """Add multiple open milestones to the repository.""" - context.milestones["v3.2.0"] = { - "id": 42, - "state": "open", - "name": "v3.2.0", - "due_on": "2026-01-31T23:59:59Z", - } - context.milestones["v3.3.0"] = { - "id": 43, - "state": "open", - "name": "v3.3.0", - "due_on": "2026-02-28T23:59:59Z", - } - context.milestones["v3.4.0"] = { - "id": 44, - "state": "open", - "name": "v3.4.0", - "due_on": "2026-03-31T23:59:59Z", - } - - -@when("the supervisor looks up the earliest open milestone") -def step_supervisor_looks_up_earliest_milestone(context: Any) -> None: - """Simulate looking up the earliest open milestone.""" - open_milestones = [m for m in context.milestones.values() if m["state"] == "open"] - if open_milestones: - # Sort by due_on date if available, otherwise by name - sorted_milestones = sorted( - open_milestones, - key=lambda m: m.get("due_on", m["name"]), - ) - context.found_milestone = sorted_milestones[0] - else: - context.found_milestone = None - - -@then('the earliest milestone "{milestone_name}" with ID {milestone_id:d} is found') -def step_earliest_milestone_found( - context: Any, milestone_name: str, milestone_id: int -) -> None: - """Verify the earliest milestone was found.""" - assert context.found_milestone is not None, "Milestone should be found" - assert context.found_milestone["name"] == milestone_name, ( - f"Expected milestone {milestone_name}, got {context.found_milestone['name']}" - ) - assert context.found_milestone["id"] == milestone_id, ( - f"Expected milestone ID {milestone_id}, got {context.found_milestone['id']}" - ) - - -@then("the milestone is in open state") -def step_milestone_is_open(context: Any) -> None: - """Verify the milestone is in open state.""" - assert context.found_milestone is not None, "Milestone should be found" - assert context.found_milestone["state"] == "open", ( - f"Expected milestone state 'open', got {context.found_milestone['state']}" - ) - - -@given("the supervisor has identified an improvement proposal") -def step_supervisor_identified_proposal(context: Any) -> None: - """Set up the proposal context.""" - context.proposal = { - "issue_number": 7888, - "title": "Proposal: improve agent-evolution-pool-supervisor — add Type label " - "and milestone assignment to improvement PRs", - "description": "Add Type/Automation label and milestone assignment " - "to improvement PRs", - } - - -@given("the Type/Automation label ID is {label_id:d}") -def step_label_id_is(context: Any, label_id: int) -> None: - """Set the label ID in the context.""" - context.label_id_for_pr = label_id - - -@given("the earliest open milestone ID is {milestone_id:d}") -def step_milestone_id_is(context: Any, milestone_id: int) -> None: - """Set the milestone ID in the context.""" - context.milestone_id_for_pr = milestone_id - - -@when("the supervisor dispatches a worker to create the PR") -def step_supervisor_dispatches_worker(context: Any) -> None: - """Simulate dispatching a worker with the metadata.""" - context.worker_prompt = { - "proposal": context.proposal, - "label_id": context.label_id_for_pr, - "milestone_id": context.milestone_id_for_pr, - "branch": "improve/agent-evolution-pool-supervisor-metadata", - } - - -@then("the worker receives the label ID {label_id:d} in the prompt") -def step_worker_receives_label_id(context: Any, label_id: int) -> None: - """Verify the worker receives the label ID.""" - assert context.worker_prompt is not None, "Worker prompt should be set" - assert context.worker_prompt["label_id"] == label_id, ( - f"Expected label ID {label_id}, got {context.worker_prompt['label_id']}" - ) - - -@then("the worker receives the milestone ID {milestone_id:d} in the prompt") -def step_worker_receives_milestone_id(context: Any, milestone_id: int) -> None: - """Verify the worker receives the milestone ID.""" - assert context.worker_prompt is not None, "Worker prompt should be set" - assert context.worker_prompt["milestone_id"] == milestone_id, ( - f"Expected milestone ID {milestone_id}, " - f"got {context.worker_prompt['milestone_id']}" - ) - - -@given("a worker is creating an improvement PR") -def step_worker_creating_pr(context: Any) -> None: - """Set up the worker context.""" - context.worker_context = { - "branch": "improve/agent-evolution-pool-supervisor-metadata", - "title": "Proposal: improve agent-evolution-pool-supervisor — add Type label " - "and milestone assignment to improvement PRs", - } - - -@given("the worker has label ID {label_id:d} for Type/Automation") -def step_worker_has_label_id(context: Any, label_id: int) -> None: - """Set the label ID for the worker.""" - context.worker_context["label_id"] = label_id - - -@given("the worker has milestone ID {milestone_id:d} for v3.2.0") -def step_worker_has_milestone_id(context: Any, milestone_id: int) -> None: - """Set the milestone ID for the worker.""" - context.worker_context["milestone_id"] = milestone_id - - -@when("the worker creates the PR using pr-creator") -def step_worker_creates_pr(context: Any) -> None: - """Simulate the worker creating a PR with metadata.""" - context.created_pr = { - "branch": context.worker_context["branch"], - "title": context.worker_context["title"], - "labels": [context.worker_context["label_id"]], - "milestone": context.worker_context["milestone_id"], - } - - -@then("the PR is created with Type/Automation label") -def step_pr_has_type_automation_label(context: Any) -> None: - """Verify the PR has the Type/Automation label.""" - assert context.created_pr is not None, "PR should be created" - assert 1397 in context.created_pr["labels"], ( - f"Expected label ID 1397 in {context.created_pr['labels']}" - ) - - -@then("the PR is assigned to milestone v3.2.0") -def step_pr_assigned_to_milestone(context: Any) -> None: - """Verify the PR is assigned to the milestone.""" - assert context.created_pr is not None, "PR should be created" - assert context.created_pr["milestone"] == 42, ( - f"Expected milestone ID 42, got {context.created_pr['milestone']}" - ) - - -@given("the Type/Automation label does not exist in the repository") -def step_label_does_not_exist(context: Any) -> None: - """Remove the Type/Automation label from the repository.""" - if "Type/Automation" in context.labels: - del context.labels["Type/Automation"] - - -@then("the label lookup returns no result") -def step_label_lookup_returns_no_result(context: Any) -> None: - """Verify the label lookup returns no result.""" - assert context.found_label is None, "Label lookup should return None" - - -@then("the supervisor logs a warning about missing label") -def step_supervisor_logs_warning_label(context: Any) -> None: - """Verify the supervisor records a warning when the label is missing.""" - assert context.found_label is None, ( - "Label should be None when logging a missing-label warning" - ) - context.warnings = getattr(context, "warnings", []) - context.warnings.append("Missing Type/Automation label") - assert "Missing Type/Automation label" in context.warnings, ( - "Warning about missing label should be recorded" - ) - - -@then("the supervisor continues without assigning a label") -def step_supervisor_continues_without_label(context: Any) -> None: - """Verify the supervisor continues without assigning a label.""" - assert not hasattr(context, "label_id_for_pr") or context.label_id_for_pr is None, ( - "Label ID should not be assigned when label is missing" - ) - - -@given("there are no open milestones in the repository") -def step_no_open_milestones(context: Any) -> None: - """Remove all open milestones from the repository.""" - context.milestones = { - k: v for k, v in context.milestones.items() if v["state"] != "open" - } - - -@then("the milestone lookup returns no result") -def step_milestone_lookup_returns_no_result(context: Any) -> None: - """Verify the milestone lookup returns no result.""" - assert context.found_milestone is None, "Milestone lookup should return None" - - -@then("the supervisor logs a warning about missing milestones") -def step_supervisor_logs_warning_milestone(context: Any) -> None: - """Verify the supervisor records a warning when milestones are missing.""" - assert context.found_milestone is None, ( - "Milestone should be None when logging a missing-milestone warning" - ) - context.warnings = getattr(context, "warnings", []) - context.warnings.append("No open milestones found") - assert "No open milestones found" in context.warnings, ( - "Warning about missing milestones should be recorded" - ) - - -@then("the supervisor continues without assigning a milestone") -def step_supervisor_continues_without_milestone(context: Any) -> None: - """Verify the supervisor continues without assigning a milestone.""" - assert ( - not hasattr(context, "milestone_id_for_pr") - or context.milestone_id_for_pr is None - ), "Milestone ID should not be assigned when milestone is missing" - - -@given("the agent-evolution-pool-supervisor.md file exists") -def step_agent_definition_exists(context: Any) -> None: - """Verify the agent definition file exists.""" - possible_paths = [ - Path(".opencode/agents/agent-evolution-pool-supervisor.md"), - Path("/app/.opencode/agents/agent-evolution-pool-supervisor.md"), - ] - - agent_file = None - for path in possible_paths: - if path.exists(): - agent_file = path - break - - assert agent_file is not None, ( - f"Agent definition file should exist at one of: {possible_paths}" - ) - context.agent_file_path = agent_file - - -@when("I read the agent definition") -def step_read_agent_definition(context: Any) -> None: - """Read the agent definition file.""" - with open(context.agent_file_path) as f: - context.agent_definition = f.read() - - -@then("the definition includes a section for label lookup") -def step_definition_includes_label_lookup(context: Any) -> None: - """Verify the definition includes label lookup documentation.""" - assert "label" in context.agent_definition.lower(), ( - "Definition should mention label lookup" - ) - assert ( - "Type/Automation" in context.agent_definition - or "type/automation" in context.agent_definition.lower() - ), "Definition should mention Type/Automation label" - - -@then("the definition includes a section for milestone lookup") -def step_definition_includes_milestone_lookup(context: Any) -> None: - """Verify the definition includes milestone lookup documentation.""" - assert "milestone" in context.agent_definition.lower(), ( - "Definition should mention milestone lookup" - ) - - -@then("the definition explains how to pass these to the worker") -def step_definition_explains_passing_to_worker(context: Any) -> None: - """Verify the definition explains how to pass metadata to the worker.""" - assert "worker" in context.agent_definition.lower(), ( - "Definition should mention passing to worker" - ) - - -@then("the definition includes error handling for missing label or milestone") -def step_definition_includes_error_handling(context: Any) -> None: - """Verify the definition includes error handling.""" - definition_lower = context.agent_definition.lower() - assert ( - "error" in definition_lower - or "handle" in definition_lower - or "gracefully" in definition_lower - ), "Definition should include error handling" diff --git a/features/steps/pr_compliance_pool_supervisor_steps.py b/features/steps/pr_compliance_pool_supervisor_steps.py deleted file mode 100644 index 468c4de94..000000000 --- a/features/steps/pr_compliance_pool_supervisor_steps.py +++ /dev/null @@ -1,219 +0,0 @@ -"""Step definitions for PR compliance checklist in implementation pool supervisor. - -This file uses parameterized @then decorators with unique step text that -distinguishes pool-supervisor checks from the shared compliance checklist -steps in pr_compliance_checklist_steps.py, preventing Behave AmbiguousStep -errors when both feature files are run together. - -Each validator is imported from the shared pr_compliance_checklist_steps module's -validation logic (via the _verify module) to avoid code duplication while using -unique step text prefixes ("Pool:") for disambiguation. -""" - -from collections.abc import Callable -from pathlib import Path -from typing import Any - -from behave import given, then, when - -PROJECT_ROOT = Path(__file__).resolve().parents[2] -AGENT_DEF_PATH = ( - PROJECT_ROOT / ".opencode" / "agents" / "implementation-pool-supervisor.md" -) - - -# --------------------------------------------------------------------------- -# Shared validation helpers — identical logic to pr_compliance_checklist_steps.py -# --------------------------------------------------------------------------- - -_required_items = [ - "CHANGELOG.md", - "CONTRIBUTORS.md", - "ISSUES CLOSED", - "CI passes", - "BDD/Behave tests", - "Epic reference", - "forgejo-label-manager", - "earliest open milestone", -] - -VALIDATORS: dict[str, Callable[[str], bool]] = { - "includes checklist section": lambda c: "PR Compliance Checklist" in c, - "is marked MANDATORY": lambda c: "MANDATORY" in c, - "has CHANGELOG.md item": lambda c: "CHANGELOG.md" in c, - "references Unreleased": lambda c: "[Unreleased]" in c, - "has CONTRIBUTORS.md item": lambda c: "CONTRIBUTORS.md" in c, - "instructs add or update": lambda c: "add or update" in c, - "has commit footer item": lambda c: "Commit footer" in c, - "specifies ISSUES CLOSED": lambda c: "ISSUES CLOSED" in c, - "has CI passes item": lambda c: "CI passes" in c, - "mentions quality gates": lambda c: "quality gates" in c, - "has BDD tests item": lambda c: "BDD/Behave tests" in c, - "instructs add or update features": lambda c: "added or updated" in c, - "has Epic reference item": lambda c: "Epic reference" in c, - "references parent Epic": lambda c: "parent Epic" in c, - "has labels item": lambda c: "Labels" in c, - "mentions forgejo-label-manager": lambda c: "forgejo-label-manager" in c, - "has milestone item": lambda c: "Milestone" in c, - "earliest open milestone": lambda c: "earliest open milestone" in c, - "all 8 items present": lambda c: all(item in c for item in _required_items), -} - - -def _make_validator(key: str) -> Callable[[Any], None]: - """Factory that creates a typed Behave validator from a shared helper.""" - - def validator(context: Any) -> None: - content = context.agent_def_content - check_fn = VALIDATORS.get(key) - assert check_fn(content), f"Pool supervisor agent definition failed: {key}" - - return validator - - -# --------------------------------------------------------------------------- -# Unique @given and @when — scoped to the pool supervisor agent def only -# --------------------------------------------------------------------------- - - -@given("the implementation-pool-supervisor.md agent definition exists") -def step_agent_def_exists(context: Any) -> None: - """Verify the pool supervisor agent definition file exists.""" - assert AGENT_DEF_PATH.exists(), f"Agent definition not found at {AGENT_DEF_PATH}" - context.agent_def_path = AGENT_DEF_PATH - - -@when("I read the pool supervisor agent definition") -def step_read_agent_def(context: Any) -> None: - """Read the pool supervisor agent definition.""" - context.agent_def_content = AGENT_DEF_PATH.read_text(encoding="utf-8") - - -# --------------------------------------------------------------------------- -# Unique @then — prefixed with "Pool:" so they never conflict with the -# shared pr_compliance_checklist_steps.py step definitions. -# --------------------------------------------------------------------------- - - -# Scenario: Pool supervisor worker prompt includes the PR compliance checklist -@then("Pool: worker prompt body includes the PR compliance checklist section") -def pool_step_prompt_includes_checklist(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes the PR compliance checklist.""" - _make_validator("includes checklist section")(context) - - -@then("Pool: the checklist is marked as MANDATORY") -def pool_step_checklist_is_mandatory(context: Any) -> None: - """Verify the pool-supervisor checklist is marked as MANDATORY.""" - _make_validator("is marked MANDATORY")(context) - - -# Scenario: Checklist item 1 — CHANGELOG.md update required -@then("Pool: worker prompt body includes a CHANGELOG.md checklist item") -def pool_step_prompt_includes_changelog_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a CHANGELOG.md checklist item.""" - _make_validator("has CHANGELOG.md item")(context) - - -@then("Pool: the item instructs workers to add an entry under the Unreleased section") -def pool_step_changelog_item_unreleased(context: Any) -> None: - """Verify the CHANGELOG.md item mentions the Unreleased section.""" - _make_validator("references Unreleased")(context) - - -# Scenario: Checklist item 2 — CONTRIBUTORS.md update required -@then("Pool: worker prompt body includes a CONTRIBUTORS.md checklist item") -def pool_step_prompt_includes_contributors_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a CONTRIBUTORS.md checklist item.""" - _make_validator("has CONTRIBUTORS.md item")(context) - - -@then("Pool: the item instructs workers to add or update their contribution entry") -def pool_step_contributors_item_add_update(context: Any) -> None: - """Verify the CONTRIBUTORS.md item instructs workers to add or update.""" - _make_validator("instructs add or update")(context) - - -# Scenario: Checklist item 3 — commit footer required -@then("Pool: worker prompt body includes a commit footer checklist item") -def pool_step_prompt_includes_commit_footer_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a commit footer checklist item.""" - _make_validator("has commit footer item")(context) - - -@then("Pool: the item specifies the ISSUES CLOSED footer format") -def pool_step_commit_footer_issues_closed(context: Any) -> None: - """Verify the commit footer item specifies the ISSUES CLOSED format.""" - _make_validator("specifies ISSUES CLOSED")(context) - - -# Scenario: Checklist item 4 — CI must pass before PR creation -@then("Pool: worker prompt body includes a CI passes checklist item") -def pool_step_prompt_includes_ci_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a CI passes checklist item.""" - _make_validator("has CI passes item")(context) - - -@then("Pool: the item instructs workers to verify all quality gates are green") -def pool_step_ci_item_quality_gates(context: Any) -> None: - """Verify the CI item instructs workers to verify quality gates are green.""" - _make_validator("mentions quality gates")(context) - - -# Scenario: Checklist item 5 — BDD/Behave tests required -@then("Pool: worker prompt body includes a BDD tests checklist item") -def pool_step_prompt_includes_bdd_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a BDD/Behave tests checklist item.""" - _make_validator("has BDD tests item")(context) - - -@then("Pool: the item instructs workers to add or update Behave feature files") -def pool_step_bdd_item_feature_files(context: Any) -> None: - """Verify the BDD item instructs workers to add or update feature files.""" - _make_validator("instructs add or update features")(context) - - -# Scenario: Checklist item 6 — Epic reference required in PR description -@then("Pool: worker prompt body includes an Epic reference checklist item") -def pool_step_prompt_includes_epic_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes an Epic reference checklist item.""" - _make_validator("has Epic reference item")(context) - - -@then("Pool: the item instructs workers to reference the parent Epic issue number") -def pool_step_epic_item_parent_reference(context: Any) -> None: - """Verify the Epic item instructs workers to reference the parent Epic.""" - _make_validator("references parent Epic")(context) - - -# Scenario: Checklist item 7 — Labels must be applied -@then("Pool: worker prompt body includes a labels checklist item") -def pool_step_prompt_includes_labels_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a labels checklist item.""" - _make_validator("has labels item")(context) - - -@then("Pool: the item instructs workers to apply labels via forgejo-label-manager") -def pool_step_labels_item_forgejo_label_manager(context: Any) -> None: - """Verify the labels item instructs workers to use forgejo-label-manager.""" - _make_validator("mentions forgejo-label-manager")(context) - - -# Scenario: Checklist item 8 — Milestone must be assigned -@then("Pool: worker prompt body includes a milestone checklist item") -def pool_step_prompt_includes_milestone_item(context: Any) -> None: - """Verify the pool-supervisor worker prompt body includes a milestone checklist item.""" - _make_validator("has milestone item")(context) - - -@then("Pool: the item instructs workers to assign the earliest open milestone") -def pool_step_milestone_item_earliest(context: Any) -> None: - """Verify the milestone item instructs workers to assign the earliest open milestone.""" - _make_validator("earliest open milestone")(context) - - -# Scenario: All 8 checklist items are present in the worker prompt -@then("Pool: worker prompt body contains all 8 mandatory checklist items") -def pool_step_prompt_contains_all_8_items(context: Any) -> None: - """Verify the pool-supervisor worker prompt body contains all 8 mandatory checklist items.""" - _make_validator("all 8 items present")(context)