Skip to content

feat(core): add ordered flag to attribute schema to ignore list eleme…#9782

Open
ajtmccarty wants to merge 3 commits into
stablefrom
ajtm-07012026-allow-order-ignore
Open

feat(core): add ordered flag to attribute schema to ignore list eleme…#9782
ajtmccarty wants to merge 3 commits into
stablefrom
ajtm-07012026-allow-order-ignore

Conversation

@ajtmccarty

@ajtmccarty ajtmccarty commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Why

When two branches both edit the same list-valued attribute (a List/JSON attribute, or a
Dropdown's choices, an attribute's enum, etc.) so that they end up holding the same elements
in a different order
, the diff reports a value conflict and merge/rebase is refused — even though
there is no semantic divergence. This is the converged-state dead-end described in #9764 for
Dropdown.choices: once both branches hold the same set of choices, the branch still cannot rebase.

Goal: let a schema author declare that element order is not significant for an attribute, so
reordering (or converging to the same set in a different order) is not treated as a conflict.

Non-goals: this does not change the rebase guard to honor ResolveDiffConflict selections
— that is a separate change. It also does not alter merge value resolution: when there is no
conflict, the merge continues to apply the branch's value as before.

Closes #9764 (resolves the converged-choices dead-end; the rebase-guard resolution handling is
out of scope here and is captured in #9654).

What changed

Behavioral changes

  • New ordered boolean on attribute schemas (default True). When set to False on a List or
    JSON-array attribute, reordering its elements is no longer a conflict during branch merge or
    rebase. Element multiplicity still matters — adding or removing an element is still a conflict.
  • The built-in schema attributes enum, dropdown choices, generic used_by, and
    restricted_namespaces are marked ordered=False, so two branches converging to the same set of
    values in a different order no longer conflict.

Implementation notes

  • Conflict detection lives in one place: ConflictsEnricher._have_same_value. For an unordered
    attribute it now compares the two JSON values as multisets (canonicalizing each element), falling
    back to exact comparison when a value is not a JSON array.
  • The enricher resolves the attribute schema from the diff (source) branch, so a branch that
    changes an attribute's ordered flag has that change honored within its own diff. Schema lookups
    degrade gracefully (fall back to order-sensitive) when a schema/branch cannot be resolved.
  • ordered uses UpdateSupport.ALLOWED: it only affects how diffs are interpreted, never stored
    data, so no data migration is required (unlike unique/read_only).

What stayed the same

  • Default behavior is unchanged (ordered=True): order-sensitive conflict detection for every
    attribute that does not opt out.
  • No data migration; merge value resolution and the rebase guard are unchanged.
  • Conflicts are still re-evaluated against live values on every recompute (both the
    update_branch_diff and recalculate paths) — a conflict recorded during a real divergence is
    cleared once the two sides converge.

Suggested review order

  1. backend/infrahub/core/diff/conflicts_enricher.py — the core comparison and schema resolution.
  2. backend/infrahub/core/schema/definitions/internal.py — the new field and the four ordered=False flips.
  3. backend/infrahub/dependencies/builder/diff/conflicts_enricher.py — wiring db into the enricher.
  4. Tests: backend/tests/component/core/diff/test_ordered_attribute_conflicts.py and additions to test_conflicts_enricher.py.
  5. Generated/rendered files (mechanical): core/schema/generated/attribute_schema.py, schema/openapi.json, docs/docs/reference/schema/*.mdx.

Impact & rollout

  • Backward compatibility: fully backward compatible — ordered defaults to True, preserving
    existing order-sensitive behavior for all attributes that do not opt out.
  • Performance: negligible; the enricher does one extra JSON parse + sort only for attributes
    flagged ordered=False.
  • Config/env changes: none. New per-attribute schema field, no feature flag.
  • Deployment notes: safe to deploy; no data migration required (UpdateSupport.ALLOWED).

Checklist

  • Tests added/updated
  • Changelog entry added (changelog/9764.fixed.md)
  • External docs updated (schema reference regenerated)
  • Internal .md docs updated (internal knowledge and AI code tools knowledge)
  • I have reviewed AI generated content

Summary by cubic

Adds an ordered flag to attribute schemas so reordering elements in List/JSON arrays no longer triggers merge/rebase conflicts. Actual adds/removes or different counts still conflict.

  • New Features
    • Added ordered: boolean to attribute schemas (default true).
    • Diff conflict logic treats List and JSON-array attributes with ordered=false as order-insensitive (multiset); schema is resolved from the diff branch so a branch’s own ordered change applies.
    • Core schema sets ordered=false for: enum, dropdown choices, generic used_by, and restricted_namespaces.
    • ConflictsEnricher now takes db; DI updated. Internals use ujson for canonicalization.
    • Field exposed in generated schema and openapi.json; regenerated frontend REST types and refreshed .betterer.results. Docs and tests added, including reorder and recompute paths.

Written for commit 361f3fb. Summary will update on new commits.

Review in cubic

…nt order in diffs

Adds an `ordered` boolean to AttributeSchema (default True). When set to False on
a List or JSON-array attribute, reordering its elements is no longer reported as a
conflict during branch merge or rebase; element counts still matter, so adding or
removing an element remains a conflict. The diff conflict enricher compares such
attributes as multisets and resolves the schema from the diff branch first, so a
branch's own `ordered` change is honored within its diff.

The built-in schema `enum`, dropdown `choices`, generic `used_by`, and
`restricted_namespaces` attributes are marked ordered=False.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added type/documentation Improvements or additions to documentation group/backend Issue related to the backend (API Server, Git Agent) labels Jul 1, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 10 files

Confidence score: 4/5

  • In changelog/9764.fixed.md, the documented default for ordered conflicts with the schema (false vs actual true), which can mislead users into relying on the wrong behavior and cause unexpected conflict handling after upgrade; update the changelog text (including the “default” parenthetical) to match the real default before merging.

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread changelog/9764.fixed.md Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 12 untouched benchmarks


Comparing ajtm-07012026-allow-order-ignore (361f3fb) with stable (0b1ec05)

Open in CodSpeed

Regenerate frontend/app/src/shared/api/rest/types.generated.ts after adding the
`ordered` field to schema/openapi.json, fixing the frontend-validate-openapi-types
CI check.

Drop the incorrect "(the default)" qualifier in the changelog: the `ordered`
attribute-schema field defaults to `true` (order-sensitive), not `false`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the group/frontend Issue related to the frontend (React) label Jul 1, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Shadow auto-approve: would require human review. Adds new ordered flag to attribute schemas and modifies core conflict detection logic for diff/merge. This is a feature change in a critical path that requires human review to ensure correctness and no unintended side effects.

Re-trigger cubic

Regenerating the frontend OpenAPI REST types for the new `ordered` field changed
the type structures that TypeScript embeds in several existing tracked error
messages. The error count and locations are unchanged (212 issues); only the
message text differs. Refresh .betterer.results so `betterer ci` passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ajtmccarty ajtmccarty marked this pull request as ready for review July 1, 2026 23:59
@ajtmccarty ajtmccarty requested review from a team as code owners July 1, 2026 23:59

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The List path is well covered, but the "JSON" branch of _UNORDERED_CAPABLE_KINDS never fires in any test. Could we add one JSON attribute with an array value (proves the JSON branch works) and one where the JSON value is a top-level dict (locks in the exact-comparison fallback)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/backend Issue related to the backend (API Server, Git Agent) group/frontend Issue related to the frontend (React) type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: rebase refuses additive Dropdown conflicts even after resolution or converging both sides to the union

2 participants