fix(tests): restore agent-evolution-pool-supervisor.md or remove its orphaned BDD scenarios
CI / helm (pull_request) Successful in 1m5s
CI / push-validation (pull_request) Successful in 1m14s
CI / build (pull_request) Successful in 1m15s
CI / lint (pull_request) Successful in 1m47s
CI / typecheck (pull_request) Successful in 1m56s
CI / quality (pull_request) Successful in 1m50s
CI / security (pull_request) Successful in 1m56s
CI / integration_tests (pull_request) Successful in 7m43s
CI / unit_tests (pull_request) Successful in 9m18s
CI / docker (pull_request) Successful in 1m35s
CI / coverage (pull_request) Successful in 24m0s
CI / status-check (pull_request) Successful in 4s
CI / push-validation (push) Successful in 46s
CI / helm (push) Successful in 1m0s
CI / lint (push) Successful in 1m17s
CI / build (push) Successful in 1m26s
CI / benchmark-publish (push) Has started running
CI / quality (push) Successful in 1m50s
CI / e2e_tests (push) Successful in 1m52s
CI / security (push) Successful in 1m59s
CI / typecheck (push) Successful in 2m3s
CI / benchmark-regression (push) Failing after 49s
CI / integration_tests (push) Successful in 4m53s
CI / unit_tests (push) Successful in 4m59s
CI / docker (push) Successful in 2m59s
CI / coverage (push) Successful in 13m4s
CI / status-check (push) Successful in 3s

Chose Option B (fallback): remove orphaned BDD scenarios for two retired agents.

Commit 3c8cf601 deleted .opencode/agents/agent-evolution-pool-supervisor.md
and .opencode/agents/implementation-pool-supervisor.md as part of a large-scale
restructuring of agent definition files. However, their corresponding Behave feature
files and step definitions were not cleaned up, causing nox -s unit_tests to fail
with AssertionError on master.

Removed files:
- features/agent_evolution_pool_supervisor_metadata.feature (7 scenarios testing
  agent-evolution-pool-supervisor.md existence and content)
- features/steps/agent_evolution_pool_supervisor_metadata_steps.py (382 lines of
  step definitions for the above feature)
- features/pr_compliance_pool_supervisor.feature (10 scenarios testing
  implementation-pool-supervisor.md existence and content)
- features/steps/pr_compliance_pool_supervisor_steps.py (219 lines of step
  definitions for the above feature)

Both agent definition files were permanently retired by the restructuring commit
and are not expected to return. Keeping orphaned tests that assert on deleted files
is not valid; removal is the correct resolution per the project's handling of
obsolete tests policy.

Quality gates verified:
- nox -s unit_tests: 694 features passed, 0 failed (was failing on master)
- nox -s lint: all checks passed
- nox -s typecheck: 0 errors, 3 warnings (pre-existing import warnings)
- nox -s coverage_report: 96.5% (meets 96.5% threshold)
- nox -s integration_tests: 1998 tests passed, 0 failed

ISSUES CLOSED: #11208
This commit was merged in pull request #11209.
This commit is contained in:
2026-05-14 04:16:04 +00:00
parent a61a418b26
commit 39f9903f1a
4 changed files with 0 additions and 722 deletions
@@ -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
@@ -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
@@ -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"
@@ -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)