[BUG] ADR-042 collection replace flags (cli_args_replace, child_types_replace, parent_types_replace) are silently dropped — not in ResourceTypeSpec domain model or database schema #9398

Open
opened 2026-04-14 16:43:26 +00:00 by HAL9000 · 1 comment
Owner

Metadata

  • Commit Message: fix(resources): persist ADR-042 collection replace flags in ResourceTypeSpec and resource_types table
  • Branch: fix/resource-type-inheritance-replace-flags-not-persisted

Background and Context

ADR-042 (Resource Type Inheritance) specifies that subtypes can explicitly replace (rather than merge) inherited collection fields by declaring <field>_replace: true in their YAML configuration:

# Replace parent's cli_args entirely rather than merging
cli_args_replace: true
cli_args:
  - name: env
    type: string

The three replace flags are:

  • cli_args_replace: bool — replace parent cli_args entirely instead of merging
  • child_types_replace: bool — replace parent child_types entirely instead of merging
  • parent_types_replace: bool — replace parent parent_types entirely instead of merging

Current Behavior

The replace flags exist in ResourceTypeConfigSchema (the YAML parsing schema at src/cleveragents/resource/schema.py) but are silently dropped at every subsequent layer:

  1. ResourceTypeSpec domain model (src/cleveragents/domain/models/core/resource_type.py) has NO cli_args_replace, child_types_replace, or parent_types_replace fields.
  2. ResourceTypeSpec.from_config() ignores these flags when loading from a YAML config dict.
  3. ResourceTypeModel database model (src/cleveragents/infrastructure/database/models.py) has NO columns for these flags.
  4. spec_to_db() and db_to_spec() in _resource_registry_data.py do not include these flags.

As a result, when a custom resource type YAML with cli_args_replace: true is registered via ResourceRegistryService.register_type(), the replace flag is silently dropped. The type is stored in the database without the flag, and when resolve_fields() is called on the type, it uses additive merge semantics instead of replace semantics.

The replace flags only work in the raw-dict test registry (used in BDD tests), not in the actual service layer.

Expected Behavior

Per ADR-042 §Collection Field Merging:

A subtype can explicitly replace (rather than merge) a collection field by declaring <field>_replace: true.

The replace flags must be:

  1. Added to ResourceTypeSpec as boolean fields (defaulting to False).
  2. Persisted to the resource_types database table as columns (cli_args_replace, child_types_replace, parent_types_replace).
  3. Included in spec_to_db() and db_to_spec() conversion functions.
  4. Included in _load_type_registry() so that resolve_fields() can use them correctly.

Evidence

# ResourceTypeSpec has no replace flags:
from cleveragents.domain.models.core.resource_type import ResourceTypeSpec
fields = ResourceTypeSpec.model_fields
print('Has cli_args_replace:', 'cli_args_replace' in fields)  # False
print('Has child_types_replace:', 'child_types_replace' in fields)  # False
print('Has parent_types_replace:', 'parent_types_replace' in fields)  # False

# from_config() silently drops the flag:
config = {
    'name': 'acme/child-type',
    'resource_kind': 'physical',
    'sandbox_strategy': 'none',
    'inherits': 'container-instance',
    'cli_args_replace': True,
    'cli_args': [{'name': 'env', 'type': 'string', 'required': False, 'description': 'env'}]
}
spec = ResourceTypeSpec.from_config(config)
print('Has cli_args_replace attr:', hasattr(spec, 'cli_args_replace'))  # False

Acceptance Criteria

  • ResourceTypeSpec gains cli_args_replace: bool = False, child_types_replace: bool = False, parent_types_replace: bool = False fields.
  • ResourceTypeSpec.from_config() reads these flags from the config dict.
  • ResourceTypeModel gains cli_args_replace, child_types_replace, parent_types_replace columns (Boolean, NOT NULL, default False).
  • An Alembic migration adds these columns to the resource_types table.
  • spec_to_db() writes these flags to the DB model.
  • db_to_spec() reads these flags from the DB model.
  • _load_type_registry() includes these flags so resolve_fields() uses them correctly.
  • BDD scenarios for replace mode (cli_args replace mode, child_types replace mode, parent_types replace mode) pass end-to-end through the service layer, not just the raw-dict test registry.
  • nox -s unit_tests -- features/resource_type_inheritance.feature passes.

Subtasks

  • Add cli_args_replace, child_types_replace, parent_types_replace fields to ResourceTypeSpec domain model
  • Update ResourceTypeSpec.from_config() to read replace flags from config dict
  • Add replace flag columns to ResourceTypeModel database model
  • Write Alembic migration to add columns to resource_types table
  • Update spec_to_db() to persist replace flags
  • Update db_to_spec() to restore replace flags
  • Update _load_type_registry() to include replace flags
  • Verify BDD replace-mode scenarios pass end-to-end through service layer
  • Run nox -s unit_tests -- features/resource_type_inheritance.feature and confirm pass
  • Verify coverage ≥97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.

Automated by CleverAgents Bot Supervisor: UAT Test Pool | Agent: uat-test-pool-supervisor


Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit Message**: `fix(resources): persist ADR-042 collection replace flags in ResourceTypeSpec and resource_types table` - **Branch**: `fix/resource-type-inheritance-replace-flags-not-persisted` ## Background and Context ADR-042 (Resource Type Inheritance) specifies that subtypes can explicitly **replace** (rather than merge) inherited collection fields by declaring `<field>_replace: true` in their YAML configuration: ```yaml # Replace parent's cli_args entirely rather than merging cli_args_replace: true cli_args: - name: env type: string ``` The three replace flags are: - `cli_args_replace: bool` — replace parent `cli_args` entirely instead of merging - `child_types_replace: bool` — replace parent `child_types` entirely instead of merging - `parent_types_replace: bool` — replace parent `parent_types` entirely instead of merging ## Current Behavior The replace flags exist in `ResourceTypeConfigSchema` (the YAML parsing schema at `src/cleveragents/resource/schema.py`) but are **silently dropped** at every subsequent layer: 1. **`ResourceTypeSpec` domain model** (`src/cleveragents/domain/models/core/resource_type.py`) has NO `cli_args_replace`, `child_types_replace`, or `parent_types_replace` fields. 2. **`ResourceTypeSpec.from_config()`** ignores these flags when loading from a YAML config dict. 3. **`ResourceTypeModel` database model** (`src/cleveragents/infrastructure/database/models.py`) has NO columns for these flags. 4. **`spec_to_db()`** and **`db_to_spec()`** in `_resource_registry_data.py` do not include these flags. As a result, when a custom resource type YAML with `cli_args_replace: true` is registered via `ResourceRegistryService.register_type()`, the replace flag is silently dropped. The type is stored in the database without the flag, and when `resolve_fields()` is called on the type, it uses additive merge semantics instead of replace semantics. The replace flags only work in the raw-dict test registry (used in BDD tests), not in the actual service layer. ## Expected Behavior Per ADR-042 §Collection Field Merging: > A subtype can explicitly **replace** (rather than merge) a collection field by declaring `<field>_replace: true`. The replace flags must be: 1. Added to `ResourceTypeSpec` as boolean fields (defaulting to `False`). 2. Persisted to the `resource_types` database table as columns (`cli_args_replace`, `child_types_replace`, `parent_types_replace`). 3. Included in `spec_to_db()` and `db_to_spec()` conversion functions. 4. Included in `_load_type_registry()` so that `resolve_fields()` can use them correctly. ## Evidence ```python # ResourceTypeSpec has no replace flags: from cleveragents.domain.models.core.resource_type import ResourceTypeSpec fields = ResourceTypeSpec.model_fields print('Has cli_args_replace:', 'cli_args_replace' in fields) # False print('Has child_types_replace:', 'child_types_replace' in fields) # False print('Has parent_types_replace:', 'parent_types_replace' in fields) # False # from_config() silently drops the flag: config = { 'name': 'acme/child-type', 'resource_kind': 'physical', 'sandbox_strategy': 'none', 'inherits': 'container-instance', 'cli_args_replace': True, 'cli_args': [{'name': 'env', 'type': 'string', 'required': False, 'description': 'env'}] } spec = ResourceTypeSpec.from_config(config) print('Has cli_args_replace attr:', hasattr(spec, 'cli_args_replace')) # False ``` ## Acceptance Criteria - [ ] `ResourceTypeSpec` gains `cli_args_replace: bool = False`, `child_types_replace: bool = False`, `parent_types_replace: bool = False` fields. - [ ] `ResourceTypeSpec.from_config()` reads these flags from the config dict. - [ ] `ResourceTypeModel` gains `cli_args_replace`, `child_types_replace`, `parent_types_replace` columns (Boolean, NOT NULL, default False). - [ ] An Alembic migration adds these columns to the `resource_types` table. - [ ] `spec_to_db()` writes these flags to the DB model. - [ ] `db_to_spec()` reads these flags from the DB model. - [ ] `_load_type_registry()` includes these flags so `resolve_fields()` uses them correctly. - [ ] BDD scenarios for replace mode (`cli_args replace mode`, `child_types replace mode`, `parent_types replace mode`) pass end-to-end through the service layer, not just the raw-dict test registry. - [ ] `nox -s unit_tests -- features/resource_type_inheritance.feature` passes. ## Subtasks - [ ] Add `cli_args_replace`, `child_types_replace`, `parent_types_replace` fields to `ResourceTypeSpec` domain model - [ ] Update `ResourceTypeSpec.from_config()` to read replace flags from config dict - [ ] Add replace flag columns to `ResourceTypeModel` database model - [ ] Write Alembic migration to add columns to `resource_types` table - [ ] Update `spec_to_db()` to persist replace flags - [ ] Update `db_to_spec()` to restore replace flags - [ ] Update `_load_type_registry()` to include replace flags - [ ] Verify BDD replace-mode scenarios pass end-to-end through service layer - [ ] Run `nox -s unit_tests -- features/resource_type_inheritance.feature` and confirm pass - [ ] Verify coverage ≥97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. --- **Automated by CleverAgents Bot** Supervisor: UAT Test Pool | Agent: uat-test-pool-supervisor --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.2.0 milestone 2026-04-14 16:46:52 +00:00
Author
Owner

Triage: Verified [AUTO-OWNR-1]

Valid bug: ADR-042 collection replace flags (cli_args_replace, child_types_replace, parent_types_replace) are silently dropped at every layer beyond the YAML parsing schema. They are missing from the ResourceTypeSpec domain model, the database schema, and the spec_to_db()/db_to_spec() conversion functions. The replace flags only work in the raw-dict test registry (used in BDD tests), not in the actual service layer.

Assigning to v3.2.0 as resource type inheritance is a core M3 feature. Priority High — the replace semantics are completely non-functional in production.

MoSCoW: Must Have — ADR-042 replace flags are part of the resource type inheritance specification. Without them, subtypes cannot replace inherited collection fields as specified.


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

✅ **Triage: Verified** [AUTO-OWNR-1] Valid bug: ADR-042 collection replace flags (`cli_args_replace`, `child_types_replace`, `parent_types_replace`) are silently dropped at every layer beyond the YAML parsing schema. They are missing from the `ResourceTypeSpec` domain model, the database schema, and the `spec_to_db()`/`db_to_spec()` conversion functions. The replace flags only work in the raw-dict test registry (used in BDD tests), not in the actual service layer. Assigning to **v3.2.0** as resource type inheritance is a core M3 feature. Priority **High** — the replace semantics are completely non-functional in production. MoSCoW: **Must Have** — ADR-042 replace flags are part of the resource type inheritance specification. Without them, subtypes cannot replace inherited collection fields as specified. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
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.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#9398
No description provided.