Files
cleveragents-core/features/database_models_lifecycle_coverage.feature
hurui200320 2005b8ef82
CI / push-validation (push) Successful in 18s
CI / build (push) Successful in 19s
CI / helm (push) Successful in 24s
CI / lint (push) Successful in 29s
CI / security (push) Successful in 1m11s
CI / e2e_tests (push) Successful in 2m56s
CI / quality (push) Successful in 3m40s
CI / typecheck (push) Successful in 3m59s
CI / integration_tests (push) Successful in 4m3s
CI / unit_tests (push) Successful in 4m55s
CI / docker (push) Successful in 10s
CI / coverage (push) Successful in 10m44s
CI / status-check (push) Successful in 1s
CI / benchmark-regression (push) Has been skipped
CI / benchmark-publish (push) Successful in 1h13m28s
feat(tests): replace all @skip tags with proper @tdd_expected_fail tags or remove them across the entire codebase (#7221)
## Summary

Replaces all 234 bare `@skip` occurrences across 82 Behave feature files with the correct TDD issue-capture tagging system described in CONTRIBUTING.md § Bug Fix Workflow.

Previously, the noxfile ran Behave with `--tags=not @skip`, silently excluding all `@skip`-tagged scenarios from every CI run. These tests never ran, never inverted results via the `@tdd_expected_fail` mechanism, and never contributed to coverage — defeating the purpose of TDD issue-capture testing. Every `@skip` occurrence had a commented-out hint line immediately above it showing the intended proper tags (e.g., `# @tdd_issue @tdd_issue_4272 @tdd_expected_fail @skip`), confirming they were all intended for conversion.

## Changes

### Mechanical conversion (234 replacements across 82 files)
- Extracted the proper TDD tags from the comment hint above each `@skip` line, removed `@skip` from the tag set, and replaced the `@skip` line with those tags.
- Removed the now-redundant comment hint lines alongside each replacement.

### Bug-fixed scenarios — `@tdd_expected_fail` removed (84 scenarios)
- After conversion, ran `nox -s unit_tests` to identify which newly-enabled `@tdd_expected_fail` scenarios now **pass** (their referenced bugs have already been fixed). Removed `@tdd_expected_fail` from those 84 scenarios and their corresponding feature-level tags, leaving only the permanent `@tdd_issue @tdd_issue_<N>` regression-guard tags.
- Affected features include: `tdd_tool_runner_env_precedence`, `tdd_automation_profile_session_leak`, `tls_certificate_check`, `project_create_persist`, `resource_type_bootstrap_*`, and 18 others.

### Noxfile cleanup
- Removed all four `--tags=not @skip` arguments from `noxfile.py` (unit_tests and coverage sessions). With zero `@skip` tags remaining in the codebase, this filter was dead code and its presence would mislead future maintainers into thinking `@skip` is still a supported escape mechanism.

### Regression guard files
- Split the regression guards into two focused files:
  - `tdd_regression_guards_exec_env.feature` for bug #4281 (exec-env precedence)
  - `tdd_regression_guards_session_list.feature` for bug #4271 (session list summary)
- Each file carries only its own `@tdd_issue` tags at the feature level, avoiding cross-contamination via Behave tag inheritance. The `Background` step (`session-list-summary mock`) only appears in the session-list file where it is actually needed.

### Duplicate tag cleanup
- Removed duplicate `@tdd_issue @tdd_issue_4287` tag lines in `tdd_skill_add_regression.feature` (lines 20 and 29).

### Inline comment for retained `@tdd_expected_fail`
- Added inline comment in `ci_workflow_validation.feature:134` explaining why this specific #4227 scenario retains `@tdd_expected_fail` despite #4227 being closed (CI YAML does not encode threshold as a machine-readable value).

### Known edge cases — `@tdd_expected_fail` retained (closed issues, fix on master, scenarios still fail)
The following issues are **closed** and their fixes **are on master**, but the specific test assertions still fail because the fixes address other aspects of the bugs. The `@tdd_expected_fail` tags are functionally correct and must remain until the specific scenario assertions pass:
- `tdd_exec_env_resolution_precedence.feature` — bug #1080 (closed 2026-03-31). The precedence-level-2-vs-4 scenario still fails.
- `session_list_summary_dedup.feature` — bug #3046 (closed 2026-04-05). The dedup-consistency scenarios still fail.
- `actor_add_update_enforcement.feature` — bug #2609 (closed 2026-04-05). The enforcement scenarios still fail.
- `ci_workflow_validation.feature:134` — #4227 (closed 2026-04-08). The CI YAML threshold assertion still fails.

## Verification

- `grep -r "@skip" features/ --include="*.feature"` → **zero results** ✓
- `grep -n "tags=not @skip" noxfile.py` → **zero results** ✓
- `nox -s unit_tests` → **629 features passed, 0 failed** ✓ (up from ~545 before this PR)
- CI all green (coverage ≥ 97%) ✓
- Integration tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓
- E2E tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓
- `CHANGELOG.md` updated with entry for this change ✓
- `CONTRIBUTORS.md` — Rui Hu already listed ✓

## Issues Addressed

Closes #7025

Co-authored-by: CleverThis <hal9000@cleverthis.com>
Reviewed-on: #7221
Reviewed-by: HAL 9000 <HAL9000@cleverthis.com>
Reviewed-by: HAL9001 <hal9001@cleverthis.com>
Co-authored-by: Rui Hu <rui.hu@cleverthis.com>
Co-committed-by: Rui Hu <rui.hu@cleverthis.com>
2026-04-13 04:56:01 +00:00

176 lines
8.8 KiB
Gherkin

@phase1 @database @models @lifecycle
Feature: Lifecycle Data Persistence and Retrieval
As a system operator
I want lifecycle actions and plans to survive database round-trips faithfully
So that no data is lost or corrupted when storing and loading lifecycle records
Background:
Given the lifecycle database is ready
And a lifecycle database session is open
@lifecycle_action @to_domain
Scenario: A stored action retains its identity and naming when loaded
Given an action record exists with valid attributes and tags
When the action record is loaded as a domain object
Then the loaded action should preserve its original identifier
And the loaded action should preserve its namespace and short name
And the loaded action should preserve its description fields
And the loaded action should preserve its actor assignments
And the loaded action should preserve its state and flags
And the loaded action should preserve its timestamps
And the loaded action should preserve its tags
@lifecycle_action @to_domain
Scenario: A stored action with input arguments loads them correctly
Given an action record exists with a structured arguments schema
When the action record is loaded as a domain object
Then the loaded action should contain the expected argument entries
And each argument entry should have the correct name and type
@lifecycle_action @to_domain
Scenario: A stored action with no inputs or tags loads empty collections
Given an action record exists with no inputs and no tags
When the action record is loaded as a domain object
Then the loaded action should have an empty arguments collection
And the loaded action should have an empty tags collection
@lifecycle_action @from_domain
Scenario: A fully populated action domain object is stored correctly
Given a complete action domain object is prepared
When the action domain object is stored as a database record
Then the stored record should preserve the action identifier
And the stored record should preserve the name components
And the stored record should preserve the description fields
And the stored record should preserve the actor assignments
And the stored record should serialize the arguments as JSON
And the stored record should serialize the tags as JSON
And the stored record should preserve the state value
And the stored record should format timestamps as ISO strings
@lifecycle_action @from_domain
Scenario: An action with an enumerated state stores the enum value
Given an action domain object is prepared with an enumerated state
When the action domain object is stored as a database record
Then the stored record state should equal the enum value
@lifecycle_action @from_domain
Scenario: An action with a custom string state stores it verbatim
Given an action-like object is prepared with a custom string state
When the custom-state action is stored as a database record
Then the stored record state should equal the custom string
@lifecycle_plan @parse_iso
Scenario: A valid ISO-8601 timestamp string is parsed to a datetime
When a valid ISO-8601 string is parsed as a timestamp
Then the parsed timestamp should be the expected datetime value
@lifecycle_plan @parse_iso
Scenario: A missing timestamp value parses to nothing
When an absent value is parsed as a timestamp
Then the parsed timestamp should be absent
@lifecycle_plan @to_iso
Scenario: A datetime is formatted as an ISO-8601 string
When a datetime value is formatted as an ISO string
Then the formatted string should match ISO-8601 format
@lifecycle_plan @to_iso
Scenario: An absent datetime formats to nothing
When an absent datetime is formatted as an ISO string
Then the formatted value should be absent
@lifecycle_plan @to_domain
Scenario: A plan in the strategize phase with queued state loads correctly
Given a plan record exists in the strategize phase with queued state
When the plan record is loaded as a domain object
Then the loaded plan should preserve its identity
And the loaded plan should be in the strategize phase
And the loaded plan processing state should be queued
And the loaded plan should preserve its description
And the loaded plan should preserve its timestamps
And the loaded plan should preserve its metadata
@lifecycle_plan @to_domain
Scenario: A plan in the strategize phase with processing state loads correctly
Given a plan record exists in the strategize phase with processing state
When the plan record is loaded as a domain object
Then the loaded plan should be in the strategize phase
And the loaded plan processing state should be processing
@lifecycle_plan @to_domain
Scenario: A completed plan loads all phase timestamps correctly
Given a plan record exists with all phase timestamps populated
When the plan record is loaded as a domain object
Then the loaded plan timestamps should include the strategize window
And the loaded plan timestamps should include the execute window
And the loaded plan timestamps should include the apply window
@lifecycle_plan @to_domain
Scenario: A plan with associated projects and tags loads them as lists
Given a plan record exists with associated project identifiers and tags
When the plan record is loaded as a domain object
Then the loaded plan should contain the expected project identifiers
And the loaded plan should contain the expected tags
@lifecycle_plan @from_domain
Scenario: A plan in STRATEGIZE phase stores the state correctly
Given a plan domain object is prepared in the strategize phase with a queued state
When the plan domain object is stored as a database record
Then the stored plan record should have state "queued"
And the stored plan record should preserve the plan identifier
And the stored plan record should preserve the phase
And the stored plan record should serialize the project identifiers as JSON
And the stored plan record should serialize the plan tags as JSON
And the stored plan record should format plan timestamps as ISO strings
And the stored plan record automation level should be "manual"
@lifecycle_plan @from_domain
Scenario: A plan with a processing state stores the state correctly
Given a plan domain object is prepared in the strategize phase with a queued state
When the plan domain object is stored as a database record
Then the stored plan record should have state "queued"
And the stored plan record phase should be "strategize"
@lifecycle_plan @from_domain
@tdd_issue @tdd_issue_4246 @tdd_expected_fail
Scenario: A plan with no explicit state defaults to queued
Given a plan domain object is prepared with neither action nor processing state
When the stateless plan domain object is stored as a database record
Then the stored plan record should have state "queued"
@lifecycle_plan @from_domain
Scenario: A plan with all phase timestamps stores them as ISO strings
Given a plan domain object is prepared with all phase timestamps
When the plan domain object is stored as a database record
Then the stored plan record should have all phase timestamps as ISO strings
@lifecycle_plan @from_domain
Scenario: A plan with non-default automation level stores the real value
Given a plan domain object is prepared with automation level "full_automation"
When the plan domain object is stored as a database record
Then the stored plan record automation level should be "full_automation"
@lifecycle_plan @from_domain
Scenario: A plan with review-before-apply automation level stores correctly
Given a plan domain object is prepared with automation level "review_before_apply"
When the plan domain object is stored as a database record
Then the stored plan record automation level should be "review_before_apply"
@lifecycle_plan @from_domain
Scenario: A plan stored with an explicit action_id preserves it
Given a plan domain object is prepared in the strategize phase with a queued state
When the plan domain object is stored with an explicit action identifier
Then the stored plan record should preserve the supplied action identifier
@lifecycle_action @round_trip
Scenario: An action survives a full save-and-reload cycle unchanged
Given a complete action domain object is prepared
When the action is saved to the database and reloaded as a domain object
Then the reloaded action should match the original action
@lifecycle_plan @round_trip
Scenario: A plan survives a full save-and-reload cycle unchanged
Given a plan record exists in the strategize phase with queued state
When the plan record is saved and then reloaded as a domain object
Then the reloaded plan should preserve its identity and phase